### Initialize Mesh Network Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Initialize the mesh network within your setup() function. This starts a WiFi network, searches for other mesh nodes, and attempts to log in. ```cpp void painlessMesh::init(String ssid, String password, uint16_t port = 5555, WiFiMode_t connectMode = WIFI_AP_STA, _auth_mode authmode = AUTH_WPA2_PSK, uint8_t channel = 1, phy_mode_t phymode = PHY_MODE_11G, uint8_t maxtpw = 82, uint8_t hidden = 0, uint8_t maxconn = 4) ``` -------------------------------- ### Initialize PainlessMesh Network Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Initializes the mesh network in the setup() function. This starts WiFi, searches for nodes, and connects. Ensure `mesh.update()` is called in the loop() for network maintenance. ```cpp #include #define MESH_PREFIX "myMeshNetwork" #define MESH_PASSWORD "securePassword123" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; void setup() { Serial.begin(115200); // Set debug message types before init() to see startup messages mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); // Initialize with scheduler for task management mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); // Alternative: Initialize with specific WiFi mode and channel // mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6); } void loop() { // Must be called in loop() for mesh maintenance mesh.update(); } ``` -------------------------------- ### PainlessMesh Initialization Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Initializes the mesh network by starting a WiFi network, searching for other mesh nodes, and logging into the best available node. If no node is found, it starts a new search. ```APIDOC ## void painlessMesh::init(String ssid, String password, uint16_t port = 5555, WiFiMode_t connectMode = WIFI_AP_STA, _auth_mode authmode = AUTH_WPA2_PSK, uint8_t channel = 1, phy_mode_t phymode = PHY_MODE_11G, uint8_t maxtpw = 82, uint8_t hidden = 0, uint8_t maxconn = 4) ### Description Initializes the mesh network. This routine starts a WiFi network, begins searching for other mesh nodes, and logs into the best available node. If no node is found, it starts a new search in 5 seconds. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Details - **ssid** (String) - The name of your mesh. All nodes share the same AP ssid. - **password** (String) - The WiFi password for your mesh. - **port** (uint16_t) - The TCP port for the mesh server. Defaults to 5555. - **connectMode** (WiFiMode_t) - WiFi connection mode (WIFI_AP, WIFI_STA, WIFI_AP_STA). Defaults to WIFI_AP_STA. - **authmode** (_auth_mode) - WiFi authentication mode. Defaults to AUTH_WPA2_PSK. - **channel** (uint8_t) - WiFi channel. Defaults to 1. - **phymode** (phy_mode_t) - WiFi physical mode. Defaults to PHY_MODE_11G. - **maxtpw** (uint8_t) - Maximum transmit power. Defaults to 82. - **hidden** (uint8_t) - Whether the SSID is hidden. Defaults to 0 (false). - **maxconn** (uint8_t) - Maximum number of connections. Defaults to 4. ### Request Example ```cpp #include painlessMesh mesh; void setup() { mesh.init("MyMeshSSID", "MyPassword"); } ``` ### Response This function returns void. ``` -------------------------------- ### Start Delay Measurement Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Initiates a network delay measurement to a specified node. ```APIDOC ## bool painlessMesh::startDelayMeas(uint32_t nodeId) ### Description Sends a packet to the specified `nodeId` to initiate a measurement of the network round-trip delay. The function returns true if the `nodeId` is connected to the mesh, and false otherwise. After calling this function, the user program must wait for a response, which will be delivered via the `onNodeDelayReceived` callback. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **nodeId** (uint32_t) - Required - The ID of the node to measure delay to. ``` -------------------------------- ### OTA Receiver Node Setup Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Initializes the mesh network and enables OTA firmware reception on a node. Ensure the role name matches the firmware filename. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | DEBUG); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); // Enable OTA reception with role name // Role must match the firmware filename: firmware_ESP32_myrole.bin mesh.initOTAReceive("myrole"); // Optional: Add progress callback // mesh.initOTAReceive("myrole", [](int current, int total) { // Serial.printf("OTA Progress: %d/%d\n", current, total); // }); mesh.setContainsRoot(true); } void loop() { mesh.update(); } ``` -------------------------------- ### PainlessMesh CMake Project Setup Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/CMakeLists.txt Sets the minimum CMake version, project name, C++ standard, and output directory. Ensures the C++ standard is required and enables compile command export. ```cmake cmake_minimum_required (VERSION 3.10) project (painlessMesh) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) ``` -------------------------------- ### OTA Sender Node Setup Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Configures the mesh to send OTA firmware updates. Requires an SD card and specific firmware file naming conventions (firmware__.bin). ```cpp // Firmware file naming: firmware__.bin // Example: firmware_ESP32_myrole.bin #include #include #define OTA_PART_SIZE 1024 painlessMesh mesh; void setupOTASender(File &firmwareFile, String role, String hardware) { // Setup OTA data callback mesh.initOTASend( [&firmwareFile](painlessmesh::plugin::ota::DataRequest pkg, char* buffer) { firmwareFile.seek(OTA_PART_SIZE * pkg.partNo); firmwareFile.readBytes(buffer, OTA_PART_SIZE); return min((unsigned)OTA_PART_SIZE, firmwareFile.size() - (OTA_PART_SIZE * pkg.partNo)); }, OTA_PART_SIZE); // Calculate MD5 hash MD5Builder md5; md5.begin(); md5.addStream(firmwareFile, firmwareFile.size()); md5.calculate(); // Announce OTA availability (broadcasts every minute for 1 hour) mesh.offerOTA(role, hardware, md5.toString(), ceil((float)firmwareFile.size() / OTA_PART_SIZE), false); } ``` -------------------------------- ### Start Network Delay Measurement Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Initiates a delay measurement to a specified `nodeId`. Returns true if the node is connected. A response is expected via the `onNodeDelayReceived` callback. ```cpp bool painlessMesh::startDelayMeas(uint32_t nodeId) ``` -------------------------------- ### Get Node Information with PainlessMesh Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Retrieve node ID, connected nodes, and network topology. Includes tasks for periodic information display. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; Task printInfoTask(TASK_SECOND * 10, TASK_FOREVER, []() { // Get this node's unique ID (based on chip ID) uint32_t myNodeId = mesh.getNodeId(); Serial.printf("My Node ID: %u\n", myNodeId); // Get list of all nodes (excluding self) std::list nodeList = mesh.getNodeList(); Serial.printf("Connected nodes: %d\n", nodeList.size()); // Get list including self std::list allNodes = mesh.getNodeList(true); Serial.printf("Total nodes (including self): %d\n", allNodes.size()); // Check if specific node is connected for (auto &nodeId : nodeList) { bool connected = mesh.isConnected(nodeId); Serial.printf("Node %u connected: %s\n", nodeId, connected ? "yes" : "no"); } // Get mesh topology as JSON String topology = mesh.subConnectionJson(true); // true for pretty print Serial.printf("Mesh topology:\n%s\n", topology.c_str()); }); void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); userScheduler.addTask(printInfoTask); printInfoTask.enable(); } void loop() { mesh.update(); } ``` -------------------------------- ### Get Node Time Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Retrieves the current mesh timebase in microseconds. ```APIDOC ## uint32_t painlessMesh::getNodeTime( void ) ### Description Returns the current value of the mesh timebase, measured in microseconds. This timebase rolls over approximately 71 minutes after the startup of the first node. Nodes attempt to maintain a common time base by synchronizing with each other using an SNTP-based protocol. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Response #### Success Response (200) - **meshTime** (uint32_t) - The current mesh time in microseconds. ``` -------------------------------- ### Get Mesh Topology as JSON Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Retrieves the current mesh topology and returns it as a JSON formatted string. ```cpp String painlessMesh::subConnectionJson() ``` -------------------------------- ### Get Node List Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Retrieves a list of all known node IDs in the mesh network. ```APIDOC ## std::list painlessMesh::getNodeList() ### Description Returns a list containing the IDs of all nodes currently known to the mesh network. This list includes both directly and indirectly connected nodes. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Response #### Success Response (200) - **nodeList** (std::list) - A list of 32-bit unsigned integers, where each integer is a node ID. ``` -------------------------------- ### Get Mesh Topology Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Retrieves the current mesh topology in JSON format. ```APIDOC ## String painlessMesh::subConnectionJson() ### Description Returns a string representing the current mesh topology in JSON format. This can be used to visualize or analyze the network structure. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Response #### Success Response (200) - **topology** (String) - A JSON string representing the mesh topology. ``` -------------------------------- ### Get List of Known Nodes Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Retrieves a list of all nodes currently known to the mesh, including both direct and indirect connections. ```cpp std::list painlessMesh::getNodeList() ``` -------------------------------- ### Get Node ID Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Retrieves the unique chip ID of the current node. ```APIDOC ## uint32_t painlessMesh::getNodeId( void ) ### Description Returns the unique chip ID of the node on which this code is currently running. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Response #### Success Response (200) - **nodeId** (uint32_t) - The chip ID of the current node. ``` -------------------------------- ### Get Node ID Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Returns the unique chip ID of the current node running the PainlessMesh code. ```cpp uint32_t painlessMesh::getNodeId( void ) ``` -------------------------------- ### Get Mesh Timebase Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Returns the current mesh timebase in microseconds. This counter resets approximately every 71 minutes. Nodes attempt to maintain a synchronized time base using an SNTP-based protocol. ```cpp uint32_t painlessMesh::getNodeTime( void ) ``` -------------------------------- ### Initialize Git Submodules Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Run these commands after cloning the repository to initialize and update submodules. ```bash git submodule init git submodule update ``` -------------------------------- ### Web Server for Mesh Broadcasting Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Sets up a web server on a mesh node to broadcast messages and retrieve node information. Requires AsyncTCP and ESPAsyncWebServer libraries. ```cpp #include #ifdef ESP8266 #include #else #include #endif #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 #define STATION_SSID "YourHomeWiFi" #define STATION_PASSWORD "YourWiFiPassword" painlessMesh mesh; AsyncWebServer server(80); void receivedCallback(const uint32_t &from, const String &msg) { Serial.printf("Received from %u: %s\n", from, msg.c_str()); } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); // Initialize mesh with same channel as external network mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6); mesh.stationManual(STATION_SSID, STATION_PASSWORD); mesh.setHostname("HTTP_BRIDGE"); mesh.setRoot(true); mesh.setContainsRoot(true); mesh.onReceive(&receivedCallback); // Setup web server endpoints server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { String html = ""; html += "

Mesh Network Control

"; html += "
"; html += ""; html += ""; html += "
"; request->send(200, "text/html", html); }); server.on("/broadcast", HTTP_GET, [](AsyncWebServerRequest *request) { if (request->hasArg("msg")) { String msg = request->arg("msg"); mesh.sendBroadcast(msg); request->send(200, "text/plain", "Message sent: " + msg); } else { request->send(400, "text/plain", "Missing 'msg' parameter"); } }); server.on("/nodes", HTTP_GET, [](AsyncWebServerRequest *request) { String json = mesh.subConnectionJson(true); request->send(200, "application/json", json); }); server.begin(); Serial.printf("Web server started. AP IP: %s\n", IPAddress(mesh.getAPIP()).toString().c_str()); } void loop() { mesh.update(); } ``` -------------------------------- ### Configure Bridge Node with PainlessMesh Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Configure a node as a bridge to connect the mesh to an external WiFi network. Requires station credentials. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 #define STATION_SSID "YourHomeWiFi" #define STATION_PASSWORD "YourWiFiPassword" painlessMesh mesh; void receivedCallback(uint32_t from, String &msg) { Serial.printf("Bridge received from %u: %s\n", from, msg.c_str()); } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); // Initialize with same channel as external network mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6); // Connect to external network mesh.stationManual(STATION_SSID, STATION_PASSWORD); // Optional: Set hostname for the bridge mesh.setHostname("MeshBridge"); // Bridge should be root node for stable mesh formation mesh.setRoot(true); // Inform all nodes that mesh contains a root mesh.setContainsRoot(true); mesh.onReceive(&receivedCallback); } void loop() { mesh.update(); // Get station IP from external network IPAddress stationIP = mesh.getStationIP(); if (stationIP != IPAddress(0, 0, 0, 0)) { // Bridge is connected to external network } } ``` -------------------------------- ### Compile Library with CMake Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Compile the library using CMake and Ninja. This generates test files for execution. ```bash cmake -G Ninja ninja ``` -------------------------------- ### Run Compiled Tests Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Execute compiled test files using 'run-parts'. ```bash run-parts --regex catch_ bin/ ``` -------------------------------- ### Configure Debug Logging Levels Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Set the desired debug message types before initializing the mesh to troubleshoot network behavior. Different levels like ERROR, STARTUP, and CONNECTION provide varying degrees of insight. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; void setup() { Serial.begin(115200); // Available debug message types: // ERROR - Error messages // STARTUP - Startup/initialization messages // MESH_STATUS - Mesh status changes // CONNECTION - Connection events // SYNC - Synchronization messages // COMMUNICATION - Communication details // GENERAL - General messages // MSG_TYPES - Message type information // REMOTE - Remote logging // S_TIME - Time synchronization // DEBUG - Debug level messages // Minimal logging (errors only) mesh.setDebugMsgTypes(ERROR); // Recommended for development mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); // Verbose logging for debugging // mesh.setDebugMsgTypes(ERROR | MESH_STATUS | CONNECTION | SYNC | // COMMUNICATION | GENERAL | MSG_TYPES | REMOTE); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); } void loop() { mesh.update(); } ``` -------------------------------- ### Include PainlessMesh Library Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Include the PainlessMesh library and create a mesh object. This is a prerequisite for using mesh functionalities. ```cpp #include painlessMesh mesh; ``` -------------------------------- ### Boost Dependency Configuration Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/CMakeLists.txt Finds and configures the Boost library, including include and library directories. This is essential for projects relying on Boost components. ```cmake FIND_PACKAGE(Boost CONFIG REQUIRED COMPONENTS system) IF(Boost_FOUND) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) ENDIF(Boost_FOUND) ``` -------------------------------- ### MQTT Bridge Integration with PainlessMesh Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Relay messages between the mesh network and an MQTT broker. Requires WiFiClient and PubSubClient libraries. ```cpp #include #include #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 #define STATION_SSID "YourHomeWiFi" #define STATION_PASSWORD "YourWiFiPassword" painlessMesh mesh; WiFiClient wifiClient; IPAddress mqttBroker(192, 168, 1, 100); PubSubClient mqttClient(mqttBroker, 1883, wifiClient); IPAddress myIP(0, 0, 0, 0); // Forward mesh messages to MQTT void receivedCallback(const uint32_t &from, const String &msg) { String topic = "painlessMesh/from/" + String(from); mqttClient.publish(topic.c_str(), msg.c_str()); } // Forward MQTT messages to mesh void mqttCallback(char* topic, uint8_t* payload, unsigned int length) { String msg = String((char*)payload).substring(0, length); String targetStr = String(topic).substring(16); // Remove "painlessMesh/to/" if (targetStr == "broadcast") { mesh.sendBroadcast(msg); } else if (targetStr == "gateway") { if (msg == "getNodes") { auto nodes = mesh.getNodeList(true); String nodeList; for (auto &id : nodes) nodeList += String(id) + " "; mqttClient.publish("painlessMesh/from/gateway", nodeList.c_str()); } } else { uint32_t target = strtoul(targetStr.c_str(), NULL, 10); if (mesh.isConnected(target)) { mesh.sendSingle(target, msg); } } } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6); mesh.stationManual(STATION_SSID, STATION_PASSWORD); mesh.setRoot(true); mesh.setContainsRoot(true); mesh.onReceive(&receivedCallback); mqttClient.setCallback(mqttCallback); } void loop() { mesh.update(); mqttClient.loop(); // Reconnect to MQTT if needed IPAddress currentIP = mesh.getStationIP(); if (myIP != currentIP) { myIP = currentIP; if (mqttClient.connect("meshBridge")) { mqttClient.subscribe("painlessMesh/to/#"); } } } ``` -------------------------------- ### Dynamic Test Executable Generation Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/CMakeLists.txt Generates executables for test files found in the 'test/**/catch_*.cpp' pattern. It includes necessary source files and sets up include directories. ```cmake FILE(GLOB TESTFILES test/**/catch_*.cpp) foreach(TESTFILE ${TESTFILES}) get_filename_component(NAME ${TESTFILE} NAME_WE) add_executable(${NAME} ${TESTFILE} test/catch/fake_serial.cpp src/scheduler.cpp) target_include_directories(${NAME} PUBLIC test/include/ test/catch/ test/ArduinoJson/src/ src/ test/TaskScheduler/src) endforeach() ``` -------------------------------- ### Configure Node as Mesh Root Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Designate a node as the mesh root to accelerate network formation and establish a stable anchor point. Ensure only one node is set as root and inform all nodes about its presence. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); // Set this node as root (only one node should be root) mesh.setRoot(true); // Tell all nodes the mesh contains a root // Call this on ALL nodes for optimal mesh formation mesh.setContainsRoot(true); // Check if this node is root if (mesh.isRoot()) { Serial.println("This node is the mesh root"); } } void loop() { mesh.update(); } ``` -------------------------------- ### Connection Test Executable Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/CMakeLists.txt Defines the 'catch_connection' executable, similar to the TCP integration test, linking with Boost and setting up include paths for necessary libraries and sources. ```cmake add_executable(catch_connection test/boost/connection.cpp test/catch/fake_serial.cpp src/scheduler.cpp) target_include_directories(catch_connection PUBLIC test/include/ test/boost/ test/ArduinoJson/src/ test/TaskScheduler/src/ src/) TARGET_LINK_LIBRARIES(catch_connection ${Boost_LIBRARIES}) ``` -------------------------------- ### Handle Connection Events Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Register callbacks for new connections, dropped connections, and topology changes. These callbacks provide information about the mesh network's state. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; void newConnectionCallback(uint32_t nodeId) { Serial.printf("New Connection: nodeId = %u\n", nodeId); Serial.printf("Mesh topology: %s\n", mesh.subConnectionJson(true).c_str()); } void changedConnectionCallback() { Serial.println("Mesh topology changed"); // Get updated list of all nodes std::list nodes = mesh.getNodeList(); Serial.printf("Total nodes in mesh: %d\n", nodes.size()); Serial.print("Node list: "); for (auto &nodeId : nodes) { Serial.printf("%u ", nodeId); } Serial.println(); } void droppedConnectionCallback(uint32_t nodeId) { Serial.printf("Dropped Connection: nodeId = %u\n", nodeId); } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); mesh.onNewConnection(&newConnectionCallback); mesh.onChangedConnections(&changedConnectionCallback); mesh.onDroppedConnection([](uint32_t nodeId) { Serial.printf("Dropped Connection %u\n", nodeId); }); } void loop() { mesh.update(); } ``` -------------------------------- ### TCP Integration Test Executable Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/CMakeLists.txt Defines the 'catch_tcp_integration' executable, linking it with Boost libraries and specifying include directories for Boost, ArduinoJson, and project sources. ```cmake add_executable(catch_tcp_integration test/boost/tcp_integration.cpp test/catch/fake_serial.cpp src/scheduler.cpp) target_include_directories(catch_tcp_integration PUBLIC test/include/ test/boost/ test/ArduinoJson/src/ test/TaskScheduler/src/ src/) TARGET_LINK_LIBRARIES(catch_tcp_integration ${Boost_LIBRARIES}) ``` -------------------------------- ### Time Synchronization Callbacks Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Track time adjustments and measure network delays using callbacks. Nodes automatically synchronize time across the mesh. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; std::list nodes; void nodeTimeAdjustedCallback(int32_t offset) { Serial.printf("Time adjusted. Current: %u, Offset: %d ms\n", mesh.getNodeTime(), offset); } void delayReceivedCallback(uint32_t from, int32_t delay) { Serial.printf("Network delay to node %u: %d microseconds\n", from, delay); } void changedConnectionCallback() { nodes = mesh.getNodeList(); // Measure delay to all nodes for (auto &nodeId : nodes) { mesh.startDelayMeas(nodeId); } } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | S_TIME); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback); mesh.onNodeDelayReceived(&delayReceivedCallback); mesh.onChangedConnections(&changedConnectionCallback); } void loop() { mesh.update(); // Get synchronized mesh time (microseconds, rolls over every 71 minutes) uint32_t meshTime = mesh.getNodeTime(); } ``` -------------------------------- ### Set Connection Change Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Register a callback function that fires when the mesh topology changes. This callback serves as a signal and does not receive any parameters. ```cpp void painlessMesh::onChangedConnections( &changedConnectionsCallback ) ``` -------------------------------- ### Set New Connection Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Define a callback function that is triggered whenever the local node establishes a new connection within the mesh. It receives the ID of the newly connected node. ```cpp void painlessMesh::onNewConnection( &newConnectionCallback ) ``` -------------------------------- ### Schedule Recurring Tasks with TaskScheduler Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Integrate recurring tasks into the mesh network using the TaskScheduler library. Tasks can be configured for various frequencies, durations, and execution counts, and must be enabled after being added to the scheduler. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; // Task runs every second Task taskSendMessage(TASK_SECOND * 1, TASK_FOREVER, []() { String msg = "Sensor value: " + String(random(0, 100)); mesh.sendBroadcast(msg); Serial.printf("Sent: %s\n", msg.c_str()); }); // Task runs every 30 seconds, 10 times total Task taskPeriodicReport(TASK_SECOND * 30, 10, []() { Serial.printf("Report: %d nodes connected\n", mesh.getNodeList().size()); }); // One-shot task Task taskOneTime(TASK_SECOND * 5, TASK_ONCE, []() { Serial.println("One-time initialization complete"); }); void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); // Add tasks to scheduler userScheduler.addTask(taskSendMessage); userScheduler.addTask(taskPeriodicReport); userScheduler.addTask(taskOneTime); // Enable tasks taskSendMessage.enable(); taskPeriodicReport.enable(); taskOneTime.enable(); // Alternative: Add task via mesh.addTask() mesh.addTask(TASK_MINUTE, TASK_FOREVER, []() { Serial.printf("Mesh time: %u\n", mesh.getNodeTime()); }); } void loop() { // mesh.update() runs both mesh tasks and user scheduler mesh.update(); } ``` -------------------------------- ### Station Manual Connection Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Connects the node to an external Wi-Fi Access Point (AP) and optionally establishes a TCP connection. ```APIDOC ## void painlessMesh::stationManual( String ssid, String password, uint16_t port, uint8_t *remote_ip ) ### Description Connects the current node to a Wi-Fi Access Point (AP) outside of the mesh network. If a `remote_ip` and `port` are provided, the node will attempt to open a TCP connection after establishing the Wi-Fi connection. Note that for this to work, the mesh network must be operating on the same Wi-Fi channel as the target AP. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **ssid** (String) - Required - The SSID of the external Wi-Fi network. - **password** (String) - Required - The password for the external Wi-Fi network. - **port** (uint16_t) - Optional - The port number for the TCP connection. If not specified, no TCP connection is attempted. - **remote_ip** (uint8_t *) - Optional - The IP address for the TCP connection. If not specified, no TCP connection is attempted. ``` -------------------------------- ### Update Mesh Network Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Add this to your loop() function to run essential maintenance tasks for the mesh network. Without it, the mesh will not function correctly. ```cpp void painlessMesh::update( void ) ``` -------------------------------- ### PainlessMesh Core Functions Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Provides essential functions for managing the mesh network, including stopping the node, performing updates, and checking connection status. ```APIDOC ## void painlessMesh::stop() ### Description Stops the mesh node, causing it to disconnect from all other nodes and cease sending messages. ### Method void ### Endpoint N/A (Library function) ### Parameters None ### Request Example ```cpp mesh.stop(); ``` ### Response This function returns void. ## void painlessMesh::update( void ) ### Description Performs various maintenance tasks for the mesh network. This routine must be called regularly, typically in the loop() function, for the mesh to operate correctly. ### Method void ### Endpoint N/A (Library function) ### Parameters None ### Request Example ```cpp void loop() { mesh.update(); } ``` ### Response This function returns void. ## bool painlessMesh::isConnected( nodeId ) ### Description Checks if a given node is currently connected to the mesh. ### Method bool ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Details - **nodeId** (uint32_t) - The ID of the node to check connection status for. ### Request Example ```cpp if (mesh.isConnected(someNodeId)) { // Node is connected } ``` ### Response #### Success Response (true/false) - **connected** (bool) - Returns true if the node is connected, false otherwise. ``` -------------------------------- ### PainlessMesh Event Callbacks Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Defines callback functions for handling received messages, new connections, and changes in mesh topology. ```APIDOC ## void painlessMesh::onReceive( &receivedCallback ) ### Description Sets a callback function that is executed whenever a message is received by this node. The callback function receives the sender's ID and the message content. ### Method void ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Details - **receivedCallback** (function pointer) - A pointer to the callback function with the signature `void receivedCallback(uint32_t from, String &msg)`. ### Request Example ```cpp void receivedCallback(uint32_t from, String &msg) { Serial.printf("Received from %u msg=%s\n", from, msg.c_str()); } void setup() { // ... other setup code ... mesh.onReceive(&receivedCallback); } ``` ### Response This function returns void. ## void painlessMesh::onNewConnection( &newConnectionCallback ) ### Description Registers a callback function that is triggered every time the local node establishes a new connection with another node in the mesh. ### Method void ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Details - **newConnectionCallback** (function pointer) - A pointer to the callback function with the signature `void newConnectionCallback(uint32_t nodeId)`. ### Request Example ```cpp void newConnectionCallback(uint32_t nodeId) { Serial.printf("New connection established with node %u\n", nodeId); } void setup() { // ... other setup code ... mesh.onNewConnection(&newConnectionCallback); } ``` ### Response This function returns void. ## void painlessMesh::onChangedConnections( &changedConnectionsCallback ) ### Description Registers a callback function that is executed whenever there is a change in the mesh topology (e.g., nodes connecting or disconnecting). ### Method void ### Endpoint N/A (Library function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Details - **changedConnectionsCallback** (function pointer) - A pointer to the callback function with the signature `void changedConnectionsCallback()`. ### Request Example ```cpp void changedConnectionsCallback() { Serial.println("Mesh topology changed."); } void setup() { // ... other setup code ... mesh.onChangedConnections(&changedConnectionsCallback); } ``` ### Response This function returns void. ``` -------------------------------- ### Connect to External WiFi AP Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Connects the node to an external WiFi Access Point. If a `remote_ip` and `port` are provided, a TCP connection is established after WiFi connection. The mesh must be on the same WiFi channel as the AP. ```cpp void painlessMesh::stationManual( String ssid, String password, uint16_t port, uint8_t *remote_ip ) ``` -------------------------------- ### Register Message Reception Callback Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Register a callback function to handle incoming messages. The callback receives the sender's nodeId and the message content. It can optionally parse JSON messages using ArduinoJson. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; // Callback function for received messages void receivedCallback(uint32_t from, String &msg) { Serial.printf("Received from %u msg=%s\n", from, msg.c_str()); // Parse JSON messages (using ArduinoJson) #if ARDUINOJSON_VERSION_MAJOR >= 6 DynamicJsonDocument doc(1024); DeserializationError error = deserializeJson(doc, msg); if (!error) { String topic = doc["topic"].as(); int value = doc["value"]; Serial.printf("Topic: %s, Value: %d\n", topic.c_str(), value); } #endif } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); // Register the receive callback mesh.onReceive(&receivedCallback); } void loop() { mesh.update(); } ``` -------------------------------- ### Set Message Receive Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Set a callback function to handle incoming messages addressed to this node. The callback receives the sender's ID and the message content. ```cpp void painlessMesh::onReceive( &receivedCallback ) ``` -------------------------------- ### Node Time Adjustment Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md This callback is triggered when the local node time is adjusted to synchronize with the mesh time. The `offset` parameter indicates the calculated adjustment delta. ```cpp void onNodeTimeAdjusted(int32_t offset) ``` -------------------------------- ### Set Debug Message Types Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Configures the internal logging level for the mesh network. ```APIDOC ## void painlessMesh::setDebugMsgTypes( uint16_t types ) ### Description Allows modification of the internal log level. The `types` parameter is a bitmask that enables specific message categories for logging. Available types are defined in `Logger.hpp` and include: ERROR, MESH_STATUS, CONNECTION, SYNC, COMMUNICATION, GENERAL, MSG_TYPES, and REMOTE. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **types** (uint16_t) - Required - A bitmask representing the desired debug message types to enable. ``` -------------------------------- ### Send Broadcast Messages with PainlessMesh Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Broadcasts a message to all nodes on the mesh network. The message can be any string content. Use `mesh.sendBroadcast(msg, true)` to include the sending node in the broadcast. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 Scheduler userScheduler; painlessMesh mesh; Task taskSendMessage(TASK_SECOND * 5, TASK_FOREVER, []() { String msg = "Hello from node "; msg += mesh.getNodeId(); msg += " myFreeMemory: " + String(ESP.getFreeHeap()); // Broadcast to all nodes (excluding self by default) bool success = mesh.sendBroadcast(msg); // To include self in broadcast: // mesh.sendBroadcast(msg, true); Serial.printf("Sending broadcast: %s (success: %d)\n", msg.c_str(), success); }); void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP); mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT); userScheduler.addTask(taskSendMessage); taskSendMessage.enable(); } void loop() { mesh.update(); } ``` -------------------------------- ### Send Single Messages with PainlessMesh Source: https://context7.com/painlessmesh/painlessmesh/llms.txt Sends a message to a specific node identified by its unique nodeId. A `receivedCallback` function is used to handle incoming messages and can be used to send replies. ```cpp #include #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 painlessMesh mesh; uint32_t targetNodeId = 0; // Set to target node's ID void receivedCallback(uint32_t from, String &msg) { Serial.printf("Received from %u: %s\n", from, msg.c_str()); // Echo the message back to sender String reply = "Echo: " + msg; bool success = mesh.sendSingle(from, reply); Serial.printf("Sent reply to %u (success: %d)\n", from, success); } void setup() { Serial.begin(115200); mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT); mesh.onReceive(&receivedCallback); } void loop() { mesh.update(); // Example: Send to specific node if known if (targetNodeId != 0 && mesh.isConnected(targetNodeId)) { mesh.sendSingle(targetNodeId, "Direct message"); } } ``` -------------------------------- ### Node Time Adjustment Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Callback function triggered when local time is adjusted to synchronize with mesh time. ```APIDOC ## void onNodeTimeAdjusted(int32_t offset) ### Description This callback is invoked every time the local node's time is adjusted to synchronize with the mesh time. The `offset` parameter represents the calculated adjustment delta applied to the local clock. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Response #### Success Response (200) - None #### Response Example - None ``` -------------------------------- ### Node Delay Measurement Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md This callback is invoked upon receiving a time delay measurement response. It provides the `nodeId` of the responding node and the one-way network trip `delay` in microseconds. ```cpp void onNodeDelayReceived(uint32_t nodeId, int32_t delay) ``` -------------------------------- ### Check Node Connection Status Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Check if a specific node is currently connected to the mesh. Requires the node ID as input. ```cpp bool painlessMesh::isConnected( nodeId ) ``` -------------------------------- ### Node Delay Received Callback Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Callback function executed when a time delay measurement response is received from a node. ```APIDOC ## void onNodeDelayReceived(uint32_t nodeId, int32_t delay) ### Description This callback is triggered when a response to a time delay measurement request is received. It provides the `nodeId` of the node that sent the response and the `delay` in microseconds, representing the one-way network trip time. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Response #### Success Response (200) - None #### Response Example - None ``` -------------------------------- ### Send Single Message Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Sends a message to a specific node identified by its `dest` ID. Returns true on success, false on failure, printing errors to Serial. ```cpp bool painlessMesh::sendSingle(uint32_t dest, String &msg) ``` -------------------------------- ### Send Single Message Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Sends a message to a specific node in the mesh network. ```APIDOC ## bool painlessMesh::sendSingle(uint32_t dest, String &msg) ### Description Sends a given message (`msg`) to a specific node identified by its `dest` ID. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **dest** (uint32_t) - Required - The ID of the destination node. - **msg** (String) - Required - The message to be sent. ``` -------------------------------- ### Send Broadcast Message Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Sends a message to all nodes in the mesh network. Optionally includes the sending node. ```APIDOC ## bool painlessMesh::sendBroadcast( String &msg, bool includeSelf = false) ### Description Sends a given message (`msg`) to every node in the entire mesh network. By default, the current node is excluded from receiving the message (`includeSelf` is false). Setting `includeSelf` to true will cause the `receivedCallback` to be invoked on the sending node as well. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **msg** (String) - Required - The message to be broadcast. - **includeSelf** (bool) - Optional - If true, the sending node will also receive the message. Defaults to false. ``` -------------------------------- ### Set Debug Message Types Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Modifies the internal logging level by specifying which types of debug messages to display. Available types include ERROR, MESH_STATUS, CONNECTION, SYNC, COMMUNICATION, GENERAL, MSG_TYPES, and REMOTE. ```cpp void painlessMesh::setDebugMsgTypes( uint16_t types ) ``` -------------------------------- ### Send Broadcast Message Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Sends a message to all nodes in the mesh network. By default, the sending node is excluded (`includeSelf = false`). Set `includeSelf = true` to include the sender in the message reception. ```cpp bool painlessMesh::sendBroadcast( String &msg, bool includeSelf = false) ``` -------------------------------- ### Stop Mesh Node Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/README.md Stops the current node, causing it to disconnect from all other nodes and cease message transmission. ```cpp void painlessMesh::stop() ``` -------------------------------- ### C++ Compiler Flags Source: https://gitlab.com/painlessmesh/painlessmesh/-/blob/develop/CMakeLists.txt Appends the '-pthread' flag to the C++ compiler flags. This is often required for multi-threaded applications. ```cmake SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.