关于ESP MESH各节点无法互联的问题(问题已解决)

zxlch_z
Posts: 23
Joined: Thu Aug 19, 2021 2:59 am

关于ESP MESH各节点无法互联的问题(问题已解决)

Postby zxlch_z » Thu Aug 19, 2021 3:10 am

最近测试esp-mesh,发现使用例程编译后没两个esp32开发板没办法组网,已经试遍所有办法。
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
...
Last edited by zxlch_z on Thu Aug 26, 2021 6:56 am, edited 1 time in total.

zxlch_z
Posts: 23
Joined: Thu Aug 19, 2021 2:59 am

Re: 关于ESP MESH各节点无法互联的问题

Postby zxlch_z » Fri Aug 20, 2021 5:45 pm

IDE是Arduino
环境是Windows 10

Who is online

Users browsing this forum: No registered users and 95 guests