diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c5d1bc8..449af1b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,44 +1,14 @@ -#stages: -# - build -# -#cache: -# paths: -# - .piolibdeps -# -#build-examples: -# stage: build -# image: registry.gitlab.com/wirelos/contraption-pipeline/platformio:v1 -# script: -# - pio upgrade -# - platformio lib --global install painlessMesh ArduinoJson TaskScheduler PubSubClient ESPAsyncTCP AsyncTCP "ESP Async WebServer" -# - platformio ci --lib="." --board=esp12e src/examples/basic/ -# - platformio ci --lib="." --board=esp12e src/examples/mesh/ -# - platformio ci --lib="." --board=esp12e src/examples/mqttBridge/ - image: python:2.7-stretch -# This folder is cached between builds -# http://docs.gitlab.com/ce/ci/yaml/README.html#cache -cache: - paths: - - firmware - stages: - - test - build before_script: - "pip install -U platformio" -firmware-build: +examples: stage: build image: python:2.7-stretch script: - pio run --target clean - pio run --environment basic - - pio run --environment wifi - - pio run --environment wifiMesh - artifacts: - paths: - - .pioenvs/*/firmware.* - - .pioenvs/*/spiffs.bin diff --git a/README.md b/README.md index d34695f..f4ce1ed 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,7 @@ # 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 - +TODO # Useful commands ```sh diff --git a/platformio.ini b/platformio.ini index c8fcf8d..1564c02 100644 --- a/platformio.ini +++ b/platformio.ini @@ -21,11 +21,7 @@ lib_deps = Hash TaskScheduler SPIFFS - ESP8266mDNS - ArduinoOTA - painlessMesh - ESPAsyncTCP - ESP Async WebServer + ArduinoJson ;[env:build] ;src_filter = +<*> - @@ -46,22 +42,4 @@ board = ${common.board} upload_speed = ${common.upload_speed} monitor_baud = ${common.monitor_baud} framework = ${common.framework} -lib_deps = ${common.lib_deps} - -[env:wifiMesh] -src_filter = +<*> - + -platform = ${common.platform} -board = ${common.board} -upload_speed = ${common.upload_speed} -monitor_baud = ${common.monitor_baud} -framework = ${common.framework} -lib_deps = ${common.lib_deps} - -[env:wifi] -src_filter = +<*> - + -platform = ${common.platform} -board = ${common.board} -upload_speed = ${common.upload_speed} -monitor_baud = ${common.monitor_baud} -framework = ${common.framework} lib_deps = ${common.lib_deps} \ No newline at end of file diff --git a/src/MeshConfig.h b/src/MeshConfig.h deleted file mode 100644 index 1a1d6e0..0000000 --- a/src/MeshConfig.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __MESHCONFIG__ -#define __MESHCONFIG__ - -// FIXME non-mesh config should have it's own struct -struct MeshConfig { - int stationMode; - int channel; - int meshPort; - const char* meshSSID; - const char* meshPassword; - const char* stationSSID; - const char* stationPassword; - const char* hostname; - uint16_t debugTypes; -}; - - -#endif \ No newline at end of file diff --git a/src/MeshNet.cpp b/src/MeshNet.cpp deleted file mode 100644 index 42c08ce..0000000 --- a/src/MeshNet.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "MeshNet.h" - -MeshNet::MeshNet(MeshConfig cfg) : Network() { - config.stationMode = cfg.stationMode; - config.channel = cfg.channel; - config.meshPort = cfg.meshPort; - config.meshSSID = cfg.meshSSID; - config.meshPassword = cfg.meshPassword; - config.stationSSID = cfg.stationSSID; - config.stationPassword = cfg.stationPassword; - config.hostname = cfg.hostname; - config.debugTypes = cfg.debugTypes; -} - -Network* MeshNet::init(){ - Serial.println("init mesh"); - config.fromFile("/config.json"); - //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on - mesh.setDebugMsgTypes( config.debugTypes ); - return this; -} - -int MeshNet::connect(){ - mesh.init( config.meshSSID, config.meshPassword, scheduler, config.meshPort, WIFI_AP_STA, config.channel ); - mesh.onNewConnection(bind(&MeshNet::newConnectionCallback, this, _1)); - mesh.onChangedConnections(bind(&MeshNet::changedConnectionCallback, this)); - mesh.onNodeTimeAdjusted(bind(&MeshNet::nodeTimeAdjustedCallback, this, _1)); - if(config.stationMode){ - connectStation(); - } - return 1; -} - -int MeshNet::connectStation() { - Serial.println("connect station"); - mesh.stationManual(config.stationSSID, config.stationPassword); - mesh.setHostname(config.hostname.c_str()); - return 1; -} -void MeshNet::sendTo(uint32_t target, String msg){ - mesh.sendSingle(target, msg); -} - -void MeshNet::broadcast(String msg, bool self){ - mesh.sendBroadcast(msg, self); - -} -void MeshNet::update(){ - // only needed when no scheduler was passed to mesh.init - mesh.update(); -} - -// example, not used, to be removed -void MeshNet::onReceive( std::function cb) { - mesh.onReceive(cb); -} - -void MeshNet::newConnectionCallback(uint32_t nodeId) { - Serial.printf("--> New Connection, nodeId = %u\n", nodeId); -} - -void MeshNet::changedConnectionCallback() { - Serial.printf("--> Changed connections %s\n",mesh.subConnectionJson().c_str()); -} - -void MeshNet::nodeTimeAdjustedCallback(int32_t offset) { - Serial.printf("--> Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset); -} \ No newline at end of file diff --git a/src/MeshNet.h b/src/MeshNet.h deleted file mode 100644 index 5da24c0..0000000 --- a/src/MeshNet.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __MESHNET_H__ -#define __MESHNET_H__ - -#ifdef ESP32 -#include -#elif defined(ESP8266) -#include -#endif // ESP32 - -#include -#include -#include "Network.h" -#include "MeshConfig.h" -#include "MeshSprocketConfig.h" - -using namespace std; -using namespace std::placeholders; - -class MeshNet : public Network { - public: - painlessMesh mesh; - MeshSprocketConfig config; - MeshNet(MeshConfig cfg); - Network* init(); - int connect(); - int connectStation(); - void configure(MeshSprocketConfig cfg); - void update(); - void newConnectionCallback(uint32_t nodeId); - void changedConnectionCallback(); - void nodeTimeAdjustedCallback(int32_t offset); - void broadcast(String msg, bool self = false); - void sendTo(uint32_t target, String msg); - void onReceive(std::function); - int isConnected(){ - return WiFi.status() == WL_CONNECTED; - } -}; - -#endif \ No newline at end of file diff --git a/src/MeshSprocketConfig.h b/src/MeshSprocketConfig.h deleted file mode 100644 index 14f89fc..0000000 --- a/src/MeshSprocketConfig.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __MESH_SPROCKET_CONFIG__ -#define __MESH_SPROCKET_CONFIG__ - -#include -#include -#include -#include "MeshConfig.h" -#include "SprocketConfig.h" -#include "JsonStruct.h" - -#define JSON_stationMode "stationMode" -#define JSON_channel "channel" -#define JSON_meshPort "meshPort" -#define JSON_meshSSID "meshSSID" -#define JSON_meshPassword "meshPassword" -#define JSON_stationSSID "stationSSID" -#define JSON_stationPassword "stationPassword" -#define JSON_hostname "hostname" - -struct MeshSprocketConfig : public JsonStruct { - int stationMode; - int channel; - int meshPort; - String meshSSID; - String meshPassword; - String stationSSID; - String stationPassword; - String hostname; - uint16_t debugTypes; - - // ------------------------------------------------------------------------------------------ - void mapJsonObject(JsonObject& root) { - root[JSON_stationMode] = stationMode; - root[JSON_channel] = channel; - root[JSON_meshPort] = meshPort; - root[JSON_meshSSID] = meshSSID; - root[JSON_meshPassword] = meshPassword; - root[JSON_stationSSID] = stationSSID; - root[JSON_stationPassword] = stationPassword; - root[JSON_hostname] = hostname; - } - - // Map a json object to this struct. - void fromJsonObject(JsonObject& json) { - stationMode = getIntAttrFromJson(json, JSON_stationMode); - channel = getIntAttrFromJson(json, JSON_channel); - meshPort = getIntAttrFromJson(json, JSON_meshPort); - meshSSID = getAttrFromJson(json, JSON_meshSSID); - meshPassword = getAttrFromJson(json, JSON_meshPassword); - stationSSID = getAttrFromJson(json, JSON_stationSSID); - stationPassword = getAttrFromJson(json, JSON_stationPassword); - hostname = getAttrFromJson(json, JSON_hostname); - }; -}; - -#endif \ No newline at end of file diff --git a/src/Sprocket.h b/src/Sprocket.h index b192f2a..1f34a7a 100644 --- a/src/Sprocket.h +++ b/src/Sprocket.h @@ -6,7 +6,6 @@ #define _TASK_PRIORITY #include -//#include #include #include #include "FS.h" diff --git a/src/SprocketMessage.h b/src/SprocketMessage.h index d80197e..5a0ce4e 100644 --- a/src/SprocketMessage.h +++ b/src/SprocketMessage.h @@ -1,5 +1,5 @@ -#ifndef __MESH_MESSAGE__ -#define __MESH_MESSAGE__ +#ifndef __SPROCKET_MESSAGE__ +#define __SPROCKET_MESSAGE__ #include #include diff --git a/src/TaskScheduler.cpp b/src/TaskScheduler.cpp new file mode 100644 index 0000000..fb4326b --- /dev/null +++ b/src/TaskScheduler.cpp @@ -0,0 +1,15 @@ +/* + * https://github.com/arkhipenko/TaskScheduler/tree/master/examples/Scheduler_example16_Multitab + */ + +// #define _TASK_TIMECRITICAL // Enable monitoring scheduling overruns +// #define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between tasks if no callback methods were invoked during the pass +// #define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only +// #define _TASK_WDT_IDS // Compile with support for wdt control points and task ids +// #define _TASK_LTS_POINTER // Compile with support for local task storage pointer +#define _TASK_PRIORITY // Support for layered scheduling priority +// #define _TASK_MICRO_RES // Support for microsecond resolution +#define _TASK_STD_FUNCTION // Support for std::function (ESP8266 ONLY) +// #define _TASK_DEBUG // Make all methods and variables public for debug purposes + +#include diff --git a/src/WiFiNet.cpp b/src/WiFiNet.cpp deleted file mode 100644 index e5e8005..0000000 --- a/src/WiFiNet.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "WiFiNet.h" - -WiFiNet::WiFiNet( - int stationMode, - const char* stationSSID, - const char* stationPassword, - const char* apSSID, - const char* apPassword, - const char* hostname, - int connectTimeout){ - config.stationMode = stationMode; - config.stationSSID = String(stationSSID); - config.stationPassword = String(stationPassword); - config.apSSID = String(apSSID); - config.apPassword = String(apPassword); - config.hostname = String(hostname); - config.connectTimeout = connectTimeout; -} - -int WiFiNet::connect(){ - config.fromFile("/config.json"); - WiFi.hostname(config.hostname); - Serial.println("Hostname: " + config.hostname); - if(!connectStation()) { - createAccessPoint(); - } - startDNS(); - return 1; -} - -int WiFiNet::connectStation(){ - if(config.stationMode == 0) return 0; - - int wifiConnectStart = millis(); - WiFi.mode(WIFI_STA); - WiFi.begin(config.stationSSID.c_str(), config.stationPassword.c_str()); - Serial.println("connect to " + config.stationSSID); - - // TODO use tasks - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - if(millis() - wifiConnectStart >= (uint)config.connectTimeout) { - Serial.println("wifi connect timeout"); - return 0; - } - } - Serial.println("IP address: " + WiFi.localIP().toString()); - Serial.println(WiFi.localIP().toString()); - return 1; -} - -int WiFiNet::createAccessPoint(){ - Serial.println("Starting SoftAP: " + String(config.apSSID)); - WiFi.disconnect(); - WiFi.mode(WIFI_AP); - WiFi.softAP(config.apSSID.c_str(), config.apPassword.c_str()); - String softApPrt = "SoftAP IP: " + WiFi.softAPIP().toString(); - Serial.println(softApPrt.c_str()); - return 1; -} - -// TODO make user configurable services -int WiFiNet::startDNS() { - if (!MDNS.begin(config.hostname.c_str())) { - Serial.println("Error setting up MDNS responder!"); - return 0; - } else { - Serial.println("mDNS responder started"); - MDNS.addService("http", "tcp", 80); - } - return 1; -} \ No newline at end of file diff --git a/src/WiFiNet.h b/src/WiFiNet.h deleted file mode 100644 index 5d3177c..0000000 --- a/src/WiFiNet.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef __WIFI_NET__ -#define __WIFI_NET__ - -#include -#include - -#ifdef ESP32 -#include -#elif defined(ESP8266) -#include -#endif // ESP32 - -#include "Network.h" - -#include -#include -#include "JsonStruct.h" -using namespace std; -using namespace std::placeholders; - -#define JSON_stationMode "stationMode" -#define JSON_stationSSID "stationSSID" -#define JSON_apPassword "apPassword" -#define JSON_apSSID "apSSID" -#define JSON_stationPassword "stationPassword" -#define JSON_hostname "hostname" -#define JSON_connect_timeout "connectTimeout" - -struct WiFiConfig : public JsonStruct { - int stationMode; - String stationSSID; - String stationPassword; - String apSSID; - String apPassword; - String hostname; - int connectTimeout; - - void mapJsonObject(JsonObject& root) { - root[JSON_stationMode] = stationMode; - root[JSON_stationSSID] = stationSSID; - root[JSON_stationPassword] = stationPassword; - root[JSON_apSSID] = apSSID; - root[JSON_apPassword] = apPassword; - root[JSON_hostname] = hostname; - root[JSON_connect_timeout] = connectTimeout; - } - - // Map a json object to this struct. - void fromJsonObject(JsonObject& json) { - stationMode = getIntAttrFromJson(json, JSON_stationMode, stationMode); - stationSSID = getAttrFromJson(json, JSON_stationSSID, stationSSID); - stationPassword = getAttrFromJson(json, JSON_stationPassword, stationPassword); - apSSID = getAttrFromJson(json, JSON_apSSID, apSSID); - apPassword = getAttrFromJson(json, JSON_apPassword, apPassword); - hostname = getAttrFromJson(json, JSON_hostname, hostname); - connectTimeout = getIntAttrFromJson(json, JSON_connect_timeout, connectTimeout); - }; -}; - -class WiFiNet : public Network { - public: - WiFiConfig config; - WiFiNet(int stationMode, const char* stationSSID, const char* stationPassword, const char* apSSID, const char* apPassword, const char* hostname, int connectTimeout); - int connect(); - int connectStation(); - int createAccessPoint(); - int startDNS(); - void configure(WiFiConfig); - int isConnected(){ - return WiFi.status() == WL_CONNECTED; - } -}; - -#endif \ No newline at end of file diff --git a/src/examples/wifi/WiFiApp.h b/src/examples/wifi/WiFiApp.h deleted file mode 100644 index ab0c1f5..0000000 --- a/src/examples/wifi/WiFiApp.h +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef __WIFI_APP__ -#define __WIFI_APP__ - -#include -#include -#include -#include -#include - -using namespace std; -using namespace std::placeholders; - -class WiFiApp : public Sprocket { - public: - AsyncWebServer* server; - WiFiApp(SprocketConfig cfg, WebServerConfig webCfg) : Sprocket(cfg) { - server = new AsyncWebServer(webCfg.port); - addPlugin(new WebServerPlugin(webCfg, server)); - addPlugin(new WebConfigPlugin(server)); - } -}; - -#endif \ No newline at end of file diff --git a/src/examples/wifi/config.h b/src/examples/wifi/config.h deleted file mode 100644 index 1ce975a..0000000 --- a/src/examples/wifi/config.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __STANDALONE_CONFIG__ -#define __STANDALONE_CONFIG__ - -// Scheduler config -#define _TASK_PRIORITY // Support for layered scheduling priority -#define _TASK_SLEEP_ON_IDLE_RUN -#define _TASK_STD_FUNCTION - -// Chip config -#define SERIAL_BAUD_RATE 115200 -#define STARTUP_DELAY 3000 - -// network config -#define SPROCKET_MODE 0 -#define AP_SSID "MyAP" -#define AP_PASSWORD "myApPwd" -#define STATION_SSID "Th1ngs4p" -#define STATION_PASSWORD "th3r31sn0sp00n" -#define HOSTNAME "standalone-node" -#define CONNECT_TIMEOUT 10000 - -// OTA config -#define OTA_PORT 8266 -#define OTA_PASSWORD "" - -// WebServer -#define WEB_CONTEXT_PATH "/" -#define WEB_DOC_ROOT "/www" -#define WEB_DEFAULT_FILE "index.html" -#define WEB_SERVER_PORT 80 - -#endif \ No newline at end of file diff --git a/src/examples/wifi/main.cpp b/src/examples/wifi/main.cpp deleted file mode 100644 index 8e300df..0000000 --- a/src/examples/wifi/main.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "config.h" -#include "WiFiNet.h" -#include "WiFiApp.h" - -WiFiNet wifi( - SPROCKET_MODE, - STATION_SSID, - STATION_PASSWORD, - AP_SSID, - AP_PASSWORD, - HOSTNAME, - CONNECT_TIMEOUT); -WiFiApp sprocket( - {STARTUP_DELAY, SERIAL_BAUD_RATE}, - {WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE, WEB_SERVER_PORT}); - -void setup() -{ - delay(3000); - wifi.connect(); - sprocket.activate(); -} - -void loop() -{ - sprocket.loop(); - yield(); -} \ No newline at end of file diff --git a/src/examples/wifiMesh/MeshApp.h b/src/examples/wifiMesh/MeshApp.h deleted file mode 100644 index e3a272f..0000000 --- a/src/examples/wifiMesh/MeshApp.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __MESH_APP__ -#define __MESH_APP__ - -#include -#include -#include - -using namespace std; -using namespace std::placeholders; - -class MeshApp : public Sprocket -{ - public: - Task heartbeatTask; - - MeshApp(SprocketConfig cfg, MeshConfig meshCfg) : Sprocket(cfg) - { - addPlugin(new MeshNetworkPlugin(meshCfg)); - subscribe("device/heartbeat", bind(&MeshApp::messageHandler, this, _1)); - } - - Sprocket *activate(Scheduler *scheduler) - { - // add a task that sends stuff to the mesh - heartbeatTask.set(TASK_SECOND * 5, TASK_FOREVER, bind(&MeshApp::heartbeat, this)); - addTask(heartbeatTask); - Serial.println("MeshApp activated"); - return this; - } - using Sprocket::activate; - - void messageHandler(String msg) - { - Serial.println(String("MeshApp: ") + msg); - } - - void heartbeat() - { - SprocketMessage msg; - msg.domain = "wirelos"; - msg.to = "broadcast"; - msg.payload = "alive"; - msg.topic = "device/heartbeat"; - msg.type = SprocketMessage::APP; - String msgStr = msg.toJsonString(); - publish("mesh/broadcast", msgStr); - } -}; - -#endif \ No newline at end of file diff --git a/src/examples/wifiMesh/README.md b/src/examples/wifiMesh/README.md deleted file mode 100644 index 53e7306..0000000 --- a/src/examples/wifiMesh/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Mesh Sprocket Example - -## OTA -mosquitto_sub -h citadel.lan -p 1883 -v -t '#' - -Enable OTA: -mosquitto_pub -h citadel.lan -p 1883 -t '/down/wirelos/gateway' -m '{"target":"broadcast", "domain": "wirelos", "msg": {"target":"broadcast", "type": 3, msg: "OTA"} }' diff --git a/src/examples/wifiMesh/config.h b/src/examples/wifiMesh/config.h deleted file mode 100644 index 2ac92af..0000000 --- a/src/examples/wifiMesh/config.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __MESH_CONFIG__ -#define __MESH_CONFIG__ - -// Scheduler config -#define _TASK_SLEEP_ON_IDLE_RUN -#define _TASK_STD_FUNCTION -#define _TASK_PRIORITY - -// Chip config -#define SERIAL_BAUD_RATE 115200 -#define STARTUP_DELAY 3000 - -// Mesh config -#define SPROCKET_MODE 0 -#define WIFI_CHANNEL 11 -#define MESH_PORT 5555 -#define MESH_PREFIX "whateverYouLike" -#define MESH_PASSWORD "somethingSneaky" -#define STATION_SSID "Th1ngs4p" -#define STATION_PASSWORD "th3r31sn0sp00n" -#define HOSTNAME "mesh-node" -#define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION -//ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE - -// OTA config -#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/wifiMesh/main.cpp b/src/examples/wifiMesh/main.cpp deleted file mode 100644 index 009c280..0000000 --- a/src/examples/wifiMesh/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "config.h" -#include "MeshApp.h" - -MeshApp sprocket( - {STARTUP_DELAY, SERIAL_BAUD_RATE}, - {SPROCKET_MODE, WIFI_CHANNEL, - MESH_PORT, MESH_PREFIX, MESH_PASSWORD, - STATION_SSID, STATION_PASSWORD, HOSTNAME, - MESH_DEBUG_TYPES}); - -void setup() -{ - delay(3000); - sprocket.activate(); -} - -void loop() -{ - sprocket.loop(); - yield(); -} \ No newline at end of file diff --git a/src/plugins/MeshManPlugin.cpp_ b/src/plugins/MeshManPlugin.cpp_ deleted file mode 100644 index 8f4d881..0000000 --- a/src/plugins/MeshManPlugin.cpp_ +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __MESH_MAN_PLUGIN__ -#define __MESH_MAN_PLUGIN__ - -#include "TaskSchedulerDeclarations.h" -#include "ArduinoOTA.h" -#include "MeshNet.h" -#include "Plugin.h" -#include -#include -#include - -using namespace std; -using namespace std::placeholders; - - -class MeshManPlugin : public Plugin { - private: - MeshNet* net; - AsyncWebServer* server; - public: - MeshManPlugin(AsyncWebServer* webServer){ - server = webServer; - } - void activate(Scheduler* userScheduler, Network* network){ - net = static_cast(network); - server->on("/mesh", HTTP_GET, std::bind(&MeshManPlugin::getMeshConnections, this, std::placeholders::_1)); - server->on("/mesh", HTTP_POST, std::bind(&MeshManPlugin::sendMsg, this, std::placeholders::_1)); - server->on("/mesh/nodeId", HTTP_GET, std::bind(&MeshManPlugin::getNodeId, this, std::placeholders::_1)); - server->on("/mesh/broadcast", HTTP_POST, std::bind(&MeshManPlugin::broadcast, this, std::placeholders::_1)); - - subscribe("mesh/heartbeat", std::bind(&MeshManPlugin::gotHeartbeat, this, std::placeholders::_1)); - } - void gotHeartbeat(String msg){ - Serial.println(String("MeshManPlugin / Heartbeat: ") + msg); - } - void getMeshConnections(AsyncWebServerRequest *request) { - request->send(200, "text/plain", net->mesh.subConnectionJson()); - } - void broadcast(AsyncWebServerRequest *request) { - String msg = ""; - if(request->hasParam("msg", true)) { - msg = request->getParam("msg", true)->value(); - } - msg = msg + "\0"; - net->mesh.sendBroadcast(msg); - request->send(200, "text/plain", msg); - } - void sendMsg(AsyncWebServerRequest *request) { - String msg = ""; - uint32_t to = 0; - if(request->hasParam("msg", true)) { - msg = request->getParam("msg", true)->value(); - } - if(request->hasParam("nodeId", true)) { - to = atoi(request->getParam("nodeId", true)->value().c_str()); - } - msg = msg + "\0"; - net->mesh.sendSingle(to, msg); - request->send(200, "text/plain", msg); - } - void getNodeId(AsyncWebServerRequest *request) { - StaticJsonBuffer<200> jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - root["nodeId"] = net->mesh.getNodeId(); - String jsonString; - root.printTo(jsonString); - request->send(200, "text/plain", jsonString); - } -}; - -#endif \ No newline at end of file diff --git a/src/plugins/MeshNetworkPlugin.cpp b/src/plugins/MeshNetworkPlugin.cpp deleted file mode 100644 index d8398d6..0000000 --- a/src/plugins/MeshNetworkPlugin.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __MESH_NETWORK_PLUGIN__ -#define __MESH_NETWORK_PLUGIN__ - -#include "Plugin.h" -#include "TaskSchedulerDeclarations.h" -#include -#include -#include "plugins/NetworkPlugin.cpp" -#include - -using namespace std; -using namespace std::placeholders; - -class MeshNetworkPlugin : public NetworkPlugin -{ - public: - MeshNetworkPlugin(MeshConfig cfg) - { - network = new MeshNet(cfg); - } - - void activate(Scheduler *userScheduler) - { - network->onReceive(bind(&MeshNetworkPlugin::dispatch, this, _1, _2)); - subscribe("mesh/broadcast", bind(&MeshNetworkPlugin::broadcast, this, _1)); - // TODO mesh/sendTo - NetworkPlugin::activate(userScheduler); - } - void broadcast(String msg) - { - network->broadcast(msg, true); - } - void dispatch(uint32_t from, String &msg) - { - SprocketMessage sMsg; - sMsg.fromJsonString(msg); - if (sMsg.valid) - { - sMsg.from = String(from); - publish(sMsg.topic, sMsg.payload); - return; - } - publish("mesh/message", msg); - } -}; - -#endif \ No newline at end of file diff --git a/src/plugins/OtaTcpPlugin.cpp_ b/src/plugins/OtaTcpPlugin.cpp_ deleted file mode 100644 index 6fcc6f1..0000000 --- a/src/plugins/OtaTcpPlugin.cpp_ +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef __OTA_CLASSIC_H__ -#define __OTA_CLASSIC_H__ - -#include "TaskSchedulerDeclarations.h" -#include "ArduinoOTA.h" -#include "MeshNet.h" -#include "Plugin.h" - -using namespace std; -using namespace std::placeholders; - -struct OtaConfig { - int port; - const char* password; -}; - -class OtaTcpPlugin : public Plugin { - private: - OtaConfig config; - Task otaTask; - MeshNet* net; - public: - OtaTcpPlugin(OtaConfig cfg){ - config = cfg; - - } - void connectUpdateNetwork() { - Serial.println("OTA connect to update-network"); - net->connectStation(); - } - void enable() { - Serial.println("OTA enable"); - ArduinoOTA.begin(); - otaTask.enable(); - } - void onMessage(SprocketMessage msg) { - if(msg.type == SprocketMessage::OTA){ - Serial.println("OTA msg received"); - WiFi.disconnect(); - net->mesh.stop(); - connectUpdateNetwork(); - enable(); - //net->mesh.sendBroadcast("my ip:" + WiFi.localIP().toString(), true); - //net->mesh.sendBroadcast("gw ip:" + WiFi.gatewayIP().toString(), true); - WiFi.gatewayIP().printTo(Serial); - } - } - void activate(Scheduler* userScheduler, Network* network){ - // connect done in network class? - //connectUpdateNetwork(network); - net = static_cast(network); - // setup task - // TOOD check if we can increase the time OTA needs to be handled - otaTask.set(TASK_MILLISECOND * 1000, TASK_FOREVER, [](){ - ArduinoOTA.handle(); - }); - userScheduler->addTask(otaTask); - - // configure OTA - ArduinoOTA.setPort(config.port); - //ArduinoOTA.setHostname(HOSTNAME); - if(strlen(config.password) > 0){ - ArduinoOTA.setPassword(config.password); - } - // setup callbacks - ArduinoOTA.onStart([]() { - Serial.println("OTA: Start"); - }); - ArduinoOTA.onEnd([]() { - Serial.println("OTA: End"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - Serial.printf("OTA: Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - Serial.printf("OTA: Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) Serial.println("OTA: Auth Failed"); - else if (error == OTA_BEGIN_ERROR) Serial.println("OTA: Begin Failed"); - else if (error == OTA_CONNECT_ERROR) Serial.println("OTA: Connect Failed"); - 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(); - } -}; - -#endif \ No newline at end of file diff --git a/src/plugins/WebConfigPlugin.cpp b/src/plugins/WebConfigPlugin.cpp deleted file mode 100644 index ba56945..0000000 --- a/src/plugins/WebConfigPlugin.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __WEB_CONFIG_PLUGIN_H__ -#define __WEB_CONFIG_PLUGIN_H__ - -#include -#include "TaskSchedulerDeclarations.h" -#include "ArduinoOTA.h" -#include "Plugin.h" -#include -#include - -using namespace std; -using namespace std::placeholders; - - -class WebConfigPlugin : public Plugin { - private: - AsyncWebServer* server; - public: - WebConfigPlugin(AsyncWebServer* webServer){ - server = webServer; - server->serveStatic("/config.json", SPIFFS, "config.json"); - } - void activate(Scheduler* userScheduler){ - server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ - Serial.println("GET /heap"); - request->send(200, "text/plain", String(ESP.getFreeHeap())); - }); - server->on("/restart", HTTP_POST, [](AsyncWebServerRequest *request){ - Serial.println("POST /restart"); - ESP.restart(); - }); - server->on("/config", HTTP_POST, [](AsyncWebServerRequest *request){ - Serial.println("POST /config"); - if(request->hasParam("config", true) && request->hasParam("fileName", true)) { - String inStr = request->getParam("config", true)->value(); - String fileName = request->getParam("fileName", true)->value(); - File f = SPIFFS.open(fileName, "w"); - if (!f) { - Serial.println("file open for write failed"); - } - Serial.println("====== Writing to SPIFFS file ========="); - f.print(inStr); - f.close(); - } - request->redirect("/"); - }); - Serial.println("WebConfig activated"); - } -}; - -#endif \ No newline at end of file diff --git a/src/plugins/WebServerConfig.h b/src/plugins/WebServerConfig.h deleted file mode 100644 index 70c2433..0000000 --- a/src/plugins/WebServerConfig.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __WEB_SERVER_CONFIG__ -#define __WEB_SERVER_CONFIG__ - -struct WebServerConfig { - const char* contextPath; - const char* docRoot; - const char* defaultFile; - int port; -}; - -#endif \ No newline at end of file diff --git a/src/plugins/WebServerPlugin.cpp b/src/plugins/WebServerPlugin.cpp deleted file mode 100644 index 54bf060..0000000 --- a/src/plugins/WebServerPlugin.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __WEB_SERVER_PLUGIN__ -#define __WEB_SERVER_PLUGIN__ - -#include -#include -#include "TaskSchedulerDeclarations.h" -#include "Plugin.h" -#include - -using namespace std; -using namespace std::placeholders; - -class WebServerPlugin : public Plugin { - private: - WebServerConfig config; - AsyncWebServer* server; - public: - WebServerPlugin(WebServerConfig cfg, AsyncWebServer* webServer){ - config = cfg; - server = webServer; - } - void activate(Scheduler* userScheduler){ - server->serveStatic(config.contextPath, SPIFFS, config.docRoot).setDefaultFile(config.defaultFile); - // TODO add auth if configured - // server->setAuthentication("user", "pass"); - server->begin(); - Serial.println("WebServer activated"); - } -}; - -#endif \ No newline at end of file diff --git a/src/utils/array.h b/src/utils/array.h new file mode 100644 index 0000000..65b7fd7 --- /dev/null +++ b/src/utils/array.h @@ -0,0 +1,6 @@ +#ifndef __ARRAY_UTILS__ +#define __ARRAY_UTILS__ + +#define ARRAY_LENGTH(array) sizeof(array)/sizeof(array[0]) + +#endif \ No newline at end of file diff --git a/src/utils/print.cpp b/src/utils/print.cpp new file mode 100644 index 0000000..197e64a --- /dev/null +++ b/src/utils/print.cpp @@ -0,0 +1,28 @@ +#include "utils/print.h" + +int FORMAT_BUFFER_SIZE(const char *format, ...) +{ + va_list args; + va_start(args, format); + int result = vsnprintf(NULL, 0, format, args); + va_end(args); + return result + 1; // safe byte for \0 +} +void PRINT_MSG(Print &out, const char *prefix, const char *format, ...) +{ + if (SPROCKET_PRINT) + { + out.print(String(prefix) + String("\t| ")); + char formatString[128], *ptr; + strncpy_P(formatString, format, sizeof(formatString)); // copy in from program mem + // null terminate - leave last char since we might need it in worst case for result's \0 + formatString[sizeof(formatString) - 2] = '\0'; + ptr = &formatString[strlen(formatString) + 1]; // our result buffer... + va_list args; + va_start(args, format); + vsnprintf(ptr, sizeof(formatString) - 1 - strlen(formatString), formatString, args); + va_end(args); + formatString[sizeof(formatString) - 1] = '\0'; + out.println(ptr); + } +} \ No newline at end of file diff --git a/src/utils/utils_print.h b/src/utils/print.h similarity index 60% rename from src/utils/utils_print.h rename to src/utils/print.h index 51ac397..ea76fc4 100644 --- a/src/utils/utils_print.h +++ b/src/utils/print.h @@ -9,7 +9,7 @@ // TODO move to sprocket -int FORMAT_BUFFER_SIZE(const char* format, ...); -void PRINT_MSG(Print &out, const char* prefix, const char* format, ...); +int FORMAT_BUFFER_SIZE(const char *format, ...); +void PRINT_MSG(Print &out, const char *prefix, const char *format, ...); #endif \ No newline at end of file diff --git a/src/utils/utils_print.cpp b/src/utils/utils_print.cpp deleted file mode 100644 index ae6c013..0000000 --- a/src/utils/utils_print.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "utils_print.h" - -int FORMAT_BUFFER_SIZE(const char* format, ...) { - va_list args; - va_start(args, format); - int result = vsnprintf(NULL, 0, format, args); - va_end(args); - return result + 1; // safe byte for \0 -} -void PRINT_MSG(Print &out, const char* prefix, const char* format, ...) { - if(SPROCKET_PRINT){ - out.print(String(prefix) + String("\t| ")); - char formatString[128], *ptr; - strncpy_P( formatString, format, sizeof(formatString) ); // copy in from program mem - // null terminate - leave last char since we might need it in worst case for result's \0 - formatString[ sizeof(formatString)-2 ]='\0'; - ptr=&formatString[ strlen(formatString)+1 ]; // our result buffer... - va_list args; - va_start (args,format); - vsnprintf(ptr, sizeof(formatString)-1-strlen(formatString), formatString, args ); - va_end (args); - formatString[ sizeof(formatString)-1 ]='\0'; - out.println(ptr); - } -} \ No newline at end of file diff --git a/src/utils/utils_web.h b/src/utils/utils_web.h deleted file mode 100644 index 0ff8d4a..0000000 --- a/src/utils/utils_web.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef __WebUtils_H___ -#define __WebUtils_H___ - -#include -#include -#include -#include - -class WebUtils { - public: - static String getRequestParameterOrDefault(AsyncWebServerRequest *request, String param, String defaultValue, bool isPost = true){ - if(request->hasParam(param, isPost)) { - return request->getParam(param, isPost)->value(); - } - return defaultValue; - } - static String parseFrame(AwsEventType type, void * arg, uint8_t *data, size_t len) { - String msg = ""; - if(type == WS_EVT_DATA){ - AwsFrameInfo * info = (AwsFrameInfo*)arg; - if(info->opcode == WS_TEXT){ - for(size_t i=0; i < info->len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for(size_t i=0; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - - } - return msg; - } - static String parseFrameAsString(AwsEventType type, void * arg, uint8_t *data, size_t len, int start = 0) { - String msg = ""; - if(type == WS_EVT_DATA){ - AwsFrameInfo * info = (AwsFrameInfo*)arg; - //if(info->final && info->index == 0 && info->len == len){ - if(info->opcode == WS_TEXT){ - for(size_t i=start; i < info->len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for(size_t i=start; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - - //} - } - return msg; - } - /* static void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { - if(type == WS_EVT_CONNECT){ - Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); - client->printf("Hello Client %u :)", client->id()); - client->ping(); - } else if(type == WS_EVT_DISCONNECT){ - Serial.printf("ws[%s][%u] disconnect: %u\n", server->url(), client->id()); - } else if(type == WS_EVT_ERROR){ - Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); - } else if(type == WS_EVT_PONG){ - Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); - } else if(type == WS_EVT_DATA){ - AwsFrameInfo * info = (AwsFrameInfo*)arg; - String msg = ""; - //the whole message is in a single frame and we got all of it's data - if(info->final && info->index == 0 && info->len == len){ - Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); - - if(info->opcode == WS_TEXT){ - for(size_t i=0; i < info->len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for(size_t i=0; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - Serial.printf("%s\n",msg.c_str()); - - if(info->opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - //message is comprised of multiple frames or the frame is split into multiple packets - else { - if(info->index == 0){ - if(info->num == 0) - Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); - } - - Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); - - if(info->opcode == WS_TEXT){ - for(size_t i=0; i < info->len; i++) { - msg += (char) data[i]; - } - } else { - char buff[3]; - for(size_t i=0; i < info->len; i++) { - sprintf(buff, "%02x ", (uint8_t) data[i]); - msg += buff ; - } - } - Serial.printf("%s\n",msg.c_str()); - - if((info->index + len) == info->len){ - Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); - if(info->final){ - Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - if(info->message_opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - } - } - } - } */ - -}; - -#endif \ No newline at end of file