diff --git a/.vscode/settings.json b/.vscode/settings.json index 8d30d4d..5b1aa28 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,27 @@ "unordered_map": "cpp", "vector": "cpp", "tuple": "cpp", - "utility": "cpp" + "utility": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "fstream": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "numeric": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" } } \ No newline at end of file diff --git a/data/pixelConfig.json b/data/pixelConfig.json index 4a0d066..0bbd7c5 100644 --- a/data/pixelConfig.json +++ b/data/pixelConfig.json @@ -1,7 +1,7 @@ { "pin": 4, - "length": 300, + "length": 32, "brightness": 64, - "updateInterval": 50, + "updateInterval": 100, "defaultColor": 100 } \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index d08fb07..fd3924d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -31,6 +31,20 @@ lib_deps = Adafruit NeoPixel [env:build] +src_filter = +<*> - + +platform = ${common.platform} +board = ${common.board} +upload_speed = ${common.upload_speed} +monitor_baud = ${common.monitor_baud} +framework = ${common.framework} +build_flags = -Wl,-Teagle.flash.4m1m.ld + -DSPROCKET_PRINT=1 +lib_deps = ${common.lib_deps} + https://gitlab.com/wirelos/sprocket-core.git#develop + + +[env:build-mesh] +src_filter = +<*> + - platform = ${common.platform} board = ${common.board} upload_speed = ${common.upload_speed} diff --git a/src/IlluCat.h b/src/IlluCat.h index 985c41a..5a9dfa0 100644 --- a/src/IlluCat.h +++ b/src/IlluCat.h @@ -2,11 +2,8 @@ #define __MESH_APP__ #include -//#include -//#include +#include #include -//#include - #include "config.h" #include "NeoPattern.cpp" @@ -24,17 +21,15 @@ using namespace std; using namespace std::placeholders; -//const byte DNS_PORT = 53; class IlluCat : public Sprocket { public: - Scheduler* ts; NeoPattern* pixels; NeoPatternDto defaultState; NeoPatternDto state; AsyncWebServer* server; AsyncWebSocket* ws; - AsyncWebSocket* wsStream; + //AsyncWebSocket* wsStream; NeoPixelConfig pixelConfig; SprocketConfig sprocketConfig; @@ -43,110 +38,42 @@ class IlluCat : public Sprocket { SprocketMessage currentMessage; - IlluCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg/* , NeoPixelConfig pixelCfg */) : Sprocket(cfg) { - //pixelConfig = pixelCfg; - + IlluCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : Sprocket(cfg) { sprocketConfig = cfg; otaConfig = otaCfg; webConfig = webCfg; - - pixelConfig.pin = 4; - pixelConfig.length = 8; - pixelConfig.brightness = 32; - pixelConfig.updateInterval = 100; - pixelConfig.defaultColor = 100; - - ts = new Scheduler(); - + // defaults + //pixelConfig.pin = 4; + //pixelConfig.length = 8; + //pixelConfig.brightness = 32; + //pixelConfig.updateInterval = 100; + //pixelConfig.defaultColor = 100; } + virtual void scanningAnimation() { pixels->Scanner(pixels->Wheel(COLOR_NOT_CONNECTED), pixelConfig.updateInterval); } virtual void defaultAnimation() { + // remove DEPRECATED USAGE String defaultStr = String(defaultState.value); PIXEL_FNCS[defaultState.mode](pixels, defaultStr.c_str()); } Sprocket* activate(Scheduler* scheduler, Network* network) { - //net = static_cast(network); - // load config files from SPIFFS - if(SPIFFS.begin()){ - pixelConfig.fromFile("/pixelConfig.json"); - defaultState.fromFile("/pixelState.json"); - state = defaultState; - } + pixelConfig.fromFile("/pixelConfig.json"); + defaultState.fromFile("/pixelState.json"); + state = defaultState; // initialize services pixels = new NeoPattern(pixelConfig.length, pixelConfig.pin, NEO_GRB + NEO_KHZ800); - server = new AsyncWebServer(80); - ws = new AsyncWebSocket("/pixel"); - wsStream = new AsyncWebSocket("/stream"); // add plugins - //addPlugin(new OtaTcpPlugin(otaConfig)); - addPlugin(new WebServerPlugin(webConfig, server)); - addPlugin(new WebConfigPlugin(server)); addPlugin(new PixelPlugin(pixelConfig, pixels)); defaultAnimation(); - - // configure DNS - // plugin? - //dnsServer->setErrorReplyCode(DNSReplyCode::NoError); - //dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); - String softApPrt = "SoftAP IP: " + WiFi.softAPIP().toString(); - PRINT_MSG(Serial, SPROCKET_TYPE, softApPrt.c_str()); - - // TODO move to plugin - // setup web stuff - server->serveStatic("/pixelConfig.json", SPIFFS, "pixelConfig.json"); - server->on("/pixel/api", HTTP_POST, bind(&IlluCat::patternWebRequestHandler, this, _1)); - ws->onEvent(bind(&IlluCat::onWsEvent, this, _1, _2, _3, _4, _5, _6)); - server->addHandler(ws); - wsStream->onEvent(bind(&IlluCat::onStream, this, _1, _2, _3, _4, _5, _6)); - server->addHandler(wsStream); - return Sprocket::activate(scheduler, network); } using Sprocket::activate; - // TODO move to utils - String getRequestParameterOrDefault(AsyncWebServerRequest *request, String param, String defaultValue, bool isPost = true){ - if(request->hasParam(param, isPost)) { - return request->getParam(param, isPost)->value(); - } - return defaultValue; - } - - - void onStream(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { - if(type == WS_EVT_DATA){ - PRINT_MSG(Serial, SPROCKET_TYPE, WsUtils::parseFrameAsString(type, arg, data, len, 0).c_str()); - pixels->ActivePattern = NONE; - pixels->handleStream(data, len); - } - } - - void patternWebRequestHandler(AsyncWebServerRequest *request) { - PRINT_MSG(Serial, SPROCKET_TYPE, "POST /pixel/api"); - currentMessage.topic = getRequestParameterOrDefault(request, "topic", ""); - currentMessage.payload = getRequestParameterOrDefault(request, "payload", ""); - currentMessage.broadcast = atoi(getRequestParameterOrDefault(request, "broadcast", "0").c_str()); - String msg = currentMessage.toJsonString(); - publish(currentMessage.topic, currentMessage.payload); - if(currentMessage.broadcast){ - network.broadcast(msg); - } - request->send(200, "text/plain", msg); - } - - virtual void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { - if(type == WS_EVT_DATA){ - String frame = WsUtils::parseFrameAsString(type, arg, data, len, 0); - dispatch(0, frame); - network.broadcast(frame); - } - } - virtual void dispatch( uint32_t from, String &msg ) { currentMessage.fromJsonString(msg); if(currentMessage.valid){ diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 72f3185..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "config.h" -//#include "MeshNet.h" -#include "WiFiNet.h" -#include "IlluCat.h" - -/* MeshNet net({ - SPROCKET_MODE, WIFI_CHANNEL, - MESH_PORT, MESH_PREFIX, MESH_PASSWORD, - STATION_SSID, STATION_PASSWORD, HOSTNAME, - MESH_DEBUG_TYPES -}); */ -WiFiNet net(SPROCKET_MODE,STATION_SSID, STATION_PASSWORD,AP_SSID, AP_PASSWORD,HOSTNAME,CONNECT_TIMEOUT); -IlluCat sprocket( - { STARTUP_DELAY, SERIAL_BAUD_RATE }, - { OTA_PORT, OTA_PASSWORD }, - { WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE }/* , - { LED_STRIP_PIN, LED_STRIP_LENGTH, LED_STRIP_BRIGHTNESS, LED_STRIP_UPDATE_INTERVAL, LED_STRIP_DEFAULT_COLOR } */ -); - -void setup() { - sprocket.join(net); -} - -void loop() { - sprocket.loop(); - yield(); -} \ No newline at end of file diff --git a/src/wifi/WebCat.h b/src/wifi/WebCat.h new file mode 100644 index 0000000..54fb09d --- /dev/null +++ b/src/wifi/WebCat.h @@ -0,0 +1,118 @@ +#ifndef __WEB_CAT__ +#define __WEB_CAT__ + +#include +#include +#include + +#include "config.h" +#include "NeoPattern.cpp" +#include "NeoPatternDto.h" +#include "NeoPattern_api_json.h" +#include "NeoPattern_api_modes.cpp" +#include "utils_print.h" +#include "utils_ws.h" +#include +#include +#include +#include +#include "PixelPlugin.h" +#include "IlluCat.h" + +using namespace std; +using namespace std::placeholders; + + +class WebCat : public IlluCat { + public: + AsyncWebServer* server; + AsyncWebSocket* ws; + //AsyncWebSocket* wsStream; + WebServerConfig webConfig; + + SprocketMessage currentMessage; + + WebCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : IlluCat(cfg, otaCfg, webCfg) { + webConfig = webCfg; + } + + Sprocket* activate(Scheduler* scheduler, Network* network) { + + Serial.println("SETUP SERVER"); + // initialize services + server = new AsyncWebServer(80); + ws = new AsyncWebSocket("/pixel"); + //wsStream = new AsyncWebSocket("/stream"); + Serial.println("init handlers"); + // TODO move to plugin + // setup web stuff + server->serveStatic("/pixelConfig.json", SPIFFS, "pixelConfig.json"); + server->on("/pixel/api", HTTP_POST, bind(&WebCat::patternWebRequestHandler, this, _1)); + ws->onEvent(bind(&WebCat::onWsEvent, this, _1, _2, _3, _4, _5, _6)); + server->addHandler(ws); + //wsStream->onEvent(bind(&WebCat::onStream, this, _1, _2, _3, _4, _5, _6)); + //server->addHandler(wsStream); + Serial.println("add plugins"); + // add plugins + // TODO add HTTP OTA instead of TCP + //addPlugin(new OtaTcpPlugin(otaConfig)); + addPlugin(new WebServerPlugin(webConfig, server)); + addPlugin(new WebConfigPlugin(server)); + + return IlluCat::activate(scheduler, network);; + }; + + + // TODO move to utils + String getRequestParameterOrDefault(AsyncWebServerRequest *request, String param, String defaultValue, bool isPost = true){ + if(request->hasParam(param, isPost)) { + return request->getParam(param, isPost)->value(); + } + return defaultValue; + } + + + void onStream(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { + if(type == WS_EVT_DATA){ + PRINT_MSG(Serial, SPROCKET_TYPE, WsUtils::parseFrameAsString(type, arg, data, len, 0).c_str()); + pixels->ActivePattern = NONE; + pixels->handleStream(data, len); + } + } + + void patternWebRequestHandler(AsyncWebServerRequest *request) { + PRINT_MSG(Serial, SPROCKET_TYPE, "POST /pixel/api"); + currentMessage.topic = getRequestParameterOrDefault(request, "topic", ""); + currentMessage.payload = getRequestParameterOrDefault(request, "payload", ""); + currentMessage.broadcast = atoi(getRequestParameterOrDefault(request, "broadcast", "0").c_str()); + String msg = currentMessage.toJsonString(); + publish(currentMessage.topic, currentMessage.payload); + if(currentMessage.broadcast){ + network.broadcast(msg); + } + request->send(200, "text/plain", msg); + } + + virtual void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { + if(type == WS_EVT_DATA){ + String frame = WsUtils::parseFrameAsString(type, arg, data, len, 0); + dispatch(0, frame); + network.broadcast(frame); + } + } + + virtual void dispatch( uint32_t from, String &msg ) { + currentMessage.fromJsonString(msg); + if(currentMessage.valid){ + currentMessage.from = from; + publish(currentMessage.topic, currentMessage.payload); + } + } + + void loop(){ + Sprocket::loop(); + yield(); + } +}; + +#endif \ No newline at end of file diff --git a/src/wifi/main.cpp b/src/wifi/main.cpp new file mode 100644 index 0000000..57f92bd --- /dev/null +++ b/src/wifi/main.cpp @@ -0,0 +1,28 @@ +#include "config.h" +#include "WiFiNet.h" +#include "WebCat.h" + +WiFiNet net( + SPROCKET_MODE, + STATION_SSID, + STATION_PASSWORD, + AP_SSID, + AP_PASSWORD, + HOSTNAME, + CONNECT_TIMEOUT +); +WebCat sprocket( + { STARTUP_DELAY, SERIAL_BAUD_RATE }, + { OTA_PORT, OTA_PASSWORD }, + { WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE } +); + +void setup() { + delay(STARTUP_DELAY); + sprocket.join(net); +} + +void loop() { + sprocket.loop(); + yield(); +} \ No newline at end of file diff --git a/src/wifiMesh/MeshCat.h b/src/wifiMesh/MeshCat.h new file mode 100644 index 0000000..083acf4 --- /dev/null +++ b/src/wifiMesh/MeshCat.h @@ -0,0 +1,39 @@ +#ifndef __MESHCAT__ +#define __MESHCAT__ + +#include +#include +#include +#include "utils_print.h" +#include "IlluCat.h" +#include "config.h" + +using namespace std; +using namespace std::placeholders; + +class MeshCat : public IlluCat { + public: + Scheduler* meshScheduler; + + MeshCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : IlluCat(cfg, otaCfg, webCfg) { + meshScheduler = new Scheduler(); + } + + Sprocket* join(Network& net){ + PRINT_MSG(Serial, SPROCKET_TYPE, "join mesh network"); + net.init(meshScheduler); + net.onReceive(bind(&IlluCat::dispatch,this, _1, _2)); + net.connect(); + network = net; + return activate(&scheduler, &net); + } + + void loop() { + meshScheduler->execute(); + yield(); + Sprocket::loop(); + yield(); + } +}; + +#endif \ No newline at end of file diff --git a/src/wifiMesh/main.cpp b/src/wifiMesh/main.cpp new file mode 100644 index 0000000..7656152 --- /dev/null +++ b/src/wifiMesh/main.cpp @@ -0,0 +1,25 @@ +#include "config.h" +#include "MeshNet.h" +#include "MeshCat.h" + +MeshNet net({ + SPROCKET_MODE, WIFI_CHANNEL, + MESH_PORT, MESH_PREFIX, MESH_PASSWORD, + STATION_SSID, STATION_PASSWORD, HOSTNAME, + MESH_DEBUG_TYPES +}); +MeshCat sprocket( + { STARTUP_DELAY, SERIAL_BAUD_RATE }, + { OTA_PORT, OTA_PASSWORD }, + { WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE } +); + +void setup() { + delay(STARTUP_DELAY); + sprocket.join(net); +} + +void loop() { + sprocket.loop(); + yield(); +} \ No newline at end of file