SmartConfig配网小程序开发
操作场景
基本原理
- 设备进入 Wi-Fi 混杂模式(promiscuous mode)以监听捕获周围的 Wi-Fi 报文。由于设备暂未联网,且 Wi-Fi 网络的数据帧已通过加密,设备无法获取 payload 的内容,但可以获取报文的某些特征数据,例如每个报文的长度。同时对于某些数据帧,例如 UDP 的广播包或多播包,其报文的帧头结构比较固定,较容易识别。
- 此时在手机 App 或者小程序侧,即可通过发送 UDP 的广播包或多播包,并利用报文的特征,例如长度变化进行编码。
- 将目标 Wi-Fi 路由器的 SSID/PSW 字符以约定的编码方式发送出去,设备端在捕获到 UDP 报文后,按约定的方式进行解码,即可得到目标 Wi-Fi 路由器的相关信息并进行联网。
设备绑定流程
SmartConfig 方式配网,每个厂商的编码方式和报文选择上有自己的协议,对于 ESP8266,采用的协议是乐鑫 ESP-TOUCH协议。
基于该协议,设备端在连接 Wi-Fi 路由器成功后,将会告知手机端自己的 IP 地址。目前本小程序已支持采用 ESP-TOUCH 协议进行 SmartConfig 配网。
SmartConfig 方式配网及设备绑定的示例流程图如下:
为了减轻局域网络负担,本实现采用组播方式,组播地址生成代码如下:
let _count = 0
function 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 = 0
const apSsidRaw = bufferFromString(apSsid)
const apSsidCrc = crcBuffer(apSsidRaw)
const apSsidLen = apSsidRaw.length
const apBssidCrc = crcBuffer(toRawBssid(apBssid))
const apPwdRaw = bufferFromString(apPassword)
const apPwdLen = apPwdRaw.length
const rawIp = toRawIpv4(ipAddress)
const ipLen = rawIp.length
const EXTRA_HEAD_LEN = 5
const totalLen = (EXTRA_HEAD_LEN + ipLen + apPwdLen + apSsidLen)
const dataCodes = []
const addDataCode = (v, index) => {
dataCodes.push(toDataCodes(v, index))
totalXor ^= v
}
let index = 0
addDataCode(totalLen, index++)
addDataCode(apPwdLen, index++)
addDataCode(apSsidCrc, index++)
addDataCode(apBssidCrc, index++)
const totalXorIndex = index // save totalXor index
dataCodes.push(null) // to fill totalXor
index++
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 * 2
u16s.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)}})
形参说明入下:
- this.data.ssid要连接的AP的SSID也就是我们通常说的WiFi名称
- this.data.bssid 要连接的AP的MAC地址,就是要连接的AP的网卡地址
- this.data.password要连接AP的密码,也就是我们通常说的WiFi密码
- this.data.localIp手机端Ip地址,后续配网成功后ESP32会回传手机ESP32的分配到的IP地址以及ESP32的网卡地址。由于ESP32回传采用的时UDP协议,无法保证可靠传输,所以建议在ESP32获得IP地址后,启动UDP广播,保证信息回传可靠。ESP32端Smartconfig代码如下:
/* Esptouch example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS 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 connected
to 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 socket
int 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 broadcast
int 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 sending
for (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 tasks
s_retry_num = 0;
}
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
s_retry_num = 0; // allow to try to reconnect
ip_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 here
bzero(&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 mode
ESP_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_handler
ESP_ERROR_CHECK(esp_wifi_start());
// got mac here and this data will be used in udp broadcasting
esp_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 broadcastdata
memcpy(&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和密码后,点击确定。
文章来源:https://www.toymoban.com/news/detail-484593.html
ESP32端成功配网的log如下:文章来源地址https://www.toymoban.com/news/detail-484593.html
[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: 1
I (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配网实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!