diff --git a/components/esp32/include/esp_mesh.h b/components/esp32/include/esp_mesh.h index 8256e8cbf..a53211756 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 */ @@ -596,6 +624,7 @@ esp_err_t esp_mesh_stop(void); * - If the packet is to an external IP network, set this parameter to the IPv4:PORT combination. * This packet will be delivered to the root firstly, then the root will forward this packet to the final IP server address. * @param[in] data pointer to a sending mesh packet + * - Field size should not exceed MESH_MPS. Note that the size of one mesh packet should not exceed MESH_MTU. * - Field proto should be set to data protocol in use (default is MESH_PROTO_BIN for binary). * - Field tos should be set to transmission tos (type of service) in use (default is MESH_TOS_P2P for point-to-point reliable). * @param[in] flag bitmap for data sent @@ -1015,9 +1044,10 @@ esp_err_t esp_mesh_set_vote_percentage(float percentage); float esp_mesh_get_vote_percentage(void); /** - * @brief Set mesh softAP associate expired time + * @brief Set mesh softAP associate expired time (default:10 seconds) * - If mesh softAP hasn't received any data from an associated child within this time, * mesh softAP will take this child inactive and disassociate it. + * - If mesh softAP is encrypted, this value should be set a greater value, such as 30 seconds. * * @param[in] seconds the expired time * @@ -1198,7 +1228,7 @@ esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, int num); bool esp_mesh_is_my_group(const mesh_addr_t *addr); /** - * @brief Set mesh network capacity + * @brief Set mesh network capacity (max:1000, default:300) * * @attention This API shall be called before mesh is started. * @@ -1412,6 +1442,43 @@ esp_err_t esp_mesh_disconnect(void); */ esp_err_t esp_mesh_connect(void); +/** + * @brief Flush scan result + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_flush_scan_result(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); + +/** + * @brief Get the router BSSID + * + * @param[out] router_bssid pointer to the router BSSID + * + * @return + * - ESP_OK + * - ESP_ERR_WIFI_NOT_INIT + * - ESP_ERR_WIFI_ARG + */ +esp_err_t esp_mesh_get_router_bssid(uint8_t *router_bssid); + #ifdef __cplusplus } #endif diff --git a/components/esp32/lib b/components/esp32/lib index f2f850e50..3a3ca5bf7 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit f2f850e5006f4780e5d8b9e1860539b4749d0593 +Subproject commit 3a3ca5bf74262fae5027ffb409e26aa3f74421c5 diff --git a/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml b/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml index ba7b925d2..d122df1bd 100644 --- a/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml +++ b/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml @@ -789,25 +789,20 @@ test cases: - - R SSC1 C +JAP:CONNECTED - - SSC SSC1 sta -D - - R SSC1 RE JAP:DISCONNECTED,\d+,8 - - - SSC SSC1 sta -C -s -p - - - R SSC1 RE JAP:DISCONNECTED,\d+,15 - - SSC SSC1 sta -C -s -p - - R SSC1 RE JAP:DISCONNECTED,\d+,201 execution time: 0.0 expected result: |- 1. disconnect event reason REASON_ASSOC_LEAVE - 2. disconnect event reason REASON_4WAY_HANDSHAKE_TIMEOUT - 3. disconnect event reason REASON_NO_AP_FOUND + 2. disconnect event reason REASON_NO_AP_FOUND initial condition: STAM1 level: Integration module: WIFI MAC steps: |- 1. sta connect to AP, and disconnect - 2. connect to AP with wrong password - 3. connect to AP not exist + 2. connect to AP not exist sub module: WIFI Connect - summary: test wifi disconnect reason REASON_ASSOC_LEAVE, REASON_4WAY_HANDSHAKE_TIMEOUT, - REASON_NO_AP_FOUND + summary: test wifi disconnect reason REASON_ASSOC_LEAVE, REASON_NO_AP_FOUND test environment: SSC_T1_1 test point 1: basic function test point 2: wifi disconnect reason test @@ -886,7 +881,7 @@ test cases: - - SSC SSC1 ap -S -s -p -t 3 -m 1 - - R SSC1 C +SAP:OK - - SSC SSC2 sta -C -s -p 1234567890 - - - R SSC2 RE JAP:DISCONNECTED,\d+,204 + - - R SSC2 RE JAP:DISCONNECTED,\d+,15 - - SSC SSC2 sta -D - - R SSC2 C +QAP:OK - - WIFI CONN @@ -896,7 +891,7 @@ test cases: execution time: 0.0 expected result: |- 1. succeed - 2. disconnect event REASON_HANDSHAKE_TIMEOUT + 2. disconnect event REASON_4WAY_HANDSHAKE_TIMEOUT 3. succeed 4. succeed 5. disconnect event REASON_ASSOC_TOOMANY @@ -910,7 +905,7 @@ test cases: 4. PC WIFI NIC connect to target1 5. target2 connect to target1 with correct password sub module: WIFI Connect - summary: test wifi disconnect reason REASON_ASSOC_TOOMANY, REASON_HANDSHAKE_TIMEOUT + summary: test wifi disconnect reason REASON_ASSOC_TOOMANY, REASON_4WAY_HANDSHAKE_TIMEOUT test environment: SSC_T2_2 test point 1: basic function test point 2: wifi disconnect reason test diff --git a/examples/mesh/internal_communication/main/Kconfig.projbuild b/examples/mesh/internal_communication/main/Kconfig.projbuild index d8de07e5b..50b649d93 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. @@ -59,7 +59,7 @@ config MESH_AP_CONNECTIONS config MESH_MAX_LAYER int "Mesh Max Layer" - range 1 15 + range 1 25 default 6 help Max layer allowed in mesh network. diff --git a/examples/mesh/internal_communication/main/mesh_main.c b/examples/mesh/internal_communication/main/mesh_main.c index fae5fa279..e6ce6255c 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; diff --git a/examples/mesh/manual_networking/main/mesh_main.c b/examples/mesh/manual_networking/main/mesh_main.c index 1b3a6f016..56df30ab6 100644 --- a/examples/mesh/manual_networking/main/mesh_main.c +++ b/examples/mesh/manual_networking/main/mesh_main.c @@ -69,6 +69,7 @@ void mesh_scan_done_handler(int num) i, record.ssid, assoc.layer, assoc.layer_cap, assoc.assoc, assoc.assoc_cap, assoc.layer2_cap, MAC2STR(record.bssid), record.primary, record.rssi, MAC2STR(assoc.mesh_id), assoc.encrypted ? "IE Encrypted" : "IE Unencrypted"); + #ifdef MESH_SET_NODE if (assoc.mesh_type != MESH_IDLE && assoc.layer_cap && assoc.assoc < assoc.assoc_cap && record.rssi > -70) { @@ -82,6 +83,7 @@ void mesh_scan_done_handler(int num) my_type = MESH_LEAF; } my_layer = parent_assoc.layer + 1; + break; } } #endif @@ -99,7 +101,7 @@ void mesh_scan_done_handler(int num) #endif } } - + esp_mesh_flush_scan_result(); if (parent_found) { /* * parent @@ -110,11 +112,20 @@ void mesh_scan_done_handler(int num) sizeof(parent_record.ssid)); parent.sta.bssid_set = 1; memcpy(&parent.sta.bssid, parent_record.bssid, 6); + ESP_ERROR_CHECK(esp_mesh_set_ap_authmode(parent_record.authmode)); if (my_type == MESH_ROOT) { + if (parent_record.authmode != WIFI_AUTH_OPEN) { + memcpy(&parent.sta.password, CONFIG_MESH_ROUTER_PASSWD, + strlen(CONFIG_MESH_ROUTER_PASSWD)); + } ESP_LOGW(MESH_TAG, "%s, "MACSTR", channel:%u, rssi:%d", parent_record.ssid, MAC2STR(parent_record.bssid), parent_record.primary, parent_record.rssi); } else { + if (parent_record.authmode != WIFI_AUTH_OPEN) { + memcpy(&parent.sta.password, CONFIG_MESH_AP_PASSWD, + strlen(CONFIG_MESH_AP_PASSWD)); + } ESP_LOGW(MESH_TAG, "%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d", parent_record.ssid, parent_assoc.layer, @@ -131,13 +142,14 @@ void mesh_scan_done_handler(int num) if (CONFIG_MESH_IE_CRYPTO_FUNCS) { /* modify IE crypto key */ ESP_LOGW(MESH_TAG, "modify IE crypto key to %s", CONFIG_MESH_IE_CRYPTO_KEY); + ESP_ERROR_CHECK(esp_mesh_set_ie_crypto_funcs(&g_wifi_default_mesh_crypto_funcs)); ESP_ERROR_CHECK(esp_mesh_set_ie_crypto_key(CONFIG_MESH_IE_CRYPTO_KEY, strlen(CONFIG_MESH_IE_CRYPTO_KEY))); } else { /* disable IE crypto */ ESP_LOGW(MESH_TAG, "disable IE crypto"); ESP_ERROR_CHECK(esp_mesh_set_ie_crypto_funcs(NULL)); } - ESP_ERROR_CHECK(esp_wifi_scan_stop()); + esp_wifi_scan_stop(); scan_config.show_hidden = 1; scan_config.scan_type = WIFI_SCAN_TYPE_PASSIVE; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0)); @@ -156,7 +168,7 @@ void mesh_event_handler(mesh_event_t event) ESP_LOGI(MESH_TAG, "ID:"MACSTR"", MAC2STR(id.addr)); mesh_layer = esp_mesh_get_layer(); ESP_ERROR_CHECK(esp_mesh_set_self_organized(0, 0)); - ESP_ERROR_CHECK(esp_wifi_scan_stop()); + esp_wifi_scan_stop(); wifi_scan_config_t scan_config = { 0 }; /* mesh softAP is hidden */ scan_config.show_hidden = 1; @@ -214,7 +226,7 @@ void mesh_event_handler(mesh_event_t event) mesh_disconnected_indicator(); mesh_layer = esp_mesh_get_layer(); if (event.info.disconnected.reason == WIFI_REASON_ASSOC_TOOMANY) { - ESP_ERROR_CHECK(esp_wifi_scan_stop()); + esp_wifi_scan_stop(); scan_config.show_hidden = 1; scan_config.scan_type = WIFI_SCAN_TYPE_PASSIVE; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0));