### Create Project from Mesh-Lite Example Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/README.md Use the `create-project-from-example` command to generate a new project based on the `mesh_local_control` example. This downloads the example for building and flashing. ```bash idf.py create-project-from-example "espressif/mesh_lite=*:mesh_local_control" ``` -------------------------------- ### Initialize and Start ESP-Mesh-Lite Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Initializes and starts the ESP-Mesh-Lite subsystem. Must be called after network interfaces are created and Wi-Fi is configured. Registers an event handler to log when the node connects to the mesh. ```c #include "nvs_flash.h" #include "esp_netif.h" #include "esp_event.h" #include "esp_bridge.h" #include "esp_mesh_lite.h" void app_main(void) { // 1. Persistent storage ESP_ERROR_CHECK(nvs_flash_init()); // 2. Network interface + event loop ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); // 3. Create all bridge network interfaces (STA + SoftAP) esp_bridge_create_all_netif(); // 4. Configure STA and SoftAP credentials via esp_bridge wifi_config_t sta_cfg = { .sta = { .ssid = "MyRouter", .password = "routerpass" } }; esp_bridge_wifi_set_config(WIFI_IF_STA, &sta_cfg); wifi_config_t ap_cfg = { .ap = { .ssid = "MeshNode", .password = "meshpass" } }; esp_bridge_wifi_set_config(WIFI_IF_AP, &ap_cfg); // 5. Build Mesh-Lite config (macro fills defaults from Kconfig) esp_mesh_lite_config_t mesh_cfg = ESP_MESH_LITE_DEFAULT_INIT(); // Optionally override fields: // mesh_cfg.max_level = 5; // mesh_cfg.mesh_id = 77; // 6. Initialize and start esp_mesh_lite_init(&mesh_cfg); // 7. Optionally set SoftAP SSID/password (can be loaded from NVS) esp_mesh_lite_set_softap_info("MeshNode_aabbcc", "meshpass"); esp_mesh_lite_start(); // begins scanning for parent nodes // 8. Register IP event to know when the node is connected ESP_ERROR_CHECK(esp_event_handler_instance_register( IP_EVENT, IP_EVENT_STA_GOT_IP, [](void*, esp_event_base_t, int32_t, void*) { ESP_LOGI("app", "Node connected, level=%d", esp_mesh_lite_get_level()); }, NULL, NULL)); } ``` -------------------------------- ### Initialization and Startup Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Initializes and starts the ESP-Mesh-Lite subsystem. This involves setting up network interfaces, configuring Wi-Fi credentials, and building the mesh configuration. ```APIDOC ## esp_mesh_lite_init / esp_mesh_lite_core_init / esp_mesh_lite_start ### Description Initializes and starts the ESP-Mesh-Lite subsystem. `esp_mesh_lite_init` wraps `esp_mesh_lite_core_init` and sets up the Mesh-Lite subsystem from a configuration struct. `esp_mesh_lite_start` triggers the first scan and connection attempt. Both must be called after `esp_bridge_create_all_netif` and Wi-Fi configuration. ### Usage Example ```c #include "nvs_flash.h" #include "esp_netif.h" #include "esp_event.h" #include "esp_bridge.h" #include "esp_mesh_lite.h" void app_main(void) { // 1. Persistent storage ESP_ERROR_CHECK(nvs_flash_init()); // 2. Network interface + event loop ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); // 3. Create all bridge network interfaces (STA + SoftAP) esp_bridge_create_all_netif(); // 4. Configure STA and SoftAP credentials via esp_bridge wifi_config_t sta_cfg = { .sta = { .ssid = "MyRouter", .password = "routerpass" } }; esp_bridge_wifi_set_config(WIFI_IF_STA, &sta_cfg); wifi_config_t ap_cfg = { .ap = { .ssid = "MeshNode", .password = "meshpass" } }; esp_bridge_wifi_set_config(WIFI_IF_AP, &ap_cfg); // 5. Build Mesh-Lite config (macro fills defaults from Kconfig) esp_mesh_lite_config_t mesh_cfg = ESP_MESH_LITE_DEFAULT_INIT(); // Optionally override fields: // mesh_cfg.max_level = 5; // mesh_cfg.mesh_id = 77; // 6. Initialize and start esp_mesh_lite_init(&mesh_cfg); // 7. Optionally set SoftAP SSID/password (can be loaded from NVS) esp_mesh_lite_set_softap_info("MeshNode_aabbcc", "meshpass"); esp_mesh_lite_start(); // begins scanning for parent nodes // 8. Register IP event to know when the node is connected ESP_ERROR_CHECK(esp_event_handler_instance_register( IP_EVENT, IP_EVENT_STA_GOT_IP, [](void*, esp_event_base_t, int32_t, void*) { ESP_LOGI("app", "Node connected, level=%d", esp_mesh_lite_get_level()); }, NULL, NULL)); } ``` ``` -------------------------------- ### ESP-IDF Project Setup Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/rainmaker/led_light/CMakeLists.txt Includes the necessary ESP-IDF CMake functions to initialize the project. This should typically be the last step in your CMakeLists.txt. ```cmake include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(led_light) ``` -------------------------------- ### Initialize and Control Zero Provisioning Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Set up Zero Provisioning to distribute Wi-Fi and mesh credentials via ESP-NOW broadcasts. Allows starting listening for a specified duration or stopping early. ```c #include "zero_provisioning.h" // On a provisioned node that will act as provisioner: void start_zero_prov(void) { // Custom data and device info shown to the unprovisioned device char cust_data[] = "{\"product\":\"smart_light\",\"ver\":\"1.0\"}"; char device_info[] = "LightNode_v1"; ESP_ERROR_CHECK(zero_prov_init(cust_data, device_info)); // Enter listening mode for 120 seconds // During this window, nearby unconfigured devices receive credentials zero_prov_listening(120); } // Stop listening early (e.g., after provisioning succeeds) void stop_zero_prov(void) { zero_prov_listening_stop(); } ``` -------------------------------- ### Generate C and H Files with protoc Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/src/proto_generate_EN.md Use the protoc command-line tool to generate C and H files from a .proto definition. Ensure you are in the correct directory and have the necessary plugins installed. ```bash protoc --c_out=. mesh_lite.proto ``` -------------------------------- ### Wi-Fi Provisioning Management Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Functions to manage SoftAP/BLE-based Wi-Fi provisioning sessions for onboarding new devices. `esp_mesh_lite_wifi_prov_mgr_init` starts the provisioning process, and `esp_mesh_lite_wifi_prov_mgr_deinit` stops it. `wifi_provision_in_progress` can be polled to check the status. ```APIDOC ## Wi-Fi Provisioning Management ### Description Manages SoftAP/BLE-based Wi-Fi provisioning sessions for onboarding new devices. ### Functions - `esp_mesh_lite_wifi_prov_mgr_init()`: Initializes the Wi-Fi provisioning manager. - `esp_mesh_lite_wifi_prov_mgr_deinit()`: Deinitializes the Wi-Fi provisioning manager. - `wifi_provision_in_progress()`: Checks if Wi-Fi provisioning is currently in progress. ### Example Usage ```c #include "wifi_prov_mgr.h" void start_provisioning(void) { ESP_ERROR_CHECK(esp_mesh_lite_wifi_prov_mgr_init()); ESP_LOGI("prov", "Provisioning started, waiting for credentials…"); // Poll or use an event to wait for completion while (wifi_provision_in_progress()) { vTaskDelay(pdMS_TO_TICKS(1000)); } ESP_LOGI("prov", "Provisioning complete"); } void stop_provisioning_early(void) { wifi_provision_stop(); esp_mesh_lite_wifi_prov_mgr_deinit(); } ``` ``` -------------------------------- ### ESP-Mesh-Lite No Router Example Log Output Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/no_router/README.md This log output shows the initialization and connection process of an ESP-Mesh-Lite network configured without a router. It includes details on network formation, IP address allocation, and periodic system information. ```c I (1386) vendor_ie: Mesh ID: 77 W (1390) vendor_ie: Error Get[4354] W (1394) vendor_ie: Error Get[4354] I (1399) ESP_Mesh_Lite_Comm: msg action add success I (1405) ESP_Mesh_Lite_Comm: Bind Socket 54, port 6364 I (1410) ESP_Mesh_Lite_Comm: Bind Socket 55, port 6363 I (1416) ESP_Mesh_Lite_Comm: Bind Socket 56, port 6366 I (1421) ESP_Mesh_Lite_Comm: Bind Socket 57, port 6365 I (1428) ESP_Mesh_Lite_Comm: msg action add success I (1433) no_router: Child node I (1436) Mesh-Lite: Mesh-Lite connecting I (1442) main_task: Returned from app_main() I (4274) vendor_ie: Mesh-Lite Scan done I (4276) vendor_ie: Find ESP_Bridge_1eb259 I (4276) vendor_ie: RTC store: ssid:ESP_Bridge_1eb259; bssid:58:cf:79:1e:b2:59 crc:3027520052 I (6340) wifi:ap channel adjust o:1,1 n:13,2 I (6340) wifi:new:<13,2>, old:<1,1>, ap:<13,2>, sta:<13,2>, prof:1 I (7031) wifi:state: init -> auth (b0) I (7033) ESP_Mesh_Lite_Comm: Retry to connect to the AP I (7044) wifi:state: auth -> assoc (0) I (7057) wifi:state: assoc -> run (10) I (7071) wifi:connected with ESP_Bridge_1eb259, aid = 1, channel 13, 40D, bssid = 58:cf:79:1e:b2:59 I (7072) wifi:security: WPA2-PSK, phy: bgn, rssi: -12 I (7074) wifi:pm start, type: 1 I (7077) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 0, mt_pti: 25000, mt_time: 10000 I (7154) wifi:AP's beacon interval = 102400 us, DTIM period = 2 I (7155) Mesh-Lite: netif network segment conflict check I (7156) ip select: IP Address:192.168.5.1 I (7160) ip select: GW Address:192.168.5.1 I (7164) ip select: NM Address:255.255.255.0 I (7170) bridge_common: ip reallocate new:192.168.5.1 W (7175) bridge_wifi: SoftAP IP network segment has changed, deauth all station I (8087) esp_netif_handlers: sta ip: 192.168.5.2, mask: 255.255.255.0, gw: 192.168.5.1 I (8088) bridge_wifi: Connected with IP Address:192.168.5.2 I (8091) ip select: IP Address:192.168.6.1 I (8096) ip select: GW Address:192.168.6.1 I (8101) ip select: NM Address:255.255.255.0 I (8106) bridge_common: ip reallocate new:192.168.6.1 W (8112) bridge_wifi: SoftAP IP network segment has changed, deauth all station I (8120) vendor_ie: RTC store: ssid:ESP_Bridge_1eb259; bssid:58:cf:79:1e:b2:59 crc:3027520052 I (11442) no_router: System information, channel: 13, layer: 2, self mac: 58:cf:79:e9:9e:c0, parent bssid: 58:cf:79:1e:b2:59, parent rssi: -14, free heap: 209280 I (21442) no_router: System information, channel: 13, layer: 2, self mac: 58:cf:79:e9:9e:c0, parent bssid: 58:cf:79:1e:b2:59, parent rssi: -13, free heap: 209280 I (31442) no_router: System information, channel: 13, layer: 2, self mac: 58:cf:79:e9:9e:c0, parent bssid: 58:cf:79:1e:b2:59, parent rssi: -13, free heap: 209280 ``` -------------------------------- ### Report and Get Node Information Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Enable child nodes to report their MAC and IP to the root, and allow the root to retrieve a list of all connected nodes. Requires CONFIG_MESH_LITE_NODE_INFO_REPORT to be enabled. ```c #include "esp_mesh_lite.h" // Called on a child node to push its info to root immediately esp_err_t err = esp_mesh_lite_report_info(); if (err != ESP_OK) { ESP_LOGW("node", "report_info failed: %s", esp_err_to_name(err)); } // Called on the root node to iterate the full node list uint32_t count = 0; const node_info_list_t *list = esp_mesh_lite_get_nodes_list(&count); ESP_LOGI("root", "Total nodes in list: %"PRIu32, count); for (const node_info_list_t *n = list; n != NULL; n = n->next) { ESP_LOGI("root", " level=%u ip=%s mac="MACSTR, n->node->level, inet_ntoa(*(struct in_addr *)&n->node->ip_addr), MAC2STR(n->node->mac_addr)); } ``` -------------------------------- ### AES Encryption Key Setup Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Enable AES encryption for all inter-node traffic. This must be called before `esp_mesh_lite_init`, and all nodes must use the same key. ```APIDOC ## esp_mesh_lite_aes_set_key ### Description Enable AES encryption for all inter-node traffic. Must be called **before** `esp_mesh_lite_init`. All nodes in the same mesh must use the same key. ### Usage Examples **Set 128-bit (16-byte) AES key – must be identical on every node in the network** ```c static const unsigned char aes_key[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; void app_main(void) { // Set key BEFORE init ESP_ERROR_CHECK(esp_mesh_lite_aes_set_key(aes_key, 128)); esp_mesh_lite_config_t cfg = ESP_MESH_LITE_DEFAULT_INIT(); esp_mesh_lite_init(&cfg); esp_mesh_lite_start(); } ``` **To disable encryption (plaintext mode – not recommended for production):** ```c // esp_mesh_lite_aes_set_key(NULL, 0); ``` ``` -------------------------------- ### Start LAN OTA Firmware Distribution Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Registers callbacks for providing and receiving firmware during LAN OTA. Prepares the OTA handle on child nodes and triggers distribution from the root node. Handles OTA events for success or failure. ```c #include "esp_mesh_lite.h" #include "esp_ota_ops.h" static esp_ota_handle_t ota_handle = 0; static const esp_partition_t *ota_partition = NULL; // Provider (root/sender): read firmware bytes from the running partition static esp_err_t provide_file(esp_mesh_lite_lan_ota_file_transfer_param_t *p) { const esp_partition_t *part = esp_ota_get_running_partition(); return esp_partition_read(part, p->offset, p->data, p->data_size); } // Receiver (child): write incoming bytes to the OTA partition static esp_err_t get_file(esp_mesh_lite_lan_ota_file_transfer_param_t *p) { return esp_ota_write(ota_handle, p->data, p->data_size); } // Receiver: finalise after all data received static esp_err_t get_file_done(void) { esp_ota_end(ota_handle); return esp_ota_set_boot_partition(ota_partition); } void start_lan_ota(void) { // Register callbacks on ALL nodes (root provides, children receive) static esp_mesh_lite_lan_ota_file_transfer_cb_t cb = { .provide_file_cb = provide_file, .get_file_cb = get_file, .get_file_done = get_file_done, }; esp_mesh_lite_ota_register_file_transfer_cb(&cb); // Prepare OTA handle on child side ota_partition = esp_ota_get_next_update_partition(NULL); esp_ota_begin(ota_partition, OTA_WITH_SEQUENTIAL_WRITES, &ota_handle); // Root node triggers distribution if (esp_mesh_lite_get_level() == 1) { esp_mesh_lite_file_transmit_config_t tx = { .type = ESP_MESH_LITE_OTA_TRANSMIT_FIRMWARE, .fw_version = "v1.0.2", .size = 890880, // actual firmware binary size in bytes .extern_url_ota_cb = NULL, }; ESP_ERROR_CHECK(esp_mesh_lite_transmit_file_start(&tx)); } } // Handle OTA events (register in event loop) static void ota_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data) { if (id == ESP_MESH_LITE_EVENT_OTA_FINISH) { esp_mesh_lite_event_ota_finish_t *e = data; if (e->reason == ESP_MESH_LITE_EVENT_OTA_SUCCESS) { ESP_LOGI("ota", "OTA success, rebooting…"); esp_restart(); } else { ESP_LOGE("ota", "OTA failed, reason=%d", e->reason); } } else if (id == ESP_MESH_LITE_EVENT_OTA_PROGRESS) { esp_mesh_lite_event_ota_progress_t *p = data; ESP_LOGI("ota", "OTA progress: %u%%", p->percentage); } } ``` -------------------------------- ### Start Wi-Fi Scan with Mesh-Lite Integration Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Registers Wi-Fi scan callbacks and an event handler for scan completion. Safely initiates a Wi-Fi scan using Mesh-Lite's gate to prevent conflicts with internal scanning, with a specified timeout. ```c #include "esp_mesh_lite.h" #include "esp_wifi.h" static volatile bool scan_pending = false; static void on_scan_start(void) { scan_pending = true; } static void on_scan_end(void) { scan_pending = false; } static const esp_mesh_lite_scan_cb_t scan_hooks = { .scan_start_cb = on_scan_start, .scan_end_cb = on_scan_end, }; static void scan_done_handler(void *arg, esp_event_base_t base, int32_t id, void *data) { if (!scan_pending) return; // not our scan uint16_t count = 0; esp_wifi_scan_get_ap_num(&count); wifi_ap_record_t *records = malloc(count * sizeof(wifi_ap_record_t)); esp_wifi_scan_get_ap_records(&count, records); for (int i = 0; i < count; i++) { ESP_LOGI("scan", "[%s] rssi=%d", records[i].ssid, records[i].rssi); } free(records); } void app_start_scan(void) { esp_mesh_lite_scan_cb_register(&scan_hooks); ESP_ERROR_CHECK(esp_event_handler_instance_register( WIFI_EVENT, WIFI_EVENT_SCAN_DONE, scan_done_handler, NULL, NULL)); // Use Mesh-Lite's scan gate to avoid conflicts; 3-second timeout if (esp_mesh_lite_wifi_scan_start(NULL, pdMS_TO_TICKS(3000)) != ESP_OK) { ESP_LOGW("scan", "Scan gate blocked"); } } ``` -------------------------------- ### Update IDF Component Manager Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/README.md If you encounter issues with the package manager, update it by running `pip install -U idf-component-manager` in your ESP-IDF environment. ```bash pip install -U idf-component-manager ``` -------------------------------- ### Topology Level and Leaf Node Configuration Source: https://context7.com/espressif/esp-mesh-lite/llms.txt These APIs allow you to control the topology level a node can occupy and designate a node as a leaf node. They should be called after initialization and before starting the mesh network. ```APIDOC ## esp_mesh_lite_set_allowed_level / esp_mesh_lite_set_disallowed_level / esp_mesh_lite_set_leaf_node ### Description These APIs restrict which topology level a node can occupy. Call them after `esp_mesh_lite_init` and before `esp_mesh_lite_start`. ### Usage Examples **Scenario A: Force this device to always be at level 1 (root)** ```c ESP_ERROR_CHECK(esp_mesh_lite_set_allowed_level(1)); ``` **Scenario B: Never allow this device to be at level 1 (force non-root)** ```c ESP_ERROR_CHECK(esp_mesh_lite_set_disallowed_level(1)); ``` **Scenario C: Make this a leaf node – it will not accept child connections** ```c ESP_ERROR_CHECK(esp_mesh_lite_set_leaf_node(true)); // Optionally enable SoftAP on the leaf anyway (e.g., for local provisioning) esp_mesh_lite_set_leaf_node_softap_status(ENABLE_SOFTAP); ``` **Scenario D: Configure networking mode so devices prefer direct router connection** ```c // when signal strength is above -70 dBm; otherwise join mesh ESP_ERROR_CHECK(esp_mesh_lite_set_networking_mode(ESP_MESH_LITE_ROUTER, -70)); ``` ``` -------------------------------- ### Configure Node Topology Levels Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Restrict node topology levels after initialization and before starting the mesh. Use `esp_mesh_lite_set_allowed_level` to force a specific level, `esp_mesh_lite_set_disallowed_level` to prevent a node from occupying a certain level, and `esp_mesh_lite_set_leaf_node` to make a node a leaf. ```c #include "esp_mesh_lite.h" // Scenario A: Force this device to always be at level 1 (root) ESP_ERROR_CHECK(esp_mesh_lite_set_allowed_level(1)); // Scenario B: Never allow this device to be at level 1 (force non-root) ESP_ERROR_CHECK(esp_mesh_lite_set_disallowed_level(1)); // Scenario C: Make this a leaf node – it will not accept child connections ESP_ERROR_CHECK(esp_mesh_lite_set_leaf_node(true)); // Optionally enable SoftAP on the leaf anyway (e.g., for local provisioning) esp_mesh_lite_set_leaf_node_softap_status(ENABLE_SOFTAP); // Scenario D: Configure networking mode so devices prefer direct router connection // when signal strength is above -70 dBm; otherwise join mesh ESP_ERROR_CHECK(esp_mesh_lite_set_networking_mode(ESP_MESH_LITE_ROUTER, -70)); ``` -------------------------------- ### Create Build Directory and Run CMake Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/wifi_provisioning/proto/README.md Steps to set up a build directory and run CMake when using the CMake build system. ```bash mkdir build cd build cmake .. ``` -------------------------------- ### Router Configuration Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Provide or retrieve the upstream router (SSID/password) that root nodes connect to. This configuration is essential before starting the mesh network. ```APIDOC ## esp_mesh_lite_set_router_config / esp_mesh_lite_get_router_config ### Description Provide or retrieve the upstream router (SSID/password) that root nodes connect to. ### Usage Examples **Set router credentials before calling `esp_mesh_lite_start()`** ```c #include "esp_mesh_lite_port.h" // mesh_lite_sta_config_t mesh_lite_sta_config_t router = {0}; strlcpy((char *)router.ssid, "HomeWiFi", sizeof(router.ssid)); strlcpy((char *)router.password, "wifipass123", sizeof(router.password)); ESP_ERROR_CHECK(esp_mesh_lite_set_router_config(&router)); ``` **Later, read back the active router config** ```c mesh_lite_sta_config_t active = {0}; if (esp_mesh_lite_get_router_config(&active) == ESP_OK) { ESP_LOGI("router", "Connected to SSID: %s", active.ssid); } ``` ``` -------------------------------- ### Build and Flash Firmware Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/wireless_debug/README.md Use this command to erase the flash, flash the firmware, and monitor the device via serial. Replace `/dev/ttyUSB0` with your actual serial port. ```bash idf.py erase_flash flash monitor -p /dev/ttyUSB0 ``` -------------------------------- ### Build and Flash ESP-Mesh-Lite Device Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/mesh_local_control/README.md Use this command to build the project, erase the flash memory, and flash the device. Replace '/dev/ttyUSBx' with your device's serial port. ```shell idf.py erase_flash flash monitor -p /dev/ttyUSBx ``` -------------------------------- ### Zero Provisioning Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Uses ESP-NOW broadcasts to distribute Wi-Fi and mesh credentials to unconfigured devices without user interaction. ```APIDOC ## `zero_prov_init` / `zero_prov_listening` / `zero_prov_listening_stop` ### Description Facilitates Zero Provisioning by allowing a configured node to act as a provisioner, distributing network credentials to unconfigured devices via ESP-NOW broadcasts. ### Functions - `zero_prov_init(const char *custom_data, const char *device_info)`: Initializes the zero provisioning module with custom data and device information. - `zero_prov_listening(uint32_t listen_duration_sec)`: Starts the listening mode for a specified duration to distribute credentials. - `zero_prov_listening_stop()`: Stops the listening mode prematurely. ### Example Usage ```c #include "zero_provisioning.h" // On a provisioned node that will act as provisioner: void start_zero_prov(void) { // Custom data and device info shown to the unprovisioned device char cust_data[] = "{\"product\":\"smart_light\",\"ver\":\"1.0\"}"; char device_info[] = "LightNode_v1"; ESP_ERROR_CHECK(zero_prov_init(cust_data, device_info)); // Enter listening mode for 120 seconds // During this window, nearby unconfigured devices receive credentials zero_prov_listening(120); } // Stop listening early (e.g., after provisioning succeeds) void stop_zero_prov(void) { zero_prov_listening_stop(); } ``` ``` -------------------------------- ### Initialize ESP-Mesh-Lite Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/README.md Call this API at the code level to enable Mesh-Lite. Ensure all network interfaces are created before initialization. ```c esp_bridge_create_all_netif(); esp_mesh_lite_config_t mesh_lite_config = ESP_MESH_LITE_DEFAULT_INIT(); esp_mesh_lite_init(&mesh_lite_config); esp_mesh_lite_start(); ``` -------------------------------- ### Initialize and Deinitialize Wi-Fi Provisioning Manager Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Initializes the Wi-Fi provisioning manager for SoftAP/BLE-based onboarding. Polls for provisioning status and deinitializes the manager when done or stopped early. ```c #include "wifi_prov_mgr.h" void start_provisioning(void) { ESP_ERROR_CHECK(esp_mesh_lite_wifi_prov_mgr_init()); ESP_LOGI("prov", "Provisioning started, waiting for credentials…"); // Poll or use an event to wait for completion while (wifi_provision_in_progress()) { vTaskDelay(pdMS_TO_TICKS(1000)); } ESP_LOGI("prov", "Provisioning complete"); } void stop_provisioning_early(void) { wifi_provision_stop(); esp_mesh_lite_wifi_prov_mgr_deinit(); } ``` -------------------------------- ### Configure Mesh Signal Quality Thresholds Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Set RSSI thresholds for parent selection and network fusion. Also configures the minimum RSSI for router connections and fusion parameters like start time and frequency. ```c #include "esp_mesh_lite.h" // RSSI → max-children-per-node mapping static const esp_mesh_lite_rssi_threshold_list_t rssi_table[] = { // { rssi_min, rssi_max, max_children } { 0, -35, 20 }, { -35, -55, 15 }, { -55, -75, 10 }, { -75, -125, 5 }, }; ESP_ERROR_CHECK(esp_mesh_lite_set_rssi_threshold( rssi_table, sizeof(rssi_table) / sizeof(rssi_table[0]), -90 /* min RSSI to consider a router */ )); // Reject router connections below -75 dBm esp_mesh_lite_set_router_min_rssi_threshold(-75); // Fusion: start 60 s after IP assignment, repeat every 120 s esp_mesh_lite_fusion_config_t fusion = { .fusion_rssi_threshold = -85, .fusion_start_time_sec = 60, .fusion_frequency_sec = 120, }; ESP_ERROR_CHECK(esp_mesh_lite_set_fusion_config(&fusion)); ``` -------------------------------- ### Initialize and Use ESP-NOW for Mesh-Lite Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Integrates ESP-NOW for out-of-band communication within Mesh-Lite, available for application use via a reserved data type. Requires `esp_mesh_lite_espnow_init()` to be called internally by `esp_mesh_lite_init()`. ```c #include "esp_mesh_lite_espnow.h" // Receive callback for application-defined ESP-NOW messages static esp_err_t app_espnow_recv(const esp_now_recv_info_t *info, const uint8_t *data, int len) { ESP_LOGI("espnow", "From "MACSTR": %.*s", MAC2STR(info->src_addr), len, (char *)data); return ESP_OK; } void init_espnow_app(void) { // esp_mesh_lite_espnow_init() is called internally by esp_mesh_lite_init() // Register application receive callback for the reserved slot ESP_ERROR_CHECK(esp_mesh_lite_espnow_recv_cb_register( ESPNOW_DATA_TYPE_RESERVE, app_espnow_recv)); } void send_espnow_broadcast(const char *message) { static uint8_t broadcast[ESP_NOW_ETH_ALEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; esp_mesh_lite_espnow_send( ESPNOW_DATA_TYPE_RESERVE, broadcast, (const uint8_t *)message, strlen(message)); } ``` -------------------------------- ### Build and Flash Firmware Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/rainmaker/led_light/README.md Commands to compile and flash the firmware for the ESP32-C3 target. Ensure your ESP-IDF environment is set up correctly before running these commands. ```bash cd esp-mesh-lite/examples/rainmaker/led_light idf.py set-target esp32c3 idf.py build idf.py flash ``` -------------------------------- ### Wi-Fi Scanning Integration Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Functions to safely trigger Wi-Fi scans without interfering with Mesh-Lite's internal scanning. `esp_mesh_lite_scan_cb_register` allows registering callbacks for scan start and end events, and `esp_mesh_lite_wifi_scan_start` initiates the scan using a gate mechanism. ```APIDOC ## Wi-Fi Scanning Integration ### Description Safely trigger a Wi-Fi scan from application code without conflicting with Mesh-Lite's internal scanning. ### Functions - `esp_mesh_lite_scan_cb_register(const esp_mesh_lite_scan_cb_t *cb)`: Registers callbacks for Wi-Fi scan start and end events. - `esp_mesh_lite_wifi_scan_start(const char *ssid, uint32_t timeout_ms)`: Initiates a Wi-Fi scan. If `ssid` is NULL, it scans for all SSIDs. `timeout_ms` specifies the duration the scan gate is held open. ### Callbacks Registered by `esp_mesh_lite_scan_cb_register` - `scan_start_cb`: Called when a scan is initiated. - `scan_end_cb`: Called when a scan is completed. ### Example Usage ```c #include "esp_mesh_lite.h" #include "esp_wifi.h" static volatile bool scan_pending = false; static void on_scan_start(void) { scan_pending = true; } static void on_scan_end(void) { scan_pending = false; } static const esp_mesh_lite_scan_cb_t scan_hooks = { .scan_start_cb = on_scan_start, .scan_end_cb = on_scan_end, }; static void scan_done_handler(void *arg, esp_event_base_t base, int32_t id, void *data) { if (!scan_pending) return; // not our scan uint16_t count = 0; esp_wifi_scan_get_ap_num(&count); wifi_ap_record_t *records = malloc(count * sizeof(wifi_ap_record_t)); esp_wifi_scan_get_ap_records(&count, records); for (int i = 0; i < count; i++) { ESP_LOGI("scan", "[%s] rssi=%d", records[i].ssid, records[i].rssi); } free(records); } void app_start_scan(void) { esp_mesh_lite_scan_cb_register(&scan_hooks); ESP_ERROR_CHECK(esp_event_handler_instance_register( WIFI_EVENT, WIFI_EVENT_SCAN_DONE, scan_done_handler, NULL, NULL)); // Use Mesh-Lite's scan gate to avoid conflicts; 3-second timeout if (esp_mesh_lite_wifi_scan_start(NULL, pdMS_TO_TICKS(3000)) != ESP_OK) { ESP_LOGW("scan", "Scan gate blocked"); } } ``` ``` -------------------------------- ### Generate C and Python Protobuf Files Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/wifi_provisioning/proto/README.md Command to generate the C and Python Protobuf files. This command overwrites existing generated files. ```bash make ``` -------------------------------- ### Initialize and Use Wireless Debugging Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Set up and utilize wireless debugging over ESP-NOW to diagnose nodes remotely without a physical serial connection. This involves registering callback functions for various debug events and initializing the wireless debug module. ```c #include "esp_mesh_lite_wireless_debug.h" static char err_buf[250]; static char *wifi_err_cb(void) { snprintf(err_buf, sizeof(err_buf), "RSSI=%d", -72); return err_buf; } static char *cloud_err_cb(void) { snprintf(err_buf, sizeof(err_buf), "cloud_unreachable"); return err_buf; } static void recv_resp_cb(char *data, size_t len) { ESP_LOGI("wdbg", "Response: %.*s", (int)len, data); } static void recv_log_cb(const esp_now_recv_info_t *info, const uint8_t *data, int len) { printf(MACSTR": %s", MAC2STR(info->src_addr), (char *)data); } void init_wireless_debug(void) { esp_mesh_lite_wireless_debug_cb_list_t cbs = { .wifi_error_cb = wifi_err_cb, .cloud_error_cb = cloud_err_cb, .recv_resp_data_cb = recv_resp_cb, .recv_debug_log_cb = recv_log_cb, }; esp_mesh_lite_wireless_debug_cb_register(&cbs); esp_mesh_lite_wireless_debug_init(); } void send_debug_command(void) { // Broadcast a "discover" command on channel 6 uint8_t broadcast[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; const char *cmd = "discover"; esp_mesh_lite_wireless_debug_send_command(broadcast, (char *)cmd, strlen(cmd), 6); } ``` -------------------------------- ### Wi-Fi Provisioning Event Handler for ESP-MESH-LITE Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/User_Guide.md This event handler is used during Wi-Fi provisioning. When Wi-Fi credentials are received, it configures ESP-MESH-LITE with the router details and initiates the connection process. If CONFIG_MESH_LITE_ENABLE is not defined, it falls back to standard Wi-Fi connection. ```c /* Event handler for catching system events */ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_PROV_EVENT) { switch (event_id) { case WIFI_PROV_START: ESP_LOGI(TAG, "Provisioning started"); break; case WIFI_PROV_CRED_RECV: { wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data; ESP_LOGI(TAG, "Received Wi-Fi credentials" "\n\tSSID : %s\n\tPassword : %s", (const char *) wifi_sta_cfg->ssid, (const char *) wifi_sta_cfg->password); #if CONFIG_MESH_LITE_ENABLE mesh_lite_sta_config_t config; memcpy((char*)config.ssid, (char*)wifi_sta_cfg->ssid, sizeof(config.ssid)); memcpy((char*)config.password, (char*)wifi_sta_cfg->password, sizeof(config.password)); config.bssid_set = wifi_sta_cfg->bssid_set; if (config.bssid_set) { memcpy((char*)config.bssid, (char*)wifi_sta_cfg->bssid, sizeof(config.bssid)); } esp_mesh_lite_set_router_config(&config); esp_mesh_lite_connect(); #else esp_wifi_set_storage(WIFI_STORAGE_FLASH); esp_wifi_set_config(ESP_IF_WIFI_STA, (wifi_config_t*)wifi_sta_cfg); esp_wifi_set_storage(WIFI_STORAGE_RAM); esp_wifi_disconnect(); esp_wifi_connect(); #endif /* CONFIG_MESH_LITE_ENABLE */ break; } } } } ``` -------------------------------- ### Sample Serial Output Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/wireless_debug/README.md This output shows the interaction when a button press triggers a wireless command. It includes command types, MAC addresses, channels, and debug logs from the application. ```text Command Type: discover MAC Address: 58:cf:79:1e:b1:14 Channel: 11 I (329519) wireless_debug: BTN: BUTTON_PRESS_UP I (329519) Mesh-Lite-Wireless-Debug: send command: discover --delay 1000 --channel 11 --mac 58:cf:79:1e:b1:14 I (330094) wireless_debug: BTN: BUTTON_PRESS_UP I (330094) Mesh-Lite-Wireless-Debug: send command: wifi_error Command Type: discover MAC Address: 58:cf:79:1e:b1:14 Channel: 11 I (330694) wireless_debug: BTN: BUTTON_PRESS_UP I (330694) Mesh-Lite-Wireless-Debug: send command: wifi_error --mac 58:cf:79:1e:b1:14 Command Type: wifi_error Command Value: This message from app_wifi_error_cb ``` -------------------------------- ### Manage SoftAP Credentials in NVS with ESP-Mesh-Lite Source: https://context7.com/espressif/esp-mesh-lite/llms.txt Persist and retrieve SoftAP SSID and password using NVS functions. Fall back to build-time defaults if credentials are not found in NVS. Use esp_mesh_lite_set_softap_info to apply the credentials. ```c #include "esp_mesh_lite.h" // Read SSID from NVS; fall back to build-time default if not stored char ssid[33] = {0}; char psw[64] = {0}; size_t ssid_sz = sizeof(ssid); size_t psw_sz = sizeof(psw); if (esp_mesh_lite_get_softap_ssid_from_nvs(ssid, &ssid_sz) != ESP_OK) { uint8_t mac[6]; esp_wifi_get_mac(WIFI_IF_AP, mac); snprintf(ssid, sizeof(ssid), "MeshNode_%%02x%%02x%%02x", mac[3], mac[4], mac[5]); } if (esp_mesh_lite_get_softap_psw_from_nvs(psw, &psw_sz) != ESP_OK) { strlcpy(psw, CONFIG_BRIDGE_SOFTAP_PASSWORD, sizeof(psw)); } esp_mesh_lite_set_softap_info(ssid, psw); // Persist new credentials when they change (e.g., via provisioning) esp_mesh_lite_set_softap_ssid_to_nvs("NewMeshSSID"); esp_mesh_lite_set_softap_psw_to_nvs("NewMeshPass"); ``` -------------------------------- ### Perform Wi-Fi Scan in Mesh-Lite Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/README.md When Mesh-Lite is active, use the `esp_mesh_lite_wifi_scan_start()` interface for Wi-Fi scans. Ensure the `scan_done` callback correctly handles externally initiated scans by using a flag. ```c if (esp_mesh_lite_wifi_scan_start(NULL, 3000 / TICK_MS) == ESP_OK) { scan_flag = true; } ``` -------------------------------- ### Define Source Files and Dependencies Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/CMakeLists.txt Sets the main source file and lists required components for the ESP-Mesh-Lite library. Conditional compilation includes additional source files based on configuration options. ```cmake set(srcs "src/esp_mesh_lite_espnow.c") set(require_components "json" "esp_wifi" "app_update" "wifi_provisioning" "qrcode" "nvs_flash" "protobuf-c" "console") if (CONFIG_MESH_LITE_ENABLE) list(APPEND srcs "src/esp_mesh_lite.c" "src/esp_mesh_lite_port.c" "src/esp_mesh_lite_log.c" "src/mesh_lite.pb-c.c") endif() if (CONFIG_MESH_LITE_PROV_ENABLE) list(APPEND srcs "src/wifi_prov/wifi_prov_mgr.c" "src/wifi_prov/zero_provisioning.c") endif() if (CONFIG_MESH_LITE_WIRELESS_DEBUG) list(APPEND srcs "src/esp_mesh_lite_wireless_debug.c") endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS include REQUIRES ${require_components}) ``` -------------------------------- ### Register ESP-NOW Receive Callback Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/components/mesh_lite/User_Guide.md Register a callback function to handle incoming ESP-NOW data. The callback runs from the Wi-Fi task, so avoid lengthy operations and consider queueing data for lower-priority task handling. Users can specify a data type or use `ESPNOW_DATA_TYPE_RESERVE`. ```c static void espnow_recv_cb(const esp_now_recv_info_t *recv_info, const uint8_t *data, int len) { esp_mesh_lite_espnow_event_t evt; espnow_recv_cb_t *recv_cb = &evt.info.recv_cb; if (recv_info->src_addr == NULL || data == NULL || len <= 0) { ESP_LOGE(TAG, "Receive cb arg error"); return; } // The receiving callback function when receiving ESP-NOW. The receiving callback function also runs from the Wi-Fi task. So, do not do lengthy operations in the callback function. // Instead, post the necessary data to a queue and handle it from a lower priority task. } esp_mesh_lite_espnow_recv_cb_register(ESPNOW_DATA_TYPE_RESERVE, espnow_recv_cb); ``` -------------------------------- ### Project Versioning with Git Describe Source: https://github.com/espressif/esp-mesh-lite/blob/release/v1.0/examples/rainmaker/led_light/CMakeLists.txt This snippet integrates git describe to automatically set the project version based on git tags and commit information. It appends git commit details to a base version string. ```cmake EXECUTE_PROCESS( COMMAND git describe --always --dirty OUTPUT_VARIABLE IMAGE_VERSION_GIT_HEAD_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE GET_GIT_VERSION_FAILED ) string(CONCAT PROJECT_V "v1.0.0" "-beta_" ${IMAGE_VERSION_GIT_HEAD_VERSION}) set(PROJECT_VER ${PROJECT_V}) ```