Skip to content

Examples

github-actions[bot] edited this page Sep 7, 2026 · 41 revisions

Examples and API Usage

This page provides practical examples of using painlessMesh.

alteriom

//************************************************************
// AlteriomPainlessMesh Example
//
// This example demonstrates how to use AlteriomPainlessMesh
// with custom packages for sensor data, commands, and status
// 
// This is the primary example that matches the folder name
// for Arduino Library Manager compatibility
//************************************************************

#include "AlteriomPainlessMesh.h"
#include "alteriom_sensor_package.hpp"

#define MESH_PREFIX "AlteriomMesh"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

Scheduler userScheduler;  // to control your personal task
painlessMesh mesh;

// Alteriom package handlers
using namespace alteriom;

// User stub
void sendSensorData();
void handleIncomingPackage(uint32_t from, String& msg);
void handleCommandPackage(CommandPackage& cmd);
void handleStatusRequest();

Task taskSendSensorData(30000, TASK_FOREVER, &sendSensorData);
Task taskSendStatus(60000, TASK_FOREVER, &handleStatusRequest);

void setup() {
  Serial.begin(115200);

  // Initialize mesh
  mesh.setDebugMsgTypes(ERROR | MESH_STATUS | CONNECTION | SYNC |
                        COMMUNICATION | GENERAL | MSG_TYPES | REMOTE);
  mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
  mesh.onReceive(&handleIncomingPackage);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  // Add tasks
  userScheduler.addTask(taskSendSensorData);
  taskSendSensorData.enable();

  userScheduler.addTask(taskSendStatus);
  taskSendStatus.enable();

basic

//************************************************************
// this is a simple example that uses the painlessMesh library
//
// 1. sends a silly message to every node on the mesh at a random time between 1 and 5 seconds
// 2. prints anything it receives to Serial.print
//
//
//************************************************************
#include "painlessMesh.h"

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

void sendMessage() {
  String msg = "Hello from node ";
  msg += mesh.getNodeId();
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(115200);

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

bridge

//************************************************************
// Bridge Node Example - Automatic Channel Detection & Resilient Initialization
//
// This example demonstrates the bridge-centric architecture that
// automatically detects the router's WiFi channel and configures the
// mesh network accordingly.
//
// Features:
// - Resilient initialization: Works even if router is unavailable at boot
// - Automatically detects router channel when available
// - Creates mesh network immediately (default channel if needed)
// - No manual channel configuration required
// - Automatically sets itself as root node
// - Retries router connection in background if initially unavailable
// - Broadcasts bridge status to mesh (Type 610 - BRIDGE_STATUS)
//   - Reports Internet connectivity status
//   - Updates every 30 seconds by default
//   - Enables nodes to implement failover and queueing logic
//
// POWER-UP ORDER INDEPENDENCE (v1.9.7+):
// The bridge now initializes successfully regardless of power-up order:
// - Bridge can boot before router is ready
// - Mesh nodes can connect immediately to bridge
// - Router connection is established automatically when available
// - No need to restart bridge when router becomes ready
//
// For more details, see BRIDGE_TO_INTERNET.md
//
// EXTERNAL DEVICE CONNECTIONS:
// ----------------------------
// External devices (phones, computers) can connect to the bridge's WiFi
// AP for debugging and testing purposes. The AP will broadcast the mesh
// SSID (e.g., "whateverYouLike") with the configured password.
//
// Connection details:
// - SSID: Your MESH_PREFIX value
// - Password: Your MESH_PASSWORD value
// - IP Range: 10.x.x.x (automatically assigned via DHCP)
// - Gateway: 10.x.x.1 (the bridge node itself)
//
// Note: ESP32 AP mode supports up to 10 concurrent connections by default,
// ESP8266 supports up to 4. If mesh nodes are already connected, fewer
// slots will be available for external devices.
//
// Troubleshooting external connections:
// 1. Ensure the bridge has successfully initialized (check serial output)
// 2. Wait a few seconds after boot for the AP to fully start
// 3. Check for channel conflicts with other WiFi networks
// 4. Try forgetting the network on your device and reconnecting
// 5. Monitor serial output with CONNECTION debug level enabled

bridge_failover

//************************************************************
// Bridge Failover with RSSI-Based Election Example
//
// This example demonstrates automatic bridge failover in painlessMesh.
// When the primary bridge loses Internet connectivity, nodes automatically
// hold an election to select a new bridge based on router signal strength.
//
// EXTERNAL DEVICE CONNECTIONS FOR DEBUGGING:
// -------------------------------------------
// You can connect phones, computers, or test devices to the mesh network
// for debugging purposes. The bridge node broadcasts the mesh SSID as a
// WiFi Access Point.
//
// Connection details:
// - SSID: "FishFarmMesh" (or your MESH_PREFIX value)
// - Password: "securepass" (or your MESH_PASSWORD value)
// - IP Range: 10.x.x.x/24 (automatically assigned via DHCP)
// - Gateway: 10.x.x.1 (the bridge node itself)
//
// Important notes:
// 1. ESP32 supports up to 10 concurrent AP connections (ESP8266: 4)
// 2. Each mesh node connection uses one slot, leaving fewer for external devices
// 3. After boot, wait 5-10 seconds for the AP to fully initialize
// 4. If you can't connect, try these troubleshooting steps:
//    - Check serial output for "AP configured" message
//    - Verify the channel matches (bridge auto-detects router's channel)
//    - Forget the network on your device and reconnect
//    - Check for WiFi channel conflicts with other networks
// 5. External devices get DHCP but have no internet routing by default
//    (they can only communicate with the mesh network itself)
//
// IMPORTANT - UNDERSTANDING INTERNET CONNECTIVITY:
// ================================================
// The mesh.hasInternetConnection() method checks if a GATEWAY (bridge) node
// has Internet access - it does NOT mean THIS node can make HTTP requests!
//
// Regular mesh nodes do NOT have direct IP routing to the Internet.
// They only communicate via the painlessMesh protocol (node-to-node).
//
// To send data to the Internet from a regular node:
//   1. Use mesh.sendToInternet() to route through a gateway
//      - Call mesh.enableSendToInternet() AFTER mesh.init() on SENDING nodes only
//      - Bridge nodes automatically handle routing via initAsBridge()
//      - See examples/sendToInternet/sendToInternet.ino for complete usage
//   2. Use initAsSharedGateway() so all nodes have router access
//      NOTE: initAsSharedGateway() requires ROUTER credentials:
//      mesh.initAsSharedGateway(MESH_PREFIX, MESH_PASSWORD,
//                               ROUTER_SSID, ROUTER_PASSWORD,  // Router creds required!
//                               &userScheduler, MESH_PORT);
//   3. Send mesh messages to bridge node which handles Internet comms

commandControl

//************************************************************
// Command/control with delivery confirmation (issue #379)
//
// A controller node periodically broadcasts a command to all nodes and
// tracks, per node, whether the command was delivered. Nodes execute
// the command in their onReceive callback; the acknowledgment is sent
// automatically by the library.
//
// The broadcast ack overload requires includeSelf to be passed
// explicitly:
//   mesh.sendBroadcast(msg, false, callback, timeoutMs);
// The callback fires once per mesh node (excluding this node).
//************************************************************
#include <painlessMesh.h>

#define MESH_SSID "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

// Define CONTROLLER on exactly one node to make it send the commands
// #define CONTROLLER

Scheduler userScheduler;
painlessMesh mesh;

uint32_t commandsSent = 0;
uint32_t nodesConfirmed = 0;
uint32_t nodesMissed = 0;
uint32_t resultsReceived = 0;
uint32_t expectedResults = 0;

void sendCommand();
Task taskSendCommand(TASK_SECOND * 15, TASK_FOREVER, &sendCommand);

void sendCommand() {
#ifdef CONTROLLER
  String cmd = String("{\"cmd\":\"setInterval\",\"seconds\":") +
               String(random(5, 60)) + String("}");
  ++commandsSent;
  nodesConfirmed = 0;
  nodesMissed = 0;
  resultsReceived = 0;
  expectedResults = mesh.getNodeList(false).size();

  bool queued = mesh.sendBroadcast(
      cmd, false,
      [](uint32_t nodeId, bool delivered, uint32_t latencyMs) {
        if (delivered) {
          ++nodesConfirmed;
          Serial.printf("Node %u confirmed command in %u ms\n", nodeId,

logClient

//************************************************************
// this is a simple example that uses the painlessMesh library to 
// setup a node that logs to a central logging node
// The logServer example shows how to configure the central logging nodes
//************************************************************
#include "painlessMesh.h"

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

Scheduler     userScheduler; // to control your personal task
painlessMesh  mesh;

// Prototype
void receivedCallback( uint32_t from, String &msg );

size_t logServerId = 0;

// Send message to the logServer every 10 seconds 
Task myLoggingTask(10000, TASK_FOREVER, []() {
#if ARDUINOJSON_VERSION_MAJOR==7
        JsonDocument jsonBuffer;
        JsonObject msg = jsonBuffer.to<JsonObject>();
#elif ARDUINOJSON_VERSION_MAJOR==6
        DynamicJsonDocument jsonBuffer(1024);
        JsonObject msg = jsonBuffer.to<JsonObject>();
#else
        DynamicJsonBuffer jsonBuffer;
        JsonObject& msg = jsonBuffer.createObject();
#endif
    msg["topic"] = "sensor";
    msg["value"] = random(0, 180);

    String str;
#if ARDUINOJSON_VERSION_MAJOR>=6
    serializeJson(msg, str);
#else
    msg.printTo(str);
#endif
    if (logServerId == 0) // If we don't know the logServer yet
        mesh.sendBroadcast(str);
    else
        mesh.sendSingle(logServerId, str);

    // log to serial
#if ARDUINOJSON_VERSION_MAJOR>=6
    serializeJson(msg, Serial);
#else
    msg.printTo(Serial);

logServer

//************************************************************
// this is a simple example that uses the painlessMesh library to 
// setup a single node (this node) as a logging node
// The logClient example shows how to configure the other nodes
// to log to this server
//************************************************************
#include "painlessMesh.h"

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

Scheduler     userScheduler; // to control your personal task
painlessMesh  mesh;
// Prototype
void receivedCallback( uint32_t from, String &msg );


// Send my ID every 10 seconds to inform others
Task logServerTask(10000, TASK_FOREVER, []() {
#if ARDUINOJSON_VERSION_MAJOR==7
        JsonDocument jsonBuffer;
        JsonObject msg = jsonBuffer.to<JsonObject>();
#elif ARDUINOJSON_VERSION_MAJOR==6
        DynamicJsonDocument jsonBuffer(1024);
        JsonObject msg = jsonBuffer.to<JsonObject>();
#else
        DynamicJsonBuffer jsonBuffer;
        JsonObject& msg = jsonBuffer.createObject();
#endif
    msg["topic"] = "logServer";
    msg["nodeId"] = mesh.getNodeId();

    String str;
#if ARDUINOJSON_VERSION_MAJOR>=6
    serializeJson(msg, str);
#else
    msg.printTo(str);
#endif
    mesh.sendBroadcast(str);

    // log to serial
#if ARDUINOJSON_VERSION_MAJOR>=6
    serializeJson(msg, Serial);
#else
    msg.printTo(Serial);
#endif
    Serial.printf("\n");
});

mqttBridge

//************************************************************
// this is a simple example that uses the painlessMesh library to
// connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
// To send a message to a mesh node, you can publish it to "painlessMesh/to/12345678" where 12345678 equals the nodeId.
// To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
// When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
// Every message from the mesh which is send to the gateway node will be published to "painlessMesh/from/12345678" where 12345678 
// is the nodeId from which the packet was send.
//************************************************************

#include <Arduino.h>
#include <painlessMesh.h>
// Requires the "PubSubClient" library by Nick O'Leary. Arduino IDE users:
// install it via Library Manager (Tools > Manage Libraries... > search
// "PubSubClient"); PlatformIO users already get it automatically from this
// example's platformio.ini.
#include <PubSubClient.h>
#include <WiFiClient.h>

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

#define   STATION_SSID     "YourAP_SSID"
#define   STATION_PASSWORD "YourAP_PWD"

#define HOSTNAME "MQTT_Bridge"

// Prototypes
void receivedCallback( const uint32_t &from, const String &msg );
void mqttCallback(char* topic, byte* payload, unsigned int length);

IPAddress getlocalIP();

IPAddress myIP(0,0,0,0);
IPAddress mqttBroker(192, 168, 1, 1);

painlessMesh  mesh;
WiFiClient wifiClient;
PubSubClient mqttClient(mqttBroker, 1883, mqttCallback, wifiClient);

void setup() {
  Serial.begin(115200);

  mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION );  // set before init() so that you can see startup messages

  // Channel set to 6. Make sure to use the same channel for your mesh and for you other
  // network (STATION_SSID)
  mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
  mesh.onReceive(&receivedCallback);

namedMesh

//************************************************************
// this is a simple example that uses the painlessMesh library
//
// This example shows how to build a mesh with named nodes using the plugin
// system
//
//
//************************************************************
#include <cstdint>
#include <map>
#include "Arduino.h"
#include "painlessMesh.h"
#include "painlessmesh/plugin.hpp"

#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

painlessMesh mesh;

// NOTE: various ideas for improvement
// - Send new names regularly and only send all names sometimes
// - Keep track of the names the neighbour already knows (when we receive them)
//   and only send unknown names/nodes
// - Use some kind of bidirectoral map, so both get_name_from_id and
//   get_id_from_name are fast

// Send the names you know to your neighbours
class NamePackage : public painlessmesh::plugin::NeighbourPackage {
 public:
  std::map<TSTRING, uint32_t> names;

  // Set an id for the package. Id can be any unique int not already in use. The
  // mesh uses the numbers 1..12, so using a number larger than that
  NamePackage() : painlessmesh::plugin::NeighbourPackage(21) {}

  NamePackage(JsonObject jsonObj)
      : painlessmesh::plugin::NeighbourPackage(jsonObj) {
    for (JsonPair kv : jsonObj) {
      names.insert(std::pair<TSTRING, uint32_t>(kv.key().c_str(), kv.value()));
    }
  }

  JsonObject addTo(JsonObject&& jsonObj) const {
    jsonObj = painlessmesh::plugin::NeighbourPackage::addTo(std::move(jsonObj));
    for (auto&& kv : names) {
      jsonObj[kv.first] = kv.second;
    }
    return jsonObj;
  }

otaReceiver

//************************************************************
// this is a simple example that uses the painlessMesh library
//
// 1. sends a silly message to every node on the mesh at a random time between 1
// and 5 seconds
// 2. prints anything it receives to Serial.print
// 3. has OTA support and can be updated remotely
//
//************************************************************
#include "painlessMesh.h"

#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

Scheduler userScheduler;  // to control your personal task
painlessMesh mesh;

// User stub
void sendMessage();  // Prototype so PlatformIO doesn't complain

Task taskSendMessage(TASK_SECOND * 1, TASK_FOREVER, &sendMessage);

void sendMessage() {
  String msg = "Hello from node ";
  msg += mesh.getNodeId();
  mesh.sendBroadcast(msg);
  taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
}

// Needed for painless library
void receivedCallback(uint32_t from, String &msg) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

void changedConnectionCallback() { Serial.printf("Changed connections\n"); }

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
}

void setup() {
  Serial.begin(115200);

  // mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC |
  // COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

otaSender

//************************************************************
// this is an example that uses the painlessmesh library to
// upload firmware to another node on the network. 
// This will upload to an ESP device running the otaReceiver.ino
//
// The naming convetions should be as follows for bin files
// firmware_<hardware>_<role>.bin
// To create your own binary files, export them and rename
// them to follow this format, where hardware will be
// "ESP8266" or "ESP32" (capitalized.)
// If sending to the otacreceiver sketch, role should be
// "otareceiver" (lowercase)
//
// This sketch assumes a Nodemcu-32s with an SD card
// connected as shown in the jpg included in the sketch folder
// This code may have to be reworked/hardware adjusted for
// other boards or ESP8266. The core code works well though
//
// MAKE SURE YOUR UPLOADED OTA FIRMWARE INCLUDES OTA SUPPORT 
// OR YOU WILL LOSE THE ABILITY TO UPLOAD MORE FIRMWARE.
// THE INCLUDED .bin DOES NOT HAVE OTA SUPPORT SO THIS MUST BE
// REFLASHED
//************************************************************

#ifdef ESP32
#else
// SD card chip-select. The D0..D8 aliases only exist on the NodeMCU/Wemos
// ESP8266 variants; the "generic" ESP8266 variant does not define them, so
// D8 fails to compile there. SS is GPIO15 on every ESP8266 variant, which is
// the exact pin D8 maps to on NodeMCU, so this is portable and equivalent.
#define CS_PIN  SS
#endif

#include "painlessMesh.h"

#include <FS.h>
#include "SD.h"
#include "SPI.h"

#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

#define OTA_PART_SIZE 1024 //How many bytes to send per OTA data packet

painlessMesh mesh;

void setup() {
  Serial.begin(115200);
  delay(1000);

priority

/**
 * Advanced Priority Example with Message Queue Integration
 * 
 * Demonstrates how to use priority messaging with the message queue
 * for offline/Internet-unavailable scenarios.
 * 
 * This example shows:
 * - Priority-based message sending
 * - Message queueing when Internet is unavailable
 * - Automatic queue flushing when Internet becomes available
 * - Priority ordering during queue flush
 * 
 * Hardware: ESP32 or ESP8266
 */

#include "painlessMesh.h"

#define MESH_PREFIX     "PriorityQueueMesh"
#define MESH_PASSWORD   "somethingSneaky"
#define MESH_PORT       5555

Scheduler userScheduler;
painlessMesh mesh;

// The queue types live in the painlessmesh namespace
using painlessmesh::MessagePriority;
using painlessmesh::QueueState;
using painlessmesh::PRIORITY_CRITICAL;
using painlessmesh::PRIORITY_HIGH;
using painlessmesh::PRIORITY_NORMAL;
using painlessmesh::PRIORITY_LOW;
using painlessmesh::QUEUE_EMPTY;
using painlessmesh::QUEUE_NORMAL;
using painlessmesh::QUEUE_75_PERCENT;
using painlessmesh::QUEUE_FULL;

// Forward declarations: Arduino's auto-prototype generation does not see
// past the global lambdas below
void sendMessage(String message, uint8_t priority);
void flushQueuedMessages();
void queueStateChanged(QueueState state, uint32_t count);

bool internetAvailable = false;
uint32_t bridgeNodeId = 0;

// Task to check bridge status
Task taskCheckBridge(5000, TASK_FOREVER, []() {
    bool hasInternet = mesh.hasInternetConnection();
    
    if (hasInternet != internetAvailable) {

reliableSensorLogging

//************************************************************
// Reliable sensor logging with delivery confirmation (issue #379)
//
// Demonstrates the per-message acknowledgment API:
// 1. every 10 seconds a sensor reading is sent to a gateway node
// 2. the reading stays in a small retry buffer until the gateway
//    confirms delivery (delivered == true)
// 3. unconfirmed readings are retried up to MAX_ATTEMPTS times
//
// Run one node with GATEWAY defined and one or more sensor nodes. The
// gateway announces its node id; only sensor nodes generate readings.
//************************************************************
#include <painlessMesh.h>

#define MESH_SSID "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

// Define GATEWAY on exactly one node.
// #define GATEWAY

// How long to wait for a delivery confirmation
#define ACK_TIMEOUT_MS 3000
// How often a reading is retried before it is dropped
#define MAX_ATTEMPTS 3

Scheduler userScheduler;
painlessMesh mesh;

// The node we log readings to. In a real deployment you would discover
// this via a broadcast announcement or hardcode your gateway's node id.
uint32_t gatewayId = 0;

// A single buffered reading awaiting confirmation
struct PendingReading {
  String payload;
  uint8_t attempts = 0;
  bool inFlight = false;
};
PendingReading pending;

void sendReading();
Task taskSendReading(TASK_SECOND * 10, TASK_FOREVER, &sendReading);
#ifdef GATEWAY
void announceGateway();
Task taskAnnounceGateway(TASK_SECOND * 5, TASK_FOREVER, &announceGateway);
#endif

void transmitPending() {
  if (gatewayId == 0 || pending.payload.length() == 0 || pending.inFlight)

sendToInternet

//************************************************************
// Mock HTTP Server Integration Example
//
// This example demonstrates how to use the mock HTTP server
// for testing sendToInternet() functionality without requiring
// actual Internet connectivity.
//
// Setup:
// 1. Start the mock server on your development machine:
//    cd test/mock-http-server
//    python3 server.py
//
// 2. Update MOCK_SERVER_IP below with your computer's IP address
//
// 3. Upload this sketch to your ESP32/ESP8266
//
// 4. Watch the serial output and mock server logs
//
// The sketch will automatically run through various test scenarios
// and report pass/fail results for each test case.
//************************************************************

#include "painlessMesh.h"

// ============================================
// Configuration
// ============================================
#define MESH_PREFIX     "TestMesh"
#define MESH_PASSWORD   "testpass123"
#define MESH_PORT       5555

// Router credentials (for bridge node)
#define ROUTER_SSID     "YourRouterSSID"
#define ROUTER_PASSWORD "YourRouterPassword"

// Mock HTTP Server Configuration
// Replace with your computer's IP address where mock server is running
#define MOCK_SERVER_IP   "192.168.1.100"  // ← CHANGE THIS
#define MOCK_SERVER_PORT 8080

// Set to true if this node should be the bridge
#define IS_BRIDGE true

// ============================================
// Global Objects
// ============================================
Scheduler userScheduler;
painlessMesh mesh;

// Test tracking

sharedGateway

//************************************************************
// Shared Gateway Example
//
// This example demonstrates the Shared Gateway Mode feature of painlessMesh.
// Unlike the Bridge Mode where only one node connects to the router,
// Shared Gateway Mode allows ALL nodes to connect to the same WiFi router
// while maintaining mesh connectivity.
//
// Key Features:
// - All nodes operate in AP+STA mode simultaneously
// - All nodes connect to the same WiFi router
// - Mesh and router operate on the same channel for reliability
// - Automatic router reconnection if connection is lost
// - Each node can independently access the Internet
//
// Use Cases:
// - Industrial sensor networks where all nodes are within router range
// - Smart building systems requiring redundant Internet access
// - Fish farm monitoring where any node can send critical alarms to cloud
// - Remote monitoring stations with shared WiFi infrastructure
//
// Hardware Requirements:
// - ESP32 or ESP8266
// - WiFi router within range of all nodes
//
// How It Works:
// 1. Each node connects to the router to detect its WiFi channel
// 2. Mesh network is initialized on the same channel as the router
// 3. Router connection is re-established using stationManual()
// 4. Periodic monitoring ensures automatic reconnection if router is lost
//
// For more details, see docs/design/SHARED_GATEWAY_DESIGN.md
//
//************************************************************
#include "painlessMesh.h"

// ============================================
// Mesh Network Configuration
// ============================================
// These settings must match across all nodes in your mesh network
#define MESH_PREFIX     "SharedGatewayMesh"  // Mesh network name (SSID prefix)
#define MESH_PASSWORD   "meshPassword123"    // Mesh network password
#define MESH_PORT       5555                 // TCP port for mesh communication

// ============================================
// Router Configuration
// ============================================
// Configure these to match your WiFi router settings
// All nodes in the mesh will connect to this same router
#define ROUTER_SSID     "YourRouterSSID"     // Your WiFi router name

startHere

//************************************************************
// this is a simple example that uses the easyMesh library
//
// 1. blinks led once for every node on the mesh
// 2. blink cycle repeats every BLINK_PERIOD
// 3. sends a silly message to every node on the mesh at a random time between 1 and 5 seconds
// 4. prints anything it receives to Serial.print
//
//
//************************************************************
#include <painlessMesh.h>

// some gpio pin that is connected to an LED...
// on my rig, this is 2, change to the right number of your LED.
#ifndef LED
  #ifdef LED_BUILTIN
    #define LED LED_BUILTIN
  #else
    #define LED 2
  #endif
#endif

#define   BLINK_PERIOD    3000 // milliseconds until cycle repeat
#define   BLINK_DURATION  100  // milliseconds LED is on for

#define   MESH_SSID       "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

// Prototypes
void sendMessage(); 
void receivedCallback(uint32_t from, String & msg);
void newConnectionCallback(uint32_t nodeId);
void changedConnectionCallback(); 
void nodeTimeAdjustedCallback(int32_t offset); 
void delayReceivedCallback(uint32_t from, int32_t delay);

Scheduler     userScheduler; // to control your personal task
painlessMesh  mesh;

bool calc_delay = false;
SimpleList<uint32_t> nodes;

void sendMessage() ; // Prototype
Task taskSendMessage( TASK_SECOND * 1, TASK_FOREVER, &sendMessage ); // start with a one second interval

// Task to blink the number of nodes
Task blinkNoNodes;
bool onFlag = false;

tcpRetryConfig

//************************************************************
// Tuning the TCP connection retry behaviour (issue #378)
//
// painlessMesh retries a failed TCP connection with exponential backoff
// before giving up and falling back to a full WiFi reconnect. The defaults
// (5 retries, 1s base delay -> 1s, 2s, 4s, 8s, 8s) are tuned for general
// purpose meshes and deliberately favour reliability over speed.
//
// setTcpRetryConfig() lets you pick a different trade-off. Three ready-made
// profiles are shown below; switch between them with ACTIVE_PROFILE.
//
// Read examples/tcpRetryConfig/README.md before changing these values - the
// defaults exist because 1.9.x raised them to fix real mesh instability.
//************************************************************
#include <painlessMesh.h>

#define   MESH_SSID       "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

// ---------------------------------------------------------------------------
// Profiles
// ---------------------------------------------------------------------------
#define PROFILE_REALTIME  1   // low latency: fail fast, reconnect fast
#define PROFILE_RELIABLE  2   // industrial: many retries, long backoff
#define PROFILE_BATTERY   3   // conserve power: few retries, long block

// >>> Change this line to try a different profile <<<
#define ACTIVE_PROFILE    PROFILE_REALTIME

// Prototypes
void sendMessage();
void receivedCallback(uint32_t from, String &msg);
void newConnectionCallback(uint32_t nodeId);
void droppedConnectionCallback(uint32_t nodeId);

Scheduler     userScheduler;
painlessMesh  mesh;

Task taskSendMessage(TASK_SECOND * 5, TASK_FOREVER, &sendMessage);

// Build the retry configuration for the selected profile.
painlessmesh::tcp::TcpRetryConfig buildRetryConfig() {
  painlessmesh::tcp::TcpRetryConfig cfg;  // starts at the library defaults

#if ACTIVE_PROFILE == PROFILE_REALTIME
  // Real-time sensor / LED meshes: a stalled node is worse than a dropped
  // one. Give up on the TCP handshake almost immediately and go straight
  // back to scanning for another parent.
  cfg.maxRetries = 1;                    // default 5

webServer

//************************************************************
// this is a simple example that uses the painlessMesh library to
// connect to a another network and broadcast message from a webpage to the edges of the mesh network.
// This sketch can be extended further using all the abilities of the AsyncWebserver library (WS, events, ...)
// for more details
// https://gitlab.com/painlessMesh/painlessMesh/wikis/bridge-between-mesh-and-another-network
// for more details about my version
// https://gitlab.com/Assassynv__V/painlessMesh
// and for more details about the AsyncWebserver library
// https://github.com/me-no-dev/ESPAsyncWebServer
//************************************************************

#include "IPAddress.h"
#include "painlessMesh.h"

#ifdef ESP8266
#include "Hash.h"
#include <ESPAsyncTCP.h>
#else
#include <AsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

#define   STATION_SSID     "mySSID"
#define   STATION_PASSWORD "myPASSWORD"

#define HOSTNAME "HTTP_BRIDGE"

// Prototype
void receivedCallback( const uint32_t &from, const String &msg );
IPAddress getlocalIP();

painlessMesh  mesh;
AsyncWebServer server(80);
IPAddress myIP(0,0,0,0);
IPAddress myAPIP(0,0,0,0);

void setup() {
  Serial.begin(115200);

  mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION );  // set before init() so that you can see startup messages

  // Channel set to 6. Make sure to use the same channel for your mesh and for you other
  // network (STATION_SSID)
  mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
  mesh.onReceive(&receivedCallback);

Clone this wiki locally