SmartConfig配网小程序开发

操作场景

基本原理

  1. 设备进入 Wi-Fi 混杂模式(promiscuous mode)以监听捕获周围的 Wi-Fi 报文。由于设备暂未联网,且 Wi-Fi 网络的数据帧已通过加密,设备无法获取 payload 的内容,但可以获取报文的某些特征数据,例如每个报文的长度。同时对于某些数据帧,例如 UDP 的广播包或多播包,其报文的帧头结构比较固定,较容易识别。
  2. 此时在手机 App 或者小程序侧,即可通过发送 UDP 的广播包或多播包,并利用报文的特征,例如长度变化进行编码。
  3. 将目标 Wi-Fi 路由器的 SSID/PSW 字符以约定的编码方式发送出去,设备端在捕获到 UDP 报文后,按约定的方式进行解码,即可得到目标 Wi-Fi 路由器的相关信息并进行联网。

设备绑定流程

SmartConfig 方式配网,每个厂商的编码方式和报文选择上有自己的协议,对于 ESP8266,采用的协议是乐鑫 ESP-TOUCH协议。

基于该协议,设备端在连接 Wi-Fi 路由器成功后,将会告知手机端自己的 IP 地址。目前本小程序已支持采用 ESP-TOUCH 协议进行 SmartConfig 配网。
SmartConfig 方式配网及设备绑定的示例流程图如下:
为了减轻局域网络负担,本实现采用组播方式,组播地址生成代码如下:

  let _count = 0function getTargetHostname() {_count %= 100_count++return `234.${_count}.${_count}.${_count}`};

乐鑫ESPTOUCH编码原理时将ssid字符串转成ASCII编码数据流,加入CRC,AP的MAC地址本身就是16进制数据无需转换ASCII码,IP地址转整型数据。最终生成的数据流转换为uint16后,利用uint16去调制udp数据包长度代码如下:

function toDatumCode(apSsid, apBssid, apPassword, ipAddress, isSsidHidden = false) {let totalXor = 0const apSsidRaw = bufferFromString(apSsid)const apSsidCrc = crcBuffer(apSsidRaw)const apSsidLen = apSsidRaw.lengthconst apBssidCrc = crcBuffer(toRawBssid(apBssid))const apPwdRaw = bufferFromString(apPassword)const apPwdLen = apPwdRaw.lengthconst rawIp = toRawIpv4(ipAddress)const ipLen = rawIp.lengthconst EXTRA_HEAD_LEN = 5const totalLen = (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen)const dataCodes = []const addDataCode = (v, index) => {dataCodes.push(toDataCodes(v, index))totalXor ^= v}let index = 0addDataCode(totalLen, index++)addDataCode(apPwdLen, index++)addDataCode(apSsidCrc, index++)addDataCode(apBssidCrc, index++)const totalXorIndex = index // save totalXor indexdataCodes.push(null)  // to fill totalXorindex++for (let i = 0; i < ipLen; i++) {addDataCode(rawIp[i], index++)}for (let i = 0; i < apPwdLen; i++) {addDataCode(apPwdRaw[i], index++)}for (let i = 0; i < apSsidRaw.length; i++) {totalXor ^= apSsidRaw[i]}if (isSsidHidden) {for (let i = 0; i < apSsidRaw.length; i++) {dataCodes.push(toDataCodes(apSsidRaw[i], index++))}}dataCodes[totalXorIndex] = toDataCodes(totalXor, totalXorIndex)const bytes = []for (const dataCode of dataCodes) {for (const b of dataCode) {bytes.push(b)}}const u16s = []for (let i = 0; i < bytes.length / 2; i++) {const n = i * 2u16s.push(((bytes[n] << 8) | bytes[n + 1]) + 40)  // EXTRA_LEN}return u16s
}

核心调用

核心调用代码如下:

    execute(this.data.ssid, this.data.bssid, this.data.password, this.data.localIp, false).then(res =>{if (res.acked){that.displaySuccess();console.log(res)}else{that.displayFail();console.log(res)}})

形参说明入下:

  1. this.data.ssid要连接的AP的SSID也就是我们通常说的WiFi名称
  2. this.data.bssid 要连接的AP的MAC地址,就是要连接的AP的网卡地址
  3. this.data.password要连接AP的密码,也就是我们通常说的WiFi密码
  4. this.data.localIp手机端Ip地址,后续配网成功后ESP32会回传手机ESP32的分配到的IP地址以及ESP32的网卡地址。由于ESP32回传采用的时UDP协议,无法保证可靠传输,所以建议在ESP32获得IP地址后,启动UDP广播,保证信息回传可靠。ESP32端Smartconfig代码如下:
/* Esptouch exampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#define HOST_IP_ADDR "255.255.255.255"
#define PORT 18266/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t s_wifi_event_group;/* The event group allows multiple bits for each event,but we only care about one event - are we connectedto the AP with an IP? */
int addr_family = 0;
int ip_protocol = 0;
const int WIFI_CONNECTED_BIT = BIT0;
const int WIFI_FAIL_BIT = BIT1;
const int WIFI_GETIP_BIT = BIT2;
const int ESPTOUCH_DONE_BIT = BIT3;
static const char *TAG = "smartconfig_example";
uint8_t broadcastData[11] = {0};      // this data will be used in UDP broadcast
char nvs_ssid[32] = "myssid";         /* stored SSID */
char nvs_password[64] = "mypassword"; /*stored PW  */
uint8_t base_mac_addr[6] = {0};
static int s_retry_num = 0;bool smartConfigIsRunning = false;
wifi_config_t wifi_config; // ssid pwd bssid etec
static void smartconfig_example_task(void *parm);
void wifi_connect()
{ESP_ERROR_CHECK(esp_wifi_disconnect());ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));esp_wifi_connect();
}
static void broadcast_task(void *pvParameters)
{uint8_t *payload = (uint8_t *)pvParameters;ESP_LOGI(TAG, "broadcast data:%d:%d:%d:%d", *payload, *(payload + 1), *(payload + 2), *(payload + 3));struct sockaddr_in dest_addr;dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(PORT);addr_family = AF_INET;ip_protocol = IPPROTO_IP;// 1.init socketint sock = socket(addr_family, SOCK_DGRAM, ip_protocol);if (sock < 0){ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);}ESP_LOGI(TAG, "Socket created, sending to %s:%d", HOST_IP_ADDR, PORT);// 2. enable broadcastint on = 1;if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0){ESP_LOGE(TAG, "Unable to enable broadcast: errno %d", errno);}ESP_LOGI(TAG, "enable broadcast, sending to %s:%d", HOST_IP_ADDR, PORT);// while for sendingfor (int i = 0; i < 30; i++){int err = sendto(sock, payload, 11, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));if (err < 0){ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);continue;}ESP_LOGI(TAG, "Message sent");// vTaskDelay(2000 / portTICK_PERIOD_MS);vTaskDelay(pdMS_TO_TICKS(2000));}if (sock != -1){ESP_LOGE(TAG, "Shutting down socket and restarting...");shutdown(sock, 0);close(sock);}vTaskDelete(NULL);
}
static void event_handler(void *arg, esp_event_base_t event_base,int32_t event_id, void *event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START){ESP_LOGI(TAG, "start to connecting to AP");wifi_connect();}else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED){if (s_retry_num < 3){esp_wifi_connect();s_retry_num++;ESP_LOGI(TAG, "retry to connect to the AP");}else if (!smartConfigIsRunning){smartConfigIsRunning = true;ESP_LOGI(TAG, "ready to start smartconfig");xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);// vTaskDelay(pdMS_TO_TICKS(5000)); // to let smartconfig suspend all taskss_retry_num = 0;}}else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP){s_retry_num = 0; // allow to try to reconnectip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));memcpy(&broadcastData[7], &event->ip_info.ip, sizeof(esp_ip4_addr_t));xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);ESP_LOGI(TAG, "connected to ap SSID:%s password:%s total len:%d", nvs_ssid, nvs_password, strlen(nvs_ssid) + strlen(nvs_password));broadcastData[0] = strlen(nvs_ssid) + strlen(nvs_password) + 9;xTaskCreate(broadcast_task, "broadcast_task", 4096, (void *)broadcastData, 3, NULL); // start upd broadcast to send ack data to cellphone}else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE){ESP_LOGI(TAG, "Scan done");}else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL){ESP_LOGI(TAG, "Found channel");}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}; */ESP_LOGI(TAG, "connected to ap SSID:%s password:%s total len:%d", nvs_ssid, nvs_password, strlen(nvs_ssid) + strlen(nvs_password));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.threshold.authmode = WIFI_AUTH_WPA2_PSK;wifi_config.sta.pmf_cfg.capable = true;wifi_config.sta.pmf_cfg.required = false;memcpy(nvs_ssid, evt->ssid, sizeof(evt->ssid));memcpy(nvs_password, evt->password, sizeof(evt->password));ESP_ERROR_CHECK(esp_wifi_disconnect());ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));ESP_LOGI(TAG, "connect to AP using new ssid and pwd");esp_wifi_connect();}else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE){smartConfigIsRunning = false;xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}static void initialise_wifi(void)
{ESP_ERROR_CHECK(esp_netif_init());s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();assert(sta_netif);wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));// initilize wifi_config herebzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, nvs_ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, nvs_password, sizeof(wifi_config.sta.password));wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;wifi_config.sta.pmf_cfg.capable = true;wifi_config.sta.pmf_cfg.required = false;// set station modeESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));// since we didnot config the ssid and pwd, only start the staion, here will jump to event_handlerESP_ERROR_CHECK(esp_wifi_start());// got mac here and this data will be used in udp broadcastingesp_err_t ret = esp_efuse_mac_get_default(base_mac_addr);if (ret != ESP_OK){ESP_LOGE(TAG, "Failed to get base MAC address from EFUSE BLK0. (%s)", esp_err_to_name(ret));ESP_LOGE(TAG, "Aborting");abort();}else{ESP_LOGI(TAG, "Base MAC Address read from EFUSE BLK0");}// copy mac to broadcastdatamemcpy(&broadcastData[1], base_mac_addr, sizeof(base_mac_addr));ESP_LOGI(TAG, "finished initialisation");/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
}static void smartconfig_example_task(void *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, WIFI_CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);/*        if (uxBits & WIFI_CONNECTED_BIT ||uxBits & ESPTOUCH_DONE_BIT){ESP_LOGI(TAG, "WiFi Connected to ap");} */if ((uxBits & WIFI_CONNECTED_BIT) || (uxBits & ESPTOUCH_DONE_BIT)){ESP_LOGI(TAG, "smartconfig over");esp_smartconfig_stop();vTaskDelete(NULL);}}
}void app_main(void)
{ESP_ERROR_CHECK(nvs_flash_init());initialise_wifi();
}

体验小程序

通过点击小程序配网标签,进行smartconfig配网,为了提高配网成功率建议线上电ESP32,ESP32在无法上网后,会启动smartconfig等待配网,这是点击小程序配网,输入SSID和密码后,点击确定。

ESP32端成功配网的log如下:

[0;32mI (48) boot: ESP-IDF v4.4.3-dirty 2nd stage bootloader[0m
[0;32mI (49) boot: compile time 14:48:05[0m
[0;32mI (49) boot: chip revision: 3[0m
[0;32mI (51) boot.esp32c3: SPI Speed      : 80MHz[0m
[0;32mI (56) boot.esp32c3: SPI Mode       : DIO[0m
[0;32mI (60) boot.esp32c3: SPI Flash Size : 4MB[0m
[0;32mI (65) boot: Enabling RNG early entropy source...[0m
[0;32mI (70) boot: Partition Table:[0m
[0;32mI (74) boot: ## Label            Usage          Type ST Offset   Length[0m
[0;32mI (81) boot:  0 nvs              WiFi data        01 02 00009000 00006000[0m
[0;32mI (89) boot:  1 phy_init         RF data          01 01 0000f000 00001000[0m
[0;32mI (96) boot:  2 factory          factory app      00 00 00010000 00100000[0m
[0;32mI (104) boot: End of partition table[0m
[0;32mI (108) esp_image: segment 0: paddr=00010020 vaddr=3c090020 size=14a98h ( 84632) map[0m
[0;32mI (130) esp_image: segment 1: paddr=00024ac0 vaddr=3fc8f400 size=02b00h ( 11008) load[0m
[0;32mI (132) esp_image: segment 2: paddr=000275c8 vaddr=40380000 size=08a50h ( 35408) load[0m
[0;32mI (142) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=83f20h (540448) map[0m
[0;32mI (228) esp_image: segment 4: paddr=000b3f48 vaddr=40388a50 size=06968h ( 26984) load[0m
[0;32mI (234) esp_image: segment 5: paddr=000ba8b8 vaddr=50000010 size=00010h (    16) load[0m
[0;32mI (239) boot: Loaded app from partition at offset 0x10000[0m
[0;32mI (240) boot: Disabling RNG early entropy source...[0m
[0;32mI (257) cpu_start: Pro cpu up.[0m
[0;32mI (266) cpu_start: Pro cpu start user code[0m
[0;32mI (266) cpu_start: cpu freq: 160000000[0m
[0;32mI (266) cpu_start: Application information:[0m
[0;32mI (269) cpu_start: Project name:     smart_config[0m
[0;32mI (274) cpu_start: App version:      1[0m
[0;32mI (279) cpu_start: Compile time:     Dec 16 2022 14:47:45[0m
[0;32mI (285) cpu_start: ELF file SHA256:  85735650546638ec...[0m
[0;32mI (291) cpu_start: ESP-IDF:          v4.4.3-dirty[0m
[0;32mI (296) heap_init: Initializing. RAM available for dynamic allocation:[0m
[0;32mI (303) heap_init: At 3FC96180 len 00046590 (281 KiB): DRAM[0m
[0;32mI (310) heap_init: At 3FCDC710 len 00002950 (10 KiB): STACK/DRAM[0m
[0;32mI (316) heap_init: At 50000020 len 00001FE0 (7 KiB): RTCRAM[0m
[0;32mI (323) spi_flash: detected chip: generic[0m
[0;32mI (327) spi_flash: flash io: dio[0m
[0;32mI (332) sleep: Configure to isolate all GPIO pins in sleep state[0m
[0;32mI (338) sleep: Enable automatic switching of GPIO sleep configuration[0m
[0;32mI (345) cpu_start: Starting scheduler.[0m
[0;32mI (356) pp: pp rom version: 9387209[0m
[0;32mI (356) net80211: net80211 rom version: 9387209[0m
I (366) wifi:wifi driver task: 3fc9f068, prio:23, stack:6656, core=0
[0;32mI (366) system_api: Base MAC address is not set[0m
[0;32mI (376) system_api: read default base MAC address from EFUSE[0m
I (386) wifi:wifi firmware version: 8cb87ff
I (386) wifi:wifi certification version: v7.0
I (386) wifi:config NVS flash: enabled
I (386) wifi:config nano formating: disabled
I (396) wifi:Init data frame dynamic rx buffer num: 32
I (396) wifi:Init management frame dynamic rx buffer num: 32
I (406) wifi:Init management short buffer num: 32
I (406) wifi:Init dynamic tx buffer num: 32
I (416) wifi:Init static tx FG buffer num: 2
I (416) wifi:Init static rx buffer size: 1600
I (416) wifi:Init static rx buffer num: 10
I (426) wifi:Init dynamic rx buffer num: 32
[0;32mI (426) wifi_init: rx ba win: 6[0m
[0;32mI (436) wifi_init: tcpip mbox: 32[0m
[0;32mI (436) wifi_init: udp mbox: 6[0m
[0;32mI (436) wifi_init: tcp mbox: 6[0m
[0;32mI (446) wifi_init: tcp tx win: 5744[0m
[0;32mI (446) wifi_init: tcp rx win: 5744[0m
[0;32mI (456) wifi_init: tcp mss: 1440[0m
[0;32mI (456) wifi_init: WiFi IRAM OP enabled[0m
[0;32mI (456) wifi_init: WiFi RX IRAM OP enabled[0m
[0;32mI (466) phy_init: phy_version 912,d001756,Jun  2 2022,16:28:07[0m
I (496) wifi:mode : sta (7c:df:a1:b3:92:34)
I (496) wifi:enable tsf
[0;32mI (506) smartconfig_example: start to connecting to AP[0m
[0;32mI (506) smartconfig_example: Base MAC Address read from EFUSE BLK0[0m
[0;32mI (506) smartconfig_example: finished initialisation[0m
[0;32mI (2906) smartconfig_example: retry to connect to the AP[0m
[0;32mI (5316) smartconfig_example: retry to connect to the AP[0m
[0;32mI (7726) smartconfig_example: retry to connect to the AP[0m
[0;32mI (10126) smartconfig_example: ready to start smartconfig[0m
I (10176) smartconfig: SC version: V3.0.1
I (14986) wifi:ic_enable_sniffer
I (14986) smartconfig: Start to find channel...
[0;32mI (14986) smartconfig_example: Scan done[0m
I (169746) smartconfig: TYPE: ESPTOUCH
I (169746) smartconfig: T|PHONE MAC:e2:8b:46:2a:e9:9b
I (169746) smartconfig: T|AP MAC:08:97:58:20:39:ea
I (169746) smartconfig: Found channel on 6-0. Start to get ssid and password...
[0;32mI (169756) smartconfig_example: Found channel[0m
I (175526) smartconfig: T|pswd: 18610717733
I (175526) smartconfig: T|ssid: wjyi_0049
I (175526) smartconfig: T|bssid: 08:97:58:20:39:ea
I (175526) wifi:ic_disable_sniffer
[0;32mI (175536) smartconfig_example: Got SSID and password[0m
[0;32mI (175536) smartconfig_example: connected to ap SSID:myssid password:mypassword total len:16[0m
[0;32mI (175616) smartconfig_example: connect to AP using new ssid and pwd[0m
I (175626) wifi:new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1
I (175626) wifi:state: init -> auth (b0)
I (175636) wifi:state: auth -> assoc (0)
I (175646) wifi:state: assoc -> run (10)
I (175676) wifi:connected with wjyi_0049, aid = 5, channel 6, BW20, bssid = 08:97:58:20:39:ea
I (175676) wifi:security: WPA2-PSK, phy: bgn, rssi: -42
I (175696) wifi:pm start, type: 1I (175696) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 0, mt_pti: 25000, mt_time: 10000
I (175696) wifi:BcnInt:102400, DTIM:2
[0;32mI (176356) esp_netif_handlers: sta ip: 192.168.0.122, mask: 255.255.255.0, gw: 192.168.0.1[0m
[0;32mI (176356) smartconfig_example: got ip:192.168.0.122[0m
[0;32mI (176356) smartconfig_example: connected to ap SSID:wjyi_0049 password:18610717733 total len:20[0m
[0;32mI (176366) smartconfig_example: smartconfig over[0m
[0;32mI (176376) smartconfig_example: broadcast data:29:124:223:161[0m
[0;32mI (176376) smartconfig_example: Socket created, sending to 255.255.255.255:18266[0m
[0;32mI (176386) smartconfig_example: enable broadcast, sending to 255.255.255.255:18266[0m
[0;32mI (176396) smartconfig_example: Message sent[0m
[0;32mI (178396) smartconfig_example: Message sent[0m
[0;32mI (180396) smartconfig_example: Message sent[0m
[0;32mI (182396) smartconfig_example: Message sent[0m
[0;32mI (184396) smartconfig_example: Message sent[0m
[0;32mI (186396) smartconfig_example: Message sent[0m
[0;32mI (188396) smartconfig_example: Message sent[0m
[0;32mI (190396) smartconfig_example: Message sent[0m
[0;32mI (192396) smartconfig_example: Message sent[0m
[0;32mI (194396) smartconfig_example: Message sent[0m
[0;32mI (196396) smartconfig_example: Message sent[0m
[0;32mI (198396) smartconfig_example: Message sent[0m
[0;32mI (200396) smartconfig_example: Message sent[0m
[0;32mI (202396) smartconfig_example: Message sent[0m
[0;32mI (204396) smartconfig_example: Message sent[0m
[0;32mI (206396) smartconfig_example: Message sent[0m
[0;32mI (208396) smartconfig_example: Message sent[0m
[0;32mI (210396) smartconfig_example: Message sent[0m
[0;32mI (212396) smartconfig_example: Message sent[0m
[0;32mI (214396) smartconfig_example: Message sent[0m
[0;32mI (216396) smartconfig_example: Message sent[0m
[0;32mI (218396) smartconfig_example: Message sent[0m
[0;32mI (220396) smartconfig_example: Message sent[0m
[0;32mI (222396) smartconfig_example: Message sent[0m
[0;32mI (224396) smartconfig_example: Message sent[0m
[0;32mI (226396) smartconfig_example: Message sent[0m
[0;32mI (228396) smartconfig_example: Message sent[0m
[0;32mI (230396) smartconfig_example: Message sent[0m
[0;32mI (232396) smartconfig_example: Message sent[0m
[0;32mI (234396) smartconfig_example: Message sent[0m
[0;31mE (236396) smartconfig_example: Shutting down socket and restarting...[0m

微信小程序Smartconfig配网实现相关推荐

  1. 【微信小程序控制硬件13 】 与硬件平台无关,微信小程序 AP 配网安信可 Wi-Fi 模块入网示例。【AT篇,附带Demo】

    文章目录 前言 一 材料准备 二 实现目的 三 配置的数据交互协议 3.1 小程序发送网络信息阶段 3.2 模组连接路由器的回调: 四 配置原理和过程 五 设备端 AT 交互过程 另外,不要把我的博客 ...

  2. 借鉴华为HiLink实现微信小程序智能配网功能

    借鉴华为HiLink实现微信小程序智能配网功能 微信小程序介绍 微信公众号智能配网 Smartconfig实现原理 Smartconfig技术的弊端 AP配网技术的出现 微信小程序智能配网 模块端设置 ...

  3. ap配网示例,esp8266和esp32微信小程序ap配网

    第一.下载程序 esp8266示例程序:: 点击下载 esp32示例程序:: 点击下载 示例程序是利用arduino IDE开发: 关于arduino IDE 的ESP8266环境配置可参考:环境配置 ...

  4. 微信小程序 airkiss 配网,SmartConfig配网,ap配网教程

    第一步,下载配网程序到esp8266 arduinoIDE开发: esp8266程序下载可参考:https://bemfa.blog.csdn.net/article/details/11771752 ...

  5. 【AT指令使用】安信可ESP-12S/ESP32S模组AT固件应用之微信小程序热点配网OTA升级

    目录 前言 一.Web 服务配网 二.操作过程 1.烧录带有Web服务功能的AT固件 2.Web服务配网过程 2.1 ESP-12S/ESP32-S搭建Web服务器 2.2 微信小程序部分的操作 3. ...

  6. 微信小程序-蓝牙配网功能

    蓝牙配网-连接设备 注:这两天接手了一个设备运维端小程序,需要在上面加一个新功能,蓝牙配网,就是通过扫描设备二维码,拿到该设备的uuid.设备名等信息,然后通过蓝牙连接上该设备并往设备中写入数据.读取 ...

  7. 微信小程序AP配网局域网通信

    目录 1,前言 2,相关资料 3,实验代码 1,前言 最近在做IOT的项目,里面有个小程序要用到AP配网,和设备做一个局域网通信.可是小程序会做安全域的校验,而局域网只能是http的协议,并且局域网没 ...

  8. wifi模块微信小程序AP配网(UDP)

    转载链接:mirrors / xuhongv / WeChatMiniAP2Net · GitCode

  9. 安信可分享 | 分享一个基于airkiss协议的配网小程序,实现小程序一键配网安信可ESP32C3\ESP8266\ESP32\ESP32S2系列的模组。(附带源码)

    文章目录 一.关于 WeChatAirkiss 1.1 应用场景 二.airkiss 简介 三.开始使用 四.API说明 五.FAQ 六.开源微信物联网控制一览表 联系我们 一.关于 WeChatAi ...

最新文章

  1. 华为p30如何把计算机放进通知栏,华为p30短信来了在通知栏怎么不显示
  2. java中椭圆类_Java中的Graphics2D类基本使用的教程
  3. 汇编语言(七)之字符串转大写
  4. .NET异步编程之新利器——Task与Await、Async
  5. 使用ArcGIS Engine来实现地图的点击查询并闪烁
  6. 服务器鉴别信息清楚,对服务器远程管理时鉴别信息未加密
  7. nrf52832-定时器例程
  8. konika电视一直显示android,康佳多屏互动电视端下载
  9. php webp格式转换,webp的格式的转换
  10. 知识点:Office插入数学公式常用的快捷键(终于可以解放鼠标了)
  11. bugku中的misc题
  12. css绘制星星闪烁,web前端炫酷特效-CSS3制作环形星星发光动画
  13. shopNC开发手册
  14. 网易笔试001(HR之声)
  15. Poco库使用:任务管理器TaskManager
  16. 微信,该文件已过期或已被清理
  17. 大神自述|7岁接触建模的大神建模师,分享建模经验与技巧
  18. 浅谈802.15.4协议
  19. RestTemplate封装
  20. strictmath_Java StrictMath cosh()方法与示例

热门文章

  1. 笔记四:Maven+SSM之整合redis
  2. 数据仓库【书籍推荐】
  3. mac chrome浏览器常用快捷键
  4. 个体工商户设立登记申请书
  5. 代码审查工具【Review Board】在Windows环境下安装与配置
  6. 网传某厂商要求潜规则showgirl 经纪公司发声明澄清
  7. DFS之最大人工岛(填海造陆) 827.
  8. [机器学习与scikit-learn-26]:算法-聚类-KMeans寻找最佳轮廓系数
  9. FPGA中用C语言指针实现内存测试
  10. 走进JavaWeb技术世界2:JSP与Servlet的曾经与现在