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.
*
* 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.
* 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__
#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
*******************************************************/
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;
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 */
*/
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;
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
*/
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;
/**
* 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
* 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
/**
* @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.
* 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
* @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.
* - 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
* 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
*
/**
* @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
*
/**
* @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
*
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
*
/**
* @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
*
* - 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
/**
* @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
* - 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
*
* - 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
/**
* @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
*
* - 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
/**
* @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
*
/**
* @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
*
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
*
/**
* @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
/**
* @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
* - 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
*
* - 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
* - 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
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
* - 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
/**
* @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
* - 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
* - 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
* - 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
* - 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
/**
* @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
*
/**
* @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
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
*/
/**
* @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
*
* - 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
}
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
*******************************************************/
-Subproject commit 963fb2baa4bf6320a89674ef1ba1de6f15ddd06d
+Subproject commit 8b6d5837a4215b83ff8a3ff088ccbb716adf05fb
--- /dev/null
+#
+# 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
+
--- /dev/null
+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
+
--- /dev/null
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
--- /dev/null
+/* 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__ */
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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");
+}