mesh: add manual networking function

1. add mesh_assoc_t to esp_mesh_internal.h file.
2. rename "node" to "device" in esp_mesh.h.
3. add MESH_EVENT_SCAN_DONE event.
4. add APIs esp_mesh_scan_get_ap_record() and esp_mesh_scan_get_ap_ie_len() to get scan results.
5. modify API esp_mesh_set_self_organized() by adding parameter "select_parent".
6. modify API esp_mesh_set_parent() by adding parameter "parent_mesh_id"
7. add manual networking example.
This commit is contained in:
qiyueixa 2018-05-21 17:22:04 +08:00
parent f453877759
commit feaa6e8a8f
9 changed files with 821 additions and 75 deletions

View File

@ -68,7 +68,7 @@
* *
* In present implementation, applications are able to access mesh stack directly without having to go through LwIP stack. * In present implementation, applications are able to access mesh stack directly without having to go through LwIP stack.
* Applications use esp_mesh_send() and esp_mesh_recv() to send and receive messages over the mesh network. * Applications use esp_mesh_send() and esp_mesh_recv() to send and receive messages over the mesh network.
* In mesh stack design, normal nodes don't require LwIP stack. But since IDF hasn't supported system without initializing LwIP stack yet, * In mesh stack design, normal devices don't require LwIP stack. But since IDF hasn't supported system without initializing LwIP stack yet,
* applications still need to do LwIP initialization and two more things are required to be done * applications still need to do LwIP initialization and two more things are required to be done
* (1)stop DHCP server on softAP interface by default * (1)stop DHCP server on softAP interface by default
* (2)stop DHCP client on station interface by default. * (2)stop DHCP client on station interface by default.
@ -78,7 +78,7 @@
* tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA) * tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)
* *
* Over the mesh network, only root is able to access external IP network. * Over the mesh network, only root is able to access external IP network.
* In application mesh event handler, once a node becomes a root, start DHCP client immediately if DHCP is chosen. * In application mesh event handler, once a device becomes a root, start DHCP client immediately if DHCP is chosen.
*/ */
#ifndef __ESP_MESH_H__ #ifndef __ESP_MESH_H__
@ -142,6 +142,14 @@ extern "C" {
#define MESH_OPT_SEND_GROUP (7) /**< data transmission by group; used with esp_mesh_send() and shall have payload */ #define MESH_OPT_SEND_GROUP (7) /**< data transmission by group; used with esp_mesh_send() and shall have payload */
#define MESH_OPT_RECV_DS_ADDR (8) /**< return a remote IP address; used with esp_mesh_send() and esp_mesh_recv() */ #define MESH_OPT_RECV_DS_ADDR (8) /**< return a remote IP address; used with esp_mesh_send() and esp_mesh_recv() */
/**
* @brief flag of mesh networking IE
*/
#define MESH_ASSOC_FLAG_VOTE_IN_PROGRESS (0x02) /**< vote in progress */
#define MESH_ASSOC_FLAG_NETWORK_FREE (0x08) /**< no root in current network */
#define MESH_ASSOC_FLAG_ROOTS_FOUND (0x20) /**< root conflict is found */
#define MESH_ASSOC_FLAG_ROOT_FIXED (0x40) /**< root is fixed */
/******************************************************* /*******************************************************
* Enumerations * Enumerations
*******************************************************/ *******************************************************/
@ -172,19 +180,21 @@ typedef enum {
and this device is specified to be a root by users, users should set a new parent and this device is specified to be a root by users, users should set a new parent
for this device. if self organized is enabled, this device will find a new parent for this device. if self organized is enabled, this device will find a new parent
by itself, users could ignore this event. */ by itself, users could ignore this event. */
MESH_EVENT_ROOT_FIXED, /**< When nodes join a network, if the setting of Root Fixed for one node is different MESH_EVENT_ROOT_FIXED, /**< when devices join a network, if the setting of Fixed Root for one device is different
from that of its parent, the node will update the setting the same as its parent's. from that of its parent, the device will update the setting the same as its parent's.
Root Fixed setting of each node is variable as that setting changes of root. */ Fixed Root setting of each device is variable as that setting changes of root. */
MESH_EVENT_SCAN_DONE, /**< if self-organized networking is disabled, user can call esp_wifi_scan_start() to trigger
this event, and add the corresponding scan done handler in this event. */
MESH_EVENT_MAX, MESH_EVENT_MAX,
} mesh_event_id_t; } mesh_event_id_t;
/** /**
* @brief node type * @brief device type
*/ */
typedef enum { typedef enum {
MESH_IDLE, /**< hasn't joined the mesh network yet */ MESH_IDLE, /**< hasn't joined the mesh network yet */
MESH_ROOT, /**< the only sink of the mesh network. Has the ability to access external IP network */ MESH_ROOT, /**< the only sink of the mesh network. Has the ability to access external IP network */
MESH_NODE, /**< intermediate node. Has the ability to forward packets over the mesh network */ MESH_NODE, /**< intermediate device. Has the ability to forward packets over the mesh network */
MESH_LEAF, /**< has no forwarding ability */ MESH_LEAF, /**< has no forwarding ability */
} mesh_type_t; } mesh_type_t;
@ -221,7 +231,7 @@ typedef enum {
typedef enum { typedef enum {
MESH_REASON_CYCLIC = 100, /**< cyclic is detected */ MESH_REASON_CYCLIC = 100, /**< cyclic is detected */
MESH_REASON_PARENT_IDLE, /**< parent is idle */ MESH_REASON_PARENT_IDLE, /**< parent is idle */
MESH_REASON_LEAF, /**< the connected node is changed to a leaf */ MESH_REASON_LEAF, /**< the connected device is changed to a leaf */
MESH_REASON_DIFF_ID, /**< in different mesh ID */ MESH_REASON_DIFF_ID, /**< in different mesh ID */
MESH_REASON_ROOTS, /**< root conflict is detected */ MESH_REASON_ROOTS, /**< root conflict is detected */
MESH_REASON_PARENT_STOPPED, /**< parent has stopped the mesh */ MESH_REASON_PARENT_STOPPED, /**< parent has stopped the mesh */
@ -331,7 +341,7 @@ typedef struct {
*/ */
typedef struct { typedef struct {
int8_t rssi; /**< rssi with router */ int8_t rssi; /**< rssi with router */
uint16_t capacity; /**< the number of nodes in its network */ uint16_t capacity; /**< the number of devices in current network */
uint8_t addr[6]; /**< other powerful root address */ uint8_t addr[6]; /**< other powerful root address */
} mesh_event_root_conflict_t; } mesh_event_root_conflict_t;
@ -350,6 +360,13 @@ typedef struct {
bool is_fixed; /**< status */ bool is_fixed; /**< status */
} mesh_event_root_fixed_t; } mesh_event_root_fixed_t;
/**
* @brief scan done event information
*/
typedef struct {
uint8_t number; /**< the number of scanned APs */
} mesh_event_scan_done_t;
/** /**
* @brief mesh event information * @brief mesh event information
*/ */
@ -362,16 +379,17 @@ typedef union {
mesh_event_disconnected_t disconnected; /**< parent disconnected */ mesh_event_disconnected_t disconnected; /**< parent disconnected */
mesh_event_no_parent_found_t no_parent; /**< no parent found */ mesh_event_no_parent_found_t no_parent; /**< no parent found */
mesh_event_layer_change_t layer_change; /**< layer change */ mesh_event_layer_change_t layer_change; /**< layer change */
mesh_event_toDS_state_t toDS_state; /**< toDS state, nodes should check this state firstly before trying to send packets to mesh_event_toDS_state_t toDS_state; /**< toDS state, devices shall check this state firstly before trying to send packets to
external IP network. This state indicates right now if root is capable external IP network. This state indicates right now if root is capable of sending
of sending packets out. If not, nodes had better to wait until this state changes packets out. If not, devices had better to wait until this state changes to be
to be MESH_TODS_REACHABLE. */ MESH_TODS_REACHABLE. */
mesh_event_vote_started_t vote_started; /**< vote started */ mesh_event_vote_started_t vote_started; /**< vote started */
mesh_event_root_got_ip_t got_ip; /**< root obtains IP address */ mesh_event_root_got_ip_t got_ip; /**< root obtains IP address */
mesh_event_root_address_t root_addr; /**< root address */ mesh_event_root_address_t root_addr; /**< root address */
mesh_event_root_switch_req_t switch_req; /**< root switch request */ mesh_event_root_switch_req_t switch_req; /**< root switch request */
mesh_event_root_conflict_t root_conflict; /**< other powerful root */ mesh_event_root_conflict_t root_conflict; /**< other powerful root */
mesh_event_root_fixed_t root_fixed; /**< root fixed */ mesh_event_root_fixed_t root_fixed; /**< root fixed */
mesh_event_scan_done_t scan_done; /**< scan done */
} mesh_event_info_t; } mesh_event_info_t;
/** /**
@ -497,7 +515,7 @@ extern mesh_event_cb_t g_mesh_event_cb;
* Check if WiFi is started. * Check if WiFi is started.
* Initialize mesh global variables with default values. * Initialize mesh global variables with default values.
* *
* @attention This API should be called after WiFi is started. * @attention This API shall be called after WiFi is started.
* *
* @return * @return
* - ESP_OK * - ESP_OK
@ -522,7 +540,7 @@ esp_err_t esp_mesh_deinit(void);
* Create TX and RX queues according to the configuration * Create TX and RX queues according to the configuration
* Register mesh packets receive callback * Register mesh packets receive callback
* *
* @attention This API should be called after esp_mesh_init() and esp_mesh_set_config(). * @attention This API shall be called after esp_mesh_init() and esp_mesh_set_config().
* *
* @return * @return
* - ESP_OK * - ESP_OK
@ -552,7 +570,7 @@ esp_err_t esp_mesh_stop(void);
/** /**
* @brief send a packet over the mesh network * @brief send a packet over the mesh network
* Send a packet to any node in the mesh network. * Send a packet to any device in the mesh network.
* Send a packet to external IP network. * Send a packet to external IP network.
* *
* @attention This API is not reentrant. * @attention This API is not reentrant.
@ -566,9 +584,9 @@ esp_err_t esp_mesh_stop(void);
* Should specify the transmission tos(type of service), P2P reliable by default. * Should specify the transmission tos(type of service), P2P reliable by default.
* @param flag * @param flag
* (1)used to speed up the route selection * (1)used to speed up the route selection
* if the packet is target to an internal node, MESH_DATA_P2P should be set. * if the packet is target to an internal device, MESH_DATA_P2P should be set.
* if the packet is outgoing to root or to external IP network, MESH_DATA_TODS should be set. * if the packet is outgoing to root or to external IP network, MESH_DATA_TODS should be set.
* if the packet is from root to an internal node, MESH_DATA_FROMDS should be set. * if the packet is from root to an internal device, MESH_DATA_FROMDS should be set.
* (2)specify if this API is block or non-block, block by default * (2)specify if this API is block or non-block, block by default
* if needs non-block, MESH_DATA_NONBLOCK should be set. * if needs non-block, MESH_DATA_NONBLOCK should be set.
* (3)in the situation of root having been changed, MESH_DATA_DROP identifies this packet can be dropped by new root * (3)in the situation of root having been changed, MESH_DATA_DROP identifies this packet can be dropped by new root
@ -581,7 +599,7 @@ esp_err_t esp_mesh_stop(void);
* @param opt options * @param opt options
* (1)in case of sending a packet to a specified group, MESH_OPT_SEND_GROUP is a good choice. * (1)in case of sending a packet to a specified group, MESH_OPT_SEND_GROUP is a good choice.
* In this option, the value field should specify the target receiver addresses in this group. * In this option, the value field should specify the target receiver addresses in this group.
* (2)root sends a packet to an internal node, this packet is from external IP network in case the receiver node responds * (2)root sends a packet to an internal device, this packet is from external IP network in case the receiver device responds
* this packet, MESH_OPT_RECV_DS_ADDR is required to attach the target DS address. * this packet, MESH_OPT_RECV_DS_ADDR is required to attach the target DS address.
* @param opt_count option count * @param opt_count option count
* Currently, this API only takes one option, so opt_count is only supported to be 1. * Currently, this API only takes one option, so opt_count is only supported to be 1.
@ -601,7 +619,7 @@ esp_err_t esp_mesh_stop(void);
* - ESP_ERR_MESH_DISCARD * - ESP_ERR_MESH_DISCARD
*/ */
esp_err_t esp_mesh_send(const mesh_addr_t *to, const mesh_data_t *data, esp_err_t esp_mesh_send(const mesh_addr_t *to, const mesh_data_t *data,
const int flag, const mesh_opt_t opt[], const int opt_count); int flag, const mesh_opt_t opt[], int opt_count);
/** /**
* @brief receive a packet targeted to self over the mesh network * @brief receive a packet targeted to self over the mesh network
@ -679,10 +697,10 @@ esp_err_t esp_mesh_recv_toDS(mesh_addr_t *from, mesh_addr_t *to,
* Root conflict function could eliminate redundant roots connected with the same BSSID, but couldn't handle roots * Root conflict function could eliminate redundant roots connected with the same BSSID, but couldn't handle roots
* connected with different BSSID. Because users might have such requirements of setting up routers with same SSID * connected with different BSSID. Because users might have such requirements of setting up routers with same SSID
* for the future replacement. But in that case, if the above situations happen, please make sure applications * for the future replacement. But in that case, if the above situations happen, please make sure applications
* implement forward functions on root to guarantee nodes in different mesh network could communicate with each other. * implement forward functions on root to guarantee devices in different mesh network can communicate with each other.
* max_connection of mesh softAP is limited by the max number of WiFi softAP supported(max:10). * max_connection of mesh softAP is limited by the max number of WiFi softAP supported(max:10).
* *
* @attention This API should be called between esp_mesh_init() and esp_mesh_start(). * @attention This API shall be called between esp_mesh_init() and esp_mesh_start().
* *
* @param config pointer to mesh stack configuration * @param config pointer to mesh stack configuration
* *
@ -707,7 +725,7 @@ esp_err_t esp_mesh_get_config(mesh_cfg_t *config);
/** /**
* @brief set router configuration * @brief set router configuration
* *
* @attention This API should be called between esp_mesh_init() and esp_mesh_start(). * @attention This API shall be called between esp_mesh_init() and esp_mesh_start().
* *
* @param router pointer to router configuration * @param router pointer to router configuration
* *
@ -731,7 +749,7 @@ esp_err_t esp_mesh_get_router(mesh_router_t *router);
/** /**
* @brief set mesh network ID * @brief set mesh network ID
* *
* @attention This API should be called between esp_mesh_init() and esp_mesh_start(). * @attention This API could be called either before esp_mesh_start() or after esp_mesh_start().
* *
* @param id pointer to mesh network ID * @param id pointer to mesh network ID
* *
@ -753,20 +771,20 @@ esp_err_t esp_mesh_set_id(const mesh_addr_t *id);
esp_err_t esp_mesh_get_id(mesh_addr_t *id); esp_err_t esp_mesh_get_id(mesh_addr_t *id);
/** /**
* @brief set node type over the mesh network(Unimplemented) * @brief set device type over the mesh network(Unimplemented)
* *
* @param type node type * @param type device type
* *
* @return * @return
* - ESP_OK * - ESP_OK
* - ESP_ERR_MESH_NOT_ALLOWED * - ESP_ERR_MESH_NOT_ALLOWED
*/ */
esp_err_t esp_mesh_set_type(const mesh_type_t type); esp_err_t esp_mesh_set_type(mesh_type_t type);
/** /**
* @brief get node type over mesh network * @brief get device type over mesh network
* *
* @attention This API should be called after having received the event MESH_EVENT_PARENT_CONNECTED. * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
* *
* @return mesh type * @return mesh type
* *
@ -776,7 +794,7 @@ mesh_type_t esp_mesh_get_type(void);
/** /**
* @brief set max layer configuration(max:15, default:15) * @brief set max layer configuration(max:15, default:15)
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param max_layer max layer value * @param max_layer max layer value
* *
@ -785,7 +803,7 @@ mesh_type_t esp_mesh_get_type(void);
* - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_ARGUMENT
* - ESP_ERR_MESH_NOT_ALLOWED * - ESP_ERR_MESH_NOT_ALLOWED
*/ */
esp_err_t esp_mesh_set_max_layer(const int max_layer); esp_err_t esp_mesh_set_max_layer(int max_layer);
/** /**
* @brief get max layer configuration * @brief get max layer configuration
@ -797,7 +815,7 @@ int esp_mesh_get_max_layer(void);
/** /**
* @brief set mesh softAP password * @brief set mesh softAP password
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param pwd pointer to the password * @param pwd pointer to the password
* @param len password length * @param len password length
@ -807,12 +825,12 @@ int esp_mesh_get_max_layer(void);
* - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_ARGUMENT
* - ESP_ERR_MESH_NOT_ALLOWED * - ESP_ERR_MESH_NOT_ALLOWED
*/ */
esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, const int len); esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, int len);
/** /**
* @brief set mesh softAP authentication mode value * @brief set mesh softAP authentication mode value
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param authmode authentication mode * @param authmode authentication mode
* *
@ -821,7 +839,7 @@ esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, const int len);
* - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_ARGUMENT
* - ESP_ERR_MESH_NOT_ALLOWED * - ESP_ERR_MESH_NOT_ALLOWED
*/ */
esp_err_t esp_mesh_set_ap_authmode(const wifi_auth_mode_t authmode); esp_err_t esp_mesh_set_ap_authmode(wifi_auth_mode_t authmode);
/** /**
* @brief get mesh softAP authentication mode * @brief get mesh softAP authentication mode
@ -834,7 +852,7 @@ wifi_auth_mode_t esp_mesh_get_ap_authmode(void);
/** /**
* @brief set mesh softAP max connection value * @brief set mesh softAP max connection value
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param connections the number of max connections * @param connections the number of max connections
* *
@ -842,7 +860,7 @@ wifi_auth_mode_t esp_mesh_get_ap_authmode(void);
* - ESP_OK * - ESP_OK
* - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_ARGUMENT
*/ */
esp_err_t esp_mesh_set_ap_connections(const int connections); esp_err_t esp_mesh_set_ap_connections(int connections);
/** /**
* @brief get mesh softAP max connection configuration * @brief get mesh softAP max connection configuration
@ -855,7 +873,7 @@ int esp_mesh_get_ap_connections(void);
/** /**
* @brief get current layer value over the mesh network * @brief get current layer value over the mesh network
* *
* @attention This API should be called after having received the event MESH_EVENT_PARENT_CONNECTED. * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
* *
* @return layer value * @return layer value
* *
@ -865,7 +883,7 @@ int esp_mesh_get_layer(void);
/** /**
* @brief get parent BSSID * @brief get parent BSSID
* *
* @attention This API should be called after having received the event MESH_EVENT_PARENT_CONNECTED. * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
* *
* @param bssid pointer to parent BSSID * @param bssid pointer to parent BSSID
* *
@ -876,7 +894,7 @@ int esp_mesh_get_layer(void);
esp_err_t esp_mesh_get_parent_bssid(mesh_addr_t *bssid); esp_err_t esp_mesh_get_parent_bssid(mesh_addr_t *bssid);
/** /**
* @brief return if the node is root * @brief return if the device is root
* *
* @return true/false * @return true/false
* *
@ -885,16 +903,20 @@ bool esp_mesh_is_root(void);
/** /**
* @brief enable/disable mesh networking self-organized, self-organized by default * @brief enable/disable mesh networking self-organized, self-organized by default
* if self-organized is disabled, users should set a parent for this node via * if self-organized is disabled, users should set a parent for this device via
* esp_mesh_set_parent(); * esp_mesh_set_parent();
* *
* @param enable * @attention This API could be called either before esp_mesh_start() or after esp_mesh_start().
*
* @param enable enable or disable self-organized networking
* @param select_parent if enable self-organized networking, let the device select a new parent or
* keep connecting to the previous parent.
* *
* @return * @return
* - ESP_OK * - ESP_OK
* - ESP_FAIL * - ESP_FAIL
*/ */
esp_err_t esp_mesh_set_self_organized(const bool enable); esp_err_t esp_mesh_set_self_organized(bool enable, bool select_parent);
/** /**
* @brief return if mesh networking is self-organized or not * @brief return if mesh networking is self-organized or not
@ -906,7 +928,7 @@ bool esp_mesh_get_self_organized(void);
/** /**
* @brief root waive itself * @brief root waive itself
* A node is elected to be a root during the networking mostly because it has a strong RSSI with router. * A device is elected to be a root during the networking mostly because it has a strong RSSI with router.
* If such superior conditions change, users could call this API to perform a root switch. * If such superior conditions change, users could call this API to perform a root switch.
* *
* In this API, users could specify a desired root address to replace itself or specify an attempts value * In this API, users could specify a desired root address to replace itself or specify an attempts value
@ -931,14 +953,14 @@ bool esp_mesh_get_self_organized(void);
* - ESP_OK * - ESP_OK
* - ESP_FAIL * - ESP_FAIL
*/ */
esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, const int reason); esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, int reason);
/** /**
* @brief set vote percentage threshold for approval of being a root * @brief set vote percentage threshold for approval of being a root
* During the networking, only obtaining vote percentage reaches this threshold, * During the networking, only obtaining vote percentage reaches this threshold,
* the node could be a root. * the device could be a root.
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param percentage vote percentage threshold * @param percentage vote percentage threshold
* *
@ -946,7 +968,7 @@ esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, const int reason);
* - ESP_OK * - ESP_OK
* - ESP_FAIL * - ESP_FAIL
*/ */
esp_err_t esp_mesh_set_vote_percentage(const float percentage); esp_err_t esp_mesh_set_vote_percentage(float percentage);
/** /**
* @brief get vote percentage threshold for approval of being a root * @brief get vote percentage threshold for approval of being a root
@ -966,7 +988,7 @@ float esp_mesh_get_vote_percentage(void);
* - ESP_OK * - ESP_OK
* - ESP_FAIL * - ESP_FAIL
*/ */
esp_err_t esp_mesh_set_ap_assoc_expire(const int seconds); esp_err_t esp_mesh_set_ap_assoc_expire(int seconds);
/** /**
* @brief get mesh softAP associate expired time * @brief get mesh softAP associate expired time
@ -976,27 +998,27 @@ esp_err_t esp_mesh_set_ap_assoc_expire(const int seconds);
int esp_mesh_get_ap_assoc_expire(void); int esp_mesh_get_ap_assoc_expire(void);
/** /**
* @brief get total number of nodes over the mesh network(including root) * @brief get total number of devices in current network(including root)
* *
* @attention The returned value might be incorrect when the network is changing. * @attention The returned value might be incorrect when the network is changing.
** **
* @return total number of nodes(including root) * @return total number of devices(including root)
*/ */
int esp_mesh_get_total_node_num(void); int esp_mesh_get_total_node_num(void);
/** /**
* @brief get the number of nodes in routing table(including self) * @brief get the number of devices in this device's sub-network(including self)
* *
* @return the number of nodes in routing table(including self) * @return the number of devices over this device's sub-network(including self)
*/ */
int esp_mesh_get_routing_table_size(void); int esp_mesh_get_routing_table_size(void);
/** /**
* @brief get routing table(including itself) * @brief get routing table of this device's sub-network(including itself)
* *
* @param mac pointer to routing table * @param mac pointer to routing table
* @param len routing table size(in bytes) * @param len routing table size(in bytes)
* @param size pointer to the number of nodes in routing table(including itself) * @param size pointer to the number of devices in routing table(including itself)
* *
* @return * @return
* - ESP_OK * - ESP_OK
@ -1015,7 +1037,7 @@ esp_err_t esp_mesh_get_routing_table(mesh_addr_t *mac, int len, int *size);
* - ESP_OK * - ESP_OK
* - ESP_FAIL * - ESP_FAIL
*/ */
esp_err_t esp_mesh_post_toDS_state(const bool reachable); esp_err_t esp_mesh_post_toDS_state(bool reachable);
/** /**
* @brief return the number of packets pending in the queue waiting to be sent by the mesh stack * @brief return the number of packets pending in the queue waiting to be sent by the mesh stack
@ -1052,9 +1074,9 @@ int esp_mesh_available_txupQ_num(const mesh_addr_t *addr, uint32_t *xseqno_in);
/** /**
* @brief set queue size * @brief set queue size
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param qsize default:72(min:36, max:105) * @param qsize default:32(min:16)
* *
* @return * @return
* - ESP_OK * - ESP_OK
@ -1079,7 +1101,7 @@ int esp_mesh_get_xon_qsize(void);
* - ESP_WIFI_ERR_NOT_INIT * - ESP_WIFI_ERR_NOT_INIT
* - ESP_WIFI_ERR_NOT_START * - ESP_WIFI_ERR_NOT_START
*/ */
esp_err_t esp_mesh_allow_root_conflicts(const bool allowed); esp_err_t esp_mesh_allow_root_conflicts(bool allowed);
/** /**
* @brief check if allow more than one root to exist in one network * @brief check if allow more than one root to exist in one network
@ -1098,7 +1120,7 @@ bool esp_mesh_is_root_conflicts_allowed(void);
* - ESP_OK * - ESP_OK
* - ESP_MESH_ERR_ARGUMENT * - ESP_MESH_ERR_ARGUMENT
*/ */
esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, const int num); esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, int num);
/** /**
* @brief delete group ID addresses * @brief delete group ID addresses
@ -1110,7 +1132,7 @@ esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, const int num);
* - ESP_OK * - ESP_OK
* - ESP_MESH_ERR_ARGUMENT * - ESP_MESH_ERR_ARGUMENT
*/ */
esp_err_t esp_mesh_delete_group_id(const mesh_addr_t *addr, const int num); esp_err_t esp_mesh_delete_group_id(const mesh_addr_t *addr, int num);
/** /**
* @brief get the number of group ID addresses * @brief get the number of group ID addresses
@ -1129,7 +1151,7 @@ int esp_mesh_get_group_num(void);
* - ESP_OK * - ESP_OK
* - ESP_MESH_ERR_ARGUMENT * - ESP_MESH_ERR_ARGUMENT
*/ */
esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, const int num); esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, int num);
/** /**
* @brief check if the specified group address is my group * @brief check if the specified group address is my group
@ -1141,7 +1163,7 @@ bool esp_mesh_is_my_group(const mesh_addr_t *addr);
/** /**
* @brief set mesh network capacity * @brief set mesh network capacity
* *
* @attention This API should be called before esp_mesh_start(). * @attention This API shall be called before esp_mesh_start().
* *
* @param num mesh network capacity * @param num mesh network capacity
* *
@ -1172,7 +1194,7 @@ esp_err_t esp_mesh_set_ie_crypto_funcs(const mesh_crypto_funcs_t *crypto_funcs);
/** /**
* @brief set mesh ie crypto key * @brief set mesh ie crypto key
* *
* @attention This API should be called after esp_mesh_set_config() and before esp_mesh_start(). * @attention This API shall be called after esp_mesh_set_config() and before esp_mesh_start().
* *
* @param key ASCII crypto key * @param key ASCII crypto key
* @param len length in bytes, range:8~64 * @param len length in bytes, range:8~64
@ -1225,21 +1247,21 @@ int esp_mesh_get_root_healing_delay(void);
esp_err_t esp_mesh_set_event_cb(const mesh_event_cb_t event_cb); esp_err_t esp_mesh_set_event_cb(const mesh_event_cb_t event_cb);
/** /**
* @brief set Root Fixed setting for nodes * @brief set Fixed Root setting for the device
* If Root Fixed setting of nodes is enabled, they won't compete to be a root. * If Fixed Root setting of the device is enabled, it won't compete to be a root.
* If a scenario needs a fixed root, all nodes in this network shall enable this setting. * If a scenario needs a fixed root, all devices in this network shall enable this setting.
* *
* @param enable enable or not * @param enable enable or not
* *
* @return * @return
* - ESP_OK * - ESP_OK
*/ */
esp_err_t esp_mesh_fix_root(const bool enable); esp_err_t esp_mesh_fix_root(bool enable);
/** /**
* @brief check if Root Fixed setting is enabled * @brief check if Fixed Root setting is enabled
* Root Fixed setting can be changed by API esp_mesh_fix_root(). * Fixed Root setting can be changed by API esp_mesh_fix_root().
* Root Fixed setting can also be changed by event MESH_EVENT_ROOT_FIXED. * Fixed Root setting can also be changed by event MESH_EVENT_ROOT_FIXED.
* *
* @return true/false * @return true/false
*/ */
@ -1247,9 +1269,9 @@ bool esp_mesh_is_root_fixed(void);
/** /**
* @brief set a specified parent * @brief set a specified parent
* self-organized networking will be disabled.
* *
* @param parent parent configuration * @param parent parent configuration, the ssid and the channel of the parent are mandatory.
* @param parent_mesh_id parent mesh ID, if not set, use the device default one.
* @param my_type my mesh type * @param my_type my mesh type
* @param my_layer my mesh layer * @param my_layer my mesh layer
* *
@ -1258,8 +1280,35 @@ bool esp_mesh_is_root_fixed(void);
* - ESP_ERR_ARGUMENT * - ESP_ERR_ARGUMENT
* - ESP_ERR_MESH_NOT_CONFIG * - ESP_ERR_MESH_NOT_CONFIG
*/ */
esp_err_t esp_mesh_set_parent(wifi_config_t *parent, mesh_type_t my_type, int my_layer); esp_err_t esp_mesh_set_parent(const wifi_config_t *parent, const mesh_addr_t *parent_mesh_id, mesh_type_t my_type, int my_layer);
/**
* @brief get mesh networking IE length of one AP
*
* @param len mesh networking IE length
*
* @return
* - ESP_OK
* - ESP_ERR_WIFI_NOT_INIT
* - ESP_ERR_WIFI_ARG
* - ESP_ERR_WIFI_FAIL
*/
esp_err_t esp_mesh_scan_get_ap_ie_len(int *len);
/**
* @brief get AP record
* Different from esp_wifi_scan_get_ap_records(), this API only gets one of scanned APs each time.
*
* @param ap_record pointer to the AP record
* @param buffer pointer to the mesh networking IE of this AP
*
* @return
* - ESP_OK
* - ESP_ERR_WIFI_NOT_INIT
* - ESP_ERR_WIFI_ARG
* - ESP_ERR_WIFI_FAIL
*/
esp_err_t esp_mesh_scan_get_ap_record(wifi_ap_record_t *ap_record, void *buffer);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -49,6 +49,46 @@ typedef struct {
int backoff_rssi; /* RSSI threshold for connecting to the root */ int backoff_rssi; /* RSSI threshold for connecting to the root */
} mesh_switch_parent_t; } mesh_switch_parent_t;
/**
* @brief mesh networking IE
*/
typedef struct {
/**< mesh networking IE head */
uint8_t eid; /**< element ID */
uint8_t len; /**< element length */
uint8_t oui[3]; /**< organization identifier */
/**< mesh networking IE content */
uint8_t type; /** mesh networking IE type */
uint8_t encryped : 1; /**< if mesh networking IE is encrypted */
uint8_t version : 7; /**< mesh networking IE version */
/**< content */
uint8_t mesh_type; /**< mesh device type */
uint8_t mesh_id[6]; /**< mesh ID */
uint8_t layer_cap; /**< max layer */
uint8_t layer; /**< current layer */
uint8_t assoc_cap; /**< max connections of mesh AP */
uint8_t assoc; /**< current connections */
uint8_t leaf_cap; /**< leaf capacity */
uint8_t leaf_assoc; /**< the number of current connected leaf */
uint16_t root_cap; /**< root capacity */
uint16_t self_cap; /**< self capacity */
uint16_t layer2_cap; /**< layer2 capacity */
uint16_t scan_ap_num; /**< the number of scanned APs */
int8_t rssi; /**< rssi of the parent */
int8_t router_rssi; /**< rssi of the router */
uint8_t flag; /**< flag of networking */
uint8_t rc_addr[6]; /**< root address */
int8_t rc_rssi; /**< root rssi */
uint8_t vote_addr[6]; /**< voter address */
int8_t vote_rssi; /**< vote rssi of the router */
uint8_t vote_ttl; /**< vote ttl */
uint16_t votes; /**< votes */
uint16_t my_votes; /**< my votes */
uint8_t reason; /**< reason */
uint8_t child[6]; /**< child address */
uint8_t toDS; /**< toDS state */
} __attribute__((packed)) mesh_assoc_t;
/******************************************************* /*******************************************************
* Function Definitions * Function Definitions
*******************************************************/ *******************************************************/

@ -1 +1 @@
Subproject commit 963fb2baa4bf6320a89674ef1ba1de6f15ddd06d Subproject commit 8b6d5837a4215b83ff8a3ff088ccbb716adf05fb

View File

@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := manual_networking
include $(IDF_PATH)/make/project.mk

View File

@ -0,0 +1,80 @@
menu "Example Configuration"
config MESH_CHANNEL
int "channel"
range 1 14
default 1
help
mesh network channel.
config MESH_ROUTER_SSID
string "Router SSID"
default "ROUTER_SSID"
help
Router SSID.
config MESH_ROUTER_PASSWD
string "Router password"
default "ROUTER_PASSWD"
help
Router password.
choice
bool "Mesh AP Authentication Mode"
default MAP_AUTH_MODE_OPEN
help
Authentication mode.
config WIFI_AUTH_OPEN
bool "WIFI_AUTH_OPEN"
config WIFI_AUTH_WPA_PSK
bool "WIFI_AUTH_WPA_PSK"
config WIFI_AUTH_WPA2_PSK
bool "WIFI_AUTH_WPA2_PSK"
config WIFI_AUTH_WPA_WPA2_PSK
bool "WIFI_AUTH_WPA_WPA2_PSK"
endchoice
config MESH_AP_AUTHMODE
int
default 0 if WIFI_AUTH_OPEN
default 2 if WIFI_AUTH_WPA_PSK
default 3 if WIFI_AUTH_WPA2_PSK
default 4 if WIFI_AUTH_WPA_WPA2_PSK
help
Mesh AP authentication mode.
config MESH_AP_PASSWD
string "Mesh AP Password"
default "MAP_PASSWD"
help
Mesh AP password.
config MESH_AP_CONNECTIONS
int "Mesh AP Connections"
range 1 10
default 6
help
The number of stations allowed to connect in.
config MESH_MAX_LAYER
int "Mesh Max Layer"
range 1 15
default 6
help
Max layer allowed in mesh network.
config MESH_ROUTE_TABLE_SIZE
int "Mesh Routing Table Size"
range 1 300
default 50
help
The number of devices over the network(max: 300).
config MESH_PARENT_SSID
string "Parent SSID"
default "PARENT_SSID"
help
Parent SSID.
endmenu

View File

@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@ -0,0 +1,57 @@
/* Mesh Manual Networking Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#ifndef __MESH_LIGHT_H__
#define __MESH_LIGHT_H__
#include "esp_err.h"
/*******************************************************
* Constants
*******************************************************/
#define MESH_LIGHT_RED (0xff)
#define MESH_LIGHT_GREEN (0xfe)
#define MESH_LIGHT_BLUE (0xfd)
#define MESH_LIGHT_YELLOW (0xfc)
#define MESH_LIGHT_PINK (0xfb)
#define MESH_LIGHT_INIT (0xfa)
#define MESH_LIGHT_WARNING (0xf9)
#define MESH_TOKEN_ID (0x0)
#define MESH_TOKEN_VALUE (0xbeef)
#define MESH_CONTROL_CMD (0x2)
/*******************************************************
* Type Definitions
*******************************************************/
/*******************************************************
* Structures
*******************************************************/
typedef struct {
uint8_t cmd;
bool on;
uint8_t token_id;
uint16_t token_value;
} mesh_light_ctl_t;
/*******************************************************
* Variables Declarations
*******************************************************/
/*******************************************************
* Function Definitions
*******************************************************/
esp_err_t mesh_light_init(void);
esp_err_t mesh_light_set(int color);
esp_err_t mesh_light_process(mesh_addr_t *from, uint8_t *buf, uint16_t len);
void mesh_connected_indicator(int layer);
void mesh_disconnected_indicator(void);
#endif /* __MESH_LIGHT_H__ */

View File

@ -0,0 +1,180 @@
/* Mesh Manual Networking Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "esp_err.h"
#include "esp_mesh.h"
#include "mesh_light.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
/*******************************************************
* Constants
*******************************************************/
/* RGB configuration on ESP-WROVER-KIT board */
#define LEDC_IO_0 (0)
#define LEDC_IO_1 (2)
#define LEDC_IO_2 (4)
#define LEDC_IO_3 (5)
/*******************************************************
* Variable Definitions
*******************************************************/
static bool s_light_inited = false;
/*******************************************************
* Function Definitions
*******************************************************/
esp_err_t mesh_light_init(void)
{
if (s_light_inited == true) {
return ESP_OK;
}
s_light_inited = true;
ledc_timer_config_t ledc_timer = {
.bit_num = LEDC_TIMER_13_BIT,
.freq_hz = 5000,
.speed_mode = LEDC_HIGH_SPEED_MODE,
.timer_num = LEDC_TIMER_0
};
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.channel = LEDC_CHANNEL_0,
.duty = 100,
.gpio_num = LEDC_IO_0,
.intr_type = LEDC_INTR_FADE_END,
.speed_mode = LEDC_HIGH_SPEED_MODE,
.timer_sel = LEDC_TIMER_0
};
ledc_channel_config(&ledc_channel);
ledc_channel.channel = LEDC_CHANNEL_1;
ledc_channel.gpio_num = LEDC_IO_1;
ledc_channel_config(&ledc_channel);
ledc_channel.channel = LEDC_CHANNEL_2;
ledc_channel.gpio_num = LEDC_IO_2;
ledc_channel_config(&ledc_channel);
ledc_channel.channel = LEDC_CHANNEL_3;
ledc_channel.gpio_num = LEDC_IO_3;
ledc_channel_config(&ledc_channel);
ledc_fade_func_install(0);
mesh_light_set(MESH_LIGHT_INIT);
return ESP_OK;
}
esp_err_t mesh_light_set(int color)
{
switch (color) {
case MESH_LIGHT_RED:
/* Red */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0);
break;
case MESH_LIGHT_GREEN:
/* Green */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0);
break;
case MESH_LIGHT_BLUE:
/* Blue */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000);
break;
case MESH_LIGHT_YELLOW:
/* Yellow */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0);
break;
case MESH_LIGHT_PINK:
/* Pink */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000);
break;
case MESH_LIGHT_INIT:
/* can't say */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000);
break;
case MESH_LIGHT_WARNING:
/* warning */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000);
break;
default:
/* off */
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0);
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0);
}
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1);
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2);
return ESP_OK;
}
void mesh_connected_indicator(int layer)
{
switch (layer) {
case 1:
mesh_light_set(MESH_LIGHT_PINK);
break;
case 2:
mesh_light_set(MESH_LIGHT_YELLOW);
break;
case 3:
mesh_light_set(MESH_LIGHT_RED);
break;
case 4:
mesh_light_set(MESH_LIGHT_BLUE);
break;
case 5:
mesh_light_set(MESH_LIGHT_GREEN);
break;
case 6:
mesh_light_set(MESH_LIGHT_WARNING);
break;
default:
mesh_light_set(0);
}
}
void mesh_disconnected_indicator(void)
{
mesh_light_set(MESH_LIGHT_WARNING);
}
esp_err_t mesh_light_process(mesh_addr_t *from, uint8_t *buf, uint16_t len)
{
mesh_light_ctl_t *in = (mesh_light_ctl_t *) buf;
if (!from || !buf || len < sizeof(mesh_light_ctl_t)) {
return ESP_FAIL;
}
if (in->token_id != MESH_TOKEN_ID || in->token_value != MESH_TOKEN_VALUE) {
return ESP_FAIL;
}
if (in->cmd == MESH_CONTROL_CMD) {
if (in->on) {
mesh_connected_indicator(esp_mesh_get_layer());
} else {
mesh_light_set(0);
}
}
return ESP_OK;
}

View File

@ -0,0 +1,327 @@
/* Mesh Manual Networking Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_mesh.h"
#include "esp_mesh_internal.h"
#include "mesh_light.h"
#include "nvs_flash.h"
/*******************************************************
* Macros
*******************************************************/
//#define MESH_SET_ROOT
#ifndef MESH_SET_ROOT
#define MESH_SET_NODE
#endif
/*******************************************************
* Constants
*******************************************************/
/*******************************************************
* Variable Definitions
*******************************************************/
static const char *MESH_TAG = "mesh_main";
static const uint8_t MESH_ID[6] = { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77};
static mesh_addr_t mesh_parent_addr;
static int mesh_layer = -1;
/*******************************************************
* Function Declarations
*******************************************************/
void mesh_event_handler(mesh_event_t event);
void mesh_scan_done_handler(int num);
/*******************************************************
* Function Definitions
*******************************************************/
void mesh_scan_done_handler(int num)
{
int i;
int ie_len = 0;
mesh_assoc_t assoc;
mesh_assoc_t parent_assoc = { .layer = CONFIG_MESH_MAX_LAYER, .rssi = -120 };
wifi_ap_record_t record;
wifi_ap_record_t parent_record = { 0, };
bool parent_found = false;
mesh_type_t my_type = MESH_IDLE;
int my_layer = -1;
for (i = 0; i < num; i++) {
esp_mesh_scan_get_ap_ie_len(&ie_len);
esp_mesh_scan_get_ap_record(&record, &assoc);
if (ie_len == sizeof(assoc)) {
ESP_LOGW(MESH_TAG,
"<MESH>[%d]%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d, ID<"MACSTR">",
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));
#ifdef MESH_SET_NODE
if (assoc.mesh_type != MESH_IDLE && assoc.layer_cap
&& assoc.assoc < assoc.assoc_cap && record.rssi > -70) {
if (assoc.layer < parent_assoc.layer || assoc.layer2_cap < parent_assoc.layer2_cap) {
parent_found = true;
memcpy(&parent_record, &record, sizeof(record));
memcpy(&parent_assoc, &assoc, sizeof(assoc));
if (parent_assoc.layer_cap != 1) {
my_type = MESH_NODE;
} else {
my_type = MESH_LEAF;
}
my_layer = parent_assoc.layer + 1;
}
}
#endif
} else {
ESP_LOGI(MESH_TAG, "[%d]%s, "MACSTR", channel:%u, rssi:%d", i,
record.ssid, MAC2STR(record.bssid), record.primary,
record.rssi);
#ifdef MESH_SET_ROOT
if (!strcmp(CONFIG_MESH_ROUTER_SSID, (char *) record.ssid)) {
parent_found = true;
memcpy(&parent_record, &record, sizeof(record));
my_type = MESH_ROOT;
my_layer = MESH_ROOT_LAYER;
}
#endif
}
}
if (parent_found) {
/*
* parent
* Both channel and ssid of the parent are mandatory.
*/
wifi_config_t parent = { 0, };
parent.sta.channel = parent_record.primary;
memcpy(&parent.sta.ssid, &parent_record.ssid,
sizeof(parent_record.ssid));
parent.sta.bssid_set = 1;
memcpy(&parent.sta.bssid, parent_record.bssid, 6);
if (my_type == MESH_ROOT) {
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 {
ESP_LOGW(MESH_TAG,
"<PARENT>%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d",
parent_record.ssid, parent_assoc.layer,
parent_assoc.layer_cap, parent_assoc.assoc,
parent_assoc.assoc_cap, parent_assoc.layer2_cap,
MAC2STR(parent_record.bssid), parent_record.primary,
parent_record.rssi);
}
ESP_ERROR_CHECK(esp_mesh_set_parent(&parent, (mesh_addr_t*)&parent_assoc.mesh_id, my_type, my_layer));
} else {
ESP_LOGW(MESH_TAG,
"no parent found, enable self-organized networking.");
ESP_ERROR_CHECK(esp_mesh_set_self_organized(1, 1));
}
}
void mesh_event_handler(mesh_event_t event)
{
mesh_addr_t id = {0,};
static uint8_t last_layer = 0;
ESP_LOGD(MESH_TAG, "esp_event_handler:%d", event.id);
switch (event.id) {
case MESH_EVENT_STARTED:
esp_mesh_get_id(&id);
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());
wifi_scan_config_t scan_config = { 0 };
/* mesh softAP is hidden */
scan_config.show_hidden = 1;
ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0));
break;
case MESH_EVENT_STOPPED:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_STOPPED>");
mesh_layer = esp_mesh_get_layer();
break;
case MESH_EVENT_CHILD_CONNECTED:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHILD_CONNECTED>aid:%d, "MACSTR"",
event.info.child_connected.aid,
MAC2STR(event.info.child_connected.mac));
break;
case MESH_EVENT_CHILD_DISCONNECTED:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHILD_DISCONNECTED>aid:%d, "MACSTR"",
event.info.child_disconnected.aid,
MAC2STR(event.info.child_disconnected.mac));
break;
case MESH_EVENT_ROUTING_TABLE_ADD:
ESP_LOGW(MESH_TAG, "<MESH_EVENT_ROUTING_TABLE_ADD>add %d, new:%d",
event.info.routing_table.rt_size_change,
event.info.routing_table.rt_size_new);
break;
case MESH_EVENT_ROUTING_TABLE_REMOVE:
ESP_LOGW(MESH_TAG, "<MESH_EVENT_ROUTING_TABLE_REMOVE>remove %d, new:%d",
event.info.routing_table.rt_size_change,
event.info.routing_table.rt_size_new);
break;
case MESH_EVENT_NO_PARNET_FOUND:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_NO_PARNET_FOUND>scan times:%d",
event.info.no_parent.scan_times);
/* TODO handler for the failure */
break;
case MESH_EVENT_PARENT_CONNECTED:
esp_mesh_get_id(&id);
mesh_layer = event.info.connected.self_layer;
memcpy(&mesh_parent_addr.addr, event.info.connected.connected.bssid, 6);
ESP_LOGI(MESH_TAG,
"<MESH_EVENT_PARENT_CONNECTED>layer:%d-->%d, parent:"MACSTR"%s, ID:"MACSTR"",
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;
mesh_connected_indicator(mesh_layer);
if (esp_mesh_is_root()) {
tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA);
}
break;
case MESH_EVENT_PARENT_DISCONNECTED:
ESP_LOGI(MESH_TAG,
"<MESH_EVENT_PARENT_DISCONNECTED>reason:%d",
event.info.disconnected.reason);
mesh_disconnected_indicator();
mesh_layer = esp_mesh_get_layer();
break;
case MESH_EVENT_LAYER_CHANGE:
mesh_layer = event.info.layer_change.new_layer;
ESP_LOGI(MESH_TAG, "<MESH_EVENT_LAYER_CHANGE>layer:%d-->%d%s",
last_layer, mesh_layer,
esp_mesh_is_root() ? "<ROOT>" :
(mesh_layer == 2) ? "<layer2>" : "");
last_layer = mesh_layer;
mesh_connected_indicator(mesh_layer);
break;
case MESH_EVENT_ROOT_ADDRESS:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_ROOT_ADDRESS>root address:"MACSTR"",
MAC2STR(event.info.root_addr.addr));
break;
case MESH_EVENT_ROOT_GOT_IP:
/* root starts to connect to server */
ESP_LOGI(MESH_TAG,
"<MESH_EVENT_ROOT_GOT_IP>sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&event.info.got_ip.ip_info.ip),
IP2STR(&event.info.got_ip.ip_info.netmask),
IP2STR(&event.info.got_ip.ip_info.gw));
break;
case MESH_EVENT_ROOT_LOST_IP:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_ROOT_LOST_IP>");
break;
case MESH_EVENT_VOTE_STARTED:
ESP_LOGI(MESH_TAG,
"<MESH_EVENT_VOTE_STARTED>attempts:%d, reason:%d, rc_addr:"MACSTR"",
event.info.vote_started.attempts,
event.info.vote_started.reason,
MAC2STR(event.info.vote_started.rc_addr.addr));
break;
case MESH_EVENT_VOTE_STOPPED:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_VOTE_STOPPED>");
break;
case MESH_EVENT_ROOT_SWITCH_REQ:
ESP_LOGI(MESH_TAG,
"<MESH_EVENT_ROOT_SWITCH_REQ>reason:%d, rc_addr:"MACSTR"",
event.info.switch_req.reason,
MAC2STR( event.info.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);
ESP_LOGI(MESH_TAG, "<MESH_EVENT_ROOT_SWITCH_ACK>layer:%d, parent:"MACSTR"", mesh_layer, MAC2STR(mesh_parent_addr.addr));
break;
case MESH_EVENT_TODS_STATE:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_TODS_REACHABLE>state:%d",
event.info.toDS_state);
break;
case MESH_EVENT_ROOT_FIXED:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_ROOT_FIXED>%s",
event.info.root_fixed.is_fixed ? "fixed" : "not fixed");
break;
case MESH_EVENT_ROOT_ASKED_YIELD:
ESP_LOGI(MESH_TAG,
"<MESH_EVENT_ROOT_ASKED_YIELD>"MACSTR", rssi:%d, capacity:%d",
MAC2STR(event.info.root_conflict.addr),
event.info.root_conflict.rssi,
event.info.root_conflict.capacity);
break;
case MESH_EVENT_CHANNEL_SWITCH:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_CHANNEL_SWITCH>");
break;
case MESH_EVENT_SCAN_DONE:
ESP_LOGI(MESH_TAG, "<MESH_EVENT_SCAN_DONE>number:%d",
event.info.scan_done.number);
mesh_scan_done_handler(event.info.scan_done.number);
break;
default:
ESP_LOGI(MESH_TAG, "unknown id:%d", event.id);
break;
}
}
void app_main(void)
{
ESP_ERROR_CHECK(mesh_light_init());
ESP_ERROR_CHECK(nvs_flash_init());
/* tcpip initialization */
tcpip_adapter_init();
/* for mesh
* stop DHCP server on softAP interface by default
* stop DHCP client on station interface by default
* */
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));
ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA));
#if 0
/* static ip settings */
tcpip_adapter_ip_info_t sta_ip;
sta_ip.ip.addr = ipaddr_addr("192.168.1.102");
sta_ip.gw.addr = ipaddr_addr("192.168.1.1");
sta_ip.netmask.addr = ipaddr_addr("255.255.255.0");
tcpip_adapter_set_ip_info(WIFI_IF_STA, &sta_ip);
#endif
/* wifi initialization */
ESP_ERROR_CHECK(esp_event_loop_init(NULL, NULL));
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&config));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH));
ESP_ERROR_CHECK(esp_wifi_start());
/* mesh initialization */
ESP_ERROR_CHECK(esp_mesh_init());
ESP_ERROR_CHECK(esp_mesh_set_ap_authmode(WIFI_AUTH_OPEN));
mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT();
/* mesh ID */
memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6);
/* mesh event callback */
cfg.event_cb = &mesh_event_handler;
/* router */
cfg.channel = CONFIG_MESH_CHANNEL;
cfg.router.ssid_len = strlen(CONFIG_MESH_ROUTER_SSID);
memcpy((uint8_t *) &cfg.router.ssid, CONFIG_MESH_ROUTER_SSID, cfg.router.ssid_len);
memcpy((uint8_t *) &cfg.router.password, CONFIG_MESH_ROUTER_PASSWD,
strlen(CONFIG_MESH_ROUTER_PASSWD));
/* mesh softAP */
cfg.mesh_ap.max_connection = CONFIG_MESH_AP_CONNECTIONS;
memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD,
strlen(CONFIG_MESH_AP_PASSWD));
ESP_ERROR_CHECK(esp_mesh_set_config(&cfg));
/* mesh start */
ESP_ERROR_CHECK(esp_mesh_start());
ESP_LOGI(MESH_TAG, "mesh starts successfully, heap:%d, %s\n", esp_get_free_heap_size(),
esp_mesh_is_root_fixed() ? "root fixed" : "root not fixed");
}