#include "ESP32_WROOM_32D.h" #include #include #include #include extern int Flag3S; #define g_uMsgCmdFrameLen (6) extern uint8_t Devicenum; extern uint8_t g_wifi_rx_buf[WIFI_RX_BUF_SIZE]; extern uint32_t g_wifi_rx_last; extern uint32_t g_wifi_rx_head; extern uint32_t g_wifi_rx_last_tick; /* 最近一次收到ESP数据的时间戳(10ms单位) */ uint8_t wifi_tx_buf[WIFI_TX_BUF_SIZE]; uint16_t wifi_tx_len; static int wifi_state = 0; //WiFi模块当前状态 static int wifi_ack_delay = 0; //WiFi应答等待 static int wifi_set_ssid = 0; //WiFi应答SSID设置 uint32_t unlink_time = 0; extern uint32_t pc_link_timeout; char TCP_IP_PORT[8] = {"8001"}; char MAC_ADDR[20] = {0}; uint32_t broadDevFlag = 0; extern uint8_t pc_channel_recv; static int resendtime = 0; uint16_t WriteComm2(char *data, uint16_t len) { //return UART_Write(UART2, data, len); HAL_UART_Transmit((UART_HandleTypeDef *)sysinf.ESPUart,(const uint8_t *)data, len,1000); // HAL_UART_Transmit_DMA((UART_HandleTypeDef *)sysinf.ESPUart,(const uint8_t *)data, len); return 0; } /*WIFI单次发送指令*/ void ESP32_Send_AT_Cmd(char *cmd,uint32_t time) { char buff[128] = {0}; strcpy(buff, cmd); strcat(buff, "\r\n"); Van_Device_Printf(VAN_LOG_WIFI,"\nW--> %s", buff); WriteComm2(buff, strlen(buff)); wifi_ack_delay = time; } void ESP32_AT(void) { ESP32_Send_AT_Cmd("AT",5000); } /*恢复出厂设置*/ void ESP32_AT_Restore(void) { ESP32_Send_AT_Cmd("AT+RESTORE",500); } /*复位*/ void ESP32_AT_RST(void) { ESP32_Send_AT_Cmd("AT+RST",8000); } /*上电自动连接AP*/ void ESP32_AT_AUTOCONN(void) { ESP32_Send_AT_Cmd("AT+CWAUTOCONN=0",5000); } /*WIFI AP/STA/AP+STA模式选择*/ void ESP32_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode) { switch ( enumMode ) { case STA: ESP32_Send_AT_Cmd ( "AT+CWMODE=1", 5000 ); break; case AP: ESP32_Send_AT_Cmd ( "AT+CWMODE=2", 5000 ); break; case STA_AP: ESP32_Send_AT_Cmd ( "AT+CWMODE=3", 5000 ); break; default: break; } } /*WIFI加入AP*/ void ESP32_JoinAP( char * pSSID, char * pPassWord, char * pMacAddr) { char cCmd [128]; my_sprintf ( cCmd, sizeof(cCmd), "AT+CWJAP=\"%s\",\"%s\",\"%s\"", pSSID, pPassWord,pMacAddr); ESP32_Send_AT_Cmd( cCmd,5000 ); } /*WIFI建立AP*/ void ESP32_SetupAP( char * pSSID, char * pPassWord) { char cCmd [40]; my_sprintf ( cCmd,sizeof(cCmd), "AT+CWSAP=\"%s\",\"%s\"", pSSID, pPassWord ); ESP32_Send_AT_Cmd( cCmd, 5000 ); } /*WIFI查询IP*/ void ESP32_GetIp(void) { ESP32_Send_AT_Cmd( "AT+CIPSTA?", 5000 ); } /*WIFI禁止自动连接*/ void ESP32_DisAutoLink(void) { ESP32_Send_AT_Cmd( "AT+CWAUTOCONN=0", 5000 ); } void ESP32_CWLAP(char * pSSID) { char cCmd [80]; my_sprintf ( cCmd, sizeof(cCmd), "AT+CWLAP=\"%s\"", pSSID); ESP32_Send_AT_Cmd( cCmd, 5000 ); } /*WIFI关闭回显*/ void ESP32_EchoOff(void) { ESP32_Send_AT_Cmd( "ATE0", 5000 ); } /*WIFI初始化*/ void ESP32_Init(void) { ESP32_Send_AT_Cmd( "+++", 5000 ); } /*WIFI 单/多连接*/ void ESP32_Enable_MultipleId (uint8_t enumEnUnvarnishTx ) { char cCmd [20]; my_sprintf ( cCmd, sizeof(cCmd), "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) ); ESP32_Send_AT_Cmd ( cCmd, 5000 ); } /*WIFI AP作为服务端开启或关闭,1---开启服务:0---关闭服务*/ void ESP32_AP_Server (uint8_t open) { char cCmd [40]; my_sprintf ( cCmd,sizeof(cCmd), "AT+CIPSERVER=%d", open); ESP32_Send_AT_Cmd( cCmd, 5000 ); } /*WIFI STA选择TCP或UDP协议*/ void ESP32_Link_Server(ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id) { char cStr [100] = { 0 }, cCmd [60]; switch ( enumE ) { case enumTCP: my_sprintf ( cStr, sizeof(cCmd), "\"%s\",\"%s\",%s,6", "TCP", ip, ComNum ); break; case enumUDP: my_sprintf ( cStr,sizeof(cCmd), "\"%s\",\"%s\",%s,9090,0", "UDP", ip, ComNum ); break; default: break; } if ( id < 5 ) my_sprintf ( cCmd,sizeof(cCmd), "AT+CIPSTART=%d,%s", id, cStr); else my_sprintf ( cCmd, sizeof(cCmd), "AT+CIPSTART=%s", cStr ); ESP32_Send_AT_Cmd ( cCmd,5000 ); } /*WIFI透传*/ void ESP32_UnvarnishSend ( void ) { ESP32_Send_AT_Cmd( "AT+CIPMODE=1", 5000 );//设置透传模式 } /*WIFI停止TCP*/ void ESP32_STOPTCP ( ENUM_ID_NO_TypeDef id ) { char cCmd [60]; my_sprintf ( cCmd,sizeof(cCmd), "AT+CIPCLOSE=%d", id); ESP32_Send_AT_Cmd ( cCmd, 20000 ); } /*退出透传*/ void ESP32_ExitUnvarnishSend( void ) { ESP32_Send_AT_Cmd("+++", 5000); } ///*设置默认波特率为460800*/ //void ESP32_SET_BUAR(void) //{ // ESP32_Send_AT_Cmd("AT+UART_DEF=460800,8,1,0,0","OK",NULL,500); //} /******************************************************************** * int WIFI_Send_Data(uint8_t *data, uint8_t len, uint8_t flag) * *描述:通过WIFI发送数据,异步 *参数:data:数据 *参数:len:数据长度 *参数:flag:1:立即发送,0:暂存 *返回:无 *其他:无 *-------------------------------------------------------------------- *记录: ********************************************************************/ int WIFI_Send_Data(uint8_t *data, uint16_t len, uint8_t flag) { char cStr [40] = {0}; if (wifi_state < WIFI_TRANS) return -1; if(wifi_ack_delay > 0) return -2; if(wifi_tx_len) return -3; if(len > WIFI_TX_BUF_SIZE){ Van_Device_Printf(VAN_LOG_WIFI,"WIFI_Send len:%d error ", len); return -1; } memcpy(&wifi_tx_buf[wifi_tx_len], data, len); wifi_tx_len += len; if(flag) { wifi_ack_delay = 3000; my_sprintf ( cStr, sizeof(cStr),"AT+CIPSEND=0,%d", wifi_tx_len ); ESP32_Send_AT_Cmd ( cStr, 3000 ); return wifi_tx_len; } return 0; } int WIFI_Send_MSG(uint8_t*msgHead,uint8_t *data, uint8_t * crc, uint16_t len) { char cStr [40] = {0}; if (wifi_state != WIFI_TRANS) return -1; if(wifi_ack_delay > 0) return -2; if(wifi_tx_len > 0) return -3; memcpy(&wifi_tx_buf[0], msgHead, g_uMsgCmdFrameLen); memcpy(&wifi_tx_buf[g_uMsgCmdFrameLen], data, len); memcpy(&wifi_tx_buf[g_uMsgCmdFrameLen+len], crc, 2); wifi_tx_len = g_uMsgCmdFrameLen+len+2; wifi_ack_delay = 3000; my_sprintf ( cStr, sizeof(cStr),"AT+CIPSEND=0,%d", wifi_tx_len ); ESP32_Send_AT_Cmd ( cStr, 3000 ); return wifi_tx_len; } int WIFI_SendIlde(void){ if(wifi_tx_len == 0) return 0; if (wifi_state < WIFI_TRANS) return 0; if(wifi_ack_delay > 0) return 0; return 1; } int WIFI_ReSend(void) { char cStr [40] = {0}; if(wifi_tx_len == 0) return 0; if (wifi_state < WIFI_TRANS) return -1; if(wifi_ack_delay > 0) return -2; wifi_ack_delay = 3000; my_sprintf ( cStr, sizeof(cStr),"AT+CIPSEND=0,%d", wifi_tx_len ); ESP32_Send_AT_Cmd ( cStr, 3000 ); return 0; } //wifi修改SSID void WIFI_set_ssid(void) { wifi_ack_delay = 0; wifi_state = WIFI_POWEROFF; wifi_set_ssid = 1; if(wifi_tx_len > 0) { WriteComm2((char *)wifi_tx_buf, wifi_tx_len); wifi_tx_len = 0; } } //wifi修改SSID void WIFI_set_CloseConnect(void) { wifi_state = WIFI_CLOSE; } // //在内存中查找字符串 // char* find_str(void *src, int size, char *str) // { // char *p = (char*)src; // int len = strlen((const char *)str); // if(len < 1) // return p; // for(int i = 0; i < size; i++) // { // if(p[i] == *str) // { // if( 0 == memcmp(&p[i], str, len)) // { // return &p[i]; // } // } // } // return NULL; // } //在内存中查找字符串 char* find_str_loop(void *src, int size, uint32_t *start, uint32_t end, char *str) { if (src == NULL || start == NULL || str == NULL || size <= 0) return NULL; unsigned char *buf = (unsigned char*)src; int head = *start; int len = strlen(str); // 空串直接返回当前位置(不移动头指针) if (len == 0) { return (char*)(buf + head); } // 计算有效数据长度 int valid_len; if (end >= head) valid_len = end - head; else valid_len = (size - head) + end; // 若有效数据长度小于目标串长度,不可能匹配 if (valid_len < len) return NULL; // 从 head 开始遍历所有可能的起始位置(不包括 end) int pos = head; while (pos != end) { // 检查从 pos 开始的 len 个字节是否与 str 匹配 int i; for (i = 0; i < len; i++) { int idx = (pos + i) % size; if (buf[idx] != (unsigned char)str[i]) break; } if (i == len) { // 完全匹配 // 更新头指针为匹配串之后的位置 *start = (pos + len) % size; return (char*)(buf + pos); } // 移动到下一个起始位置 pos = (pos + 1) % size; // 如果移动后到达 end,提前终止(有效数据遍历完毕) // 但 while 条件会处理,可省略 } // 未找到 return NULL; } /******************************************************************** * WIFI_recv_deal() * *描述:接收帧解析 *参数:无 *返回:无 *其他:无 *-------------------------------------------------------------------- *记录: ********************************************************************/ void WIFI_recv_deal(void) { char *p; int data_len = g_wifi_rx_last>g_wifi_rx_head?(g_wifi_rx_last-g_wifi_rx_head):(WIFI_RX_BUF_SIZE+g_wifi_rx_last-g_wifi_rx_head); // int udp_data_len = 0; char* data = (char*)g_wifi_rx_buf; if((data_len < 5)&&(wifi_state != WIFI_TRANS)) return; //判断是否接收完成 if(wifi_state > WIFI_LISTEN) { if(data[g_wifi_rx_last-1] != '\n' && data[g_wifi_rx_last-2] != '\r') { if(wifi_state == WIFI_TRANS){ if(data[g_wifi_rx_last-1] != '>' && data[g_wifi_rx_last-2] != '>'){ return; } } } } switch (wifi_state) { //指令模式 case WIFI_POWEROFF: case WIFI_ERROR: if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last,"ready") || NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last,"boot")) { wifi_state = WIFI_POWERON; wifi_ack_delay = 0; memset(wifi_tx_buf,0,sizeof(wifi_tx_buf)); wifi_tx_len = 0; // wifi_receive_clear(); } break; case WIFI_POWERON: case WIFI_INIT: case WIFI_STATION: case WIFI_DISAUTO: case WIFI_LINK_AP: case WIFI_GET_IP: case WIFI_SETMUX: case WIFI_LISTEN: if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "OK\r\n")) { Van_Device_Printf(VAN_LOG_WIFI,"\nW<-- %s", data); wifi_ack_delay = 0; if(WIFI_LISTEN == wifi_state){ /*上电需要广播地址*/ broadDevFlag = 1; sysinf.s10_flag = 1; resendtime = 0; memset(wifi_tx_buf, 0, sizeof(wifi_tx_buf)); wifi_tx_len = 0; // if(sysinf.connectTcpFlag == 1){ // if(wifi_tx_len){ // char cStr [40] = {0}; // my_sprintf ( cStr,sizeof(cStr), "AT+CIPSEND=0,%d", wifi_tx_len ); // ESP32_Send_AT_Cmd ( cStr, 3000 ); // } // // sysinf.pc_link_timeout = 0; // // sysinf.pc_channel_recv = PC_CONNECT_TYPE_WIFI; // } // wifi_receive_clear(); } wifi_state++; resendtime = 0; HAL_Delay(1000); // } break; case WIFI_CWLAP:{ char* strStart = find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last,sysinf.wifiname); uint32_t apHeader = g_wifi_rx_head; if(NULL != strStart) { if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "OK\r\n")){ /*循环始终需要OK,找到OK后,恢复APhead位置,重新搜寻mac*/ g_wifi_rx_head = apHeader; Van_Device_Printf(VAN_LOG_WIFI,"\nW<-- %s", data); wifi_ack_delay = 0; strStart+=strlen(sysinf.wifiname); strStart =find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last,",\""); unsigned int startPos = ((unsigned int)strStart-(unsigned int)g_wifi_rx_buf + 2)%WIFI_RX_BUF_SIZE;/*跳过,\*/ for(unsigned i=0;i<17;i++){ MAC_ADDR[i] = g_wifi_rx_buf[(i+startPos)%WIFI_RX_BUF_SIZE]; } MAC_ADDR[18] = 0; wifi_state++; } // wifi_receive_clear(); } } break; //数据模式 case WIFI_TRANS: //收到AT+CIPSEND回应,可发送数据 if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "CLOSED")) { Van_Device_Printf(VAN_LOG_WIFI,"\nW<-- %d %s", data_len,data); wifi_state = WIFI_LISTEN; wifi_ack_delay = 0;//从发送写指令,到此才算发送完成 broadDevFlag = 0; } else if ((NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "ERROR"))|| (NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last,"SEND FAIL"))) { if(resendtime < MAX_RESEND_TIME){ char cStr [40] = {0}; my_sprintf ( cStr,sizeof(cStr), "AT+CIPSEND=0,%d", wifi_tx_len ); ESP32_Send_AT_Cmd ( cStr, 3000 ); resendtime ++; }else{ wifi_state = WIFI_POWEROFF; wifi_ack_delay = 0; } // wifi_receive_clear(); } else if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "SEND OK")) { //收到AT+CIPSEND回应,可发送数据 Van_Device_Printf(VAN_LOG_WIFI,"\n--> SEND OK", wifi_tx_len); wifi_ack_delay = 0;//从发送写指令,到此才算发送完成 resendtime = 0; memset(wifi_tx_buf, 0, sizeof(wifi_tx_buf)); wifi_tx_len = 0; // wifi_receive_clear(); } else if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, ">")) { wifi_receive_clear(); Van_Device_Printf(VAN_LOG_WIFI,"\n--> OK W %d", wifi_tx_len); WriteComm2((char *)wifi_tx_buf, wifi_tx_len); wifi_ack_delay = 3000; } // else if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, ">")) // { // wifi_receive_clear(); // Van_Device_Printf(VAN_LOG_WIFI,"\n--> > W %d", wifi_tx_len); // WriteComm2((char *)wifi_tx_buf, wifi_tx_len+1); // wifi_ack_delay = 3000; // } if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "DISCONNECT")) { Van_Device_Printf(VAN_LOG_WIFI,"\nW--> %s", data); wifi_state = WIFI_POWEROFF; wifi_ack_delay = 0; } //收到PC数据 p = find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "+IPD,0,"); if(NULL != p) { int iProcLen = DecodeNew(&uart0_massage,uart0_data,g_wifi_rx_buf, &g_wifi_rx_head,g_wifi_rx_last,WIFI_RX_BUF_SIZE); /* 过滤其他设备的UDP广播: 命令为PC_CMD_SETIP且数据以"Mini7"开头(本机send_Devinf_pc广播的设备信息), 说明是同类设备发出的广播而非上位机下发的SETIP,丢弃不做后续处理 */ if(iProcLen > 0 && PC_CMD_SETIP == uart0_massage.cmd && strncmp((const char *)uart0_data, "Mini7", 5) == 0) { Van_Device_Printf(VAN_LOG_WIFI, "\n[WiFi] filter peer device broadcast"); wifi_receive_clear(); iProcLen = 0; /* 标记为已过滤,跳过后续PC命令处理 */ } if (iProcLen > 0) { sysinf.pc_channel_recv = PC_CONNECT_TYPE_WIFI; sysinf.pc_link_timeout = 0; uart0_massage.data = (char *)uart0_data; query_pc_cmd(&uart0_massage); wifi_receive_clear(); } // wifi_receive_clear(); // set_pc_chanel_recv(1); // b2b_recv_data(p, udp_data_len); } break; case WIFI_CLOSE:{ if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "CLOSED\r\n")) { wifi_state = WIFI_LISTEN; wifi_ack_delay = 0; } } break; default: break; } if(WIFI_TRANS != wifi_state){ wifi_receive_clear(); } } void WIFI_send_deal(void) { static uint8_t try_count = 0; static uint8_t try_con = 0; static uint32_t wifi_start_delay = 0; static uint8_t res_count = 0; uint8_t wifi_result = 0; //启动超时 if(wifi_state < WIFI_LISTEN && wifi_start_delay++ > 120*10) { wifi_start_delay = 0; wifi_state = WIFI_POWEROFF; wifi_ack_delay = 0; } //等待模块应答 if(wifi_ack_delay > 0) { wifi_ack_delay -= 100; return; } if(resendtime >= MAX_RESEND_TIME){ wifi_state = WIFI_POWEROFF; } if((WIFI_TRANS != wifi_state )|| ((WIFI_TRANS == wifi_state)&& wifi_tx_len )){ resendtime++; } switch (wifi_state) { case WIFI_POWEROFF: case WIFI_ERROR: ESP32_AT_RST(); wifi_start_delay = 0; resendtime = 0; try_count = 0; if(sysinf.connectTcpFlag){ /*持续5次均不能链接到tcp,状态回退,重启链接udp*/ res_count++; if(res_count > 5){ sysinf.connectTcpFlag = 0; } } break; case WIFI_POWERON: ESP32_AT(); break; case WIFI_INIT: ESP32_EchoOff(); break; case WIFI_STATION: ESP32_Net_Mode_Choose(STA); break; case WIFI_DISAUTO: ESP32_DisAutoLink(); try_count = 0; resendtime = 0; break; case WIFI_CWLAP: ESP32_CWLAP(sysinf.wifiname); try_count++; if(try_count == MAX_RESEND_TIME) { wifi_state = WIFI_POWEROFF; if(wifi_set_ssid == 1) { wifi_set_ssid = 0; wifi_result = 0xff; data_send_to_pc(PC_CMD_SETWIFI, (char *)&wifi_result, 1); } Van_Device_Printf(VAN_LOG_ERROR, "no wifi AP:%s\n\r",sysinf.wifiname); } try_con = 0; resendtime = 0; break; case WIFI_LINK_AP: ESP32_JoinAP(sysinf.wifiname, sysinf.password,MAC_ADDR); try_con++ ; if(try_con == MAX_RESEND_TIME) { wifi_state = WIFI_POWEROFF; if(wifi_set_ssid == 1) { wifi_set_ssid = 0; wifi_result = 0xfe; data_send_to_pc(PC_CMD_SETWIFI, (char *)&wifi_result, 1); } Van_Device_Printf(VAN_LOG_ERROR, "can't jonn AP:%s %s\n\r",sysinf.wifiname,sysinf.password); } break; case WIFI_GET_IP: ESP32_GetIp(); if(wifi_set_ssid == 1) { wifi_set_ssid = 0; wifi_result = 1; data_send_to_pc(PC_CMD_SETWIFI, (char *)&wifi_result, 1); } break; case WIFI_SETMUX: ESP32_Enable_MultipleId(1); break; case WIFI_LISTEN: if(sysinf.connectTcpFlag){ if(resendtime < MAX_RESEND_TIME) { ESP32_Link_Server(enumTCP,sysinf.TCP_IP_Addr, sysinf.TCP_IP_PORT, Multiple_ID_0); }else{ /*多次TCP未链接,链接UDP*/ // connectTcpFlag = 0; // resendtime = 0; memset(wifi_tx_buf, 0, sizeof(wifi_tx_buf)); wifi_tx_len = 0; } }else{ if(resendtime < MAX_RESEND_TIME) { ESP32_Link_Server(enumUDP,User_ESP32_UDPServer_IP, User_ESP32_UDPServer_PORT, Multiple_ID_0); } } break; case WIFI_TRANS: if(resendtime < MAX_RESEND_TIME) { if(wifi_tx_len){ char cStr [40] = {0}; Van_Device_Printf(VAN_LOG_WIFI,"\nbuflen:%d %d %s",g_wifi_rx_head,g_wifi_rx_last, g_wifi_rx_buf); my_sprintf ( cStr,sizeof(cStr),"AT+CIPSEND=0,%d", wifi_tx_len ); ESP32_Send_AT_Cmd ( cStr, 3000 ); } } if(sysinf.connectTcpFlag){ /*tcp链接上,复位计数清零*/ res_count = 0; } break; case WIFI_CLOSE: ESP32_STOPTCP(Single_ID_0); break; default: wifi_state = WIFI_ERROR; break; } } /* ======================================================================== * 热点配网(SoftAP WiFi配网)状态机 * 触发 : 按键长按30s -> WIFI_provision_request() (usr_motor.c) * 流程 : 复位ESP32 -> AP模式(AT+CWMODE=2) -> 建热点 * OneChip_Mini7 / test1234 (192.168.4.1/255.255.255.0) * -> AT+CIPAP? 查询热点IP -> AT+CWDHCP? 查询DHCP状态 * -> AT+CIPMUX=1 -> AT+CIPSERVER=1,8002 启动TCP服务 * -> 手机连接热点,经TCP 8002下发: * {"ssid":"Onechip_602","password":"onchip1003"} * -> 解析JSON, ssid->sysinf.wifiname, password->sysinf.password * -> cfg_save_cfg_param() 保存到Flash * -> 复位ESP32进入正常STA模式(按新配置自动连接) * 说明 : 热点地址192.168.4.1/255.255.255.0为ESP32 SoftAP默认值,无需配置 * ===================================================================== */ #define WIFI_PROV_AP_SSID "OneChip_Mini7" /* 热点名称 */ #define WIFI_PROV_AP_PWD "test1234" /* 热点密码 */ #define WIFI_PROV_AP_CHANNEL 6 /* 信道 */ #define WIFI_PROV_AP_ECN 3 /* 加密:3=WPA2_PSK */ #define WIFI_PROV_TCP_PORT 8002 /* TCP服务端口 */ #define WIFI_PROV_CMD_TIMEOUT 500 /* 单条AT指令超时:5s(10ms) */ #define WIFI_PROV_RST_TIMEOUT 1000 /* AT+RST等待ready:10s */ #define WIFI_PROV_LISTEN_TIMEOUT 30000 /* 等待配网数据总超时:300s */ #define WIFI_PROV_MAX_RETRY 3 /* 指令失败重试次数 */ #define WIFI_PROV_RX_IDLE_TIMEOUT 100 /* 无有效IPD残留数据清空时限:1s(10ms) */ typedef enum { WIFI_PROV_IDLE = 0, /* 空闲 */ WIFI_PROV_START, /* 启动初始化 */ WIFI_PROV_RST, /* 复位ESP32,重启进入AP主机模式 */ WIFI_PROV_WAIT_READY, /* 等待模块重启完成 */ WIFI_PROV_MODE, /* AT+CWMODE=2 设置AP模式 */ WIFI_PROV_SAP, /* AT+CWSAP 建立热点 */ WIFI_PROV_IP_Q, /* AT+CIPAP? 查询SoftAP接口IP(默认192.168.4.1) */ WIFI_PROV_DHCP_Q, /* AT+CWDHCP? 查询DHCP使能状态 */ WIFI_PROV_MUX, /* AT+CIPMUX=1 打开多连接 */ WIFI_PROV_SERVER, /* AT+CIPSERVER=1,8002 启动TCP服务 */ WIFI_PROV_LISTEN, /* 等待手机下发配网JSON */ WIFI_PROV_ACK_SEND, /* AT+CIPSEND 向手机应答 */ WIFI_PROV_ACK_DATA, /* 等待'>'并发送应答数据 */ WIFI_PROV_SAVE, /* 保存配置到Flash */ WIFI_PROV_DONE, /* 配网完成,复位进入正常模式 */ } wifi_prov_state_t; static volatile uint8_t wifi_prov_request = 0; /* 配网请求标志(可被ISR置位) */ static uint8_t wifi_prov_active = 0; /* 配网进行中 */ static uint8_t wifi_prov_state = WIFI_PROV_IDLE; static uint8_t wifi_prov_retry = 0; static uint8_t wifi_prov_wait = 0; /* 1=正在等待应答 */ static uint8_t wifi_prov_json_ok = 0; /* 解析到的配置是否有效 */ static uint8_t wifi_prov_linkid = 0; /* TCP链路ID */ static uint32_t wifi_prov_tick = 0; /* 起始时间戳(10ms单位) */ static uint32_t wifi_prov_timeout = 0; /* 等待超时(10ms单位) */ static char wifi_prov_ipd[WIFI_RX_BUF_SIZE];/* +IPD载荷累积缓存(JSON) */ static uint16_t wifi_prov_ipd_len = 0; static char wifi_prov_ack[WIFI_RX_BUF_SIZE];/* 应答JSON */ static void wifi_prov_enter(void); static void wifi_prov_exit(void); static void wifi_prov_abort(void); /* 配网进行中? */ uint8_t WIFI_provision_active(void) { return wifi_prov_active; } /* 请求进入热点配网模式(按键长按30s调用,允许在中断中调用) */ uint8_t WIFI_provision_request(void) { if (wifi_prov_active != 0) return 0; /* 已在配网中 */ wifi_prov_request = 1; return 1; } /* 配网状态机内部发送AT指令 */ static void wifi_prov_send_cmd(const char *cmd, uint32_t timeout10ms) { char buff[128] = {0}; strcpy(buff, cmd); strcat(buff, "\r\n"); Van_Device_Printf(VAN_LOG_WIFI, "\nP--> %s", buff); WriteComm2(buff, strlen(buff)); wifi_prov_wait = 1; wifi_prov_tick = sysinf.conter10ms; wifi_prov_timeout = timeout10ms; } /* 从ESP接收环中提取一个完整的+IPD报文载荷并追加到累积缓存 * 返回: 1=取到完整报文; 0=暂无完整报文(继续等待); * -1=帧头/载荷异常(不打印、不清空、不消费,继续等待直到总超时退出) */ static int wifi_prov_capture_ipd(void) { uint32_t head = g_wifi_rx_head; uint32_t last = g_wifi_rx_last; uint32_t avail = (last + WIFI_RX_BUF_SIZE - head) % WIFI_RX_BUF_SIZE; int pos = -1; uint32_t i; if (avail == 0) return 0; /* 查找"+IPD,"头 */ for (i = 0; (i + 5) <= avail; i++) { uint32_t p = (head + i) % WIFI_RX_BUF_SIZE; if (g_wifi_rx_buf[p] == '+' && g_wifi_rx_buf[(p + 1) % WIFI_RX_BUF_SIZE] == 'I' && g_wifi_rx_buf[(p + 2) % WIFI_RX_BUF_SIZE] == 'P' && g_wifi_rx_buf[(p + 3) % WIFI_RX_BUF_SIZE] == 'D' && g_wifi_rx_buf[(p + 4) % WIFI_RX_BUF_SIZE] == ',') { pos = (int)i; break; } } if (pos < 0) return 0; /* 缓冲内无+IPD报文 */ i = (uint32_t)(pos + 5); if (i >= avail) return 0; /* 帧头不完整,继续等待 */ /* 解析头: +IPD,,: */ if (g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] < '0' || g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] > '9') return -1; /* linkid非数字,帧损坏 */ { uint32_t linkid = 0; while (i < avail && g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] >= '0' && g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] <= '9') { linkid = linkid * 10 + (uint32_t)(g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] - '0'); i++; } if (i >= avail) return 0; /* linkid未完,继续等待 */ if (g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] != ',') return -1; /* 缺少逗号分隔,帧损坏 */ wifi_prov_linkid = (uint8_t)linkid; i++; if (i >= avail) return 0; if (g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] < '0' || g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] > '9') return -1; /* 长度非数字,帧损坏 */ { uint32_t pktlen = 0; while (i < avail && g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] >= '0' && g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] <= '9') { pktlen = pktlen * 10 + (uint32_t)(g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] - '0'); i++; } if (i >= avail) return 0; /* len未完,继续等待 */ if (g_wifi_rx_buf[(head + i) % WIFI_RX_BUF_SIZE] != ':') return -1; /* 缺少冒号分隔,帧损坏 */ i++; /* 跳过 ':' */ if (pktlen == 0) return -1; /* 空载荷异常 */ if (avail < i + pktlen) return 0; /* 载荷尚未收完,继续等待 */ if ((uint16_t)(wifi_prov_ipd_len + pktlen) < sizeof(wifi_prov_ipd)) { uint32_t k; for (k = 0; k < pktlen; k++) { char c = (char)g_wifi_rx_buf[(head + i + k) % WIFI_RX_BUF_SIZE]; if (c == '\r' || c == '\n') /* 去掉行结束符 */ continue; wifi_prov_ipd[wifi_prov_ipd_len++] = c; } wifi_prov_ipd[wifi_prov_ipd_len] = '\0'; } else { /* 载荷超限无法累积: 丢弃该帧载荷,重新接收 */ wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; } /* 消费该报文 */ g_wifi_rx_head = (head + i + pktlen) % WIFI_RX_BUF_SIZE; return 1; } } } /* 解析配网JSON: {"ssid":"xxx","password":"xxx"} * 返回: 0=成功; -1=失败 */ static int wifi_prov_parse_json(const char *json, char *ssid, uint16_t ssidCap, char *pwd, uint16_t pwdCap) { cJSON *root = NULL; cJSON *it = NULL; int rlt = -1; if (json == NULL || json[0] != '{' || ssid == NULL || pwd == NULL) return -1; ssid[0] = '\0'; pwd[0] = '\0'; root = cJSON_Parse(json); if (root == NULL) return -1; it = cJSON_GetObjectItem(root, "ssid"); if (it == NULL || !cJSON_IsString(it) || it->valuestring == NULL || it->valuestring[0] == '\0') goto out; /* 必须包含非空ssid */ if (strlen(it->valuestring) >= (size_t)ssidCap) goto out; /* ssid超长 */ strcpy(ssid, it->valuestring); it = cJSON_GetObjectItem(root, "password"); if (it != NULL && cJSON_IsString(it) && it->valuestring != NULL) { if (strlen(it->valuestring) >= (size_t)pwdCap) goto out; /* 密码超长 */ strcpy(pwd, it->valuestring); /* 允许开放网络密码为空 */ } rlt = 0; out: cJSON_Delete(root); return rlt; } /* 生成应答JSON */ static void wifi_prov_build_ack(uint8_t accepted, const char *reason) { if (accepted) { my_sprintf(wifi_prov_ack, sizeof(wifi_prov_ack), "{\"v\":1,\"status\":\"accepted\",\"sn\":\"%s\"}\r\n", sysinf.SN); } else { if (reason == NULL) reason = "invalid"; my_sprintf(wifi_prov_ack, sizeof(wifi_prov_ack), "{\"v\":1,\"status\":\"rejected\",\"reason\":\"%s\"}\r\n", reason); } } /* 进入热点配网模式 */ static void wifi_prov_enter(void) { wifi_prov_active = 1; wifi_prov_state = WIFI_PROV_START; wifi_prov_retry = 0; wifi_prov_wait = 0; wifi_prov_linkid = 0; wifi_prov_json_ok = 0; wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; memset(wifi_tx_buf, 0, sizeof(wifi_tx_buf)); wifi_tx_len = 0; wifi_ack_delay = 0; wifi_state = WIFI_POWEROFF; /* 暂停正常wifi流程 */ wifi_receive_clear(); Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] enter, AP=%s pwd=%s port=%d", WIFI_PROV_AP_SSID, WIFI_PROV_AP_PWD, WIFI_PROV_TCP_PORT); beep_set(BEEP_SCANOK); /* 提示进入配网 */ } /* 退出热点配网,回到正常STA流程 */ static void wifi_prov_exit(void) { wifi_prov_active = 0; wifi_prov_request = 0; wifi_prov_state = WIFI_PROV_IDLE; wifi_prov_wait = 0; wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; memset(wifi_tx_buf, 0, sizeof(wifi_tx_buf)); wifi_tx_len = 0; wifi_ack_delay = 0; wifi_receive_clear(); /* 交给正常流程:WIFI_POWEROFF会先AT+RST复位模块,再按新配置重连 */ WIFI_set_ssid(); Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] exit to normal STA"); } /* 配网失败,恢复到正常STA模式 */ static void wifi_prov_abort(void) { Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] abort, exit to normal STA"); wifi_prov_exit(); } /* 检查AT指令应答;收到OK后切到okState;出错则重试,超过次数退出配网 * 返回: 1=收到OK并已切状态; 0=仍在等待; -1=失败(已重发或已中止) */ static int wifi_prov_check_cmd_resp(uint8_t okState) { if (NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "OK\r\n")) { wifi_receive_clear(); wifi_prov_wait = 0; wifi_prov_retry = 0; wifi_prov_state = okState; return 1; } if (NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "ERROR") || (uint32_t)(sysinf.conter10ms - wifi_prov_tick) >= wifi_prov_timeout) { wifi_receive_clear(); wifi_prov_wait = 0; if (++wifi_prov_retry < WIFI_PROV_MAX_RETRY) return -1; /* 由状态机重发指令 */ wifi_prov_abort(); return -1; } return 0; } /* 查询类AT指令处理: 发送AT+CIPAP?/AT+CWDHCP?后等待回复,收到OK(或超时)后 * 将完整应答打印到调试日志并切到okState状态 * 返回: 0=仍在等待; 1=已收到回复并切状态 */ static uint8_t wifi_prov_query_done(uint8_t okState) { char tmp[WIFI_RX_BUF_SIZE]; uint32_t head = g_wifi_rx_head; uint32_t last = g_wifi_rx_last; uint32_t n = 0; if (wifi_prov_wait == 0) return 0; /* 线性化接收缓冲,便于查找与打印 */ while (head != last && n < (uint32_t)(WIFI_RX_BUF_SIZE - 1)) { tmp[n++] = (char)g_wifi_rx_buf[head]; head = (head + 1) % WIFI_RX_BUF_SIZE; } tmp[n] = '\0'; if (strstr(tmp, "OK") != NULL || (uint32_t)(sysinf.conter10ms - wifi_prov_tick) >= wifi_prov_timeout) { /* 打印查询结果(含OK结尾),确认热点IP与DHCP状态 */ Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] <-%s", tmp); wifi_receive_clear(); wifi_prov_wait = 0; wifi_prov_retry = 0; wifi_prov_state = okState; return 1; } return 0; } /* 热点配网状态机主处理(每次进入WIFI_process调用) */ static void wifi_prov_process(void) { switch (wifi_prov_state) { case WIFI_PROV_IDLE: default: break; /* 启动初始化 */ case WIFI_PROV_START: wifi_receive_clear(); wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; wifi_prov_wait = 0; wifi_prov_state = WIFI_PROV_RST; break; /* 1. 复位ESP32,重启进入AP主机模式 */ case WIFI_PROV_RST: wifi_prov_send_cmd("AT+RST", WIFI_PROV_RST_TIMEOUT); wifi_prov_state = WIFI_PROV_WAIT_READY; wifi_prov_retry = 0; break; case WIFI_PROV_WAIT_READY: if (NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "ready") || NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "boot")) { wifi_receive_clear(); wifi_prov_state = WIFI_PROV_MODE; } else if ((uint32_t)(sysinf.conter10ms - wifi_prov_tick) >= wifi_prov_timeout) { wifi_receive_clear(); if (++wifi_prov_retry < WIFI_PROV_MAX_RETRY) wifi_prov_state = WIFI_PROV_RST; /* 重试复位 */ else wifi_prov_abort(); } break; /* 2. 设置AP模式 */ case WIFI_PROV_MODE: if (wifi_prov_wait != 0) wifi_prov_check_cmd_resp(WIFI_PROV_SAP); else wifi_prov_send_cmd("AT+CWMODE=2", WIFI_PROV_CMD_TIMEOUT); break; /* 3. 建立热点: 名称OneChip_Mini7, 密码test1234 */ case WIFI_PROV_SAP: { char cStr[128] = {0}; if (wifi_prov_wait != 0) wifi_prov_check_cmd_resp(WIFI_PROV_IP_Q); else { my_sprintf(cStr, sizeof(cStr), "AT+CWSAP=\"%s\",\"%s\",%d,%d", WIFI_PROV_AP_SSID, WIFI_PROV_AP_PWD, WIFI_PROV_AP_CHANNEL, WIFI_PROV_AP_ECN); wifi_prov_send_cmd(cStr, WIFI_PROV_CMD_TIMEOUT); } break; } /* 4. 查询SoftAP接口IP(默认192.168.4.1),确认热点地址 */ case WIFI_PROV_IP_Q: if (wifi_prov_wait != 0) wifi_prov_query_done(WIFI_PROV_DHCP_Q); else wifi_prov_send_cmd("AT+CIPAP?", WIFI_PROV_CMD_TIMEOUT); break; /* 5. 查询DHCP使能状态(确认AP侧能分配192.168.4.x) */ case WIFI_PROV_DHCP_Q: if (wifi_prov_wait != 0) wifi_prov_query_done(WIFI_PROV_MUX); else wifi_prov_send_cmd("AT+CWDHCP?", WIFI_PROV_CMD_TIMEOUT); break; /* 6. 打开多连接 */ case WIFI_PROV_MUX: if (wifi_prov_wait != 0) wifi_prov_check_cmd_resp(WIFI_PROV_SERVER); else wifi_prov_send_cmd("AT+CIPMUX=1", WIFI_PROV_CMD_TIMEOUT); break; /* 7. 启动TCP服务端: 端口8002 */ case WIFI_PROV_SERVER: { char cStr[48] = {0}; if (wifi_prov_wait != 0) { if (wifi_prov_check_cmd_resp(WIFI_PROV_LISTEN) == 1) wifi_prov_tick = sysinf.conter10ms; /* 记录开始等待配网的时间 */ } else { my_sprintf(cStr, sizeof(cStr), "AT+CIPSERVER=1,%d", WIFI_PROV_TCP_PORT); wifi_prov_send_cmd(cStr, WIFI_PROV_CMD_TIMEOUT); } break; } /* 8. 等待手机经TCP下发配网JSON(总超时300s) */ case WIFI_PROV_LISTEN: if ((uint32_t)(sysinf.conter10ms - wifi_prov_tick) >= WIFI_PROV_LISTEN_TIMEOUT) { Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] wait cfg timeout"); wifi_prov_wait = 0; wifi_prov_state = WIFI_PROV_DONE; /* 超时未收到配置,直接退出 */ break; } /* 接收并解析+IPD报文 */ { int ipdRlt = wifi_prov_capture_ipd(); if (ipdRlt > 0) { if (wifi_prov_ipd_len >= (uint16_t)(sizeof(wifi_prov_ipd) - 2)) { /* 累积超限,丢弃重收 */ wifi_receive_clear(); wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; } } else { /* 存在接收数据但未解析出有效+IPD,且距最近接收超1s: 打印残留并清空 */ if (g_wifi_rx_head != g_wifi_rx_last && (uint32_t)(sysinf.conter10ms - g_wifi_rx_last_tick) >= WIFI_PROV_RX_IDLE_TIMEOUT) { Van_Device_Printf(VAN_LOG_WIFI, "\r\n%s", g_wifi_rx_buf); wifi_receive_clear(); wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; } } } /* 累积到完整JSON后解析 */ if (wifi_prov_ipd_len > 0 && wifi_prov_ipd[0] == '{' && wifi_prov_ipd[wifi_prov_ipd_len - 1] == '}') { char ssid[sizeof(sysinf.wifiname)]; char pwd[sizeof(sysinf.password)]; if (wifi_prov_parse_json(wifi_prov_ipd, ssid, (uint16_t)sizeof(ssid), pwd, (uint16_t)sizeof(pwd)) == 0) { memset(sysinf.wifiname, 0, sizeof(sysinf.wifiname)); memset(sysinf.password, 0, sizeof(sysinf.password)); strcpy(sysinf.wifiname, ssid); strcpy(sysinf.password, pwd); wifi_prov_json_ok = 1; Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] got cfg: ssid=%s pwd=%s", sysinf.wifiname, sysinf.password); } else { wifi_prov_json_ok = 0; Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] bad json: %s", wifi_prov_ipd); } wifi_prov_build_ack(wifi_prov_json_ok, "invalid"); wifi_prov_state = WIFI_PROV_ACK_SEND; } break; /* 9. 向手机应答(accepted/rejected) */ case WIFI_PROV_ACK_SEND: { char cStr[48] = {0}; Van_Device_Printf(VAN_LOG_WIFI, "\r\nack json: %s", wifi_prov_ack); wifi_receive_clear(); my_sprintf(cStr, sizeof(cStr), "AT+CIPSEND=%d,%d", wifi_prov_linkid, (int)strlen(wifi_prov_ack)); wifi_prov_send_cmd(cStr, WIFI_PROV_CMD_TIMEOUT); /* CIPSEND属非透传"先握手后发数": 复位wait,由ACK_DATA收到OK后真正发载荷 */ wifi_prov_wait = 0; wifi_prov_state = WIFI_PROV_ACK_DATA; break; } case WIFI_PROV_ACK_DATA: if (wifi_prov_wait == 0) { /* 等待 'OK\r\n' 提示符后发送应答数据 */ if(NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE ,&g_wifi_rx_head, g_wifi_rx_last, "OK\r\n")) { wifi_receive_clear(); wifi_prov_wait = 1; wifi_prov_tick = sysinf.conter10ms; wifi_prov_timeout = WIFI_PROV_CMD_TIMEOUT; WriteComm2(wifi_prov_ack, strlen(wifi_prov_ack)); } else if (NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "ERROR") || NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "CLOSED") || (uint32_t)(sysinf.conter10ms - wifi_prov_tick) >= wifi_prov_timeout) { /* 应答失败或超时,继续后续流程 */ Van_Device_Printf(VAN_LOG_WIFI, "\r\n%s", g_wifi_rx_buf); wifi_receive_clear(); wifi_prov_wait = 0; wifi_prov_state = (wifi_prov_json_ok != 0) ? WIFI_PROV_SAVE : WIFI_PROV_LISTEN; wifi_prov_ipd_len = 0; wifi_prov_ipd[0] = '\0'; if (wifi_prov_json_ok == 0) wifi_prov_tick = sysinf.conter10ms; /* 重新计时 */ } } else { /* 等待SEND OK */ if (NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "SEND OK") || NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "ERROR") || NULL != find_str_loop(g_wifi_rx_buf, WIFI_RX_BUF_SIZE, &g_wifi_rx_head, g_wifi_rx_last, "CLOSED") || (uint32_t)(sysinf.conter10ms - wifi_prov_tick) >= wifi_prov_timeout) { Van_Device_Printf(VAN_LOG_WIFI, "\r\n%s", g_wifi_rx_buf); wifi_receive_clear(); wifi_prov_wait = 0; wifi_prov_state = (wifi_prov_json_ok != 0) ? WIFI_PROV_SAVE : WIFI_PROV_LISTEN; wifi_prov_ipd_len = 0; /* 无效配置则清空缓存重新等待 */ wifi_prov_ipd[0] = '\0'; if (wifi_prov_json_ok == 0) wifi_prov_tick = sysinf.conter10ms; /* 重新计时 */ } } break; /* 10. 保存配网参数到Flash */ case WIFI_PROV_SAVE: { uint8_t saveRlt = cfg_save_cfg_param(); Van_Device_Printf(VAN_LOG_WIFI, "\r\n[Provision] cfg_save_cfg_param=%d", saveRlt); wifi_prov_state = WIFI_PROV_DONE; break; } /* 11. 配网完成: 复位ESP32进入正常模式 */ case WIFI_PROV_DONE: wifi_prov_exit(); break; } } //wifi任务 void WIFI_process() { /* 热点配网模式优先处理 */ if (wifi_prov_request != 0 || wifi_prov_active != 0) { if (wifi_prov_request != 0) { wifi_prov_request = 0; wifi_prov_enter(); } wifi_prov_process(); return; } if(sysinf.pc_channel_recv == 2 && wifi_state > WIFI_SETMUX){ /*串口状态下,不走wifi处理*/ return; } WIFI_recv_deal(); WIFI_send_deal(); } static uint32_t m_pow_n(uint32_t m, int32_t n) { uint32_t i = 0, ret = 1; if (n < 0) return 0; for (i = 0; i < n; i++) { ret *= m; } return ret; } // 返回值为打印字符的个数 // 支持%d,%o, %x,%s,%c,%f(只打印6位数字) int my_sprintf(char *pdes,unsigned int len, const char* str, ...) { if (str == NULL) return -1; uint32_t ret_num = 0;// 返回打印字符的个数 char* pStr = (char*)str;// 指向str int ArgIntVal = 0; // 接收整型 uint32_t ArgHexVal = 0;// 接十六进制 char* ArgStrVal = NULL; // 接收字符型 double ArgFloVal = 0.0; // 接受浮点型 uint32_t val_seg = 0; // 数据切分 uint32_t val_temp = 0; // 临时保存数据 int cnt = 0; // 数据长度计数 int cnt_float = 0; // 数据长度计数 va_list pArgs; // 定义va_list类型指针,用于存储参数的地址 va_start(pArgs, str); // 初始化pArgs while (*pStr != '\0') { switch (*pStr) { case ' ': case '\r': case '\n': *pdes++ = (*pStr); ret_num++; break; case '\t': *pdes++ =(*pStr); ret_num += 4; break; case '%': pStr++; // % 格式解析 if('.' == *pStr) { pStr++; cnt_float = *pStr - '0';// %.Nf,输出指定位数小数 pStr++; } switch (*pStr) { case '%': *pdes++ =('%');// %%,输出% ret_num++; pStr++; continue; case 'c': ArgIntVal = va_arg(pArgs, int);// %c,输出char *pdes++ =((char)ArgIntVal); ret_num++; pStr++; continue; case 'd': // 接收整型 ArgIntVal = va_arg(pArgs, int); if (ArgIntVal < 0)// 如果为负数打印,负号 { ArgIntVal = -ArgIntVal;// 取相反数 *pdes++ =('-'); ret_num++; } val_seg = ArgIntVal;// 赋值给 val_seg处理数据 // 计算ArgIntVal长度 if (ArgIntVal) { while (val_seg) { cnt++; val_seg /= 10; } } else cnt = 1;// 数字0的长度为1 ret_num += cnt;// 字符个数加上整数的长度 // 将整数转为单个字符打印 while (cnt) { val_seg = ArgIntVal / m_pow_n(10, cnt - 1); ArgIntVal %= m_pow_n(10, cnt - 1); *pdes++ =((char)val_seg + '0'); cnt--; } pStr++; continue; case 'o': // 接收整型 ArgIntVal = va_arg(pArgs, int); if (ArgIntVal < 0)// 如果为负数打印,负号 { ArgIntVal = -ArgIntVal;// 取相反数 *pdes++ =('-'); ret_num++; } val_seg = ArgIntVal;// 赋值给 val_seg处理数据 // 计算ArgIntVal长度 if (ArgIntVal) { while (val_seg) { cnt++; val_seg /= 8; } } else cnt = 1;// 数字0的长度为1 ret_num += cnt;// 字符个数加上整数的长度 // 将整数转为单个字符打印 while (cnt) { val_seg = ArgIntVal / m_pow_n(8, cnt - 1); ArgIntVal %= m_pow_n(8, cnt - 1); *pdes++ =((char)val_seg + '0'); cnt--; } pStr++; continue; case 'x': // 接收16进制 ArgHexVal = va_arg(pArgs, uint32_t); val_seg = ArgHexVal; // 计算ArgIntVal长度 if (ArgHexVal) { while (val_seg) { cnt++; val_seg /= 16; } } else cnt = 1;// 数字0的长度为1 ret_num += cnt;// 字符个数加上整数的长度 // 将整数转为单个字符打印 while (cnt) { val_seg = ArgHexVal / m_pow_n(16, cnt - 1); ArgHexVal %= m_pow_n(16, cnt - 1); if (val_seg <= 9) *pdes++ =((char)val_seg + '0'); else { //*pdes++ =((char)val_seg - 10 + 'a'); //小写字母 *pdes++ =((char)val_seg - 10 + 'A'); } cnt--; } pStr++; continue; case 'b': // 接收整型 ArgIntVal = va_arg(pArgs, int); val_seg = ArgIntVal; // 计算ArgIntVal长度 if (ArgIntVal) { while (val_seg) { cnt++; val_seg /= 2; } } else cnt = 1;// 数字0的长度为1 ret_num += cnt;// 字符个数加上整数的长度 // 将整数转为单个字符打印 while (cnt) { val_seg = ArgIntVal / m_pow_n(2, cnt - 1); ArgIntVal %= m_pow_n(2, cnt - 1); *pdes++ =((char)val_seg + '0'); cnt--; } pStr++; continue; case 's': // 接收字符 ArgStrVal = va_arg(pArgs, char*); ret_num += (uint32_t)strlen(ArgStrVal); while (*ArgStrVal) { *pdes++ =(*ArgStrVal); ArgStrVal++; } pStr++; continue; case 'f': // 接收浮点型 保留6为小数,不采取四舍五入 ArgFloVal = va_arg(pArgs, double); val_seg = (uint32_t)ArgFloVal;// 取整数部分 val_temp = val_seg; // 临时保存整数部分数据 ArgFloVal = ArgFloVal - val_seg;// 得出余下的小数部分 // 计算整数部分长度 if (val_seg) { while (val_seg) { cnt++; val_seg /= 10; } } else cnt = 1;// 数字0的长度为1 ret_num += cnt;// 字符个数加上整数的长度 // 将整数转为单个字符打印 while (cnt) { val_seg = val_temp / m_pow_n(10, cnt - 1); val_temp %= m_pow_n(10, cnt - 1); *pdes++ =((char)val_seg + '0'); cnt--; } // 打印小数点 *pdes++ =('.'); ret_num++; // printf("\r\n %f\r\n", ArgFloVal); if(cnt_float == 0) cnt_float = 6; // 开始输出小数部分 //ArgFloVal *= 1000000; ArgFloVal *= m_pow_n(10, cnt_float); val_temp = (int)ArgFloVal;// 取整数部分 while (cnt_float) { val_seg = val_temp / m_pow_n(10, cnt_float - 1); val_temp %= m_pow_n(10, cnt_float - 1); *pdes++ =((char)val_seg + '0'); cnt_float--; } ret_num += 6; pStr++; continue; default:// % 匹配错误,暂输出空格 *pdes++ =(' '); ret_num++; break; } break; default: *pdes++ =(*pStr); ret_num++; break; } pStr++; if(ret_num > len){ break; } } va_end(pArgs);// 结束取参数 *pdes++ = 0; return ret_num; }