ESP-MESH Programming Guide
This is a programming guide for ESP-MESH, including the API reference and coding examples. This guide is split into the following parts:
For documentation regarding the ESP-MESH protocol, please see the :doc:`ESP-MESH API Guide<../../api-guides/mesh>`.
ESP-MESH Programming Model
The ESP-MESH software stack is built atop the Wi-Fi Driver/FreeRTOS and may use the LwIP Stack in some instances (i.e. the root node). The following diagram illustrates the ESP-MESH software stack.
An application interfaces with ESP-MESH via ESP-MESH Events. Since ESP-MESH is built atop the Wi-Fi stack, it is also possible for the application to interface with the Wi-Fi driver via the Wi-Fi Event Task. The following diagram illustrates the interfaces for the various System Events in an ESP-MESH application.
The :cpp:type:`mesh_event_id_t` defines all possible ESP-MESH system events and can indicate events such as the connection/disconnection of parent/child. Before ESP-MESH system events can be used, the application must register a Mesh Event Callback via :cpp:func:`esp_mesh_set_config`. The callback is used to receive events from the ESP-MESH stack as well as the LwIP Stack and should contain handlers for each event relevant to the application.
Typical use cases of system events include using events such as :cpp:enumerator:`MESH_EVENT_PARENT_CONNECTED` and :cpp:enumerator:`MESH_EVENT_CHILD_CONNECTED` to indicate when a node can begin transmitting data upstream and downstream respectively. Likewise, :cpp:enumerator:`MESH_EVENT_ROOT_GOT_IP` and :cpp:enumerator:`MESH_EVENT_ROOT_LOST_IP` can be used to indicate when the root node can and cannot transmit data to the external IP network.
When using ESP-MESH under self-organized mode, users must ensure that no calls to Wi-Fi API are made. This is due to the fact that the self-organizing mode will internally make Wi-Fi API calls to connect/disconnect/scan etc. Any Wi-Fi calls from the application (including calls from callbacks and handlers of Wi-Fi events) may interfere with ESP-MESH's self-organizing behavior. Therefore, user's should not call Wi-Fi APIs after :cpp:func:`esp_mesh_start` is called, and before :cpp:func:`esp_mesh_stop` is called.
LwIP & ESP-MESH
The application can access the ESP-MESH stack directly without having to go through the LwIP stack. The LwIP stack is only required by the root node to transmit/receive data to/from an external IP network. However, since every node can potentially become the root node (due to automatic root node selection), each node must still initialize the LwIP stack.
Each node is required to initialize LwIP by calling :cpp:func:`tcpip_adapter_init`. In order to prevent non-root node access to LwIP, the application should stop the following services after LwIP initialization:
- DHCP server service on the softAP interface.
- DHCP client service on the station interface.
The following code snippet demonstrates how to initialize LwIP for ESP-MESH applications.
/* 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)); /* do not specify system event callback, use NULL instead. */ ESP_ERROR_CHECK(esp_event_loop_init(NULL, NULL));
ESP-MESH requires a root node to be connected with a router. Therefore, in the event that a node becomes the root, the corresponding handler must start the DHCP client service and immediately obtain an IP address. Doing so will allow other nodes to begin transmitting/receiving packets to/from the external IP network. However, this step is unnecessary if static IP settings are used.
Writing an ESP-MESH Application
The prerequisites for starting ESP-MESH is to initialize LwIP and Wi-Fi, The following code snippet demonstrates the necessary prerequisite steps before ESP-MESH itself can be initialized.
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)); /* do not specify system event callback, use NULL instead. */ ESP_ERROR_CHECK(esp_event_loop_init(NULL, NULL)); /* Wi-Fi initialization */ 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());
After initializing LwIP and Wi-Fi, the process of getting an ESP-MESH network up and running can be summarized into the following three steps:
The following code snippet demonstrates how to initialize ESP-MESH
/* mesh initialization */ ESP_ERROR_CHECK(esp_mesh_init());
Configuring an ESP-MESH Network
ESP-MESH is configured via :cpp:func:`esp_mesh_set_config` which receives its arguments using the :cpp:type:`mesh_cfg_t` structure. The structure contains the following parameters used to configure ESP-MESH:
|Channel||Range from 1 to 14|
|Event Callback||Callback for Mesh Events, see :cpp:type:`mesh_event_cb_t`|
|Mesh ID||ID of ESP-MESH Network, see :cpp:type:`mesh_addr_t`|
|Router||Router Configuration, see :cpp:type:`mesh_router_t`|
|Mesh AP||Mesh AP Configuration, see :cpp:type:`mesh_ap_cfg_t`|
|Crypto Functions||Crypto Functions for Mesh IE, see :cpp:type:`mesh_crypto_funcs_t`|
The following code snippet demonstrates how to configure ESP-MESH.
/* Enable the Mesh IE encryption by default */ 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; /* channel (must match the router's channel) */ cfg.channel = CONFIG_MESH_CHANNEL; /* router */ 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));
The following code snippet demonstrates how to start ESP-MESH.
/* mesh start */ ESP_ERROR_CHECK(esp_mesh_start());
After starting ESP-MESH, the application should check for ESP-MESH events to determine when it has connected to the network. After connecting, the application can start transmitting and receiving packets over the ESP-MESH network using :cpp:func:`esp_mesh_send` and :cpp:func:`esp_mesh_recv`.
ESP-IDF contains these ESP-MESH example projects:
:example:`The Internal Communication Example<mesh/internal_communication>` demonstrates how to setup a ESP-MESH network and have the root node send a data packet to every node within the network.
:example:`The Manual Networking Example<mesh/manual_networking>` demonstrates how to use ESP-MESH without the self-organizing features. This example shows how to program a node to manually scan for a list of potential parent nodes and select a parent node based on custom criteria.