Includes:
- Mesh usb adapter codes (for esp32/esp2866).
- Mesh gateway codes (Convert messages between mesh network and MQTT broker)
- Slave node example codes (Slave node can read sensors, control switches/lights or something else)
Features:
- Works on EspNow broadcast
- Nearly instant connection after poweron
- Maximum number of slave nodes: unlimited
- Flooding mesh support
- a message cache. If a received packet is already found in the cache --> it will not be retransmitted or handled again
- Mesh nodes use MQTT service (subscribe/publish)
- Master node (USBAdapter=ESP32 or ESP2866) is connected to RaspberryPi's USB port
- Each Nodes can communicate with each other
- ESP32, ESP2866, ESP01
- Ping about 40-60ms
- ttl support
- Battery node support
- AES128
- Retransmission support
- Request/Reply support
- Send and pray support (Send a message to all nodes without reply/ack)
- Easy to configure (just set channel, secure keys and bsid)
- Simple mqqt interface. All nodes can use mqtt services via master node (subsribe,unsubscribe,publish,get).
- MQTT local cache on raspberry
- Arduino
____________________________________ ( ) | | ( Internet ) | | (____________________________________) ^ |MQTT | +--------------------|-------+ | RaspberryPi V | |-------------+ +--+-------| | MeshGateway |<->| MQTT | +-------------------------------------+ | | | broker | | ESPNOW mesh network | +-----+-------+---+----------+ | Node6 | ^ | Node1 Node3 | | USB(SerialData) | +------------+ Node3 Node5 | +------------------------------>| USBAdapter | Node4 | | | (Master) | NodeX Node7 | | +------------+ | +-------------------------------------+
Flooding mesh network
In this network example ttl must be >= 5
SlaveNode | | Message from master to BatteryNode | ---------------------------+ | ttl=5 ttl=4 | SlaveNode-------MasterNode-------------SlaveNode | | | | | | | | | | | | | SlaveNode | | | | | | | | | | +------------------------------------------------> | | ttl=3 ttl=2 ttl=1 SlaveNode-------SlaveNode-------------SlaveNode-------SlaveNode-------------SlaveNode---------BatteryNode | | | | | | | | | | | | +-----------SlaveNode-----------------+
Message relay
The Master sends a request to the farthest node and the farthest node replies.

Arduino libraries (dependencies):
- https://github.com/arttupii/espNowFloodingMeshLibrary
- https://github.com/arttupii/ArduinoCommands
- https://github.com/arttupii/SimpleMqttLibrary
- https://github.com/kakopappa/arduino-esp8266-aes-lib (Only ESP2866)
Slave Node examples
- PIR-sensor node: https://github.com/arttupii/PirSensorNode
- Relay switch node: https://github.com/arttupii/mesh-relay
- Temperature sensor node: https://github.com/arttupii/mesh-dallas
Early demo video
Mesh usb adapter
Mesh slave node codes
- Esp32/Esp2866/Esp-01
- https://github.com/arttupii/EspNowUsb/tree/master/arduinoSlaveNode/main
MeshGateway software for RaspberryPi (conversation between mesh and mqtt broker)
Slave node code example
Slave node updates the button's state to topic device1/switch/led/value. The led state can be controlled with topic device1/switch/led/set on/off.
#include <EspNowFloodingMesh.h>
#include<SimpleMqtt.h>
/********NODE SETUP********/
#define ESP_NOW_CHANNEL 1
const char deviceName[] = "device1";
unsigned char secredKey[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
unsigned char iv[16] = {0xb2, 0x4b, 0xf2, 0xf7, 0x7a, 0xc5, 0xec, 0x0c, 0x5e, 0x1f, 0x4d, 0xc1, 0xae, 0x46, 0x5e, 0x75};
const int ttl = 3;
const int bsid = 0x112233;
/*****************************/
#define LED 1
#define BUTTON_PIN 2
SimpleMQTT simpleMqtt = SimpleMQTT(ttl, deviceName);
bool setLed;
bool ledValue;
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
espNowFloodingMesh_secredkey(secredKey);
espNowFloodingMesh_setAesInitializationVector(iv);
espNowFloodingMesh_setToMasterRole(false, ttl);
espNowFloodingMesh_begin(ESP_NOW_CHANNEL, bsid);
espNowFloodingMesh_ErrorDebugCB([](int level, const char *str) {
Serial.print(level); Serial.println(str); //If you want print some debug prints
});
if (!espNowFloodingMesh_syncWithMasterAndWait()) {
//Sync failed??? No connection to master????
Serial.println("No connection to master!!! Reboot");
ESP.restart();
}
//Handle MQTT events from master. Do not call publish() inside of call back. --> Endless event loop and crash
simpleMqtt.handleEvents([](const char *topic, const char* value) {
simpleMqtt._ifSwitch(VALUE, "led", [](MQTT_switch value){ //<--> Listening topic switch/led/value/value
if(value==SWITCH_ON) {
ledValue = true;
}
if(value==SWITCH_OFF) {
ledValue = false;
}
});
simpleMqtt._ifSwitch(SET, "led", [](MQTT_switch set){ //<-->Listening topic device1/switch/led/set
if(set==SWITCH_ON) {
setLed = true;
}
if(set==SWITCH_OFF) {
setLed = false;
}
});
});
if (!simpleMqtt._switch(SUBSCRIBE, "led")) { //Subscribe topic device1/switch/led/set and get topic device1/switch/led/value from cache
Serial.println("MQTT operation failed. No connection to gateway");
}
}
bool buttonStatechange = false;
void loop() {
espNowFloodingMesh_loop();
int p = digitalRead(BUTTON_PIN);
if (p == HIGH && buttonStatechange == false) {
buttonStatechange = true;
setLed = true;
}
if (p == LOW && buttonStatechange == true) {
buttonStatechange = false;
setLed = false;
}
if (ledValue == true && setLed == false) {
ledValue = false;
Serial.println("LED_OFF");
//digitalWrite(LED,HIGH);
if (!simpleMqtt._switch(PUBLISH, "led", SWITCH_OFF)) { //publish topic device1/switch/led/value off
Serial.println("Publish failed... Reboot");
Serial.println(ESP.getFreeHeap());
ESP.restart();
}
}
if (ledValue == false && setLed == true) {
ledValue = true;
Serial.println("LED_ON");
if (!simpleMqtt._switch(PUBLISH, "led", SWITCH_ON)) { //publish topic device1/switch/led/value on
Serial.println("Publish failed... Reboot");
Serial.println(ESP.getFreeHeap());
ESP.restart();
}
}
delay(100);
}
Config file for MeshGateway on RasperryPi
module.exports = {
"usbPort": "/dev/ttyUSB0",
"mesh": {
"secredKey": [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF],
"ttl": 3,
"channel": 1
},
"dbCacheFile":"./cache.json",
"mqtt": {
"host": "mqtt://localhost",
"root": "mesh/"
}
}