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;
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
*/
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
*/
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;
/**
* @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;
/**
*/
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 */
* - 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
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
*
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.
*
*/
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
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)) {
event.info.root_conflict.capacity);
break;
case MESH_EVENT_CHANNEL_SWITCH:
- ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHANNEL_SWITCH>");
+ ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHANNEL_SWITCH>new channel:%d", event.info.channel_switch.channel);
break;
case MESH_EVENT_SCAN_DONE:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_SCAN_DONE>number:%d",
event.info.scan_done.number);
break;
+ case MESH_EVENT_NETWORK_STATE:
+ ESP_LOGI(MESH_TAG, "<MESH_EVENT_NETWORK_STATE>is_rootless:%d",
+ event.info.network_state.is_rootless);
+ break;
+ case MESH_EVENT_STOP_RECONNECTION:
+ ESP_LOGI(MESH_TAG, "<MESH_EVENT_STOP_RECONNECTION>");
+ break;
+ case MESH_EVENT_FIND_NETWORK:
+ ESP_LOGI(MESH_TAG, "<MESH_EVENT_FIND_NETWORK>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, "<MESH_EVENT_ROUTER_SWITCH>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;
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) {
my_type = MESH_LEAF;
}
my_layer = parent_assoc.layer + 1;
+ break;
}
}
#endif
#endif
}
}
-
+ esp_mesh_flush_scan_result();
if (parent_found) {
/*
* parent
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, "<PARENT>%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,
"<PARENT>%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d",
parent_record.ssid, parent_assoc.layer,
if (CONFIG_MESH_IE_CRYPTO_FUNCS) {
/* modify IE crypto key */
ESP_LOGW(MESH_TAG, "<Config>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, "<Config>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));
ESP_LOGI(MESH_TAG, "<MESH_EVENT_STARTED>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;
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));