diff --git a/data/www/gradients.json b/data/www/gradients.json index d184f8d..2b8556f 100644 --- a/data/www/gradients.json +++ b/data/www/gradients.json @@ -3,6 +3,10 @@ "text": "None", "value": ["#000000", "#000000"] }, + { + "text": "Stadler", + "value": ["#0B3F75", "#0B3F75"] + }, { "text": "Blu", "value": ["#00416A", "#E4E5E6"] diff --git a/data/www/index.html b/data/www/index.html index 508a322..4bb3ac4 100644 --- a/data/www/index.html +++ b/data/www/index.html @@ -39,7 +39,7 @@ data-name="pattern" data-topic="pixels/pattern" data-default="0" - data-entries='[{"text": "None", "value": "0"}, {"text": "Rainbow", "value": "1"}, {"text": "TheaterChase", "value": "2"}, {"text": "Color Wipe", "value": "3"}, {"text": "Scanner", "value": "4"}, {"text": "Fade", "value": "5"}]' + data-entries='[{"text": "None", "value": "0"}, {"text": "Rainbow", "value": "1"}, {"text": "TheaterChase", "value": "2"}, {"text": "Color Wipe", "value": "3"}, {"text": "Scanner", "value": "4"}, {"text": "Fade", "value": "5"}, {"text": "Fire", "value": "6"}]' >
  • 0){ + if (bufferSize > 0) + { drawFrameBuffer(TotalSteps, frameBuffer, bufferSize); } break; @@ -379,6 +388,84 @@ class NeoPattern : public Adafruit_NeoPixel return Color(WheelPos * 3, 255 - WheelPos * 3, 0); } } + /** + * Effects from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ + */ + void Fire(int Cooling, int Sparking) + { + byte heat[numPixels()]; + int cooldown; + + // Step 1. Cool down every cell a little + for (int i = 0; i < numPixels(); i++) + { + cooldown = random(0, ((Cooling * 10) / numPixels()) + 2); + + if (cooldown > heat[i]) + { + heat[i] = 0; + } + else + { + heat[i] = heat[i] - cooldown; + } + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for (int k = numPixels() - 1; k >= 2; k--) + { + heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; + } + + // Step 3. Randomly ignite new 'sparks' near the bottom + if (random(255) < Sparking) + { + int y = random(7); + heat[y] = heat[y] + random(160, 255); + //heat[y] = random(160,255); + } + + // Step 4. Convert heat to LED colors + for (int j = 0; j < numPixels(); j++) + { + setPixelHeatColor(j, heat[j]); + } + + showStrip(); + } + + void setPixelHeatColor(int Pixel, byte temperature) + { + // Scale 'heat' down from 0-255 to 0-191 + byte t192 = round((temperature / 255.0) * 191); + + // calculate ramp up from + byte heatramp = t192 & 0x3F; // 0..63 + heatramp <<= 2; // scale up to 0..252 + + // figure out which third of the spectrum we're in: + if (t192 > 0x80) + { // hottest + setPixel(Pixel, 255, 255, heatramp); + } + else if (t192 > 0x40) + { // middle + setPixel(Pixel, 255, heatramp, 0); + } + else + { // coolest + setPixel(Pixel, heatramp, 0, 0); + } + } + + void setPixel(int Pixel, byte red, byte green, byte blue) + { + setPixelColor(Pixel, Color(red, green, blue)); + } + void showStrip() + { + show(); + } }; #endif \ No newline at end of file diff --git a/lib/NeoPattern/NeoPatternDto.h b/lib/NeoPattern/NeoPatternDto.h index 145d402..99a1e7a 100644 --- a/lib/NeoPattern/NeoPatternDto.h +++ b/lib/NeoPattern/NeoPatternDto.h @@ -11,11 +11,12 @@ #define ARRAY_LENGTH(array) sizeof(array)/sizeof(array[0]) struct NeoPixelConfig : public JsonStruct { - int pin; - int length; - int brightness; - int updateInterval; - int defaultColor; + // FIXME constants! + int pin = 4; + int length = 8; + int brightness = 100; + int updateInterval = 100; + int defaultColor = 100; // FIXME remove unused void mapJsonObject(JsonObject& root) { root["pin"] = pin; root["length"] = length; @@ -24,11 +25,11 @@ struct NeoPixelConfig : public JsonStruct { root["defaultColor"] = defaultColor; } void fromJsonObject(JsonObject& json) { - pin = getIntAttrFromJson(json, "pin"); - length = getIntAttrFromJson(json, "length"); - brightness = getIntAttrFromJson(json, "brightness"); - updateInterval = getIntAttrFromJson(json, "updateInterval"); - defaultColor = getIntAttrFromJson(json, "defaultColor"); + pin = getIntAttrFromJson(json, "pin", pin); + length = getIntAttrFromJson(json, "length", length); + brightness = getIntAttrFromJson(json, "brightness", brightness); + updateInterval = getIntAttrFromJson(json, "updateInterval", updateInterval); + defaultColor = getIntAttrFromJson(json, "defaultColor", defaultColor); } }; diff --git a/lib/sprocket-utils/utils_ws.h b/lib/sprocket-utils/utils_web.h similarity index 93% rename from lib/sprocket-utils/utils_ws.h rename to lib/sprocket-utils/utils_web.h index 33ea353..0ff8d4a 100644 --- a/lib/sprocket-utils/utils_ws.h +++ b/lib/sprocket-utils/utils_web.h @@ -1,13 +1,19 @@ -#ifndef __WSUTILS_H___ -#define __WSUTILS_H___ +#ifndef __WebUtils_H___ +#define __WebUtils_H___ #include #include #include #include -class WsUtils { +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){ diff --git a/src/IlluCat.cpp_ b/src/IlluCat.cpp_ new file mode 100644 index 0000000..cab9551 --- /dev/null +++ b/src/IlluCat.cpp_ @@ -0,0 +1,18 @@ +#include "IlluCat.h" + +IlluCat::IlluCat(SprocketConfig cfg, OtaConfig otaCfg, WebServerConfig webCfg) : Sprocket(cfg) +{ + sprocketConfig = cfg; + otaConfig = otaCfg; + webConfig = webCfg; + server = new AsyncWebServer(80); + server->serveStatic(PIXEL_CONFIG_FILE, SPIFFS, "pixelConfig.json"); +} + +void IlluCat::setup() +{ + addPlugin(new PixelPlugin()); + addPlugin(new WebServerPlugin(webConfig, server)); + addPlugin(new WebConfigPlugin(server)); + addPlugin(new WebApi(server, 1)); +} \ No newline at end of file diff --git a/src/IlluCat.h b/src/IlluCat.h index 9ab820d..4143776 100644 --- a/src/IlluCat.h +++ b/src/IlluCat.h @@ -1,5 +1,5 @@ -#ifndef __MESH_APP__ -#define __MESH_APP__ +#ifndef __ILLUCAT__ +#define __ILLUCAT__ #include #include @@ -8,14 +8,11 @@ #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 "WebApi.cpp" #include "PixelPlugin.h" using namespace std; @@ -24,127 +21,26 @@ using namespace std::placeholders; class IlluCat : public Sprocket { public: - NeoPattern* pixels; - NeoPatternDto defaultState; - NeoPatternDto state; AsyncWebServer* server; - AsyncWebSocket* ws; - //AsyncWebSocket* wsStream; - - NeoPixelConfig pixelConfig; SprocketConfig sprocketConfig; OtaConfig otaConfig; WebServerConfig webConfig; - SprocketMessage currentMessage; - 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() { - pixels->RainbowCycle(pixelConfig.updateInterval); - } - Sprocket* activate(Scheduler* scheduler, Network* network) { - - // load config files from SPIFFS - if(SPIFFS.begin()){ - 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"); - defaultAnimation(); + server->serveStatic(PIXEL_CONFIG_FILE, SPIFFS, "pixelConfig.json"); + } - // add plugins - // TODO add HTTP OTA instead of TCP - //addPlugin(new OtaTcpPlugin(otaConfig)); + void setup(){ + addPlugin(new PixelPlugin()); addPlugin(new WebServerPlugin(webConfig, server)); addPlugin(new WebConfigPlugin(server)); - addPlugin(new PixelPlugin(pixelConfig, pixels)); - - - // 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 - 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; + addPlugin(new WebApi(server, 1)); } - - 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/PixelPlugin.cpp b/src/PixelPlugin.cpp new file mode 100644 index 0000000..d6ad2f0 --- /dev/null +++ b/src/PixelPlugin.cpp @@ -0,0 +1,127 @@ +#include "PixelPlugin.h" + +PixelPlugin::PixelPlugin(NeoPixelConfig cfg, NeoPattern *neoPattern) +{ + pixelConfig = cfg; + pixels = neoPattern; + applyConfig(pixelConfig); + defaultAnimation(); +} + +PixelPlugin::PixelPlugin(NeoPattern *neoPattern) +{ + pixels = neoPattern; + loadConfigFromFile(); + applyConfig(pixelConfig); + defaultAnimation(); +} + +PixelPlugin::PixelPlugin() +{ + loadConfigFromFile(); + pixels = new NeoPattern(pixelConfig.length, pixelConfig.pin, NEO_GRB + NEO_KHZ800); + applyConfig(pixelConfig); + defaultAnimation(); +} + +void PixelPlugin::loadConfigFromFile(){ + if (SPIFFS.begin()){ + pixelConfig.fromFile(PIXEL_CONFIG_FILE); + } +} + +void PixelPlugin::applyConfig(NeoPixelConfig cfg) +{ + pixels->setBrightness(pixelConfig.brightness); +} + +void PixelPlugin::defaultAnimation() { + pixels->RainbowCycle(pixelConfig.updateInterval); + animate(); +} + +void PixelPlugin::activate(Scheduler *userScheduler, Network *network) +{ + animation.set(TASK_MILLISECOND * pixelConfig.updateInterval, TASK_FOREVER, bind(&PixelPlugin::animate, this)); + userScheduler->addTask(animation); + animation.enable(); + + subscribe("pixels/colorWheel", bind(&PixelPlugin::colorWheel, this, _1)); + subscribe("pixels/color", bind(&PixelPlugin::setColor, this, _1)); + subscribe("pixels/color2", bind(&PixelPlugin::setColor2, this, _1)); + subscribe("pixels/pattern", bind(&PixelPlugin::setPattern, this, _1)); + subscribe("pixels/totalSteps", bind(&PixelPlugin::setTotalSteps, this, _1)); + subscribe("pixels/brightness", bind(&PixelPlugin::setBrightness, this, _1)); + subscribe("pixels/state", bind(&PixelPlugin::setState, this, _1)); + + PRINT_MSG(Serial, SPROCKET_TYPE, "NeoPixels activated"); +} + +void PixelPlugin::setState(String msg) +{ + PRINT_MSG(Serial, SPROCKET_TYPE, msg.c_str()); + state.fromJsonString(msg); + //pixels->setBrightness(state.brightness); + //pixels->ColorSet(state.color); + pixels->Index = 0; + pixels->Color1 = state.color; + pixels->Color2 = state.color2; + pixels->TotalSteps = state.totalSteps; + pixels->ActivePattern = (pattern)state.pattern; + pixels->Direction = FORWARD; +} + +void PixelPlugin::colorWheel(String msg) +{ + int color = atoi(msg.c_str()); + pixels->ActivePattern = NONE; + pixels->ColorSet(pixels->Wheel(color)); +} + +void PixelPlugin::setTotalSteps(String msg) +{ + pixels->TotalSteps = atoi(msg.c_str()); +} + +void PixelPlugin::setBrightness(String msg) +{ + int inVal = atoi(msg.c_str()); + pixels->setBrightness(inVal); + pixels->show(); +} + +void PixelPlugin::setColor(String msg) +{ + pixels->ActivePattern = NONE; + pixels->Color1 = atoi(msg.c_str()); + //if(pixels->ActivePattern == NONE){ + pixels->ColorSet(pixels->Color1); + //} +} + +void PixelPlugin::setColor2(String msg) +{ + pixels->Color2 = atoi(msg.c_str()); +} + +void PixelPlugin::setPattern(String msg) +{ + pixels->Index = 0; + pixels->Direction = FORWARD; + pixels->ActivePattern = (pattern)atoi(msg.c_str()); +} + +void PixelPlugin::animate() +{ + pixels->Update(); +} + +void PixelPlugin::enable() +{ + animation.enable(); +} + +void PixelPlugin::disable() +{ + animation.disable(); +} \ No newline at end of file diff --git a/src/PixelPlugin.h b/src/PixelPlugin.h index ae9f331..e1a727d 100644 --- a/src/PixelPlugin.h +++ b/src/PixelPlugin.h @@ -9,10 +9,15 @@ #include "Plugin.h" #include "NeoPatternDto.h" #include "NeoPattern.cpp" +#include "config.h" using namespace std; using namespace std::placeholders; +#ifndef PIXEL_CONFIG_FILE +#define PIXEL_CONFIG_FILE "/pixelConfig.json" +#endif + class PixelPlugin : public Plugin { private: NeoPixelConfig pixelConfig; @@ -20,77 +25,24 @@ class PixelPlugin : public Plugin { NeoPatternState state; public: Task animation; - PixelPlugin(NeoPixelConfig cfg, NeoPattern* neoPattern){ - pixelConfig = cfg; - pixels = neoPattern; - pixels->begin(); - pixels->setBrightness(pixelConfig.brightness); - - } - void activate(Scheduler* userScheduler, Network* network){ - subscribe("pixels/colorWheel", bind(&PixelPlugin::colorWheel, this, _1)); - subscribe("pixels/color", bind(&PixelPlugin::setColor, this, _1)); - subscribe("pixels/color2", bind(&PixelPlugin::setColor2, this, _1)); - subscribe("pixels/pattern", bind(&PixelPlugin::setPattern, this, _1)); - subscribe("pixels/totalSteps", bind(&PixelPlugin::setTotalSteps, this, _1)); - subscribe("pixels/brightness", bind(&PixelPlugin::setBrightness, this, _1)); - subscribe("pixels/state", bind(&PixelPlugin::setState, this, _1)); - - animation.set(TASK_MILLISECOND * pixelConfig.updateInterval, TASK_FOREVER, bind(&PixelPlugin::animate, this)); - userScheduler->addTask(animation); - animation.enable(); - PRINT_MSG(Serial, SPROCKET_TYPE, "NeoPixels activated"); - } - - void setState(String msg) { - PRINT_MSG(Serial, SPROCKET_TYPE, msg.c_str()); - state.fromJsonString(msg); - //pixels->setBrightness(state.brightness); - //pixels->ColorSet(state.color); - pixels->Index = 0; - pixels->Color1 = state.color; - pixels->Color2 = state.color2; - pixels->TotalSteps = state.totalSteps; - pixels->ActivePattern = (pattern) state.pattern; - pixels->Direction = FORWARD; - } - void colorWheel(String msg){ - int color = atoi(msg.c_str()); - pixels->ActivePattern = NONE; - pixels->ColorSet(pixels->Wheel(color)); - } - void setTotalSteps(String msg){ - pixels->TotalSteps = atoi(msg.c_str()); - } - void setBrightness(String msg){ - int inVal = atoi(msg.c_str()); - pixels->setBrightness(inVal); - pixels->show(); - } - void setColor(String msg){ - pixels->ActivePattern = NONE; - pixels->Color1 = atoi(msg.c_str()); - //if(pixels->ActivePattern == NONE){ - pixels->ColorSet(pixels->Color1); - //} - } - void setColor2(String msg){ - pixels->Color2 = atoi(msg.c_str()); - } - void setPattern(String msg){ - pixels->Index = 0; - pixels->Direction = FORWARD; - pixels->ActivePattern = (pattern)atoi(msg.c_str()); - } - void animate(){ - pixels->Update(); - } - void enable(){ - animation.enable(); - } - void disable(){ - animation.disable(); - } + PixelPlugin(NeoPixelConfig cfg, NeoPattern* neoPattern); + PixelPlugin(NeoPattern *neoPattern); + PixelPlugin(); + void loadConfigFromFile(); + void applyConfig(NeoPixelConfig cfg); + void applyConfigFromFile(); + void activate(Scheduler* userScheduler, Network* network); + void defaultAnimation(); + void setState(String msg); + void colorWheel(String msg); + void setTotalSteps(String msg); + void setBrightness(String msg); + void setColor(String msg); + void setColor2(String msg); + void setPattern(String msg); + void animate(); + void enable(); + void disable(); }; #endif \ No newline at end of file diff --git a/src/WebApi.cpp b/src/WebApi.cpp new file mode 100644 index 0000000..1c5860c --- /dev/null +++ b/src/WebApi.cpp @@ -0,0 +1,74 @@ +#ifndef __WEBAPI_PLUGIN__ +#define __WEBAPI_PLUGIN__ + +#include +#include + +#include "config.h" +#include "utils_print.h" +#include "utils_web.h" +#include +#include + +using namespace std; +using namespace std::placeholders; + +// TODO headerfile + +class WebApi : public Plugin { + private: + Network* network; + public: + AsyncWebServer* server; + AsyncWebSocket* ws; + SprocketMessage currentMessage; + + int broadcast; + + WebApi(AsyncWebServer* _server, int _broadcast = 0){ + server = _server; + broadcast = _broadcast; + } + + void activate(Scheduler* _scheduler, Network* _network) { + network = _network; + ws = new AsyncWebSocket("/ws"); // FIXME constant /ws + ws->onEvent(bind(&WebApi::onWsEvent, this, _1, _2, _3, _4, _5, _6)); + server->addHandler(ws); + server->on("/api", HTTP_POST, bind(&WebApi::postRequestHandler, this, _1)); + } + + void postRequestHandler(AsyncWebServerRequest *request) { + PRINT_MSG(Serial, SPROCKET_TYPE, "POST WebApi"); + currentMessage.topic = WebUtils::getRequestParameterOrDefault(request, "topic", ""); + currentMessage.payload = WebUtils::getRequestParameterOrDefault(request, "payload", ""); + currentMessage.broadcast = atoi(WebUtils::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); + } + void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) { + // FIXME to limitted + if(type == WS_EVT_DATA){ + String frame = WebUtils::parseFrameAsString(type, arg, data, len, 0); + dispatch(0, frame); + } + } + + void dispatch( uint32_t from, String &msg ) { + currentMessage.fromJsonString(msg); + if(currentMessage.valid){ + currentMessage.from = from; + publish(currentMessage.topic, currentMessage.payload); + if(broadcast){ + network->broadcast(msg); + } + } + } + +}; + +#endif \ No newline at end of file diff --git a/src/config.h b/src/config.h index b8025ea..ba28385 100644 --- a/src/config.h +++ b/src/config.h @@ -25,6 +25,8 @@ #define MESH_DEBUG_TYPES ERROR | STARTUP | CONNECTION //ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE +#define PIXEL_CONFIG_FILE "/pixelConfig.json" + // OTA config #define OTA_PORT 8266 #define OTA_PASSWORD "" diff --git a/src/wifi/WebCat.h b/src/wifi/WebCat.h deleted file mode 100644 index 54fb09d..0000000 --- a/src/wifi/WebCat.h +++ /dev/null @@ -1,118 +0,0 @@ -#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 index 2b751c7..05f873b 100644 --- a/src/wifi/main.cpp +++ b/src/wifi/main.cpp @@ -18,6 +18,7 @@ IlluCat sprocket( ); void setup() { + sprocket.setup(); sprocket.join(net); } diff --git a/src/wifiMesh/main.cpp b/src/wifiMesh/main.cpp index a9b7f0a..6dfc6a4 100644 --- a/src/wifiMesh/main.cpp +++ b/src/wifiMesh/main.cpp @@ -15,6 +15,7 @@ MeshCat sprocket( ); void setup() { + sprocket.setup(); sprocket.join(net); }