From 73e9f4af8f64de1726cf04fa7f453dac180e1632 Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Sun, 10 Jun 2018 21:42:57 +0200 Subject: [PATCH] mesh mqtt gateway example --- platformio.ini | 19 +++- src/MeshNet.h | 9 +- src/Network.h | 2 + src/examples/mesh/MeshApp.h | 20 ++-- .../mesh/mesh_example_non_sprocket.cpp_ | 66 ------------ src/examples/mqttBridge/MqttMeshBridge.h | 101 ++++++++++++++++++ src/examples/mqttBridge/bridge.cpp | 29 +++++ 7 files changed, 164 insertions(+), 82 deletions(-) delete mode 100644 src/examples/mesh/mesh_example_non_sprocket.cpp_ create mode 100644 src/examples/mqttBridge/MqttMeshBridge.h create mode 100644 src/examples/mqttBridge/bridge.cpp diff --git a/platformio.ini b/platformio.ini index 9b6076d..95b085d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; http://docs.platformio.org/page/projectconf.html [platformio] -env_default = mesh +env_default = meshMqttBridge [common] framework = arduino @@ -34,7 +34,7 @@ lib_deps = ${common.lib_deps} ;upload_port = 192.168.1.168 [env:basic] -src_filter = +<*> + - +src_filter = +<*> + - - platform = espressif8266 board = esp12e upload_speed = 921600 @@ -45,11 +45,22 @@ lib_deps = ${common.lib_deps} [env:mesh] -src_filter = +<*> + - +src_filter = +<*> + - - platform = espressif8266 board = esp12e upload_speed = 921600 monitor_baud = 115200 framework = ${common.framework} lib_deps = ${common.lib_deps} - painlessMesh \ No newline at end of file + painlessMesh + +[env:meshMqttBridge] +src_filter = +<*> + - - +platform = espressif8266 +board = esp12e +upload_speed = 921600 +monitor_baud = 115200 +framework = ${common.framework} +lib_deps = ${common.lib_deps} + painlessMesh + PubSubClient \ No newline at end of file diff --git a/src/MeshNet.h b/src/MeshNet.h index b9e4ed0..8a3e3f9 100644 --- a/src/MeshNet.h +++ b/src/MeshNet.h @@ -2,7 +2,7 @@ #define __MESHNET_H__ #include - +#include #include "Network.h" using namespace std; @@ -13,15 +13,13 @@ using namespace std::placeholders; #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555 - - class MeshNet : public Network { public: painlessMesh mesh; Network* init(){ Serial.println("init mesh"); //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on - mesh.setDebugMsgTypes( ERROR | STARTUP); + mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION); mesh.init( MESH_PREFIX, MESH_PASSWORD, scheduler, MESH_PORT, WIFI_AP_STA, 11 ); //mesh.onReceive(bind(&MeshNet::receivedCallback,this, _1, _2)); mesh.onNewConnection(bind(&MeshNet::newConnectionCallback, this, _1)); @@ -31,6 +29,9 @@ class MeshNet : public Network { return this; } Network* connect(){ + Serial.println("connect station"); + mesh.stationManual("tErAx1d", "ramalamadingdong"); + mesh.setHostname("MeshNode"); return this; } void broadcast(String msg){ diff --git a/src/Network.h b/src/Network.h index 5aaed9e..9bfc17c 100644 --- a/src/Network.h +++ b/src/Network.h @@ -3,12 +3,14 @@ #include #include +#include class Network { public: uint32_t id = 0; Network(){} Scheduler* scheduler; + //WiFiClient wifiClient; virtual Network* init() { return this; }; virtual Network* connect() { return this; }; virtual void update() {}; diff --git a/src/examples/mesh/MeshApp.h b/src/examples/mesh/MeshApp.h index c8b823d..d3e926c 100644 --- a/src/examples/mesh/MeshApp.h +++ b/src/examples/mesh/MeshApp.h @@ -3,6 +3,7 @@ #include #include "App.h" +#include "MeshNet.h" #define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" @@ -17,18 +18,21 @@ class MeshApp : public App { MeshNet* net; MeshApp() /* : App(sprkt) */ { } + + void activate(Scheduler* scheduler, Network* network) { + net = static_cast(network); + net->mesh.onReceive(bind(&MeshApp::receivedCallback,this, _1, _2)); + // add a task that sends stuff to the mesh + someTask.set(TASK_SECOND * 5, TASK_FOREVER, + bind(&MeshApp::advertise, this, net)); + scheduler->addTask(someTask); + someTask.enable(); + } + void advertise(MeshNet* network){ String msg = "Hi, my name is " + String(network->id); network->broadcast(msg); } - void activate(Scheduler* scheduler, Network* network) { - net = static_cast(network); - someTask.set(TASK_SECOND * 5, TASK_FOREVER, - bind(&MeshApp::advertise, this, net)); - net->mesh.onReceive(bind(&MeshApp::receivedCallback,this, _1, _2)); - scheduler->addTask(someTask); - someTask.enable(); - } void receivedCallback( uint32_t from, String &msg ) { Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str()); diff --git a/src/examples/mesh/mesh_example_non_sprocket.cpp_ b/src/examples/mesh/mesh_example_non_sprocket.cpp_ deleted file mode 100644 index e6d484e..0000000 --- a/src/examples/mesh/mesh_example_non_sprocket.cpp_ +++ /dev/null @@ -1,66 +0,0 @@ -//************************************************************ -// 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 %s\n",mesh.subConnectionJson().c_str()); -} - -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 - //mesh.setDebugMsgTypes( ERROR | STARTUP ); // set before init() so that you can see startup messages - - mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT, WIFI_AP_STA, 6 ); - mesh.onReceive(&receivedCallback); - mesh.onNewConnection(&newConnectionCallback); - mesh.onChangedConnections(&changedConnectionCallback); - mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback); - - userScheduler.addTask( taskSendMessage ); - taskSendMessage.enable(); -} - -void loop() { - userScheduler.execute(); // it will run mesh scheduler as well - mesh.update(); -} \ No newline at end of file diff --git a/src/examples/mqttBridge/MqttMeshBridge.h b/src/examples/mqttBridge/MqttMeshBridge.h new file mode 100644 index 0000000..e331259 --- /dev/null +++ b/src/examples/mqttBridge/MqttMeshBridge.h @@ -0,0 +1,101 @@ +#ifndef __MESH_MQTT_BRIDGE_APP__ +#define __MESH_MQTT_BRIDGE_APP__ + +#include +#include +#include +#include "App.h" +#include "MeshNet.h" + +#define MQTT_CLIENT_NAME "meshBridge" +#define MQTT_BROKER_HOST "citadel.lan" +#define MQTT_BROKER_PORT 1883 +#define MQTT_TOPIC_ROOT "mesh" + +using namespace std; +using namespace std::placeholders; + +WiFiClient wifiClient; + +class MqttMeshBridge : public App { + public: + Task connectTask; + Task processTask; + MeshNet* net; + PubSubClient* client; + + MqttMeshBridge() /* : App(sprkt) */ { + } + + void activate(Scheduler* scheduler, Network* network) { + net = static_cast(network); + net->mesh.onReceive(bind(&MqttMeshBridge::receivedCallback,this, _1, _2)); + client = new PubSubClient(MQTT_BROKER_HOST, MQTT_BROKER_PORT, bind(&MqttMeshBridge::mqttCallback, this, _1, _2, _3), wifiClient); + // add a task that sends stuff to the mesh + enableConnectTask(scheduler); + enableProcessTask(scheduler); + } + + void enableConnectTask(Scheduler* scheduler){ + connectTask.set(TASK_SECOND * 5, TASK_FOREVER, + bind(&MqttMeshBridge::connect, this)); + scheduler->addTask(connectTask); + connectTask.enable(); + } + + void enableProcessTask(Scheduler* scheduler){ + processTask.set(TASK_MILLISECOND * 5, TASK_FOREVER, + bind(&MqttMeshBridge::process, this)); + scheduler->addTask(processTask); + processTask.enable(); + } + + void process(){ + client->loop(); + } + + void connect() { + if (!client->connected()) { + if (client->connect(MQTT_CLIENT_NAME)) { + Serial.println("MQTT connected"); + client->publish("mesh/from/gateway","Ready!"); + client->subscribe("mesh/to/#"); + } + } + } + + void receivedCallback( uint32_t from, String &msg ) { + Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str()); + String topic = "mesh/from/" + String(from); + client->publish(topic.c_str(), msg.c_str()); + } + + void mqttCallback(char* topic, uint8_t* payload, unsigned int length) { + char* cleanPayload = (char*)malloc(length+1); + payload[length] = '\0'; + memcpy(cleanPayload, payload, length+1); + String msg = String(cleanPayload); + free(cleanPayload); + + int topicRootLength = String(MQTT_TOPIC_ROOT).length(); + String targetStr = String(topic).substring(topicRootLength + 4); + + if(targetStr == "gateway"){ + if(msg == "getNodes") { + client->publish("mesh/from/gateway", net->mesh.subConnectionJson().c_str()); + } + } else if(targetStr == "broadcast") { + net->mesh.sendBroadcast(msg); + } else { + uint32_t target = strtoul(targetStr.c_str(), NULL, 10); + if(net->mesh.isConnected(target)){ + net->mesh.sendSingle(target, msg); + } else { + client->publish("mesh/from/gateway", "Client not connected!"); + } + } + } + +}; + +#endif \ No newline at end of file diff --git a/src/examples/mqttBridge/bridge.cpp b/src/examples/mqttBridge/bridge.cpp new file mode 100644 index 0000000..6ca0e24 --- /dev/null +++ b/src/examples/mqttBridge/bridge.cpp @@ -0,0 +1,29 @@ +#define _TASK_SLEEP_ON_IDLE_RUN +#define _TASK_STD_FUNCTION + +#include "Network.h" +#include "MeshNet.h" +#include "Sprocket.h" +#include "AppStack.h" +#include "MqttMeshBridge.h" + +#define SERIAL_BAUD_RATE 115200 +#define STARTUP_DELAY 3000 + +SprocketConfig config = { SERIAL_BAUD_RATE }; + +Sprocket sprocket; +MeshNet net; +MqttMeshBridge app; + +void setup() { + delay(STARTUP_DELAY); + sprocket.init(config); + sprocket.join(net, app); +} + +void loop() { + net.update(); + sprocket.loop(); + yield(); +} \ No newline at end of file