diff --git a/components/esp32/include/esp_mesh.h b/components/esp32/include/esp_mesh.h index 8256e8cbf758..62b05d7c0c9c 100644 --- a/components/esp32/include/esp_mesh.h +++ b/components/esp32/include/esp_mesh.h @@ -187,6 +187,11 @@ typedef enum { this event, and add the corresponding scan done handler in this event. */ MESH_EVENT_NETWORK_STATE, /**< network state, such as whether current mesh network has a root. */ MESH_EVENT_STOP_RECONNECTION, /**< the root stops reconnecting to the router and non-root devices stop reconnecting to their parents. */ + MESH_EVENT_FIND_NETWORK, /**< when the channel field in mesh configuration is set to zero, mesh stack will perform a + full channel scan to find a mesh network that can join, and return the channel value + after finding it. */ + MESH_EVENT_ROUTER_SWITCH, /**< if users specify BSSID of the router in mesh configuration, when the root connects to another + router with the same SSID, this event will be posted and the new router information is attached. */ MESH_EVENT_MAX, } mesh_event_id_t; @@ -310,6 +315,14 @@ typedef struct { mesh_addr_t rc_addr; /**< root address specified by users via API esp_mesh_waive_root() */ } mesh_event_vote_started_t; +/** + * @brief find a mesh network that this device can join + */ +typedef struct { + uint8_t channel; /**< channel number of the new found network */ + uint8_t router_bssid[6]; /**< router BSSID */ +} mesh_event_find_network_t; + /** * @brief IP settings from LwIP stack */ @@ -381,6 +394,11 @@ typedef struct { bool is_rootless; /**< whether current mesh network has a root */ } mesh_event_network_state_t; +/** + * @brief New router information + */ +typedef system_event_sta_connected_t mesh_event_router_switch_t; + /** * @brief Mesh event information */ @@ -405,6 +423,8 @@ typedef union { mesh_event_root_fixed_t root_fixed; /**< fixed root */ mesh_event_scan_done_t scan_done; /**< scan done */ mesh_event_network_state_t network_state; /**< network state, such as whether current mesh network has a root. */ + mesh_event_find_network_t find_network; /**< network found that can join */ + mesh_event_router_switch_t router_switch; /**< new router information */ } mesh_event_info_t; /** @@ -445,10 +465,16 @@ typedef struct { * @brief Router configuration */ typedef struct { - uint8_t ssid[32]; /**< SSID */ - uint8_t ssid_len; /**< length of SSID */ - uint8_t bssid[6]; /**< BSSID, if router is hidden, this value is mandatory */ - uint8_t password[64]; /**< password */ + uint8_t ssid[32]; /**< SSID */ + uint8_t ssid_len; /**< length of SSID */ + uint8_t bssid[6]; /**< BSSID, if this value is specified, users should also specify "allow_router_switch". */ + uint8_t password[64]; /**< password */ + bool allow_router_switch; /**< if the BSSID is specified and this value is also set, when the router of this specified BSSID + fails to be found after "fail" (mesh_attempts_t) times, the whole network is allowed to switch + to another router with the same SSID. The new router might also be on a different channel. + The default value is false. + There is a risk that if the password is different between the new switched router and the previous + one, the mesh network could be established but the root will never connect to the new switched router. */ } mesh_router_t; /** @@ -464,6 +490,8 @@ typedef struct { */ typedef struct { uint8_t channel; /**< channel, the mesh network on */ + bool allow_channel_switch; /**< if this value is set, when "fail" (mesh_attempts_t) times is reached, device will change to + a full channel scan for a network that could join. The default value is false. */ mesh_event_cb_t event_cb; /**< mesh event callback */ mesh_addr_t mesh_id; /**< mesh network identification */ mesh_router_t router; /**< router configuration */ @@ -1412,6 +1440,23 @@ esp_err_t esp_mesh_disconnect(void); */ esp_err_t esp_mesh_connect(void); +/** + * @brief Cause the root device to add Channel Switch Announcement Element (CSA IE) to beacon + * - Set the new channel + * - Set how many beacons with CSA IE will be sent before changing a new channel + * - Enable the channel switch function + * + * @attention This API is only called by the root. + * + * @param[in] new_bssid the new router BSSID if the router changes + * @param[in] csa_newchan the new channel number to which the whole network is moving + * @param[in] csa_count channel switch period(beacon count), unit is based on beacon interval of its softAP, the default value is 15. + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_switch_channel(const uint8_t *new_bssid, int csa_newchan, int csa_count); + #ifdef __cplusplus } #endif diff --git a/components/esp32/lib b/components/esp32/lib index 892a63089b5a..b16383705d78 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 892a63089b5ab74114a86c2a3202bfa755bfd320 +Subproject commit b16383705d7844e125f5063cb642f5964f2d8ff4 diff --git a/docs/en/api-guides/mesh.rst b/docs/en/api-guides/mesh.rst index 87488be1206e..20d35d68b19a 100644 --- a/docs/en/api-guides/mesh.rst +++ b/docs/en/api-guides/mesh.rst @@ -774,6 +774,37 @@ a shallower parent node. Due to parent node switching, a self-organized ESP-MESH network can dynamically adjust its network layout to ensure each connection has a good RSSI and that the number of layers in the network is minimized. +Network Channel Switching +------------------------- + +The list shows network changes allowed by different combinations of four parameters channel, allow_channel_switch, +router BSSID and allow_router_switch. More information will be added soon. + ++-------------------------------------------------------------------------+------------------------------+ +| Mesh Configuration | Network Changes | ++===========+======================+================+=====================+==============================+ +| channel | allow_channel_switch | router BSSID | allow_router_switch | when no root appears | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| not set | X | not set | X | channel and router BSSID | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| not set | X | set | 0 | channel | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| not set | X | set | 1 | channel and router BSSID | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| set | 1 | not set | X | channel and router BSSID | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| set | 0 | not set | X | router BSSID | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| set | 1 | set | 0 | channel | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| set | 0 | set | 0 | | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| set | 1 | set | 1 | channel and router BSSID | ++-----------+----------------------+----------------+---------------------+------------------------------+ +| set | 0 | set | 1 | router BSSID | ++-----------+----------------------+----------------+---------------------+------------------------------+ + + .. --------------------------- Data Transmission ------------------------------ .. _mesh-data-transmission: @@ -1010,4 +1041,4 @@ Further Notes - Mesh networking IE uses AES encryption -Router and internet icon made by `Smashicons `_ from `www.flaticon.com `_ \ No newline at end of file +Router and internet icon made by `Smashicons `_ from `www.flaticon.com `_ diff --git a/examples/mesh/internal_communication/main/Kconfig.projbuild b/examples/mesh/internal_communication/main/Kconfig.projbuild index d8de07e5bcbd..e7f46ada30c6 100644 --- a/examples/mesh/internal_communication/main/Kconfig.projbuild +++ b/examples/mesh/internal_communication/main/Kconfig.projbuild @@ -2,8 +2,8 @@ menu "Example Configuration" config MESH_CHANNEL int "channel" - range 1 14 - default 1 + range 0 14 + default 0 help mesh network channel. diff --git a/examples/mesh/internal_communication/main/mesh_main.c b/examples/mesh/internal_communication/main/mesh_main.c index fae5fa27998a..e6ce6255c2bd 100644 --- a/examples/mesh/internal_communication/main/mesh_main.c +++ b/examples/mesh/internal_communication/main/mesh_main.c @@ -85,7 +85,6 @@ void esp_mesh_p2p_tx_main(void *arg) vTaskDelay(10 * 1000 / portTICK_RATE_MS); continue; } - esp_mesh_get_routing_table((mesh_addr_t *) &route_table, CONFIG_MESH_ROUTE_TABLE_SIZE * 6, &route_table_size); if (send_count && !(send_count % 100)) { @@ -309,12 +308,27 @@ void mesh_event_handler(mesh_event_t event) event.info.root_conflict.capacity); break; case MESH_EVENT_CHANNEL_SWITCH: - ESP_LOGI(MESH_TAG, ""); + ESP_LOGI(MESH_TAG, "new channel:%d", event.info.channel_switch.channel); break; case MESH_EVENT_SCAN_DONE: ESP_LOGI(MESH_TAG, "number:%d", event.info.scan_done.number); break; + case MESH_EVENT_NETWORK_STATE: + ESP_LOGI(MESH_TAG, "is_rootless:%d", + event.info.network_state.is_rootless); + break; + case MESH_EVENT_STOP_RECONNECTION: + ESP_LOGI(MESH_TAG, ""); + break; + case MESH_EVENT_FIND_NETWORK: + ESP_LOGI(MESH_TAG, "new channel:%d, router BSSID:"MACSTR"", + event.info.find_network.channel, MAC2STR(event.info.find_network.router_bssid)); + break; + case MESH_EVENT_ROUTER_SWITCH: + ESP_LOGI(MESH_TAG, "new router:%s, channel:%d, "MACSTR"", + event.info.router_switch.ssid, event.info.router_switch.channel, MAC2STR(event.info.router_switch.bssid)); + break; default: ESP_LOGI(MESH_TAG, "unknown id:%d", event.id); break;