From 52fdf0e5e0da3733d121ad60cf935aabf37d23e8 Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Wed, 29 Aug 2018 09:03:38 +0200 Subject: [PATCH] move webserver stuff to plugin --- README.md | 12 +++-- data/www/index.html | 7 +++ platformio.ini | 4 +- src/MeshNet.cpp | 1 + src/Plugin.h | 8 +-- src/Sprocket.cpp | 6 +-- src/Sprocket.h | 2 +- src/base/MeshSprocket.h | 9 +++- src/examples/mesh/{MeshApp.cpp => MeshApp.h} | 7 +-- src/examples/mesh/config.h | 5 ++ src/examples/mesh/main.cpp | 12 ++--- src/plugins/OtaTcpPlugin.cpp | 4 +- src/plugins/WebConfigPlugin.cpp | 57 ++++++++++++++++++++ src/plugins/WebSO.h | 13 +++++ src/plugins/WebServerPlugin.cpp | 33 ++++++++++++ 15 files changed, 156 insertions(+), 24 deletions(-) create mode 100644 data/www/index.html rename src/examples/mesh/{MeshApp.cpp => MeshApp.h} (90%) create mode 100644 src/plugins/WebConfigPlugin.cpp create mode 100644 src/plugins/WebSO.h create mode 100644 src/plugins/WebServerPlugin.cpp diff --git a/README.md b/README.md index bd7a948..d34695f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ -# Sprocket-Core -Library to build a mesh network of single purpose nodes. +# Sprocket-Lib +Library to build a mesh network of Sprockets. + +## Lifecycle +TODO docs +sprocket.init -> Serial.begin & SPIFFS.begin +sprocket.join(network) -> network.init & sprocket.activate -> plugins.activate +network->onReceive -> sprocket.dispatch -> plugins.onMessage &sprocket.onMessage -## WTF is a sprocket? -A sprocket is a device that has a single purpose, for example a PIR sensor node that notifies other nodes if there is motion or an LED node that lights up when a message is received. # Useful commands ```sh diff --git a/data/www/index.html b/data/www/index.html new file mode 100644 index 0000000..62b5718 --- /dev/null +++ b/data/www/index.html @@ -0,0 +1,7 @@ + + + + +

Sprocket

+ + \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 78a249a..01a3efc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -55,7 +55,9 @@ lib_deps = ${common.lib_deps} painlessMesh ESP8266mDNS ArduinoOTA -;upload_port = 192.168.1.247 + ESP Async WebServer + ESPAsyncTCP +upload_port = 192.168.1.247 [env:meshMqttBridge] src_filter = +<*> - + diff --git a/src/MeshNet.cpp b/src/MeshNet.cpp index 65a6566..2160e6f 100644 --- a/src/MeshNet.cpp +++ b/src/MeshNet.cpp @@ -43,6 +43,7 @@ void MeshNet::sendTo(uint32_t target, String msg){ void MeshNet::broadcast(String msg){ mesh.sendBroadcast(msg); + } void MeshNet::update(){ // only needed when no scheduler was passed to mesh.init diff --git a/src/Plugin.h b/src/Plugin.h index c046e3e..4a1bea7 100644 --- a/src/Plugin.h +++ b/src/Plugin.h @@ -9,10 +9,10 @@ class Plugin { protected: Scheduler* scheduler; public: - virtual void setup(Scheduler*, Network*); - virtual void enable(); - virtual void disable(); - virtual void onMessage(MeshMessage msg); + virtual void activate(Scheduler*, Network*); + virtual void enable(){}; + virtual void disable(){}; + virtual void onMessage(MeshMessage msg){}; }; #endif \ No newline at end of file diff --git a/src/Sprocket.cpp b/src/Sprocket.cpp index b720c18..a19110c 100644 --- a/src/Sprocket.cpp +++ b/src/Sprocket.cpp @@ -20,7 +20,7 @@ Sprocket* Sprocket::activate() { } Sprocket* Sprocket::activate(Scheduler* scheduler, Network* network) { // setup plugins - setupPlugins(scheduler, network); + activatePlugins(scheduler, network); return this; } @@ -54,9 +54,9 @@ void Sprocket::addPlugin(Plugin* p){ plugins.push_back(p); } -void Sprocket::setupPlugins(Scheduler* scheduler, Network* network){ +void Sprocket::activatePlugins(Scheduler* scheduler, Network* network){ for(Plugin* p : plugins){ - p->setup(scheduler, network); + p->activate(scheduler, network); } } diff --git a/src/Sprocket.h b/src/Sprocket.h index 93b0f83..676facc 100644 --- a/src/Sprocket.h +++ b/src/Sprocket.h @@ -36,7 +36,7 @@ class Sprocket { virtual void dispatch( uint32_t from, String &msg ); void addPlugin(Plugin* p); - void setupPlugins(Scheduler* scheduler, Network* network); + void activatePlugins(Scheduler* scheduler, Network* network); void dispatchMessageToPlugins(MeshMessage msg); }; diff --git a/src/base/MeshSprocket.h b/src/base/MeshSprocket.h index bc25570..7a55dbf 100644 --- a/src/base/MeshSprocket.h +++ b/src/base/MeshSprocket.h @@ -8,18 +8,25 @@ #include #include #include +#include #include +#include +#include #include "config.h" using namespace std; using namespace std::placeholders; +AsyncWebServer WEBSERVER(80); + class MeshSprocket : public Sprocket { public: MeshNet* net; - MeshSprocket(SprocketConfig cfg, OtaConfig otaCfg) : Sprocket(cfg) { + MeshSprocket(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : Sprocket(cfg) { addPlugin(new OtaTcpPlugin(otaCfg)); + addPlugin(new WebServerPlugin(webCfg, &WEBSERVER)); + addPlugin(new WebConfigPlugin(&WEBSERVER)); } Sprocket* activate(Scheduler* scheduler, Network* network) { diff --git a/src/examples/mesh/MeshApp.cpp b/src/examples/mesh/MeshApp.h similarity index 90% rename from src/examples/mesh/MeshApp.cpp rename to src/examples/mesh/MeshApp.h index e738a7f..dd1191b 100644 --- a/src/examples/mesh/MeshApp.cpp +++ b/src/examples/mesh/MeshApp.h @@ -8,12 +8,13 @@ using namespace std; using namespace std::placeholders; + class MeshApp : public MeshSprocket { public: Task heartbeatTask; - MeshApp(SprocketConfig cfg, OtaConfig otaCfg) : MeshSprocket(cfg, otaCfg) { - + MeshApp(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : MeshSprocket(cfg, otaCfg, webCfg) { + } Sprocket* activate(Scheduler* scheduler, Network* network) { @@ -23,7 +24,7 @@ class MeshApp : public MeshSprocket { // add a task that sends stuff to the mesh heartbeatTask.set(TASK_SECOND * 5, TASK_FOREVER, bind(&MeshApp::heartbeat, this, net)); addTask(heartbeatTask); - + return this; } using MeshSprocket::activate; diff --git a/src/examples/mesh/config.h b/src/examples/mesh/config.h index 66a2092..e1a48a5 100644 --- a/src/examples/mesh/config.h +++ b/src/examples/mesh/config.h @@ -25,4 +25,9 @@ #define OTA_PORT 8266 #define OTA_PASSWORD "" +// WebServer +#define WEB_CONTEXT_PATH "/" +#define WEB_DOC_ROOT "/www" +#define WEB_DEFAULT_FILE "index.html" + #endif \ No newline at end of file diff --git a/src/examples/mesh/main.cpp b/src/examples/mesh/main.cpp index e8dabc6..1b985dd 100644 --- a/src/examples/mesh/main.cpp +++ b/src/examples/mesh/main.cpp @@ -1,11 +1,6 @@ #include "config.h" #include "MeshNet.h" -#include "MeshApp.cpp" - -MeshApp sprocket( - { STARTUP_DELAY, SERIAL_BAUD_RATE }, - { OTA_PORT, OTA_PASSWORD } -); +#include "MeshApp.h" MeshNet net({ SPROCKET_MODE, WIFI_CHANNEL, @@ -13,6 +8,11 @@ MeshNet net({ STATION_SSID, STATION_PASSWORD, HOSTNAME, MESH_DEBUG_TYPES }); +MeshApp sprocket( + { STARTUP_DELAY, SERIAL_BAUD_RATE }, + { OTA_PORT, OTA_PASSWORD }, + { WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE } +); void setup() { sprocket.join(net); diff --git a/src/plugins/OtaTcpPlugin.cpp b/src/plugins/OtaTcpPlugin.cpp index f0c9cd1..4bbcebd 100644 --- a/src/plugins/OtaTcpPlugin.cpp +++ b/src/plugins/OtaTcpPlugin.cpp @@ -44,7 +44,7 @@ class OtaTcpPlugin : public Plugin { WiFi.gatewayIP().printTo(Serial); } } - void setup(Scheduler* userScheduler, Network* network){ + void activate(Scheduler* userScheduler, Network* network){ // connect done in network class? //connectUpdateNetwork(network); net = static_cast(network); @@ -79,6 +79,8 @@ class OtaTcpPlugin : public Plugin { else if (error == OTA_RECEIVE_ERROR) Serial.println("OTA: Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("OTA: End Failed"); }); + + enable(); } void disable(){ otaTask.disable(); diff --git a/src/plugins/WebConfigPlugin.cpp b/src/plugins/WebConfigPlugin.cpp new file mode 100644 index 0000000..fc04f95 --- /dev/null +++ b/src/plugins/WebConfigPlugin.cpp @@ -0,0 +1,57 @@ +#ifndef __WEB_CONFIG_PLUGIN_H__ +#define __WEB_CONFIG_PLUGIN_H__ + +#include "TaskSchedulerDeclarations.h" +#include "ArduinoOTA.h" +#include "MeshNet.h" +#include "Plugin.h" +#include +#include + +using namespace std; +using namespace std::placeholders; + + +class WebConfigPlugin : public Plugin { + private: + MeshNet* net; + AsyncWebServer* server; + public: + WebConfigPlugin(AsyncWebServer* webServer){ + server = webServer; + } + void activate(Scheduler* userScheduler, Network* network){ + + net = static_cast(network); + + server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ + Serial.println("GET /heap"); + request->send(200, "text/plain", String(ESP.getFreeHeap())); + }); + server->on("/config", HTTP_GET, [](AsyncWebServerRequest *request){ + Serial.println("GET /config"); + + MeshSprocketConfig config; + config.fromFile("/config.json"); + config.meshPassword = ""; + config.stationPassword = ""; + request->send(200, "text/plain", config.toJsonString()); + }); + // TODO needs testing + server->on("/config", HTTP_POST, [](AsyncWebServerRequest *request){ + Serial.println("POST /config"); + // read existing config + MeshSprocketConfig config; + config.fromFile("/config.json"); + if(request->hasParam("mesh", true)) { + String inStr = request->getParam("mesh", true)->value(); + config.fromJsonString(inStr); + Serial.println(config.toJsonString()); + // config.saveFile("/config.json"); + } + request->send(200, "text/plain", String(ESP.getFreeHeap())); + }); + } +}; + +#endif \ No newline at end of file diff --git a/src/plugins/WebSO.h b/src/plugins/WebSO.h new file mode 100644 index 0000000..3a34072 --- /dev/null +++ b/src/plugins/WebSO.h @@ -0,0 +1,13 @@ +#ifndef __SHARED_PLUGINS__ +#define __SHARED_PLUGINS__ + +#include +extern AsyncWebServer WEBSERVER; + +struct WebServerConfig { + const char* contextPath; + const char* docRoot; + const char* defaultFile; +}; + +#endif \ No newline at end of file diff --git a/src/plugins/WebServerPlugin.cpp b/src/plugins/WebServerPlugin.cpp new file mode 100644 index 0000000..5c458f5 --- /dev/null +++ b/src/plugins/WebServerPlugin.cpp @@ -0,0 +1,33 @@ +#ifndef __WEB_SERVER_PLUGIN__ +#define __WEB_SERVER_PLUGIN__ + +#include +#include "TaskSchedulerDeclarations.h" +#include "ArduinoOTA.h" +#include "MeshNet.h" +#include "Plugin.h" +#include + +using namespace std; +using namespace std::placeholders; + +class WebServerPlugin : public Plugin { + private: + WebServerConfig config; + MeshNet* net; + AsyncWebServer* server; + public: + WebServerPlugin(WebServerConfig cfg, AsyncWebServer* webServer){ + config = cfg; + server = webServer; + } + void activate(Scheduler* userScheduler, Network* network){ + //connectUpdateNetwork(network); + net = static_cast(network); + server->serveStatic(config.contextPath, SPIFFS, config.docRoot).setDefaultFile(config.defaultFile); + server->begin(); + Serial.println("WebServer activated"); + } +}; + +#endif \ No newline at end of file