ESP32-S3 Wsmartconfig一键配网+阿里云点灯 在原先正点原子的MQTT_ALIYUN基础上开发 Wifi_SmartConfig之前的例程也有 想写这个的原因主要是 发现在用阿里云平台上例程中没有实现硬件的开发 想做一个更贴近于企业级的项目1.在MQTT事件回调函数 连接事件标识中 加入新的自定义订阅 topic这个格式一定要按照这个阿里云的规范去填之前问AI的时候 得到的信息是有些平台是可以不用完整的填入/PRODUCT_KEY/DEVICE_NAME这一部分的 直接类名就可以了#define DEVICE_SUBSCRIBE_LIGHT /PRODUCT_KEY/DEVICE_NAME/user/light/set case MQTT_EVENT_CONNECTED: /* 连接事件 */ ESP_LOGI(TAG, MQTT_EVENT_CONNECTED); /* 订阅主题 */ msg_id esp_mqtt_client_subscribe(client, DEVICE_SUBSCRIBE, 0); ESP_LOGI(TAG, sent subscribe successful, msg_id%d, msg_id); msg_id esp_mqtt_client_subscribe(client, DEVICE_SUBSCRIBE_LIGHT, 0); ESP_LOGI(TAG, sent subscribe successful, msg_id%d, msg_id); break;2.在接收数据这里加入 判断是否是自定义订阅的那个点灯数据case MQTT_EVENT_DATA: /* 接收数据事件 */ /* 接收平台点灯指令 */ if (event-topic_len strlen(DEVICE_SUBSCRIBE_LIGHT) memcmp(event-topic, DEVICE_SUBSCRIBE_LIGHT, event-topic_len) 0) { // 提取指令内容event-data 也是非 \0 结尾的 char cmd_buf[16] {0}; int copy_len event-data_len 15 ? event-data_len : 15; memcpy(cmd_buf, event-data, copy_len); // 处理指令 if (strcmp(cmd_buf, ON) 0) { LED0(0); spilcd_show_string(0, 90, 240, 16, 16, LED: ON, RED); esp_mqtt_client_publish(client, DEVICE_PUBLISH_REPLY, OK, 0, 1, 0); } else if (strcmp(cmd_buf, OFF) 0) { LED0(1); spilcd_show_string(0, 90, 240, 16, 16, LED: OFF, RED); esp_mqtt_client_publish(client, DEVICE_PUBLISH_REPLY, OK, 0, 1, 0); } } break;这里接收数据的时候有个注意的点回调函数带的结构体event-data是订阅主题名数据的形式可以用event-data_len得到数据的实际长度 然后拷贝出来再去解析以上就是点灯的主要代码部分 阿里云部分需要通过登录到 阿里云“物联网控制平台”去创建这个自定义topic1.这里创建自定义topic的时候注意下这个填类名就行了为什么这里就只用类名 代码里订阅的时候我明明MQTT初始化 都填了这些参数了 订阅还要我填感觉调用库里那个API发送的时候应该自动填入才对2.权限注意下 我是设计的点灯只有平台给我下发消息 我们单片机去点灯 所以我用的是订阅另外发布的话 就是反过来 我们单片机去给平台发这样发布只需要在平台创建这个topic就行了 单片机端可以直接发3.平台下发点灯指令填入“ON”或者OFF开灯或关灯SmartConfig 一键配网这个是ESP32官方的开发的一种UDP方式配网 用乐鑫的APP “EspTouch”将手机先连到设备需要连接的Wifi先只支持4G 然后手机通过UDP广播方式跟单片机那边通讯 发送wifi的SSID password具体代码实现如下1.在回调事件里 STA启动这个事件里调用smartconfig的配置任务//STA启动后 启动smartconfig配置任务 if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_START) { network_connet.connet_state | 0x04; network_connet.fun(network_connet.connet_state); xTaskCreate(smartconfig_task, smartconfig_task, 4096, NULL, 3, NULL); }2.smartconfig配置函数这个事件的那来个标志位就是用在事件回调里去置位的static EventGroupHandle_t s_wifi_event_group; static const int CONNECTED_BIT BIT0; static const int ESPTOUCH_DONE_BIT BIT1; static void smartconfig_task(void * parm) { parm parm; EventBits_t uxBits; /* 设置配网协议 */ ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) ); /* 设置配网参数 */ smartconfig_start_config_t cfg SMARTCONFIG_START_CONFIG_DEFAULT(); /* 开始配网 */ ESP_ERROR_CHECK( esp_smartconfig_start(cfg) ); while (1) { /* 获取事件 */ uxBits xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); /* 配网成功 */ if(uxBits CONNECTED_BIT) { ESP_LOGI(TAG, WiFi Connected to ap); } /* 智能配置结束 */ if(uxBits ESPTOUCH_DONE_BIT) { ESP_LOGI(TAG, smartconfig over); esp_smartconfig_stop(); vTaskDelete(NULL); } } }注册配网要用的事件ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL) ); ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL) ); ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL) );用到的事件回调处理static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { static int s_retry_num 0; /* 扫描到要连接的WIFI事件 */ if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_START) { network_connet.connet_state | 0x04; network_connet.fun(network_connet.connet_state); xTaskCreate(smartconfig_task, smartconfig_task, 4096, NULL, 3, NULL); } /* 连接WIFI事件 */ else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_CONNECTED) { network_connet.connet_state | 0x80; network_connet.fun(network_connet.connet_state); } /* 连接WIFI失败事件 */ else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_DISCONNECTED) { network_connet.connet_state | 0x02; /* 尝试连接 */ if (s_retry_num 20) { esp_wifi_connect(); s_retry_num ; ESP_LOGI(TAG, retry to connect to the AP); } else { xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT); network_connet.fun(network_connet.connet_state); } ESP_LOGI(TAG,connect to the AP fail); } /* 工作站从连接的AP获得IP */ else if(event_base IP_EVENT event_id IP_EVENT_STA_GOT_IP) { network_connet.connet_state | 0x01; ip_event_got_ip_t* event (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, static ip: IPSTR, IP2STR(event-ip_info.ip)); s_retry_num 0; sprintf(network_connet.ip_buf, static ip: IPSTR, IP2STR(event-ip_info.ip)); network_connet.fun(network_connet.connet_state); xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT); } else if (event_base SC_EVENT event_id SC_EVENT_SCAN_DONE) { /*配网步骤扫描完成*/ ESP_LOGI(TAG, Scan done); spilcd_show_string(0, 90, 320, 16, 16, In the distribution network......, BLUE); } else if (event_base SC_EVENT event_id SC_EVENT_FOUND_CHANNEL) { /*配网步骤找到频道*/ ESP_LOGI(TAG, Found channel); } /* 已成功收到APP发送的 SSID和密码*/ else if (event_base SC_EVENT event_id SC_EVENT_GOT_SSID_PSWD) { ESP_LOGI(TAG, Got SSID and password); smartconfig_event_got_ssid_pswd_t *evt (smartconfig_event_got_ssid_pswd_t *)event_data; wifi_config_t wifi_config; uint8_t ssid[33] { 0 }; uint8_t password[65] { 0 }; uint8_t rvd_data[33] { 0 }; bzero(wifi_config, sizeof(wifi_config_t)); memcpy(wifi_config.sta.ssid, evt-ssid, sizeof(wifi_config.sta.ssid)); memcpy(wifi_config.sta.password, evt-password, sizeof(wifi_config.sta.password)); wifi_config.sta.bssid_set evt-bssid_set; if (wifi_config.sta.bssid_set true) { memcpy(wifi_config.sta.bssid, evt-bssid, sizeof(wifi_config.sta.bssid)); } memcpy(ssid, evt-ssid, sizeof(evt-ssid)); memcpy(password, evt-password, sizeof(evt-password)); ESP_LOGI(TAG, SSID:%s, ssid); ESP_LOGI(TAG, PASSWORD:%s, password); spilcd_fill(0,90,320,240,WHITE); sprintf(lcd_buff, %s,ssid); spilcd_show_string(0, 90, 320, 16, 16, lcd_buff, BLUE); sprintf(lcd_buff, %s,password); spilcd_show_string(0, 110, 320, 16, 16, lcd_buff, BLUE); spilcd_show_string(0, 130, 320, 16, 16, Successful distribution network, BLUE); /* 手机APPEspTouch软件使用ESPTOUCH V2模式会执行以下代码 */ if (evt-type SC_TYPE_ESPTOUCH_V2) { ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) ); ESP_LOGI(TAG, RVD_DATA:); for (int i 0; i 33; i) { printf(%02x , rvd_data[i]); } printf(\n); } ESP_ERROR_CHECK( esp_wifi_disconnect() ); ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, wifi_config) ); esp_wifi_connect(); } else if (event_base SC_EVENT event_id SC_EVENT_SEND_ACK_DONE) { /*配网步骤 已完成给APP发送ACK*/ xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT); } }基本过程就是扫描-然后找到通道-获取到SSID PASSWORD 顺带就连接这个wifi 然后回复ACK手机APP上就会收到这个信息 配网就OK了