1 // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 /*
16  *   Software Stack demonstrated:
17  *  |------------------------------------------------------------------------------|
18  *  |            |                                                                 |
19  *  |            |                          Application                            |
20  *  |            |-----------------------------------------------------------------|
21  *  |            |               | Protocols: |      |      |               |      |
22  *  |            |   Mesh Stack  | HTTP, DNS, |      |      |     Other     |      |
23  *  |   RTOS:    | (Networking,  | DHCP, ...  |      |      |   Components  |      |
24  *  | (freeRTOS) | self-healing, |------------|      |      |               |      |
25  *  |            | flow control, |  Network Stack:   |      |               |      |
26  *  |            | ...)          |      (LwIP)       |      |               |      |
27  *  |            |-----------------------------------|      |---------------|      |
28  *  |            |                                                  |              |
29  *  |            |                       Wi-Fi Driver               |              |
30  *  |            |--------------------------------------------------|              |
31  *  |            |                                                                 |
32  *  |            |                       Platform HAL                              |
33  *  |------------------------------------------------------------------------------|
34  *
35  *   System Events delivery:
36  *
37  *  |---------------|
38  *  |               |                    default handler
39  *  |  Wi-Fi stack  |     events     |---------------------|
40  *  |               | -------------> |                     |
41  *  |---------------|                |                     |
42  *                                   |      event task     |
43  *  |---------------|     events     |                     |
44  *  |               | -------------> |                     |
45  *  |  LwIP stack   |                |---------------------|
46  *  |               |--------|
47  *  |---------------|        |
48  *                           |         mesh event callback handler
49  *                           |       |----------------------------|
50  *                           |-----> |                            |
51  *  |---------------|                |        application         |
52  *  |               |     events     |            task            |
53  *  |  mesh stack   | -------------> |                            |
54  *  |               |                |----------------------------|
55  *  |---------------|
56  *
57  *
58  *  Mesh Stack
59  *
60  *  Mesh event defines almost all system events applications tasks need.
61  *  Mesh event contains Wi-Fi connection states on station interface, children connection states on softAP interface and etc..
62  *  Applications need to register a mesh event callback handler by API esp_mesh_set_config() firstly.
63  *  This handler is to receive events posted from mesh stack and LwIP stack.
64  *  Applications could add relative handler for each event.
65  *  Examples:
66  *  (1) Applications could use Wi-Fi station connect states to decide when to send data to its parent, to the root or to external IP network;
67  *  (2) Applications could use Wi-Fi softAP states to decide when to send data to its children.
68  *
69  *  In present implementation, applications are able to access mesh stack directly without having to go through LwIP stack.
70  *  Applications use esp_mesh_send() and esp_mesh_recv() to send and receive messages over the mesh network.
71  *  In mesh stack design, normal devices don't require LwIP stack. But since IDF hasn't supported system without initializing LwIP stack yet,
72  *  applications still need to do LwIP initialization and two more things are required to be done
73  *  (1) stop DHCP server on softAP interface by default
74  *  (2) stop DHCP client on station interface by default.
75  *  Examples:
76  *  tcpip_adapter_init();
77  *  tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP);
78  *  tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
79  *
80  *  Over the mesh network, only the root is able to access external IP network.
81  *  In application mesh event handler, once a device becomes a root, start DHCP client immediately whether DHCP is chosen.
82  */
83 
84 #ifndef __ESP_MESH_H__
85 #define __ESP_MESH_H__
86 
87 #include "esp_err.h"
88 #include "esp_wifi.h"
89 #include "esp_wifi_types.h"
90 #include "esp_mesh_internal.h"
91 #include "lwip/ip_addr.h"
92 
93 #ifdef __cplusplus
94 extern "C" {
95 #endif
96 
97 /*******************************************************
98  *                Constants
99  *******************************************************/
100 #define MESH_ROOT_LAYER                   (1)       /**< root layer value */
101 #define MESH_MTU                          (1500)    /**< max transmit unit(in bytes) */
102 #define MESH_MPS                          (1472)    /**< max payload size(in bytes) */
103 /**
104  * @brief Mesh error code definition
105  */
106 #define ESP_ERR_MESH_WIFI_NOT_START       (ESP_ERR_MESH_BASE + 1)    /**< Wi-Fi isn't started */
107 #define ESP_ERR_MESH_NOT_INIT             (ESP_ERR_MESH_BASE + 2)    /**< mesh isn't initialized */
108 #define ESP_ERR_MESH_NOT_CONFIG           (ESP_ERR_MESH_BASE + 3)    /**< mesh isn't configured */
109 #define ESP_ERR_MESH_NOT_START            (ESP_ERR_MESH_BASE + 4)    /**< mesh isn't started */
110 #define ESP_ERR_MESH_NOT_SUPPORT          (ESP_ERR_MESH_BASE + 5)    /**< not supported yet */
111 #define ESP_ERR_MESH_NOT_ALLOWED          (ESP_ERR_MESH_BASE + 6)    /**< operation is not allowed */
112 #define ESP_ERR_MESH_NO_MEMORY            (ESP_ERR_MESH_BASE + 7)    /**< out of memory */
113 #define ESP_ERR_MESH_ARGUMENT             (ESP_ERR_MESH_BASE + 8)    /**< illegal argument */
114 #define ESP_ERR_MESH_EXCEED_MTU           (ESP_ERR_MESH_BASE + 9)    /**< packet size exceeds MTU */
115 #define ESP_ERR_MESH_TIMEOUT              (ESP_ERR_MESH_BASE + 10)   /**< timeout */
116 #define ESP_ERR_MESH_DISCONNECTED         (ESP_ERR_MESH_BASE + 11)   /**< disconnected with parent on station interface */
117 #define ESP_ERR_MESH_QUEUE_FAIL           (ESP_ERR_MESH_BASE + 12)   /**< queue fail */
118 #define ESP_ERR_MESH_QUEUE_FULL           (ESP_ERR_MESH_BASE + 13)   /**< queue full */
119 #define ESP_ERR_MESH_NO_PARENT_FOUND      (ESP_ERR_MESH_BASE + 14)   /**< no parent found to join the mesh network */
120 #define ESP_ERR_MESH_NO_ROUTE_FOUND       (ESP_ERR_MESH_BASE + 15)   /**< no route found to forward the packet */
121 #define ESP_ERR_MESH_OPTION_NULL          (ESP_ERR_MESH_BASE + 16)   /**< no option found */
122 #define ESP_ERR_MESH_OPTION_UNKNOWN       (ESP_ERR_MESH_BASE + 17)   /**< unknown option */
123 #define ESP_ERR_MESH_XON_NO_WINDOW        (ESP_ERR_MESH_BASE + 18)   /**< no window for software flow control on upstream */
124 #define ESP_ERR_MESH_INTERFACE            (ESP_ERR_MESH_BASE + 19)   /**< low-level Wi-Fi interface error */
125 #define ESP_ERR_MESH_DISCARD_DUPLICATE    (ESP_ERR_MESH_BASE + 20)   /**< discard the packet due to the duplicate sequence number */
126 #define ESP_ERR_MESH_DISCARD              (ESP_ERR_MESH_BASE + 21)   /**< discard the packet */
127 #define ESP_ERR_MESH_VOTING               (ESP_ERR_MESH_BASE + 22)   /**< vote in progress */
128 #define ESP_ERR_MESH_XMIT                 (ESP_ERR_MESH_BASE + 23)   /**< XMIT */
129 #define ESP_ERR_MESH_QUEUE_READ           (ESP_ERR_MESH_BASE + 24)   /**< error in reading queue */
130 #define ESP_ERR_MESH_PS                   (ESP_ERR_MESH_BASE + 25)   /**< mesh PS is not specified as enable or disable */
131 #define ESP_ERR_MESH_RECV_RELEASE         (ESP_ERR_MESH_BASE + 26)   /**< release esp_mesh_recv_toDS */
132 
133 /**
134  * @brief Flags bitmap for esp_mesh_send() and esp_mesh_recv()
135  */
136 #define MESH_DATA_ENC           (0x01)  /**< data encrypted (Unimplemented) */
137 #define MESH_DATA_P2P           (0x02)  /**< point-to-point delivery over the mesh network */
138 #define MESH_DATA_FROMDS        (0x04)  /**< receive from external IP network */
139 #define MESH_DATA_TODS          (0x08)  /**< identify this packet is target to external IP network */
140 #define MESH_DATA_NONBLOCK      (0x10)  /**< esp_mesh_send() non-block */
141 #define MESH_DATA_DROP          (0x20)  /**< in the situation of the root having been changed, identify this packet can be dropped by new root */
142 #define MESH_DATA_GROUP         (0x40)  /**< identify this packet is target to a group address */
143 
144 /**
145  * @brief Option definitions for esp_mesh_send() and esp_mesh_recv()
146  */
147 #define MESH_OPT_SEND_GROUP     (7)     /**< data transmission by group; used with esp_mesh_send() and shall have payload */
148 #define MESH_OPT_RECV_DS_ADDR   (8)     /**< return a remote IP address; used with esp_mesh_send() and esp_mesh_recv() */
149 
150 /**
151  * @brief Flag of mesh networking IE
152  */
153 #define MESH_ASSOC_FLAG_VOTE_IN_PROGRESS    (0x02)     /**< vote in progress */
154 #define MESH_ASSOC_FLAG_NETWORK_FREE        (0x08)     /**< no root in current network */
155 #define MESH_ASSOC_FLAG_ROOTS_FOUND         (0x20)     /**< root conflict is found */
156 #define MESH_ASSOC_FLAG_ROOT_FIXED          (0x40)     /**< fixed root */
157 
158 
159 /**
160  * @brief Mesh PS (Power Save) duty cycle type
161  */
162 #define MESH_PS_DEVICE_DUTY_REQUEST         (0x01)    /**< requests to join a network PS without specifying a device duty cycle. After the
163                                                            device joins the network, a network duty cycle will be provided by the network */
164 #define MESH_PS_DEVICE_DUTY_DEMAND          (0x04)    /**< requests to join a network PS and specifies a demanded device duty cycle */
165 #define MESH_PS_NETWORK_DUTY_MASTER         (0x80)    /**< indicates the device is the NWK-DUTY-MASTER (network duty cycle master) */
166 
167 /**
168  * @brief Mesh PS (Power Save) duty cycle applied rule
169  */
170 #define MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE         (0)    /** the specified network duty is applied to the entire network <*/
171 #define MESH_PS_NETWORK_DUTY_APPLIED_UPLINK         (1)    /** the specified network duty is applied to only the up-link path <*/
172 
173 /*******************************************************
174  *                Enumerations
175  *******************************************************/
176 /**
177  * @brief Enumerated list of mesh event id
178  */
179 typedef enum {
180     MESH_EVENT_STARTED,                 /**< mesh is started */
181     MESH_EVENT_STOPPED,                 /**< mesh is stopped */
182     MESH_EVENT_CHANNEL_SWITCH,          /**< channel switch */
183     MESH_EVENT_CHILD_CONNECTED,         /**< a child is connected on softAP interface */
184     MESH_EVENT_CHILD_DISCONNECTED,      /**< a child is disconnected on softAP interface */
185     MESH_EVENT_ROUTING_TABLE_ADD,       /**< routing table is changed by adding newly joined children */
186     MESH_EVENT_ROUTING_TABLE_REMOVE,    /**< routing table is changed by removing leave children */
187     MESH_EVENT_PARENT_CONNECTED,        /**< parent is connected on station interface */
188     MESH_EVENT_PARENT_DISCONNECTED,     /**< parent is disconnected on station interface */
189     MESH_EVENT_NO_PARENT_FOUND,         /**< no parent found */
190     MESH_EVENT_LAYER_CHANGE,            /**< layer changes over the mesh network */
191     MESH_EVENT_TODS_STATE,              /**< state represents whether the root is able to access external IP network */
192     MESH_EVENT_VOTE_STARTED,            /**< the process of voting a new root is started either by children or by the root */
193     MESH_EVENT_VOTE_STOPPED,            /**< the process of voting a new root is stopped */
194     MESH_EVENT_ROOT_ADDRESS,            /**< the root address is obtained. It is posted by mesh stack automatically. */
195     MESH_EVENT_ROOT_SWITCH_REQ,         /**< root switch request sent from a new voted root candidate */
196     MESH_EVENT_ROOT_SWITCH_ACK,         /**< root switch acknowledgment responds the above request sent from current root */
197     MESH_EVENT_ROOT_ASKED_YIELD,        /**< the root is asked yield by a more powerful existing root. If self organized is disabled
198                                              and this device is specified to be a root by users, users should set a new parent
199                                              for this device. if self organized is enabled, this device will find a new parent
200                                              by itself, users could ignore this event. */
201     MESH_EVENT_ROOT_FIXED,              /**< when devices join a network, if the setting of Fixed Root for one device is different
202                                              from that of its parent, the device will update the setting the same as its parent's.
203                                              Fixed Root Setting of each device is variable as that setting changes of the root. */
204     MESH_EVENT_SCAN_DONE,               /**< if self-organized networking is disabled, user can call esp_wifi_scan_start() to trigger
205                                              this event, and add the corresponding scan done handler in this event. */
206     MESH_EVENT_NETWORK_STATE,           /**< network state, such as whether current mesh network has a root. */
207     MESH_EVENT_STOP_RECONNECTION,       /**< the root stops reconnecting to the router and non-root devices stop reconnecting to their parents. */
208     MESH_EVENT_FIND_NETWORK,            /**< when the channel field in mesh configuration is set to zero, mesh stack will perform a
209                                              full channel scan to find a mesh network that can join, and return the channel value
210                                              after finding it. */
211     MESH_EVENT_ROUTER_SWITCH,           /**< if users specify BSSID of the router in mesh configuration, when the root connects to another
212                                              router with the same SSID, this event will be posted and the new router information is attached. */
213     MESH_EVENT_PS_PARENT_DUTY,          /**< parent duty */
214     MESH_EVENT_PS_CHILD_DUTY,           /**< child duty */
215     MESH_EVENT_PS_DEVICE_DUTY,          /**< device duty */
216     MESH_EVENT_MAX,
217 } mesh_event_id_t;
218 
219 /** @brief ESP-MESH event base declaration */
220 ESP_EVENT_DECLARE_BASE(MESH_EVENT);
221 
222 /**
223  * @brief Device type
224  */
225 typedef enum {
226     MESH_IDLE,    /**< hasn't joined the mesh network yet */
227     MESH_ROOT,    /**< the only sink of the mesh network. Has the ability to access external IP network */
228     MESH_NODE,    /**< intermediate device. Has the ability to forward packets over the mesh network */
229     MESH_LEAF,    /**< has no forwarding ability */
230     MESH_STA,     /**< connect to router with a standlone Wi-Fi station mode, no network expansion capability */
231 } mesh_type_t;
232 
233 /**
234  * @brief Protocol of transmitted application data
235  */
236 typedef enum {
237     MESH_PROTO_BIN,     /**< binary */
238     MESH_PROTO_HTTP,    /**< HTTP protocol */
239     MESH_PROTO_JSON,    /**< JSON format */
240     MESH_PROTO_MQTT,    /**< MQTT protocol */
241     MESH_PROTO_AP,      /**< IP network mesh communication of node's AP interface */
242     MESH_PROTO_STA,     /**< IP network mesh communication of node's STA interface */
243 } mesh_proto_t;
244 
245 /**
246  * @brief For reliable transmission, mesh stack provides three type of services
247  */
248 typedef enum {
249     MESH_TOS_P2P,    /**< provide P2P (point-to-point) retransmission on mesh stack by default */
250     MESH_TOS_E2E,    /**< provide E2E (end-to-end) retransmission on mesh stack (Unimplemented) */
251     MESH_TOS_DEF,    /**< no retransmission on mesh stack */
252 } mesh_tos_t;
253 
254 /**
255  * @brief Vote reason
256  */
257 typedef enum {
258     MESH_VOTE_REASON_ROOT_INITIATED = 1,    /**< vote is initiated by the root */
259     MESH_VOTE_REASON_CHILD_INITIATED,       /**< vote is initiated by children */
260 } mesh_vote_reason_t;
261 
262 /**
263  * @brief Mesh disconnect reason code
264  */
265 typedef enum {
266     MESH_REASON_CYCLIC = 100,               /**< cyclic is detected */
267     MESH_REASON_PARENT_IDLE,                /**< parent is idle */
268     MESH_REASON_LEAF,                       /**< the connected device is changed to a leaf */
269     MESH_REASON_DIFF_ID,                    /**< in different mesh ID */
270     MESH_REASON_ROOTS,                      /**< root conflict is detected */
271     MESH_REASON_PARENT_STOPPED,             /**< parent has stopped the mesh */
272     MESH_REASON_SCAN_FAIL,                  /**< scan fail */
273     MESH_REASON_IE_UNKNOWN,                 /**< unknown IE */
274     MESH_REASON_WAIVE_ROOT,                 /**< waive root */
275     MESH_REASON_PARENT_WORSE,               /**< parent with very poor RSSI */
276     MESH_REASON_EMPTY_PASSWORD,             /**< use an empty password to connect to an encrypted parent */
277     MESH_REASON_PARENT_UNENCRYPTED,         /**< connect to an unencrypted parent/router */
278 } mesh_disconnect_reason_t;
279 
280 /**
281  * @brief Mesh topology
282  */
283 typedef enum {
284     MESH_TOPO_TREE,                         /**< tree topology */
285     MESH_TOPO_CHAIN,                        /**< chain topology */
286 } esp_mesh_topology_t;
287 
288 /*******************************************************
289  *                Structures
290  *******************************************************/
291 /**
292  * @brief IP address and port
293  */
294 typedef struct {
295     ip4_addr_t ip4;    /**< IP address */
296     uint16_t port;     /**< port */
297 } __attribute__((packed)) mip_t;
298 
299 /**
300  * @brief Mesh address
301  */
302 typedef union {
303     uint8_t addr[6];    /**< mac address */
304     mip_t mip;          /**< mip address */
305 } mesh_addr_t;
306 
307 /**
308  * @brief Channel switch information
309  */
310 typedef struct {
311     uint8_t channel;    /**< new channel */
312 } mesh_event_channel_switch_t;
313 
314 /**
315  * @brief Parent connected information
316  */
317 typedef struct {
318     wifi_event_sta_connected_t connected; /**< parent information, same as Wi-Fi event SYSTEM_EVENT_STA_CONNECTED does */
319     uint16_t self_layer;                  /**< layer */
320     uint8_t duty;                         /**< parent duty */
321 } mesh_event_connected_t;
322 
323 /**
324  * @brief No parent found information
325  */
326 typedef struct {
327     int scan_times;    /**< scan times being through */
328 } mesh_event_no_parent_found_t;
329 
330 /**
331  * @brief Layer change information
332  */
333 typedef struct {
334     uint16_t new_layer; /**< new layer */
335 } mesh_event_layer_change_t;
336 
337 /**
338  * @brief The reachability of the root to a DS (distribute system)
339  */
340 typedef enum {
341     MESH_TODS_UNREACHABLE,    /**< the root isn't able to access external IP network */
342     MESH_TODS_REACHABLE,      /**< the root is able to access external IP network */
343 } mesh_event_toDS_state_t;
344 
345 /**
346  * @brief vote started information
347  */
348 typedef struct {
349     int reason;             /**< vote reason, vote could be initiated by children or by the root itself */
350     int attempts;           /**< max vote attempts before stopped */
351     mesh_addr_t rc_addr;    /**< root address specified by users via API esp_mesh_waive_root() */
352 } mesh_event_vote_started_t;
353 
354 /**
355  * @brief find a mesh network that this device can join
356  */
357 typedef struct {
358     uint8_t channel;            /**< channel number of the new found network */
359     uint8_t router_bssid[6];    /**< router BSSID */
360 } mesh_event_find_network_t;
361 
362 /**
363  * @brief Root address
364  */
365 typedef mesh_addr_t mesh_event_root_address_t;
366 
367 /**
368  * @brief Parent disconnected information
369  */
370 typedef wifi_event_sta_disconnected_t mesh_event_disconnected_t;
371 
372 /**
373  * @brief Child connected information
374  */
375 typedef wifi_event_ap_staconnected_t mesh_event_child_connected_t;
376 
377 /**
378  * @brief Child disconnected information
379  */
380 typedef wifi_event_ap_stadisconnected_t mesh_event_child_disconnected_t;
381 
382 /**
383  * @brief Root switch request information
384  */
385 typedef struct {
386     int reason;             /**< root switch reason, generally root switch is initialized by users via API esp_mesh_waive_root() */
387     mesh_addr_t rc_addr;    /**< the address of root switch requester */
388 } mesh_event_root_switch_req_t;
389 
390 /**
391  * @brief Other powerful root address
392  */
393 typedef struct {
394     int8_t rssi;           /**< rssi with router */
395     uint16_t capacity;     /**< the number of devices in current network */
396     uint8_t addr[6];       /**< other powerful root address */
397 } mesh_event_root_conflict_t;
398 
399 /**
400  * @brief Routing table change
401  */
402 typedef struct {
403     uint16_t rt_size_new;      /**< the new value */
404     uint16_t rt_size_change;   /**< the changed value */
405 } mesh_event_routing_table_change_t;
406 
407 /**
408  * @brief Root fixed
409  */
410 typedef struct {
411     bool is_fixed;     /**< status */
412 } mesh_event_root_fixed_t;
413 
414 /**
415  * @brief Scan done event information
416  */
417 typedef struct {
418     uint8_t  number;     /**< the number of APs scanned */
419 } mesh_event_scan_done_t;
420 
421 /**
422  * @brief Network state information
423  */
424 typedef struct {
425     bool is_rootless;     /**< whether current mesh network has a root */
426 } mesh_event_network_state_t;
427 
428 /**
429  * @brief New router information
430  */
431 typedef wifi_event_sta_connected_t mesh_event_router_switch_t;
432 
433 /**
434  * @brief PS duty information
435  */
436 typedef struct {
437     uint8_t duty;                                 /**< parent or child duty */
438     mesh_event_child_connected_t child_connected; /**< child info */
439 } mesh_event_ps_duty_t;
440 
441 /**
442  * @brief Mesh event information
443  */
444 typedef union {
445     mesh_event_channel_switch_t channel_switch;            /**< channel switch */
446     mesh_event_child_connected_t child_connected;          /**< child connected */
447     mesh_event_child_disconnected_t child_disconnected;    /**< child disconnected */
448     mesh_event_routing_table_change_t routing_table;       /**< routing table change */
449     mesh_event_connected_t connected;                      /**< parent connected */
450     mesh_event_disconnected_t disconnected;                /**< parent disconnected */
451     mesh_event_no_parent_found_t no_parent;                /**< no parent found */
452     mesh_event_layer_change_t layer_change;                /**< layer change */
453     mesh_event_toDS_state_t toDS_state;                    /**< toDS state, devices shall check this state firstly before trying to send packets to
454                                                                 external IP network. This state indicates right now whether the root is capable of sending
455                                                                 packets out. If not, devices had better to wait until this state changes to be
456                                                                 MESH_TODS_REACHABLE. */
457     mesh_event_vote_started_t vote_started;                /**< vote started */
458     mesh_event_root_address_t root_addr;                   /**< root address */
459     mesh_event_root_switch_req_t switch_req;               /**< root switch request */
460     mesh_event_root_conflict_t root_conflict;              /**< other powerful root */
461     mesh_event_root_fixed_t root_fixed;                    /**< fixed root */
462     mesh_event_scan_done_t scan_done;                      /**< scan done */
463     mesh_event_network_state_t network_state;              /**< network state, such as whether current mesh network has a root. */
464     mesh_event_find_network_t find_network;                /**< network found that can join */
465     mesh_event_router_switch_t router_switch;              /**< new router information */
466     mesh_event_ps_duty_t ps_duty;                          /**< PS duty information */
467 } mesh_event_info_t;
468 
469 /**
470  * @brief Mesh option
471  */
472 typedef struct {
473     uint8_t type;    /**< option type */
474     uint16_t len;    /**< option length */
475     uint8_t *val;    /**< option value */
476 } __attribute__((packed)) mesh_opt_t;
477 
478 /**
479  * @brief Mesh data for esp_mesh_send() and esp_mesh_recv()
480  */
481 typedef struct {
482     uint8_t *data;         /**< data */
483     uint16_t size;         /**< data size */
484     mesh_proto_t proto;    /**< data protocol */
485     mesh_tos_t tos;        /**< data type of service */
486 } mesh_data_t;
487 
488 /**
489  * @brief Router configuration
490  */
491 typedef struct {
492     uint8_t ssid[32];             /**< SSID */
493     uint8_t ssid_len;             /**< length of SSID */
494     uint8_t bssid[6];             /**< BSSID, if this value is specified, users should also specify "allow_router_switch". */
495     uint8_t password[64];         /**< password */
496     bool allow_router_switch;     /**< if the BSSID is specified and this value is also set, when the router of this specified BSSID
497                                        fails to be found after "fail" (mesh_attempts_t) times, the whole network is allowed to switch
498                                        to another router with the same SSID. The new router might also be on a different channel.
499                                        The default value is false.
500                                        There is a risk that if the password is different between the new switched router and the previous
501                                        one, the mesh network could be established but the root will never connect to the new switched router. */
502 } mesh_router_t;
503 
504 /**
505  * @brief Mesh softAP configuration
506  */
507 typedef struct {
508     uint8_t password[64];              /**< mesh softAP password */
509     /**
510      * max number of stations allowed to connect in, default 6, max 10
511      * = max_connection + nonmesh_max_connection
512      */
513     uint8_t max_connection;            /**< max mesh connections */
514     uint8_t nonmesh_max_connection;    /**< max non-mesh connections */
515 } mesh_ap_cfg_t;
516 
517 /**
518  * @brief Mesh initialization configuration
519  */
520 typedef struct {
521     uint8_t channel;                            /**< channel, the mesh network on */
522     bool allow_channel_switch;                  /**< if this value is set, when "fail" (mesh_attempts_t) times is reached, device will change to
523                                                      a full channel scan for a network that could join. The default value is false. */
524     mesh_addr_t mesh_id;                        /**< mesh network identification */
525     mesh_router_t router;                       /**< router configuration */
526     mesh_ap_cfg_t mesh_ap;                      /**< mesh softAP configuration */
527     const mesh_crypto_funcs_t *crypto_funcs;    /**< crypto functions */
528 } mesh_cfg_t;
529 
530 /**
531  * @brief Vote address configuration
532  */
533 typedef union {
534     int attempts;           /**< max vote attempts before a new root is elected automatically by mesh network. (min:15, 15 by default) */
535     mesh_addr_t rc_addr;    /**< a new root address specified by users for API esp_mesh_waive_root() */
536 } mesh_rc_config_t;
537 
538 /**
539  * @brief Vote
540  */
541 typedef struct {
542     float percentage;           /**< vote percentage threshold for approval of being a root */
543     bool is_rc_specified;       /**< if true, rc_addr shall be specified (Unimplemented).
544                                      if false, attempts value shall be specified to make network start root election. */
545     mesh_rc_config_t config;    /**< vote address configuration */
546 } mesh_vote_t;
547 
548 /**
549  * @brief The number of packets pending in the queue waiting to be sent by the mesh stack
550  */
551 typedef struct {
552     int to_parent;        /**< to parent queue */
553     int to_parent_p2p;    /**< to parent (P2P) queue */
554     int to_child;         /**< to child queue */
555     int to_child_p2p;     /**< to child (P2P) queue */
556     int mgmt;             /**< management queue */
557     int broadcast;        /**< broadcast and multicast queue */
558 } mesh_tx_pending_t;
559 
560 /**
561  * @brief The number of packets available in the queue waiting to be received by applications
562  */
563 typedef struct {
564     int toDS;      /**< to external DS */
565     int toSelf;    /**< to self */
566 } mesh_rx_pending_t;
567 
568 /*******************************************************
569  *                Variable Declaration
570  *******************************************************/
571 /* mesh IE crypto callback function */
572 extern const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs;
573 
574 #define MESH_INIT_CONFIG_DEFAULT() { \
575     .crypto_funcs = &g_wifi_default_mesh_crypto_funcs, \
576 }
577 
578 /*******************************************************
579  *                Function Definitions
580  *******************************************************/
581 /**
582  * @brief      Mesh initialization
583  *             - Check whether Wi-Fi is started.
584  *             - Initialize mesh global variables with default values.
585  *
586  * @attention  This API shall be called after Wi-Fi is started.
587  *
588  * @return
589  *    - ESP_OK
590  *    - ESP_FAIL
591  */
592 esp_err_t esp_mesh_init(void);
593 
594 /**
595  * @brief      Mesh de-initialization
596  *
597  *             - Release resources and stop the mesh
598  *
599  * @return
600  *    - ESP_OK
601  *    - ESP_FAIL
602  */
603 esp_err_t esp_mesh_deinit(void);
604 
605 /**
606  * @brief      Start mesh
607  *             - Initialize mesh IE.
608  *             - Start mesh network management service.
609  *             - Create TX and RX queues according to the configuration.
610  *             - Register mesh packets receive callback.
611  *
612  * @attention  This API shall be called after mesh initialization and configuration.
613  *
614  * @return
615  *    - ESP_OK
616  *    - ESP_FAIL
617  *    - ESP_ERR_MESH_NOT_INIT
618  *    - ESP_ERR_MESH_NOT_CONFIG
619  *    - ESP_ERR_MESH_NO_MEMORY
620  */
621 esp_err_t esp_mesh_start(void);
622 
623 /**
624  * @brief      Stop mesh
625  *             - Deinitialize mesh IE.
626  *             - Disconnect with current parent.
627  *             - Disassociate all currently associated children.
628  *             - Stop mesh network management service.
629  *             - Unregister mesh packets receive callback.
630  *             - Delete TX and RX queues.
631  *             - Release resources.
632  *             - Restore Wi-Fi softAP to default settings if Wi-Fi dual mode is enabled.
633  *             - Set Wi-Fi Power Save type to WIFI_PS_NONE.
634  *
635  * @return
636  *    - ESP_OK
637  *    - ESP_FAIL
638  */
639 esp_err_t esp_mesh_stop(void);
640 
641 /**
642  * @brief      Send a packet over the mesh network
643  *             - Send a packet to any device in the mesh network.
644  *             - Send a packet to external IP network.
645  *
646  * @attention  This API is not reentrant.
647  *
648  * @param[in]  to  the address of the final destination of the packet
649  *             - If the packet is to the root, set this parameter to NULL.
650  *             - If the packet is to an external IP network, set this parameter to the IPv4:PORT combination.
651  *               This packet will be delivered to the root firstly, then the root will forward this packet to the final IP server address.
652  * @param[in]  data  pointer to a sending mesh packet
653  *             - Field size should not exceed MESH_MPS. Note that the size of one mesh packet should not exceed MESH_MTU.
654  *             - Field proto should be set to data protocol in use (default is MESH_PROTO_BIN for binary).
655  *             - Field tos should be set to transmission tos (type of service) in use (default is MESH_TOS_P2P for point-to-point reliable).
656  * @param[in]  flag  bitmap for data sent
657  *             -  Speed up the route search
658  *               - If the packet is to the root and "to" parameter is NULL, set this parameter to 0.
659  *               - If the packet is to an internal device, MESH_DATA_P2P should be set.
660  *               - If the packet is to the root ("to" parameter isn't NULL) or to external IP network, MESH_DATA_TODS should be set.
661  *               - If the packet is from the root to an internal device, MESH_DATA_FROMDS should be set.
662  *             - Specify whether this API is block or non-block, block by default
663  *               - If needs non-blocking, MESH_DATA_NONBLOCK should be set. Otherwise, may use esp_mesh_send_block_time() to specify a blocking time.
664  *             - In the situation of the root change, MESH_DATA_DROP identifies this packet can be dropped by the new root
665  *               for upstream data to external IP network, we try our best to avoid data loss caused by the root change, but
666  *               there is a risk that the new root is running out of memory because most of memory is occupied by the pending data which
667  *               isn't read out in time by esp_mesh_recv_toDS().
668  *
669  *               Generally, we suggest esp_mesh_recv_toDS() is called after a connection with IP network is created. Thus data outgoing
670  *               to external IP network via socket is just from reading esp_mesh_recv_toDS() which avoids unnecessary memory copy.
671  *
672  * @param[in]  opt  options
673  *             - In case of sending a packet to a certain group, MESH_OPT_SEND_GROUP is a good choice.
674  *               In this option, the value field should be set to the target receiver addresses in this group.
675  *             - Root sends a packet to an internal device, this packet is from external IP network in case the receiver device responds
676  *             this packet, MESH_OPT_RECV_DS_ADDR is required to attach the target DS address.
677  * @param[in]  opt_count  option count
678  *             - Currently, this API only takes one option, so opt_count is only supported to be 1.
679  *
680  * @return
681  *    - ESP_OK
682  *    - ESP_FAIL
683  *    - ESP_ERR_MESH_ARGUMENT
684  *    - ESP_ERR_MESH_NOT_START
685  *    - ESP_ERR_MESH_DISCONNECTED
686  *    - ESP_ERR_MESH_OPT_UNKNOWN
687  *    - ESP_ERR_MESH_EXCEED_MTU
688  *    - ESP_ERR_MESH_NO_MEMORY
689  *    - ESP_ERR_MESH_TIMEOUT
690  *    - ESP_ERR_MESH_QUEUE_FULL
691  *    - ESP_ERR_MESH_NO_ROUTE_FOUND
692  *    - ESP_ERR_MESH_DISCARD
693  */
694 esp_err_t esp_mesh_send(const mesh_addr_t *to, const mesh_data_t *data,
695                         int flag, const mesh_opt_t opt[],  int opt_count);
696 /**
697  * @brief      Set blocking time of esp_mesh_send()
698  *
699  * @attention  This API shall be called before mesh is started.
700  *
701  * @param[in]  time_ms  blocking time of esp_mesh_send(), unit:ms
702  *
703  * @return
704  *    - ESP_OK
705  */
706 esp_err_t esp_mesh_send_block_time(uint32_t time_ms);
707 
708 /**
709  * @brief      Receive a packet targeted to self over the mesh network
710  *
711  * @attention  Mesh RX queue should be checked regularly to avoid running out of memory.
712  *             - Use esp_mesh_get_rx_pending() to check the number of packets available in the queue waiting
713  *             to be received by applications.
714  *
715  * @param[out] from  the address of the original source of the packet
716  * @param[out] data  pointer to the received mesh packet
717  *             - Field proto is the data protocol in use. Should follow it to parse the received data.
718  *             - Field tos is the transmission tos (type of service) in use.
719  * @param[in]  timeout_ms  wait time if a packet isn't immediately available (0:no wait, portMAX_DELAY:wait forever)
720  * @param[out] flag  bitmap for data received
721  *             - MESH_DATA_FROMDS represents data from external IP network
722  *             - MESH_DATA_TODS represents data directed upward within the mesh network
723  *
724  *             flag could be MESH_DATA_FROMDS or MESH_DATA_TODS.
725  * @param[out] opt  options desired to receive
726  *             - MESH_OPT_RECV_DS_ADDR attaches the DS address
727  * @param[in]  opt_count  option count desired to receive
728  *             - Currently, this API only takes one option, so opt_count is only supported to be 1.
729  *
730  * @return
731  *    - ESP_OK
732  *    - ESP_ERR_MESH_ARGUMENT
733  *    - ESP_ERR_MESH_NOT_START
734  *    - ESP_ERR_MESH_TIMEOUT
735  *    - ESP_ERR_MESH_DISCARD
736  */
737 esp_err_t esp_mesh_recv(mesh_addr_t *from, mesh_data_t *data, int timeout_ms,
738                         int *flag, mesh_opt_t opt[], int opt_count);
739 
740 /**
741  * @brief      Receive a packet targeted to external IP network
742  *             - Root uses this API to receive packets destined to external IP network
743  *             - Root forwards the received packets to the final destination via socket.
744  *             - If no socket connection is ready to send out the received packets and this esp_mesh_recv_toDS()
745  *             hasn't been called by applications, packets from the whole mesh network will be pending in toDS queue.
746  *
747  *             Use esp_mesh_get_rx_pending() to check the number of packets available in the queue waiting
748  *             to be received by applications in case of running out of memory in the root.
749  *
750  *             Using esp_mesh_set_xon_qsize() users may configure the RX queue size, default:32. If this size is too large,
751  *             and esp_mesh_recv_toDS() isn't called in time, there is a risk that a great deal of memory is occupied
752  *             by the pending packets. If this size is too small, it will impact the efficiency on upstream. How to
753  *             decide this value depends on the specific application scenarios.
754  *
755  * @attention  This API is only called by the root.
756  *
757  * @param[out] from  the address of the original source of the packet
758  * @param[out] to  the address contains remote IP address and port (IPv4:PORT)
759  * @param[out] data  pointer to the received packet
760  *             - Contain the protocol and applications should follow it to parse the data.
761  * @param[in]  timeout_ms  wait time if a packet isn't immediately available (0:no wait, portMAX_DELAY:wait forever)
762  * @param[out] flag  bitmap for data received
763  *             - MESH_DATA_TODS represents the received data target to external IP network. Root shall forward this data to external IP network via the association with router.
764  *
765  *             flag could be MESH_DATA_TODS.
766  * @param[out] opt  options desired to receive
767  * @param[in]  opt_count  option count desired to receive
768  *
769  * @return
770  *    - ESP_OK
771  *    - ESP_ERR_MESH_ARGUMENT
772  *    - ESP_ERR_MESH_NOT_START
773  *    - ESP_ERR_MESH_TIMEOUT
774  *    - ESP_ERR_MESH_DISCARD
775  *    - ESP_ERR_MESH_RECV_RELEASE
776  */
777 esp_err_t esp_mesh_recv_toDS(mesh_addr_t *from, mesh_addr_t *to,
778                              mesh_data_t *data, int timeout_ms, int *flag, mesh_opt_t opt[],
779                              int opt_count);
780 
781 /**
782  * @brief      Set mesh stack configuration
783  *             - Use MESH_INIT_CONFIG_DEFAULT() to initialize the default values, mesh IE is encrypted by default.
784  *             - Mesh network is established on a fixed channel (1-14).
785  *             - Mesh event callback is mandatory.
786  *             - Mesh ID is an identifier of an MBSS. Nodes with the same mesh ID can communicate with each other.
787  *             - Regarding to the router configuration, if the router is hidden, BSSID field is mandatory.
788  *
789  *             If BSSID field isn't set and there exists more than one router with same SSID, there is a risk that more
790  *             roots than one connected with different BSSID will appear. It means more than one mesh network is established
791  *             with the same mesh ID.
792  *
793  *             Root conflict function could eliminate redundant roots connected with the same BSSID, but couldn't handle roots
794  *             connected with different BSSID. Because users might have such requirements of setting up routers with same SSID
795  *             for the future replacement. But in that case, if the above situations happen, please make sure applications
796  *             implement forward functions on the root to guarantee devices in different mesh networks can communicate with each other.
797  *             max_connection of mesh softAP is limited by the max number of Wi-Fi softAP supported (max:10).
798  *
799  * @attention  This API shall be called before mesh is started after mesh is initialized.
800  *
801  * @param[in]  config  pointer to mesh stack configuration
802  *
803  * @return
804  *    - ESP_OK
805  *    - ESP_ERR_MESH_ARGUMENT
806  *    - ESP_ERR_MESH_NOT_ALLOWED
807  */
808 esp_err_t esp_mesh_set_config(const mesh_cfg_t *config);
809 
810 /**
811  * @brief      Get mesh stack configuration
812  *
813  * @param[out] config  pointer to mesh stack configuration
814  *
815  * @return
816  *    - ESP_OK
817  *    - ESP_ERR_MESH_ARGUMENT
818  */
819 esp_err_t esp_mesh_get_config(mesh_cfg_t *config);
820 
821 /**
822  * @brief      Get router configuration
823  *
824  * @attention  This API is used to dynamically modify the router configuration after mesh is configured.
825  *
826  * @param[in]  router  pointer to router configuration
827  *
828  * @return
829  *    - ESP_OK
830  *    - ESP_ERR_MESH_ARGUMENT
831  */
832 esp_err_t esp_mesh_set_router(const mesh_router_t *router);
833 
834 /**
835  * @brief      Get router configuration
836  *
837  * @param[out] router  pointer to router configuration
838  *
839  * @return
840  *    - ESP_OK
841  *    - ESP_ERR_MESH_ARGUMENT
842  */
843 esp_err_t esp_mesh_get_router(mesh_router_t *router);
844 
845 /**
846  * @brief      Set mesh network ID
847  *
848  * @attention  This API is used to dynamically modify the mesh network ID.
849  *
850  * @param[in]  id  pointer to mesh network ID
851  *
852  * @return
853  *    - ESP_OK
854  *    - ESP_ERR_MESH_ARGUMENT: invalid argument
855  */
856 esp_err_t esp_mesh_set_id(const mesh_addr_t *id);
857 
858 /**
859  * @brief      Get mesh network ID
860  *
861  * @param[out] id  pointer to mesh network ID
862  *
863  * @return
864  *    - ESP_OK
865  *    - ESP_ERR_MESH_ARGUMENT
866  */
867 esp_err_t esp_mesh_get_id(mesh_addr_t *id);
868 
869 /**
870  * @brief      Designate device type over the mesh network
871  *            - MESH_IDLE: designates a device as a self-organized node for a mesh network
872  *            - MESH_ROOT: designates the root node for a mesh network
873  *            - MESH_LEAF: designates a device as a standalone Wi-Fi station that connects to a parent
874  *            - MESH_STA: designates a device as a standalone Wi-Fi station that connects to a router
875  *
876  * @param[in]  type  device type
877  *
878  * @return
879  *    - ESP_OK
880  *    - ESP_ERR_MESH_NOT_ALLOWED
881  */
882 esp_err_t esp_mesh_set_type(mesh_type_t type);
883 
884 /**
885  * @brief      Get device type over mesh network
886  *
887  * @attention  This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
888  *
889  * @return     mesh type
890  *
891  */
892 mesh_type_t esp_mesh_get_type(void);
893 
894 /**
895  * @brief      Set network max layer value
896  *             - for tree topology, the max is 25.
897  *             - for chain topology, the max is 1000.
898  *             - Network max layer limits the max hop count.
899  *
900  * @attention  This API shall be called before mesh is started.
901  *
902  * @param[in]  max_layer  max layer value
903  *
904  * @return
905  *    - ESP_OK
906  *    - ESP_ERR_MESH_ARGUMENT
907  *    - ESP_ERR_MESH_NOT_ALLOWED
908  */
909 esp_err_t esp_mesh_set_max_layer(int max_layer);
910 
911 /**
912  * @brief      Get max layer value
913  *
914  * @return     max layer value
915  */
916 int esp_mesh_get_max_layer(void);
917 
918 /**
919  * @brief      Set mesh softAP password
920  *
921  * @attention  This API shall be called before mesh is started.
922  *
923  * @param[in]  pwd  pointer to the password
924  * @param[in]  len  password length
925  *
926  * @return
927  *    - ESP_OK
928  *    - ESP_ERR_MESH_ARGUMENT
929  *    - ESP_ERR_MESH_NOT_ALLOWED
930  */
931 esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, int len);
932 
933 /**
934  * @brief      Set mesh softAP authentication mode
935  *
936  * @attention  This API shall be called before mesh is started.
937  *
938  * @param[in]  authmode  authentication mode
939  *
940  * @return
941  *    - ESP_OK
942  *    - ESP_ERR_MESH_ARGUMENT
943  *    - ESP_ERR_MESH_NOT_ALLOWED
944  */
945 esp_err_t esp_mesh_set_ap_authmode(wifi_auth_mode_t authmode);
946 
947 /**
948  * @brief      Get mesh softAP authentication mode
949  *
950  * @return     authentication mode
951  */
952 wifi_auth_mode_t esp_mesh_get_ap_authmode(void);
953 
954 /**
955  * @brief      Set mesh max connection value
956  *             - Set mesh softAP max connection = mesh max connection + non-mesh max connection
957  *
958  * @attention  This API shall be called before mesh is started.
959  *
960  * @param[in]  connections  the number of max connections
961  *
962  * @return
963  *    - ESP_OK
964  *    - ESP_ERR_MESH_ARGUMENT
965  */
966 esp_err_t esp_mesh_set_ap_connections(int connections);
967 
968 /**
969  * @brief      Get mesh max connection configuration
970  *
971  * @return     the number of mesh max connections
972  */
973 int esp_mesh_get_ap_connections(void);
974 
975 /**
976  * @brief      Get non-mesh max connection configuration
977  *
978  * @return     the number of non-mesh max connections
979  */
980 int esp_mesh_get_non_mesh_connections(void);
981 
982 /**
983  * @brief      Get current layer value over the mesh network
984  *
985  * @attention  This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
986  *
987  * @return     layer value
988  *
989  */
990 int esp_mesh_get_layer(void);
991 
992 /**
993  * @brief      Get the parent BSSID
994  *
995  * @attention  This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
996  *
997  * @param[out] bssid  pointer to parent BSSID
998  *
999  * @return
1000  *    - ESP_OK
1001  *    - ESP_FAIL
1002  */
1003 esp_err_t esp_mesh_get_parent_bssid(mesh_addr_t *bssid);
1004 
1005 /**
1006  * @brief      Return whether the device is the root node of the network
1007  *
1008  * @return     true/false
1009  */
1010 bool esp_mesh_is_root(void);
1011 
1012 /**
1013  * @brief      Enable/disable self-organized networking
1014  *             - Self-organized networking has three main functions:
1015  *             select the root node;
1016  *             find a preferred parent;
1017  *             initiate reconnection if a disconnection is detected.
1018  *             - Self-organized networking is enabled by default.
1019  *             - If self-organized is disabled, users should set a parent for the device via esp_mesh_set_parent().
1020  *
1021  * @attention  This API is used to dynamically modify whether to enable the self organizing.
1022  *
1023  * @param[in]  enable  enable or disable self-organized networking
1024  * @param[in]  select_parent  Only valid when self-organized networking is enabled.
1025  *             - if select_parent is set to true, the root will give up its mesh root status and search for a new parent
1026  *             like other non-root devices.
1027  *
1028  * @return
1029  *    - ESP_OK
1030  *    - ESP_FAIL
1031  */
1032 esp_err_t esp_mesh_set_self_organized(bool enable, bool select_parent);
1033 
1034 /**
1035  * @brief      Return whether enable self-organized networking or not
1036  *
1037  * @return     true/false
1038  */
1039 bool esp_mesh_get_self_organized(void);
1040 
1041 /**
1042  * @brief      Cause the root device to give up (waive) its mesh root status
1043  *             - A device is elected root primarily based on RSSI from the external router.
1044  *             - If external router conditions change, users can call this API to perform a root switch.
1045  *             - In this API, users could specify a desired root address to replace itself or specify an attempts value
1046  *             to ask current root to initiate a new round of voting. During the voting, a better root candidate would
1047  *             be expected to find to replace the current one.
1048  *             - If no desired root candidate, the vote will try a specified number of attempts (at least 15). If no better
1049  *             root candidate is found, keep the current one. If a better candidate is found, the new better one will
1050  *             send a root switch request to the current root, current root will respond with a root switch acknowledgment.
1051  *             - After that, the new candidate will connect to the router to be a new root, the previous root will disconnect
1052  *             with the router and choose another parent instead.
1053  *
1054  *             Root switch is completed with minimal disruption to the whole mesh network.
1055  *
1056  * @attention  This API is only called by the root.
1057  *
1058  * @param[in]  vote  vote configuration
1059  *             - If this parameter is set NULL, the vote will perform the default 15 times.
1060  *
1061  *             - Field percentage threshold is 0.9 by default.
1062  *             - Field is_rc_specified shall be false.
1063  *             - Field attempts shall be at least 15 times.
1064  * @param[in]  reason  only accept MESH_VOTE_REASON_ROOT_INITIATED for now
1065  *
1066  * @return
1067  *    - ESP_OK
1068  *    - ESP_ERR_MESH_QUEUE_FULL
1069  *    - ESP_ERR_MESH_DISCARD
1070  *    - ESP_FAIL
1071  */
1072 esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, int reason);
1073 
1074 /**
1075  * @brief      Set vote percentage threshold for approval of being a root (default:0.9)
1076  *             - During the networking, only obtaining vote percentage reaches this threshold,
1077  *             the device could be a root.
1078  *
1079  * @attention  This API shall be called before mesh is started.
1080  *
1081  * @param[in]  percentage  vote percentage threshold
1082  *
1083  * @return
1084  *    - ESP_OK
1085  *    - ESP_FAIL
1086  */
1087 esp_err_t esp_mesh_set_vote_percentage(float percentage);
1088 
1089 /**
1090  * @brief      Get vote percentage threshold for approval of being a root
1091  *
1092  * @return     percentage threshold
1093  */
1094 float esp_mesh_get_vote_percentage(void);
1095 
1096 /**
1097  * @brief      Set mesh softAP associate expired time (default:10 seconds)
1098  *             - If mesh softAP hasn't received any data from an associated child within this time,
1099  *             mesh softAP will take this child inactive and disassociate it.
1100  *             - If mesh softAP is encrypted, this value should be set a greater value, such as 30 seconds.
1101  *
1102  * @param[in]  seconds  the expired time
1103  *
1104  * @return
1105  *    - ESP_OK
1106  *    - ESP_FAIL
1107  */
1108 esp_err_t esp_mesh_set_ap_assoc_expire(int seconds);
1109 
1110 /**
1111  * @brief      Get mesh softAP associate expired time
1112  *
1113  * @return     seconds
1114  */
1115 int esp_mesh_get_ap_assoc_expire(void);
1116 
1117 /**
1118  * @brief      Get total number of devices in current network (including the root)
1119  *
1120  * @attention  The returned value might be incorrect when the network is changing.
1121  **
1122  * @return     total number of devices (including the root)
1123  */
1124 int esp_mesh_get_total_node_num(void);
1125 
1126 /**
1127  * @brief      Get the number of devices in this device's sub-network (including self)
1128  *
1129  * @return     the number of devices over this device's sub-network (including self)
1130  */
1131 int esp_mesh_get_routing_table_size(void);
1132 
1133 /**
1134  * @brief      Get routing table of this device's sub-network (including itself)
1135  *
1136  * @param[out] mac  pointer to routing table
1137  * @param[in]  len  routing table size(in bytes)
1138  * @param[out] size  pointer to the number of devices in routing table (including itself)
1139  *
1140  * @return
1141  *    - ESP_OK
1142  *    - ESP_ERR_MESH_ARGUMENT
1143  */
1144 esp_err_t esp_mesh_get_routing_table(mesh_addr_t *mac, int len, int *size);
1145 
1146 /**
1147  * @brief      Post the toDS state to the mesh stack
1148  *
1149  * @attention  This API is only for the root.
1150  *
1151  * @param[in]  reachable  this state represents whether the root is able to access external IP network
1152  *
1153  * @return
1154  *    - ESP_OK
1155  *    - ESP_FAIL
1156  */
1157 esp_err_t esp_mesh_post_toDS_state(bool reachable);
1158 
1159 /**
1160  * @brief      Return the number of packets pending in the queue waiting to be sent by the mesh stack
1161  *
1162  * @param[out] pending  pointer to the TX pending
1163  *
1164  * @return
1165  *    - ESP_OK
1166  *    - ESP_FAIL
1167  */
1168 esp_err_t esp_mesh_get_tx_pending(mesh_tx_pending_t *pending);
1169 
1170 /**
1171  * @brief      Return the number of packets available in the queue waiting to be received by applications
1172  *
1173  * @param[out] pending  pointer to the RX pending
1174  *
1175  * @return
1176  *    - ESP_OK
1177  *    - ESP_FAIL
1178  */
1179 esp_err_t esp_mesh_get_rx_pending(mesh_rx_pending_t *pending);
1180 
1181 /**
1182  * @brief      Return the number of packets could be accepted from the specified address
1183  *
1184  * @param[in]  addr  self address or an associate children address
1185  * @param[out] xseqno_in  sequence number of the last received packet from the specified address
1186  *
1187  * @return    the number of upQ for a certain address
1188  */
1189 int esp_mesh_available_txupQ_num(const mesh_addr_t *addr, uint32_t *xseqno_in);
1190 
1191 /**
1192  * @brief      Set the number of queue
1193  *
1194  * @attention  This API shall be called before mesh is started.
1195  *
1196  * @param[in]  qsize  default:32 (min:16)
1197  *
1198  * @return
1199  *    - ESP_OK
1200  *    - ESP_FAIL
1201  */
1202 esp_err_t esp_mesh_set_xon_qsize(int qsize);
1203 
1204 /**
1205  * @brief      Get queue size
1206  *
1207  * @return     the number of queue
1208  */
1209 int esp_mesh_get_xon_qsize(void);
1210 
1211 /**
1212  * @brief      Set whether allow more than one root existing in one network
1213  *
1214  * @param[in]  allowed  allow or not
1215  *
1216  * @return
1217  *    - ESP_OK
1218  *    - ESP_WIFI_ERR_NOT_INIT
1219  *    - ESP_WIFI_ERR_NOT_START
1220  */
1221 esp_err_t esp_mesh_allow_root_conflicts(bool allowed);
1222 
1223 /**
1224  * @brief      Check whether allow more than one root to exist in one network
1225  *
1226  * @return     true/false
1227  */
1228 bool esp_mesh_is_root_conflicts_allowed(void);
1229 
1230 /**
1231  * @brief      Set group ID addresses
1232  *
1233  * @param[in]  addr  pointer to new group ID addresses
1234  * @param[in]  num  the number of group ID addresses
1235  *
1236  * @return
1237  *    - ESP_OK
1238  *    - ESP_MESH_ERR_ARGUMENT
1239  */
1240 esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, int num);
1241 
1242 /**
1243  * @brief      Delete group ID addresses
1244  *
1245  * @param[in]  addr  pointer to deleted group ID address
1246  * @param[in]  num  the number of group ID addresses
1247  *
1248  * @return
1249  *    - ESP_OK
1250  *    - ESP_MESH_ERR_ARGUMENT
1251  */
1252 esp_err_t esp_mesh_delete_group_id(const mesh_addr_t *addr, int num);
1253 
1254 /**
1255  * @brief      Get the number of group ID addresses
1256  *
1257  * @return     the number of group ID addresses
1258  */
1259 int esp_mesh_get_group_num(void);
1260 
1261 /**
1262  * @brief      Get group ID addresses
1263  *
1264  * @param[out] addr  pointer to group ID addresses
1265  * @param[in]  num  the number of group ID addresses
1266  *
1267  * @return
1268  *    - ESP_OK
1269  *    - ESP_MESH_ERR_ARGUMENT
1270  */
1271 esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, int num);
1272 
1273 /**
1274  * @brief      Check whether the specified group address is my group
1275  *
1276  * @return     true/false
1277  */
1278 bool esp_mesh_is_my_group(const mesh_addr_t *addr);
1279 
1280 /**
1281  * @brief      Set mesh network capacity (max:1000, default:300)
1282  *
1283  * @attention  This API shall be called before mesh is started.
1284  *
1285  * @param[in]  num  mesh network capacity
1286  *
1287  * @return
1288  *    - ESP_OK
1289  *    - ESP_ERR_MESH_NOT_ALLOWED
1290  *    - ESP_MESH_ERR_ARGUMENT
1291  */
1292 esp_err_t esp_mesh_set_capacity_num(int num);
1293 
1294 /**
1295  * @brief      Get mesh network capacity
1296  *
1297  * @return     mesh network capacity
1298  */
1299 int esp_mesh_get_capacity_num(void);
1300 
1301 /**
1302  * @brief      Set mesh IE crypto functions
1303  *
1304  * @attention  This API can be called at any time after mesh is initialized.
1305  *
1306  * @param[in]  crypto_funcs  crypto functions for mesh IE
1307  *           - If crypto_funcs is set to NULL, mesh IE is no longer encrypted.
1308  * @return
1309  *    - ESP_OK
1310  */
1311 esp_err_t esp_mesh_set_ie_crypto_funcs(const mesh_crypto_funcs_t *crypto_funcs);
1312 
1313 /**
1314  * @brief      Set mesh IE crypto key
1315  *
1316  * @attention  This API can be called at any time after mesh is initialized.
1317  *
1318  * @param[in]  key  ASCII crypto key
1319  * @param[in]  len  length in bytes, range:8~64
1320  *
1321  * @return
1322  *    - ESP_OK
1323  *    - ESP_MESH_ERR_ARGUMENT
1324  */
1325 esp_err_t esp_mesh_set_ie_crypto_key(const char *key, int len);
1326 
1327 /**
1328  * @brief      Get mesh IE crypto key
1329  *
1330  * @param[out] key  ASCII crypto key
1331  * @param[in]  len  length in bytes, range:8~64
1332  *
1333  * @return
1334  *    - ESP_OK
1335  *    - ESP_MESH_ERR_ARGUMENT
1336  */
1337 esp_err_t esp_mesh_get_ie_crypto_key(char *key, int len);
1338 
1339 /**
1340  * @brief      Set delay time before starting root healing
1341  *
1342  * @param[in]  delay_ms  delay time in milliseconds
1343  *
1344  * @return
1345  *    - ESP_OK
1346  */
1347 esp_err_t esp_mesh_set_root_healing_delay(int delay_ms);
1348 
1349 /**
1350  * @brief      Get delay time before network starts root healing
1351  *
1352  * @return     delay time in milliseconds
1353  */
1354 int esp_mesh_get_root_healing_delay(void);
1355 
1356 /**
1357  * @brief      Enable network Fixed Root Setting
1358  *             - Enabling fixed root disables automatic election of the root node via voting.
1359  *             - All devices in the network shall use the same Fixed Root Setting (enabled or disabled).
1360  *             - If Fixed Root is enabled, users should make sure a root node is designated for the network.
1361  *
1362  * @param[in]  enable  enable or not
1363  *
1364  * @return
1365  *    - ESP_OK
1366  */
1367 esp_err_t esp_mesh_fix_root(bool enable);
1368 
1369 /**
1370  * @brief      Check whether network Fixed Root Setting is enabled
1371  *             - Enable/disable network Fixed Root Setting by API esp_mesh_fix_root().
1372  *             - Network Fixed Root Setting also changes with the "flag" value in parent networking IE.
1373  *
1374  * @return     true/false
1375  */
1376 bool esp_mesh_is_root_fixed(void);
1377 
1378 /**
1379  * @brief      Set a specified parent for the device
1380  *
1381  * @attention  This API can be called at any time after mesh is configured.
1382  *
1383  * @param[in]  parent  parent configuration, the SSID and the channel of the parent are mandatory.
1384  *             - If the BSSID is set, make sure that the SSID and BSSID represent the same parent,
1385  *             otherwise the device will never find this specified parent.
1386  * @param[in]  parent_mesh_id  parent mesh ID,
1387  *             - If this value is not set, the original mesh ID is used.
1388  * @param[in]  my_type  mesh type
1389  *             - MESH_STA is not supported.
1390  *             - If the parent set for the device is the same as the router in the network configuration,
1391  *            then my_type shall set MESH_ROOT and my_layer shall set MESH_ROOT_LAYER.
1392  * @param[in]  my_layer  mesh layer
1393  *             - my_layer of the device may change after joining the network.
1394  *             - If my_type is set MESH_NODE, my_layer shall be greater than MESH_ROOT_LAYER.
1395  *             - If my_type is set MESH_LEAF, the device becomes a standalone Wi-Fi station and no longer
1396  *             has the ability to extend the network.
1397  *
1398  * @return
1399  *    - ESP_OK
1400  *    - ESP_ERR_ARGUMENT
1401  *    - ESP_ERR_MESH_NOT_CONFIG
1402  */
1403 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);
1404 
1405 /**
1406  * @brief      Get mesh networking IE length of one AP
1407  *
1408  * @param[out] len  mesh networking IE length
1409  *
1410  * @return
1411  *    - ESP_OK
1412  *    - ESP_ERR_WIFI_NOT_INIT
1413  *    - ESP_ERR_WIFI_ARG
1414  *    - ESP_ERR_WIFI_FAIL
1415  */
1416 esp_err_t esp_mesh_scan_get_ap_ie_len(int *len);
1417 
1418 /**
1419  * @brief      Get AP record
1420  *
1421  * @attention  Different from esp_wifi_scan_get_ap_records(), this API only gets one of APs scanned each time.
1422  *             See "manual_networking" example.
1423  *
1424  * @param[out] ap_record  pointer to one AP record
1425  * @param[out] buffer  pointer to the mesh networking IE of this AP
1426  *
1427  * @return
1428  *    - ESP_OK
1429  *    - ESP_ERR_WIFI_NOT_INIT
1430  *    - ESP_ERR_WIFI_ARG
1431  *    - ESP_ERR_WIFI_FAIL
1432  */
1433 esp_err_t esp_mesh_scan_get_ap_record(wifi_ap_record_t *ap_record, void *buffer);
1434 
1435 /**
1436  * @brief      Flush upstream packets pending in to_parent queue and to_parent_p2p queue
1437  *
1438  * @return
1439  *    - ESP_OK
1440  */
1441 esp_err_t esp_mesh_flush_upstream_packets(void);
1442 
1443 /**
1444  * @brief      Get the number of nodes in the subnet of a specific child
1445  *
1446  * @param[in]  child_mac  an associated child address of this device
1447  * @param[out] nodes_num  pointer to the number of nodes in the subnet of a specific child
1448  *
1449  * @return
1450  *    - ESP_OK
1451  *    - ESP_ERR_MESH_NOT_START
1452  *    - ESP_ERR_MESH_ARGUMENT
1453  */
1454 esp_err_t esp_mesh_get_subnet_nodes_num(const mesh_addr_t *child_mac, int *nodes_num);
1455 
1456 /**
1457  * @brief      Get nodes in the subnet of a specific child
1458  *
1459  * @param[in]  child_mac  an associated child address of this device
1460  * @param[out] nodes  pointer to nodes in the subnet of a specific child
1461  * @param[in]  nodes_num  the number of nodes in the subnet of a specific child
1462  *
1463  * @return
1464  *    - ESP_OK
1465  *    - ESP_ERR_MESH_NOT_START
1466  *    - ESP_ERR_MESH_ARGUMENT
1467  */
1468 esp_err_t esp_mesh_get_subnet_nodes_list(const mesh_addr_t *child_mac, mesh_addr_t *nodes, int nodes_num);
1469 
1470 /**
1471  * @brief      Disconnect from current parent
1472  *
1473  * @return
1474  *    - ESP_OK
1475  */
1476 esp_err_t esp_mesh_disconnect(void);
1477 
1478 /**
1479  * @brief      Connect to current parent
1480  *
1481  * @return
1482  *    - ESP_OK
1483  */
1484 esp_err_t esp_mesh_connect(void);
1485 
1486 /**
1487  * @brief      Flush scan result
1488  *
1489  * @return
1490  *    - ESP_OK
1491  */
1492 esp_err_t esp_mesh_flush_scan_result(void);
1493 
1494 /**
1495  * @brief      Cause the root device to add Channel Switch Announcement Element (CSA IE) to beacon
1496  *             - Set the new channel
1497  *             - Set how many beacons with CSA IE will be sent before changing a new channel
1498  *             - Enable the channel switch function
1499  *
1500  * @attention  This API is only called by the root.
1501  *
1502  * @param[in]  new_bssid  the new router BSSID if the router changes
1503  * @param[in]  csa_newchan  the new channel number to which the whole network is moving
1504  * @param[in]  csa_count  channel switch period(beacon count), unit is based on beacon interval of its softAP, the default value is 15.
1505  *
1506  * @return
1507  *    - ESP_OK
1508  */
1509 esp_err_t esp_mesh_switch_channel(const uint8_t *new_bssid, int csa_newchan, int csa_count);
1510 
1511 /**
1512  * @brief      Get the router BSSID
1513  *
1514  * @param[out] router_bssid  pointer to the router BSSID
1515  *
1516  * @return
1517  *    - ESP_OK
1518  *    - ESP_ERR_WIFI_NOT_INIT
1519  *    - ESP_ERR_WIFI_ARG
1520  */
1521 esp_err_t esp_mesh_get_router_bssid(uint8_t *router_bssid);
1522 
1523 /**
1524  * @brief      Get the TSF time
1525  *
1526  * @return     the TSF time
1527  */
1528 int64_t esp_mesh_get_tsf_time(void);
1529 
1530 /**
1531  * @brief      Set mesh topology. The default value is MESH_TOPO_TREE
1532  *             - MESH_TOPO_CHAIN supports up to 1000 layers
1533  *
1534  * @attention  This API shall be called before mesh is started.
1535  *
1536  * @param[in]  topo  MESH_TOPO_TREE or MESH_TOPO_CHAIN
1537  *
1538  * @return
1539  *    - ESP_OK
1540  *    - ESP_MESH_ERR_ARGUMENT
1541  *    - ESP_ERR_MESH_NOT_ALLOWED
1542  */
1543 esp_err_t esp_mesh_set_topology(esp_mesh_topology_t topo);
1544 
1545 /**
1546  * @brief      Get mesh topology
1547  *
1548  * @return     MESH_TOPO_TREE or MESH_TOPO_CHAIN
1549  */
1550 esp_mesh_topology_t esp_mesh_get_topology(void);
1551 
1552 /**
1553  * @brief      Enable mesh Power Save function
1554  *
1555  * @attention  This API shall be called before mesh is started.
1556  *
1557  * @return
1558  *    - ESP_OK
1559  *    - ESP_ERR_WIFI_NOT_INIT
1560  *    - ESP_ERR_MESH_NOT_ALLOWED
1561  */
1562 esp_err_t esp_mesh_enable_ps(void);
1563 
1564 /**
1565  * @brief      Disable mesh Power Save function
1566  *
1567  * @attention  This API shall be called before mesh is started.
1568  *
1569  * @return
1570  *    - ESP_OK
1571  *    - ESP_ERR_WIFI_NOT_INIT
1572  *    - ESP_ERR_MESH_NOT_ALLOWED
1573  */
1574 esp_err_t esp_mesh_disable_ps(void);
1575 
1576 /**
1577  * @brief      Check whether the mesh Power Save function is enabled
1578  *
1579  * @return     true/false
1580  */
1581 bool esp_mesh_is_ps_enabled(void);
1582 
1583 /**
1584  * @brief      Check whether the device is in active state
1585  *             - If the device is not in active state, it will neither transmit nor receive frames.
1586  *
1587  * @return     true/false
1588  */
1589 bool esp_mesh_is_device_active(void);
1590 
1591 /**
1592  * @brief      Set the device duty cycle and type
1593  *             - The range of dev_duty values is 1 to 100. The default value is 10.
1594  *             - dev_duty = 100, the PS will be stopped.
1595  *             - dev_duty is better to not less than 5.
1596  *             - dev_duty_type could be MESH_PS_DEVICE_DUTY_REQUEST or MESH_PS_DEVICE_DUTY_DEMAND.
1597  *             - If dev_duty_type is set to MESH_PS_DEVICE_DUTY_REQUEST, the device will use a nwk_duty provided by the network.
1598  *             - If dev_duty_type is set to MESH_PS_DEVICE_DUTY_DEMAND, the device will use the specified dev_duty.
1599  *
1600  * @attention  This API can be called at any time after mesh is started.
1601  *
1602  * @param[in]  dev_duty  device duty cycle
1603  * @param[in]  dev_duty_type  device PS duty cycle type, not accept MESH_PS_NETWORK_DUTY_MASTER
1604  *
1605  * @return
1606  *    - ESP_OK
1607  *    - ESP_FAIL
1608  */
1609 esp_err_t esp_mesh_set_active_duty_cycle(int dev_duty, int dev_duty_type);
1610 
1611 /**
1612  * @brief      Get device duty cycle and type
1613  *
1614  * @param[out] dev_duty  device duty cycle
1615  * @param[out] dev_duty_type  device PS duty cycle type
1616  *
1617  * @return
1618  *    - ESP_OK
1619  */
1620 esp_err_t esp_mesh_get_active_duty_cycle(int* dev_duty, int* dev_duty_type);
1621 
1622 /**
1623  * @brief      Set the network duty cycle, duration and rule
1624  *             - The range of nwk_duty values is 1 to 100. The default value is 10.
1625  *             - nwk_duty is the network duty cycle the entire network or the up-link path will use. A device that successfully
1626  *             sets the nwk_duty is known as a NWK-DUTY-MASTER.
1627  *             - duration_mins specifies how long the specified nwk_duty will be used. Once duration_mins expires, the root will take
1628  *             over as the NWK-DUTY-MASTER. If an existing NWK-DUTY-MASTER leaves the network, the root will take over as the
1629  *             NWK-DUTY-MASTER again.
1630  *             - duration_mins = (-1) represents nwk_duty will be used until a new NWK-DUTY-MASTER with a different nwk_duty appears.
1631  *             - Only the root can set duration_mins to (-1).
1632  *             - If applied_rule is set to MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE, the nwk_duty will be used by the entire network.
1633  *             - If applied_rule is set to MESH_PS_NETWORK_DUTY_APPLIED_UPLINK, the nwk_duty will only be used by the up-link path nodes.
1634  *             - The root does not accept MESH_PS_NETWORK_DUTY_APPLIED_UPLINK.
1635  *             - A nwk_duty with duration_mins(-1) set by the root is the default network duty cycle used by the entire network.
1636  *
1637  * @attention  This API can be called at any time after mesh is started.
1638  *             - In self-organized network, if this API is called before mesh is started in all devices, (1)nwk_duty shall be set to the
1639  *             same value for all devices; (2)duration_mins shall be set to (-1); (3)applied_rule shall be set to
1640  *             MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE; after the voted root appears, the root will become the NWK-DUTY-MASTER and broadcast
1641  *             the nwk_duty and its identity of NWK-DUTY-MASTER.
1642  *             - If the root is specified (FIXED-ROOT), call this API in the root to provide a default nwk_duty for the entire network.
1643  *             - After joins the network, any device can call this API to change the nwk_duty, duration_mins or applied_rule.
1644  *
1645  * @param[in]  nwk_duty  network duty cycle
1646  * @param[in]  duration_mins  duration (unit: minutes)
1647  * @param[in]  applied_rule  only support MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE
1648  *
1649  * @return
1650  *    - ESP_OK
1651  *    - ESP_FAIL
1652  */
1653 esp_err_t esp_mesh_set_network_duty_cycle(int nwk_duty, int duration_mins, int applied_rule);
1654 
1655 /**
1656  * @brief      Get the network duty cycle, duration, type and rule
1657  *
1658  * @param[out] nwk_duty  current network duty cycle
1659  * @param[out] duration_mins  the duration of current nwk_duty
1660  * @param[out] dev_duty_type  if it includes MESH_PS_DEVICE_DUTY_MASTER, this device is the current NWK-DUTY-MASTER.
1661  * @param[out] applied_rule  MESH_PS_NETWORK_DUTY_APPLIED_ENTIRE
1662  *
1663  * @return
1664  *    - ESP_OK
1665  */
1666 esp_err_t esp_mesh_get_network_duty_cycle(int* nwk_duty, int* duration_mins, int* dev_duty_type, int* applied_rule);
1667 
1668 /**
1669  * @brief      Get the running active duty cycle
1670  *          - The running active duty cycle of the root is 100.
1671  *          - If duty type is set to MESH_PS_DEVICE_DUTY_REQUEST, the running active duty cycle is nwk_duty provided by the network.
1672  *          - If duty type is set to MESH_PS_DEVICE_DUTY_DEMAND, the running active duty cycle is dev_duty specified by the users.
1673  *          - In a mesh network, devices are typically working with a certain duty-cycle (transmitting, receiving and sleep) to
1674  *            reduce the power consumption. The running active duty cycle decides the amount of awake time within a beacon interval.
1675  *            At each start of beacon interval, all devices wake up, broadcast beacons, and transmit packets if they do have pending
1676  *            packets for their parents or for their children. Note that Low-duty-cycle means devices may not be active in most of
1677  *            the time, the latency of data transmission might be greater.
1678  *
1679  * @return     the running active duty cycle
1680  */
1681 int esp_mesh_get_running_active_duty_cycle(void);
1682 
1683 /**
1684  * @brief      Duty signaling
1685  *
1686  * @param[in]  fwd_times  the times of forwarding duty signaling packets
1687  *
1688  * @return
1689  *    - ESP_OK
1690  */
1691 esp_err_t esp_mesh_ps_duty_signaling(int fwd_times);
1692 #ifdef __cplusplus
1693 }
1694 #endif
1695 #endif /* __ESP_MESH_H__ */
1696