SDK是Arduino 2.0.0 rc1(idf 4.4)。之前用IDF3.3.1测试也是相同的结果。
使用idf 4.4的代码如下(两块开发板刷入相同内容)。
Code: Select all
#include <Arduino.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mesh.h"
#include "esp_mesh_internal.h"
#include "nvs_flash.h"
#include "esp_netif.h"
static bool is_mesh_connected = false;
static mesh_addr_t mesh_parent_addr;
static int mesh_layer = -1;
static esp_netif_t *netif_sta = NULL;
#define CONFIG_MESH_ROUTE_TABLE_SIZE 50
uint8_t g_meshAddr[6] = {0};
uint8_t g_deviceId[6] = {0};
#define CONFIG_MESH_TOPOLOGY MESH_TOPO_TREE /* MESH_TOPO_TREE / MESH_TOPO_CHAIN */
#define CONFIG_MESH_PS_DEV_DUTY 10 /* 1 - 100 */
#define CONFIG_MESH_PS_DEV_DUTY_TYPE MESH_PS_DEVICE_DUTY_REQUEST /* MESH_PS_DEVICE_DUTY_REQUEST / MESH_PS_DEVICE_DUTY_DEMAND */
#define CONFIG_MESH_PS_NWK_DUTY 10
#define CONFIG_MESH_PS_NWK_DUTY_DURATION -1
#define CONFIG_MESH_PS_NWK_DUTY_RULE MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE
//#define CONFIG_MESH_ENABLE_PS
void mesh_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
mesh_addr_t id = {0};
static uint8_t last_layer = 0;
switch(event_id)
{
case MESH_EVENT_STARTED:
{
esp_mesh_get_id(&id);
Serial.printf("<MESH_EVENT_MESH_STARTED>ID:%02x:%02x:%02x:%02x:%02x:%02x\n", MAC2STR(id.addr));
is_mesh_connected = false;
mesh_layer = esp_mesh_get_layer();
}
break;
case MESH_EVENT_STOPPED:
{
Serial.printf("<MESH_EVENT_STOPPED>\n");
is_mesh_connected = false;
mesh_layer = esp_mesh_get_layer();
}
break;
case MESH_EVENT_CHILD_CONNECTED:
{
mesh_event_child_connected_t *child_connected = (mesh_event_child_connected_t *)event_data;
Serial.printf("<MESH_EVENT_CHILD_CONNECTED>aid:%d, %02x:%02x:%02x:%02x:%02x:%02x\n",
child_connected->aid,
MAC2STR(child_connected->mac));
}
break;
case MESH_EVENT_CHILD_DISCONNECTED:
{
mesh_event_child_disconnected_t *child_disconnected = (mesh_event_child_disconnected_t *)event_data;
Serial.printf("<MESH_EVENT_CHILD_DISCONNECTED>aid:%d, %02x:%02x:%02x:%02x:%02x:%02x\n",
child_disconnected->aid,
MAC2STR(child_disconnected->mac));
}
break;
case MESH_EVENT_ROUTING_TABLE_ADD:
{
mesh_event_routing_table_change_t *routing_table = (mesh_event_routing_table_change_t *)event_data;
Serial.printf("<MESH_EVENT_ROUTING_TABLE_ADD>add %d, new:%d\n",
routing_table->rt_size_change,
routing_table->rt_size_new);
}
break;
case MESH_EVENT_ROUTING_TABLE_REMOVE:
{
mesh_event_routing_table_change_t *routing_table = (mesh_event_routing_table_change_t *)event_data;
Serial.printf("<MESH_EVENT_ROUTING_TABLE_REMOVE>remove %d, new:%d\n",
routing_table->rt_size_change,
routing_table->rt_size_new);
}
break;
case MESH_EVENT_NO_PARENT_FOUND:
{
mesh_event_no_parent_found_t *no_parent = (mesh_event_no_parent_found_t *)event_data;
Serial.printf("<MESH_EVENT_NO_PARENT_FOUND>scan times:%d\n",
no_parent->scan_times);
}
/* TODO handler for the failure */
break;
case MESH_EVENT_PARENT_CONNECTED:
{
mesh_event_connected_t *connected = (mesh_event_connected_t *)event_data;
esp_mesh_get_id(&id);
mesh_layer = connected->self_layer;
memcpy(&mesh_parent_addr.addr, connected->connected.bssid, 6);
Serial.printf(
"<MESH_EVENT_PARENT_CONNECTED>layer:%d-->%d, parent:%02x:%02x:%02x:%02x:%02x:%02x%s, ID:%02x:%02x:%02x:%02x:%02x:%02x\n",
last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr),
esp_mesh_is_root() ? "<ROOT>" :
(mesh_layer == 2) ? "<layer2>" : "", MAC2STR(id.addr));
last_layer = mesh_layer;
is_mesh_connected = true;
if(esp_mesh_is_root())
{
// 根节点需要在这里开启DHCP获取IP
esp_netif_dhcpc_start(netif_sta);
}
else
{
}
// 开启2个任务
// -> esp_mesh_comm_p2p_start();
}
break;
case MESH_EVENT_PARENT_DISCONNECTED:
{
mesh_event_disconnected_t *disconnected = (mesh_event_disconnected_t *)event_data;
Serial.printf(
"<MESH_EVENT_PARENT_DISCONNECTED>reason:%d\n",
disconnected->reason);
is_mesh_connected = false;
mesh_layer = esp_mesh_get_layer();
}
break;
case MESH_EVENT_LAYER_CHANGE:
{
mesh_event_layer_change_t *layer_change = (mesh_event_layer_change_t *)event_data;
mesh_layer = layer_change->new_layer;
Serial.printf("<MESH_EVENT_LAYER_CHANGE>layer:%d-->%d%s\n",
last_layer, mesh_layer,
esp_mesh_is_root() ? "<ROOT>" :
(mesh_layer == 2) ? "<layer2>" : "");
last_layer = mesh_layer;
if(mesh_layer == 1)
{
// 这里1是根节点,意味着节点此时变化为根节点
// 此处可以添加节点切换的用户自定义功能
}
else
{
}
}
break;
case MESH_EVENT_ROOT_ADDRESS:
{
mesh_event_root_address_t *root_addr = (mesh_event_root_address_t *)event_data;
esp_mesh_get_id(&id);
Serial.printf("<MESH_EVENT_ROOT_ADDRESS>root address:%02x:%02x:%02x:%02x:%02x:%02x, ID:%02x:%02x:%02x:%02x:%02x:%02x\n",
MAC2STR(root_addr->addr), MAC2STR(id.addr));
// 此处登记自身在路由表中的地址
int route_table_size = 0;
mesh_addr_t route_table[CONFIG_MESH_ROUTE_TABLE_SIZE];
esp_mesh_get_routing_table((mesh_addr_t *) &route_table, CONFIG_MESH_ROUTE_TABLE_SIZE * 6, &route_table_size);
memcpy(g_meshAddr, route_table[0].addr, 6);
Serial.printf("<MESH_EVENT_ROOT_ADDRESS>meshAddr:%02x:%02x:%02x:%02x:%02x:%02x\n", MAC2STR(g_meshAddr));
// 此处设置默认设备ID
memcpy(g_deviceId, g_meshAddr, 6);
}
break;
case MESH_EVENT_VOTE_STARTED:
{
mesh_event_vote_started_t *vote_started = (mesh_event_vote_started_t *)event_data;
Serial.printf(
"<MESH_EVENT_VOTE_STARTED>attempts:%d, reason:%d, rc_addr:%02x:%02x:%02x:%02x:%02x:%02x\n",
vote_started->attempts,
vote_started->reason,
MAC2STR(vote_started->rc_addr.addr));
}
break;
case MESH_EVENT_VOTE_STOPPED:
{
Serial.printf("<MESH_EVENT_VOTE_STOPPED>\n");
break;
}
case MESH_EVENT_ROOT_SWITCH_REQ:
{
mesh_event_root_switch_req_t *switch_req = (mesh_event_root_switch_req_t *)event_data;
Serial.printf(
"<MESH_EVENT_ROOT_SWITCH_REQ>reason:%d, rc_addr:%02x:%02x:%02x:%02x:%02x:%02x\n",
switch_req->reason,
MAC2STR( switch_req->rc_addr.addr));
}
break;
case MESH_EVENT_ROOT_SWITCH_ACK:
{
/* new root */
mesh_layer = esp_mesh_get_layer();
esp_mesh_get_parent_bssid(&mesh_parent_addr);
Serial.printf("<MESH_EVENT_ROOT_SWITCH_ACK>layer:%d, parent:%02x:%02x:%02x:%02x:%02x:%02x\n", mesh_layer, MAC2STR(mesh_parent_addr.addr));
}
break;
case MESH_EVENT_TODS_STATE:
{
mesh_event_toDS_state_t *toDs_state = (mesh_event_toDS_state_t *)event_data;
Serial.printf("<MESH_EVENT_TODS_REACHABLE>state:%d\n", *toDs_state);
}
break;
case MESH_EVENT_ROOT_FIXED:
{
mesh_event_root_fixed_t *root_fixed = (mesh_event_root_fixed_t *)event_data;
Serial.printf("<MESH_EVENT_ROOT_FIXED>%s\n",
root_fixed->is_fixed ? "fixed" : "not fixed");
}
break;
case MESH_EVENT_ROOT_ASKED_YIELD:
{
mesh_event_root_conflict_t *root_conflict = (mesh_event_root_conflict_t *)event_data;
Serial.printf(
"<MESH_EVENT_ROOT_ASKED_YIELD>%02x:%02x:%02x:%02x:%02x:%02x, rssi:%d, capacity:%d\n",
MAC2STR(root_conflict->addr),
root_conflict->rssi,
root_conflict->capacity);
}
break;
case MESH_EVENT_CHANNEL_SWITCH:
{
mesh_event_channel_switch_t *channel_switch = (mesh_event_channel_switch_t *)event_data;
Serial.printf("<MESH_EVENT_CHANNEL_SWITCH>new channel:%d\n", channel_switch->channel);
}
break;
case MESH_EVENT_SCAN_DONE:
{
mesh_event_scan_done_t *scan_done = (mesh_event_scan_done_t *)event_data;
Serial.printf("<MESH_EVENT_SCAN_DONE>number:%d\n",
scan_done->number);
}
break;
case MESH_EVENT_NETWORK_STATE:
{
mesh_event_network_state_t *network_state = (mesh_event_network_state_t *)event_data;
Serial.printf("<MESH_EVENT_NETWORK_STATE>is_rootless:%d\n",
network_state->is_rootless);
}
break;
case MESH_EVENT_STOP_RECONNECTION:
{
Serial.printf("<MESH_EVENT_STOP_RECONNECTION>\n");
}
break;
case MESH_EVENT_FIND_NETWORK:
{
mesh_event_find_network_t *find_network = (mesh_event_find_network_t *)event_data;
Serial.printf("<MESH_EVENT_FIND_NETWORK>new channel:%d, router BSSID:%02x:%02x:%02x:%02x:%02x:%02x\n",
find_network->channel, MAC2STR(find_network->router_bssid));
}
break;
case MESH_EVENT_ROUTER_SWITCH:
{
mesh_event_router_switch_t *router_switch = (mesh_event_router_switch_t *)event_data;
Serial.printf("<MESH_EVENT_ROUTER_SWITCH>new router:%s, channel:%d, %02x:%02x:%02x:%02x:%02x:%02x\n",
router_switch->ssid, router_switch->channel, MAC2STR(router_switch->bssid));
}
break;
default:
Serial.printf("unknown id:%d\n", event_id);
break;
}
}
void ip_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
Serial.printf("<IP_EVENT_STA_GOT_IP>IP: %d.%d.%d.%d\n", IP2STR(&event->ip_info.ip));
}
#define DEFAULT_MESH_SSID "aaaaaaaaaa" /* Max=30+1 Min=8+1(Base64编码6字节MAC有8位)*/
#define DEFAULT_MESH_PASSWORD "bbbbbbbbbb" /* Max=60+1 */
#define DEFAULT_MESH_CHANNEL 6
#define DEFAULT_MESH_MAX_PLAYER 6
#define DEFAULT_MESH_AP_PASSWD "MESH_AP_PASSWORD"
#define DEFAULT_MESH_AP_CONNECTIONS 6
static const uint8_t MESH_ID[6] = { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77};
//static const uint8_t MESH_ID[6] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
/* 初始化NVS */
nvs_flash_init();
/* 初始化底层TCP/IP堆栈 */
esp_netif_init();
/* 事件初始化*/
esp_event_loop_create_default();
/* 为 Mesh 创建STA和AP模式网络接口(仅保存STA接口供进一步处理),并关闭DHCP服务器和客户端(DHCP客户端只有设备升根节点才启用) */
esp_netif_create_default_wifi_mesh_netifs(&netif_sta, NULL);
/* Wi-Fi 初始化 */
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&config);
/* 注册 IP 事件处理程序 */
esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL);
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
esp_wifi_start();
/* Mesh 初始化 */
esp_mesh_init();
/* 注册 Mesh 事件处理程序 */
esp_event_handler_register(MESH_EVENT, ESP_EVENT_ANY_ID, &mesh_event_handler, NULL);
/* set mesh topology */
esp_mesh_set_topology(CONFIG_MESH_TOPOLOGY);
/* 设置 Mesh 最大层 */
esp_mesh_set_max_layer(DEFAULT_MESH_MAX_PLAYER);
/* 设置 Mesh 根节点推举百分比(只有达到此阈值才可成为根) */
esp_mesh_set_vote_percentage(1);
// ???
esp_mesh_set_xon_qsize(128);
#ifdef CONFIG_MESH_ENABLE_PS
/* Enable mesh PS function */
esp_mesh_enable_ps();
/* 设置 Mesh AP模式关联过期时间(在AP模式下此时间内未收到某个子节点的任何数据,Mesh将子节点置为不活跃的并分离它) */
esp_mesh_set_ap_assoc_expire(60);
/* better to increase the announce interval to avoid too much management traffic, if a small duty cycle is set. */
esp_mesh_set_announce_interval(600, 3300);
#else
/* Disable mesh PS function */
esp_mesh_disable_ps();
esp_mesh_set_ap_assoc_expire(10);
#endif
/* Mesh 配置 */
/* 默认启用 Mesh IE 加密 */
mesh_cfg_t cfg;
cfg.crypto_funcs = &g_wifi_default_mesh_crypto_funcs;
/* Mesh ID */
memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6);
/* 路由器 */
/* 信道(需与路由器信道匹配)*/
cfg.channel = DEFAULT_MESH_CHANNEL;
// 这里为了方便直接填写了要接入WIFI的SSID和密码
cfg.router.ssid_len = strlen(DEFAULT_MESH_SSID);
strcpy((char*)cfg.router.ssid, DEFAULT_MESH_SSID);
strcpy((char*)cfg.router.password, DEFAULT_MESH_PASSWORD);
/* Mesh softAP */
esp_mesh_set_ap_authmode(WIFI_AUTH_WPA2_PSK);
cfg.mesh_ap.max_connection = DEFAULT_MESH_AP_CONNECTIONS;
strcpy((char*)cfg.mesh_ap.password, DEFAULT_MESH_AP_PASSWD);
esp_mesh_set_config(&cfg);
/* Mesh 启动 */
esp_mesh_start();
#ifdef CONFIG_MESH_ENABLE_PS
/* set the device active duty cycle. (default:10, MESH_PS_DEVICE_DUTY_REQUEST) */
esp_mesh_set_active_duty_cycle(CONFIG_MESH_PS_DEV_DUTY, CONFIG_MESH_PS_DEV_DUTY_TYPE);
/* set the network active duty cycle. (default:10, -1, MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE) */
esp_mesh_set_network_duty_cycle(CONFIG_MESH_PS_NWK_DUTY, CONFIG_MESH_PS_NWK_DUTY_DURATION, CONFIG_MESH_PS_NWK_DUTY_RULE);
#endif
Serial.printf("mesh starts successfully, heap:%d, %s<%d>%s, ps:%d\n", esp_get_minimum_free_heap_size(),
esp_mesh_is_root_fixed() ? "root fixed" : "root not fixed",
esp_mesh_get_topology(), esp_mesh_get_topology() ? "(chain)":"(tree)", esp_mesh_is_ps_enabled());
}
void loop() {
// put your main code here, to run repeatedly:
//delay(10);
Serial.println(esp_mesh_get_type());
delay(1000);
}
运行结果输出以下内容:
setCpuFrequencyMhz(): PLL: 480 / 2 = 240 Mhz, APB: 80000000 Hz
mesh starts successfully, heap:106896, root not fixed<0>(tree), ps:0
<MESH_EVENT_NO_PARENT_FOUND>scan times:60
<MESH_EVENT_NO_PARENT_FOUND>scan times:60
<MESH_EVENT_NO_PARENT_FOUND>scan times:60
<MESH_EVENT_NO_PARENT_FOUND>scan times:60
<MESH_EVENT_NO_PARENT_FOUND>scan times:60
...