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/example.config.json b/data/example.config.json index 7777ec7..b441a17 100644 --- a/data/example.config.json +++ b/data/example.config.json @@ -1,6 +1,9 @@ { "stationMode": 0, "hostname": "illucat", + "apSSID": "illucat", + "apPassword": "illumination", + "connectTimeout": 20000, "stationSSID": "MyWifi", "stationPassword": "myWifiPassword", "meshSSID": "illucat", diff --git a/data/pixelConfig.json b/data/pixelConfig.json index 3b6fb38..7e7f125 100644 --- a/data/pixelConfig.json +++ b/data/pixelConfig.json @@ -1,7 +1,7 @@ { "pin": 4, - "length": 32, + "length": 8, "brightness": 64, - "updateInterval": 50, + "updateInterval": 100, "defaultColor": 100 } \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index d08fb07..de10233 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} @@ -42,6 +56,7 @@ lib_deps = ${common.lib_deps} https://gitlab.com/wirelos/sprocket-core.git#develop [env:release] +src_filter = +<*> - + platform = ${common.platform} board = ${common.board} upload_speed = ${common.upload_speed} @@ -54,6 +69,7 @@ lib_deps = ${common.lib_deps} [env:nodemcu] +src_filter = +<*> - + platform = ${common.platform} board = nodemcu upload_speed = ${common.upload_speed} diff --git a/src/IlluCat.h b/src/IlluCat.h index e34e4f8..7e00875 100644 --- a/src/IlluCat.h +++ b/src/IlluCat.h @@ -1,9 +1,9 @@ #ifndef __MESH_APP__ #define __MESH_APP__ -#include -#include +#include #include +#include #include "config.h" #include "NeoPattern.cpp" @@ -21,14 +21,15 @@ using namespace std; using namespace std::placeholders; -class IlluCat : public MeshSprocket { + +class IlluCat : public Sprocket { public: NeoPattern* pixels; NeoPatternDto defaultState; NeoPatternDto state; AsyncWebServer* server; AsyncWebSocket* ws; - AsyncWebSocket* wsStream; + //AsyncWebSocket* wsStream; NeoPixelConfig pixelConfig; SprocketConfig sprocketConfig; @@ -37,31 +38,27 @@ class IlluCat : public MeshSprocket { SprocketMessage currentMessage; - IlluCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg/* , NeoPixelConfig pixelCfg */) : MeshSprocket(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; - } + 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"); @@ -73,17 +70,20 @@ class IlluCat : public MeshSprocket { pixels = new NeoPattern(pixelConfig.length, pixelConfig.pin, NEO_GRB + NEO_KHZ800); server = new AsyncWebServer(80); ws = new AsyncWebSocket("/pixel"); - wsStream = new AsyncWebSocket("/stream"); + //wsStream = new AsyncWebSocket("/stream"); + defaultAnimation(); // add plugins - addPlugin(new OtaTcpPlugin(otaConfig)); + // TODO add HTTP OTA instead of TCP + //addPlugin(new OtaTcpPlugin(otaConfig)); addPlugin(new WebServerPlugin(webConfig, server)); addPlugin(new WebConfigPlugin(server)); addPlugin(new PixelPlugin(pixelConfig, pixels)); - defaultAnimation(); + - String softApPrt = "SoftAP IP: " + WiFi.softAPIP().toString(); - PRINT_MSG(Serial, SPROCKET_TYPE, softApPrt.c_str()); + // FIXME move to networking + //String softApPrt = "SoftAP IP: " + WiFi.softAPIP().toString(); + //PRINT_MSG(Serial, SPROCKET_TYPE, softApPrt.c_str()); // TODO move to plugin // setup web stuff @@ -91,11 +91,11 @@ class IlluCat : public MeshSprocket { 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); + //wsStream->onEvent(bind(&IlluCat::onStream, this, _1, _2, _3, _4, _5, _6)); + //server->addHandler(wsStream); - return MeshSprocket::activate(scheduler, network); - } using MeshSprocket::activate; + return Sprocket::activate(scheduler, network); + } using Sprocket::activate; // TODO move to utils String getRequestParameterOrDefault(AsyncWebServerRequest *request, String param, String defaultValue, bool isPost = true){ @@ -122,7 +122,7 @@ class IlluCat : public MeshSprocket { String msg = currentMessage.toJsonString(); publish(currentMessage.topic, currentMessage.payload); if(currentMessage.broadcast){ - net->mesh.sendBroadcast(msg); + network.broadcast(msg); } request->send(200, "text/plain", msg); } @@ -131,7 +131,7 @@ class IlluCat : public MeshSprocket { if(type == WS_EVT_DATA){ String frame = WsUtils::parseFrameAsString(type, arg, data, len, 0); dispatch(0, frame); - net->mesh.sendBroadcast(frame); + network.broadcast(frame); } } @@ -144,7 +144,8 @@ class IlluCat : public MeshSprocket { } void loop(){ - MeshSprocket::loop(); + Sprocket::loop(); + yield(); } }; diff --git a/src/config.h b/src/config.h index ec43677..b8025ea 100644 --- a/src/config.h +++ b/src/config.h @@ -8,17 +8,20 @@ // Chip config #define SPROCKET_TYPE "ILLUCAT" #define SERIAL_BAUD_RATE 115200 -#define STARTUP_DELAY 3000 +#define STARTUP_DELAY 1000 // Mesh config #define SPROCKET_MODE 0 #define WIFI_CHANNEL 11 #define MESH_PORT 5555 +#define AP_SSID "illucat" +#define AP_PASSWORD "illumination" #define MESH_PREFIX "illucat-mesh" #define MESH_PASSWORD "th3r31sn0sp00n" #define STATION_SSID "MyAP" #define STATION_PASSWORD "th3r31sn0sp00n" #define HOSTNAME "illucat" +#define CONNECT_TIMEOUT 10000 #define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION //ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE 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..2b751c7 --- /dev/null +++ b/src/wifi/main.cpp @@ -0,0 +1,27 @@ +#include "config.h" +#include "WiFiNet.h" +#include "IlluCat.h" + +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 } +); + +void setup() { + 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/main.cpp b/src/wifiMesh/main.cpp similarity index 63% rename from src/main.cpp rename to src/wifiMesh/main.cpp index 440847f..a9b7f0a 100644 --- a/src/main.cpp +++ b/src/wifiMesh/main.cpp @@ -1,6 +1,6 @@ #include "config.h" #include "MeshNet.h" -#include "IlluCat.h" +#include "MeshCat.h" MeshNet net({ SPROCKET_MODE, WIFI_CHANNEL, @@ -8,11 +8,10 @@ MeshNet net({ STATION_SSID, STATION_PASSWORD, HOSTNAME, MESH_DEBUG_TYPES }); -IlluCat sprocket( +MeshCat 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 } */ + { WEB_CONTEXT_PATH, WEB_DOC_ROOT, WEB_DEFAULT_FILE } ); void setup() {