mesh: add channel switch function

1. add network channel switch function.
   - users can obtain the new channel through the event MESH_EVENT_CHANNEL_SWITCH.
   - the entire network will be moved to the same channel as the router without user intervention.
   - if no router is in the network, users can call esp_mesh_switch_channel() on the root side to
     move the entire network to their desired channel.
2. support not configuring the network channel.
3. support not configuring the router BSSID even if the router is hidden.
4. add allow_channel_switch to mesh configuration.
   - if the channel is not specified, this value will be ignored.
   - if the channel is specified and this value is set, when "fail" (mesh_attempts_t) times of parent selection
     or look for networks are reached, device will change to perform a full channel scan for networks that could join.
   - if the channel is specified and this value is set to 0, when a root is not elected, channel switch is not allowed.
     but when a root appears, the root performs a full channel scan during the process of connecting to the router,
     so even allow_channel_switch is set to 0, the root may still switch channel and eventually the entire network
    changes channel.
5. add allow_router_switch to mesh router configuration.
   - if the BSSID of router is not specified, this value will be ignored.
   - if the BSSID of router is specified and this value is set, when the router of this specified BSSID fails to be found
     after "fail" (mesh_attempts_t) times, the entire network is allowed to switch to another router with the same SSID.
6. modify the root to perform a full channel scan when esp_wifi_connect().
7. support handling beacon without DS Paramter Set.
This commit is contained in:
qiyuexia 2018-11-22 00:57:59 +08:00 committed by qiyueixa
parent fa59b1b1c9
commit 1692896e5e
5 changed files with 100 additions and 10 deletions

View file

@ -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

@ -1 +1 @@
Subproject commit 892a63089b5ab74114a86c2a3202bfa755bfd320
Subproject commit b16383705d7844e125f5063cb642f5964f2d8ff4

View file

@ -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 <https://smashicons.com>`_ from `www.flaticon.com <https://smashicons.com>`_
Router and internet icon made by `Smashicons <https://smashicons.com>`_ from `www.flaticon.com <https://smashicons.com>`_

View file

@ -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.

View file

@ -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, "<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;