From feaa6e8a8fea2e8e473cbf02269027507bf771cb Mon Sep 17 00:00:00 2001 From: qiyueixa Date: Mon, 21 May 2018 17:22:04 +0800 Subject: [PATCH] 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. --- components/esp32/include/esp_mesh.h | 197 +++++++---- components/esp32/include/esp_mesh_internal.h | 40 +++ components/esp32/lib | 2 +- examples/mesh/manual_networking/Makefile | 9 + .../manual_networking/main/Kconfig.projbuild | 80 +++++ .../mesh/manual_networking/main/component.mk | 4 + .../main/include/mesh_light.h | 57 +++ .../mesh/manual_networking/main/mesh_light.c | 180 ++++++++++ .../mesh/manual_networking/main/mesh_main.c | 327 ++++++++++++++++++ 9 files changed, 821 insertions(+), 75 deletions(-) create mode 100644 examples/mesh/manual_networking/Makefile create mode 100644 examples/mesh/manual_networking/main/Kconfig.projbuild create mode 100644 examples/mesh/manual_networking/main/component.mk create mode 100644 examples/mesh/manual_networking/main/include/mesh_light.h create mode 100644 examples/mesh/manual_networking/main/mesh_light.c create mode 100644 examples/mesh/manual_networking/main/mesh_main.c diff --git a/components/esp32/include/esp_mesh.h b/components/esp32/include/esp_mesh.h index b504149e1..14bd21f7e 100644 --- a/components/esp32/include/esp_mesh.h +++ b/components/esp32/include/esp_mesh.h @@ -68,7 +68,7 @@ * * 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. - * 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 * (1)stop DHCP server on softAP interface by default * (2)stop DHCP client on station interface by default. @@ -78,7 +78,7 @@ * tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); * * 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__ @@ -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_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 *******************************************************/ @@ -172,19 +180,21 @@ typedef enum { 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 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 - from that of its parent, the node will update the setting the same as its parent's. - Root Fixed setting of each node is variable as that setting changes of root. */ + 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 device will update the setting the same as its parent's. + 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_id_t; /** - * @brief node type + * @brief device type */ typedef enum { 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_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_type_t; @@ -221,7 +231,7 @@ typedef enum { typedef enum { MESH_REASON_CYCLIC = 100, /**< cyclic is detected */ 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_ROOTS, /**< root conflict is detected */ MESH_REASON_PARENT_STOPPED, /**< parent has stopped the mesh */ @@ -331,7 +341,7 @@ typedef struct { */ typedef struct { 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 */ } mesh_event_root_conflict_t; @@ -350,6 +360,13 @@ typedef struct { bool is_fixed; /**< status */ } 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 */ @@ -362,16 +379,17 @@ typedef union { mesh_event_disconnected_t disconnected; /**< parent disconnected */ mesh_event_no_parent_found_t no_parent; /**< no parent found */ 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 - external IP network. This state indicates right now if root is capable - of sending packets out. If not, nodes had better to wait until this state changes - to be MESH_TODS_REACHABLE. */ + 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 of sending + packets out. If not, devices had better to wait until this state changes to be + MESH_TODS_REACHABLE. */ mesh_event_vote_started_t vote_started; /**< vote started */ mesh_event_root_got_ip_t got_ip; /**< root obtains IP address */ mesh_event_root_address_t root_addr; /**< root address */ mesh_event_root_switch_req_t switch_req; /**< root switch request */ mesh_event_root_conflict_t root_conflict; /**< other powerful root */ mesh_event_root_fixed_t root_fixed; /**< root fixed */ + mesh_event_scan_done_t scan_done; /**< scan done */ } mesh_event_info_t; /** @@ -497,7 +515,7 @@ extern mesh_event_cb_t g_mesh_event_cb; * Check if WiFi is started. * 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 * - ESP_OK @@ -522,7 +540,7 @@ esp_err_t esp_mesh_deinit(void); * Create TX and RX queues according to the configuration * 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 * - ESP_OK @@ -552,7 +570,7 @@ esp_err_t esp_mesh_stop(void); /** * @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. * * @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. * @param flag * (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 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 * 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 @@ -581,7 +599,7 @@ esp_err_t esp_mesh_stop(void); * @param opt options * (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. - * (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. * @param opt_count option count * 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_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 @@ -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 * 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 - * 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). * - * @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 * @@ -707,7 +725,7 @@ esp_err_t esp_mesh_get_config(mesh_cfg_t *config); /** * @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 * @@ -731,7 +749,7 @@ esp_err_t esp_mesh_get_router(mesh_router_t *router); /** * @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 * @@ -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); /** - * @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 * - ESP_OK * - 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 * @@ -776,7 +794,7 @@ mesh_type_t esp_mesh_get_type(void); /** * @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 * @@ -785,7 +803,7 @@ mesh_type_t esp_mesh_get_type(void); * - ESP_ERR_MESH_ARGUMENT * - 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 @@ -797,7 +815,7 @@ int esp_mesh_get_max_layer(void); /** * @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 len password length @@ -807,12 +825,12 @@ int esp_mesh_get_max_layer(void); * - ESP_ERR_MESH_ARGUMENT * - 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 * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @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_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 @@ -834,7 +852,7 @@ wifi_auth_mode_t esp_mesh_get_ap_authmode(void); /** * @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 * @@ -842,7 +860,7 @@ wifi_auth_mode_t esp_mesh_get_ap_authmode(void); * - ESP_OK * - 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 @@ -855,7 +873,7 @@ int esp_mesh_get_ap_connections(void); /** * @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 * @@ -865,7 +883,7 @@ int esp_mesh_get_layer(void); /** * @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 * @@ -876,7 +894,7 @@ int esp_mesh_get_layer(void); 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 * @@ -885,16 +903,20 @@ bool esp_mesh_is_root(void); /** * @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(); * - * @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 * - ESP_OK * - 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 @@ -906,7 +928,7 @@ bool esp_mesh_get_self_organized(void); /** * @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. * * 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_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 * 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 * @@ -946,7 +968,7 @@ esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, const int reason); * - ESP_OK * - 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 @@ -966,7 +988,7 @@ float esp_mesh_get_vote_percentage(void); * - ESP_OK * - 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 @@ -976,27 +998,27 @@ esp_err_t esp_mesh_set_ap_assoc_expire(const int seconds); 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. ** - * @return total number of nodes(including root) + * @return total number of devices(including root) */ 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); /** - * @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 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 * - 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_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 @@ -1052,9 +1074,9 @@ int esp_mesh_available_txupQ_num(const mesh_addr_t *addr, uint32_t *xseqno_in); /** * @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 * - ESP_OK @@ -1079,7 +1101,7 @@ int esp_mesh_get_xon_qsize(void); * - ESP_WIFI_ERR_NOT_INIT * - 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 @@ -1098,7 +1120,7 @@ bool esp_mesh_is_root_conflicts_allowed(void); * - ESP_OK * - 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 @@ -1110,7 +1132,7 @@ esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, const int num); * - ESP_OK * - 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 @@ -1129,7 +1151,7 @@ int esp_mesh_get_group_num(void); * - ESP_OK * - 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 @@ -1141,7 +1163,7 @@ bool esp_mesh_is_my_group(const mesh_addr_t *addr); /** * @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 * @@ -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 * - * @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 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); /** - * @brief set Root Fixed setting for nodes - * If Root Fixed setting of nodes is enabled, they won't compete to be a root. - * If a scenario needs a fixed root, all nodes in this network shall enable this setting. + * @brief set Fixed Root setting for the device + * 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 devices in this network shall enable this setting. * * @param enable enable or not * * @return * - 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 - * Root Fixed setting can be changed by API esp_mesh_fix_root(). - * Root Fixed setting can also be changed by event MESH_EVENT_ROOT_FIXED. + * @brief check if Fixed Root setting is enabled + * Fixed Root setting can be changed by API esp_mesh_fix_root(). + * Fixed Root setting can also be changed by event MESH_EVENT_ROOT_FIXED. * * @return true/false */ @@ -1247,9 +1269,9 @@ bool esp_mesh_is_root_fixed(void); /** * @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_layer my mesh layer * @@ -1258,8 +1280,35 @@ bool esp_mesh_is_root_fixed(void); * - ESP_ERR_ARGUMENT * - 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 } diff --git a/components/esp32/include/esp_mesh_internal.h b/components/esp32/include/esp_mesh_internal.h index 19273ba06..da349297e 100644 --- a/components/esp32/include/esp_mesh_internal.h +++ b/components/esp32/include/esp_mesh_internal.h @@ -49,6 +49,46 @@ typedef struct { int backoff_rssi; /* RSSI threshold for connecting to the root */ } 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 *******************************************************/ diff --git a/components/esp32/lib b/components/esp32/lib index 963fb2baa..8b6d5837a 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 963fb2baa4bf6320a89674ef1ba1de6f15ddd06d +Subproject commit 8b6d5837a4215b83ff8a3ff088ccbb716adf05fb diff --git a/examples/mesh/manual_networking/Makefile b/examples/mesh/manual_networking/Makefile new file mode 100644 index 000000000..6a51b332d --- /dev/null +++ b/examples/mesh/manual_networking/Makefile @@ -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 + diff --git a/examples/mesh/manual_networking/main/Kconfig.projbuild b/examples/mesh/manual_networking/main/Kconfig.projbuild new file mode 100644 index 000000000..a3bad4bfd --- /dev/null +++ b/examples/mesh/manual_networking/main/Kconfig.projbuild @@ -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 + diff --git a/examples/mesh/manual_networking/main/component.mk b/examples/mesh/manual_networking/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/mesh/manual_networking/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/mesh/manual_networking/main/include/mesh_light.h b/examples/mesh/manual_networking/main/include/mesh_light.h new file mode 100644 index 000000000..ecf4e0678 --- /dev/null +++ b/examples/mesh/manual_networking/main/include/mesh_light.h @@ -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__ */ diff --git a/examples/mesh/manual_networking/main/mesh_light.c b/examples/mesh/manual_networking/main/mesh_light.c new file mode 100644 index 000000000..478050381 --- /dev/null +++ b/examples/mesh/manual_networking/main/mesh_light.c @@ -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 +#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; +} diff --git a/examples/mesh/manual_networking/main/mesh_main.c b/examples/mesh/manual_networking/main/mesh_main.c new file mode 100644 index 000000000..2703dd5b6 --- /dev/null +++ b/examples/mesh/manual_networking/main/mesh_main.c @@ -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 +#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, + "[%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, "%s, "MACSTR", channel:%u, rssi:%d", + parent_record.ssid, MAC2STR(parent_record.bssid), + parent_record.primary, parent_record.rssi); + } else { + ESP_LOGW(MESH_TAG, + "%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, "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_layer = esp_mesh_get_layer(); + break; + case MESH_EVENT_CHILD_CONNECTED: + ESP_LOGI(MESH_TAG, "aid:%d, "MACSTR"", + event.info.child_connected.aid, + MAC2STR(event.info.child_connected.mac)); + break; + case MESH_EVENT_CHILD_DISCONNECTED: + ESP_LOGI(MESH_TAG, "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, "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, "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, "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, + "layer:%d-->%d, parent:"MACSTR"%s, ID:"MACSTR"", + last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr), + esp_mesh_is_root() ? "" : + (mesh_layer == 2) ? "" : "", 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, + "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, "layer:%d-->%d%s", + last_layer, mesh_layer, + esp_mesh_is_root() ? "" : + (mesh_layer == 2) ? "" : ""); + last_layer = mesh_layer; + mesh_connected_indicator(mesh_layer); + break; + case MESH_EVENT_ROOT_ADDRESS: + ESP_LOGI(MESH_TAG, "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, + "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, ""); + break; + case MESH_EVENT_VOTE_STARTED: + ESP_LOGI(MESH_TAG, + "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, ""); + break; + case MESH_EVENT_ROOT_SWITCH_REQ: + ESP_LOGI(MESH_TAG, + "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, "layer:%d, parent:"MACSTR"", mesh_layer, MAC2STR(mesh_parent_addr.addr)); + break; + case MESH_EVENT_TODS_STATE: + ESP_LOGI(MESH_TAG, "state:%d", + event.info.toDS_state); + break; + case MESH_EVENT_ROOT_FIXED: + ESP_LOGI(MESH_TAG, "%s", + event.info.root_fixed.is_fixed ? "fixed" : "not fixed"); + break; + case MESH_EVENT_ROOT_ASKED_YIELD: + ESP_LOGI(MESH_TAG, + ""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, ""); + break; + case MESH_EVENT_SCAN_DONE: + ESP_LOGI(MESH_TAG, "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"); +}