Skip to content

Commit

Permalink
WLED Compatibility commit + ESPAsyncWebServer fork change
Browse files Browse the repository at this point in the history
platformio: change from me-no-dev to aircoookie fork of ESPAsyncWebServer (in ewowi fork, with StarMod mods)

AppModLeds: add ON variable (WIP, to test wled-native and wled nodes tab)

SysModUI: processJson: support v(erbose) - WLED compatibility

SysModWeb:
- add CORS access-control (WLED compatibility)
- setupJsonHandlers: support v(erbose) - WLED compatibility
- serveJson: send state and info json ,WLED compatibility: for wled-native and wled nodes tab
  • Loading branch information
ewowi committed Oct 26, 2023
1 parent 9151869 commit 583bcb9
Show file tree
Hide file tree
Showing 9 changed files with 998 additions and 967 deletions.
7 changes: 2 additions & 5 deletions data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function linearToLogarithm(json, value) {

let result = Math.exp(minv + scale*(value-minp));

console.log(json, minv, maxv, scale, result);
// console.log(json, minv, maxv, scale, result);

return Math.round(result);
}
Expand Down Expand Up @@ -316,11 +316,8 @@ function generateHTML(parentNode, json, rowNr = -1) {
// buttonCancelNode.addEventListener('click', (event) => {console.log(json.type + " click", event);});
// }
if (json.type == "number") {
if (json.min) valueNode.min = json.min;
valueNode.min = json.min?json.min:0; //if not specified then unsigned value (min=0)
if (json.max) valueNode.max = json.max;
// valueNode.setAttribute('size', '4');
// valueNode.maxlength = 4;
// valueNode.size = 4;
}
else {
if (json.max) valueNode.setAttribute('maxlength', json.max); //for text and textarea set max length valueNode.maxlength is not working for some reason
Expand Down
4 changes: 2 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
[starmod]
lib_deps =
https://github.com/bblanchon/ArduinoJson.git
https://github.com/ewowi/ESPAsyncWebServer.git ;me-no-dev + 64 + queueLength
; https://github.com/ewoudwijma/ESPAsyncWebServer.git ;aircoookie + getClients
; https://github.com/ewowi/ESPAsyncWebServer.git ;me-no-dev + 64 + queueLength
https://github.com/ewoudwijma/ESPAsyncWebServer.git ;aircoookie + getClients
; https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 ;optionally combine with aircoookie
; https://github.com/lost-hope/ESPAsyncWebServer.git#master ;artifx on <ip>/edit

Expand Down
12 changes: 12 additions & 0 deletions src/App/AppModLeds.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
#include <vector>
#include "FastLED.h"

// #define FASTLED_RGBW

//https://www.partsnotincluded.com/fastled-rgbw-neopixels-sk6812/
inline uint16_t getRGBWsize(uint16_t nleds){
uint16_t nbytes = nleds * 4;
if(nbytes % 3 > 0) return nbytes / 3 + 1;
else return nbytes / 3;
}

//https://github.com/FastLED/FastLED/blob/master/examples/DemoReel100/DemoReel100.ino
//https://blog.ja-ke.tech/2019/06/02/neopixel-performance.html

Expand All @@ -44,6 +53,9 @@ class AppModLeds:public Module {

parentVar = ui->initModule(parentVar, name);

ui->initCheckBox(parentVar, "on");
// ui->initCheckBox(parentVar, "v");

//logarithmic slider (10)
ui->initSlider(parentVar, "bri", 5, 0, 255, 10, false, [](JsonObject var) { //uiFun
web->addResponse(var["id"], "label", "Brightness");
Expand Down
6 changes: 5 additions & 1 deletion src/Sys/SysModUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,11 @@ const char * SysModUI::processJson(JsonVariant &json) {
JsonVariant value = pair.value();

// commands
if (pair.key() == "uiFun") { //JsonString can do ==
if (pair.key() == "v") {
// do nothing as it is no real var bu the verbose command of WLED
USER_PRINTF("processJson v type\n", pair.value().as<String>());
}
else if (pair.key() == "uiFun") { //JsonString can do ==
//find the select var and collect it's options...
if (value.is<JsonArray>()) { //should be
for (JsonVariant value2: value.as<JsonArray>()) {
Expand Down
4 changes: 2 additions & 2 deletions src/Sys/SysModUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class SysModUI:public Module {
else
var["value"] = value; //if value is a pointer, it needs to have a value
}

if (min) var["min"] = min;
if (max) var["max"] = max;

Expand All @@ -138,7 +138,7 @@ class SysModUI:public Module {
//run the change function and send response to all? websocket clients
static void setChFunAndWs(JsonObject var, const char * value = nullptr);

//interpret json and run commands or set values
//interpret json and run commands or set values like deserializeJson / deserializeState / deserializeConfig
static const char * processJson(JsonVariant &json); //static for setupJsonHandlers

//called to rebuild selects and tables (tbd: also label and comments is done again, that is not needed)
Expand Down
68 changes: 42 additions & 26 deletions src/Sys/SysModWeb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ unsigned long SysModWeb::wsSendDataWsCounter = 0;
SysModWeb::SysModWeb() :Module("Web") {
ws = new AsyncWebSocket("/ws");
server = new AsyncWebServer(80);

//CORS compatiblity
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*");

responseDocLoopTask = new DynamicJsonDocument(2048);
responseDocAsyncTCP = new DynamicJsonDocument(3072);
};
Expand Down Expand Up @@ -187,7 +193,7 @@ void SysModWeb::wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client,
USER_PRINT_Async("wsEvent deserializeJson failed with code %s\n", error.c_str());
client->text("{\"success\":true}"); // we have to send something back otherwise WS connection closes
} else {
const char * error = processWSFunc(responseVariant); //processJson, adds to responsedoc
const char * error = processWSFunc(responseVariant); //processJson, adds to responseDoc / responseVariant

if (responseVariant.size()) {
print->printJson("WS_EVT_DATA json", responseVariant);
Expand Down Expand Up @@ -539,14 +545,21 @@ bool SysModWeb::setupJsonHandlers(const char * uri, const char * (*processFunc)(

print->printJson("AsyncCallbackJsonWebHandler", json);
const char * pErr = processFunc(json); //processJson
if (responseVariant.size()) {

//WLED compatibility
if (json["v"]) { //WLED compatibility: verbose response
serveJson (request);
}
else
if (responseVariant.size()) { //responseVariant set by processFunc
char resStr[200];
serializeJson(responseVariant, resStr, 200);
USER_PRINT_Async("processJsonUrl response %s\n", resStr);
request->send(200, "text/plain", resStr);
request->send(200, "application/json", resStr);
}
else
request->send(200, "text/plain", "OKOK");
// request->send(200, "text/plain", "OK");
request->send(200, "application/json", F("{\"success\":true}"));
});
server->addHandler(handler);
return true;
Expand Down Expand Up @@ -618,49 +631,52 @@ JsonDocument * SysModWeb::getResponseDoc() {
}

void SysModWeb::serveJson(AsyncWebServerRequest *request) {
JsonArray model = SysModModel::model->as<JsonArray>();
USER_PRINTF("serveJson %s, %s %d %d %d %d\n", request->client()->remoteIP().toString().c_str(), request->url().c_str(), model.size(), measureJson(model), model.memoryUsage(), SysModModel::model->capacity());

AsyncJsonResponse * response;

if (request->url().indexOf("si") > 0) {
// if (request->url().indexOf("si") > 0) {
USER_PRINTF("serveJson si %s, %s\n", request->client()->remoteIP().toString().c_str(), request->url().c_str());
response = new AsyncJsonResponse(false, 5000); //object
JsonObject root = response->getRoot();

//temporary set all WLED variables (as otherwise WLED-native does not show the instance): tbd: clean up
const char* jsonState = "{\"on\":true,\"bri\":10,\"transition\":7,\"ps\":9,\"pl\":-1,\"AudioReactive\":{\"on\":false},\"CustomEffects\":{\"on\":true},\"nl\":{\"on\":false,\"dur\":60,\"mode\":1,\"tbri\":0,\"rem\":-1},\"udpn\":{\"send\":false,\"recv\":true},\"lor\":0,\"mainseg\":0,\"seg\":[{\"id\":0,\"start\":0,\"stop\":144,\"len\":144,\"grp\":1,\"spc\":0,\"of\":0,\"on\":true,\"frz\":false,\"bri\":255,\"cct\":127,\"col\":[[182,15,98,0],[0,0,0,0],[255,224,160,0]],\"fx\":174,\"sx\":128,\"ix\":128,\"pal\":11,\"c1\":8,\"c2\":20,\"c3\":31,\"sel\":true,\"rev\":false,\"mi\":false,\"o1\":false,\"o2\":false,\"o3\":false,\"ssim\":0,\"mp12\":1}]}";
const char* jsonInfo = "{\"ver\":\"0.14.0-mdev\",\"vid\":2209091,\"leds\":{\"count\":144,\"pwr\":248,\"fps\":41,\"maxpwr\":2000,\"maxseg\":32,\"cpal\":0,\"seglc\":[11],\"lc\":11,\"rgbw\":true,\"wv\":2,\"cct\":0},\"str\":false,\"name\":\"StarModewowi\",\"udpport\":21324,\"live\":false,\"liveseg\":-1,\"lm\":\"\",\"lip\":\"\",\"ws\":0,\"fxcount\":177,\"palcount\":71,\"maps\":[0],\"wifi\":{\"bssid\":\"96:83:C4:2D:4B:8A\",\"rssi\":-43,\"signal\":100,\"channel\":11},\"fs\":{\"u\":45,\"t\":983,\"pmt\":0},\"ndc\":1,\"arch\":\"esp32\",\"core\":\"v3.3.6-16-gcc5440f6a2\",\"lwip\":0,\"freeheap\":173488,\"uptime\":31264,\"u\":{\"Temperature\":[0,\" Sensor Error!\"],\"opt\":111,\"brand\":\"StarMod\",\"product\":\"LED\",\"mac\":\"3ce90e874ac0\",\"ip\":\"192.168.8.102\"}";
//temporary set all WLED variables (as otherwise WLED-native does not show the instance): tbd: clean up (state still needed, info not)
const char* jsonState = "{\"transition\":7,\"ps\":9,\"pl\":-1,\"nl\":{\"on\":false,\"dur\":60,\"mode\":1,\"tbri\":0,\"rem\":-1},\"udpn\":{\"send\":false,\"recv\":true},\"lor\":0,\"mainseg\":0,\"seg\":[{\"id\":0,\"start\":0,\"stop\":144,\"len\":144,\"grp\":1,\"spc\":0,\"of\":0,\"on\":true,\"frz\":false,\"bri\":255,\"cct\":127,\"col\":[[182,15,98,0],[0,0,0,0],[255,224,160,0]],\"fx\":0,\"sx\":128,\"ix\":128,\"pal\":11,\"c1\":8,\"c2\":20,\"c3\":31,\"sel\":true,\"rev\":false,\"mi\":false,\"o1\":false,\"o2\":false,\"o3\":false,\"ssim\":0,\"mp12\":1}]}";
StaticJsonDocument<5000> docState;
deserializeJson(docState, jsonState);
StaticJsonDocument<5000> docInfo;
deserializeJson(docInfo, jsonInfo);
root["state"] = docState;
root["info"] = docInfo;


root["state"]["bri"] = mdl->getValue("bri");
root["state"]["on"] = true;
root["state"]["on"] = mdl->getValue("on").as<bool>();
root["info"]["name"] = mdl->getValue("serverName");
// root["info"]["ver"] = "0.14.0-mdev";
// root["info"]["arch"] = "esp32"; //platformName
// root["info"]["wifi"]["rssi"] = -42;
root["info"]["arch"] = "esp32"; //platformName

root["info"]["rel"] = "StarMod";
root["info"]["ver"] = "0.0.1";
root["info"]["vid"] = mdl->getValue("version").as<uint32_t>(); //WLED-native needs int otherwise status offline!!!
root["info"]["leds"]["count"] = 999;
root["info"]["leds"]["countP"] = 998;
root["info"]["leds"]["fps"] = mdl->getValue("fps"); //tbd: should be realFps but is ro var
root["info"]["wifi"]["rssi"] = WiFi.RSSI();// mdl->getValue("rssi"); (ro)

String escapedMac;
escapedMac = WiFi.macAddress();
escapedMac.replace(":", "");
escapedMac.toLowerCase();
root["info"]["mac"] = (char *)escapedMac.c_str(); //copy mdns->escapedMac gives LoadProhibited crash, tbd: find out why
root["info"]["ip"] = (char *)WiFi.localIP().toString().c_str();
// print->printJson("serveJson", root);
}
else { // return model.json
response = new AsyncJsonResponse(true, model.memoryUsage()); //array tbd: here copy is mode, see WLED for using reference
JsonArray root = response->getRoot();
// }
// else { // return model.json
// JsonArray model = SysModModel::model->as<JsonArray>();
// USER_PRINTF("serveJson model %s, %s %d %d %d %d\n", request->client()->remoteIP().toString().c_str(), request->url().c_str(), model.size(), measureJson(model), model.memoryUsage(), SysModModel::model->capacity());

// root = module does not work? so add ead element individually
for (JsonObject module: model)
root.add(module);
// response = new AsyncJsonResponse(true, model.memoryUsage()); //array tbd: here copy is mode, see WLED for using reference
// JsonArray root = response->getRoot();

}
// // root = module does not work? so add each element individually
// for (JsonObject module: model)
// root.add(module);
// }

response->setLength();
request->send(response);
Expand Down
6 changes: 4 additions & 2 deletions src/Sys/SysModWeb.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ class SysModWeb:public Module {
//try this !!!: curl -X POST "http://192.168.121.196/json" -d '{"pin2":false}' -H "Content-Type: application/json"
//curl -X POST "http://4.3.2.1/json" -d '{"pin2":false}' -H "Content-Type: application/json"
//curl -X POST "http://4.3.2.1/json" -d '{"bri":20}' -H "Content-Type: application/json"
//curl -X POST "http://192.168.8.102/json" -d '{"fx":2}' -H "Content-Type: application/json"
//curl -X POST "http://192.168.8.125/json" -d '{"fx":2}' -H "Content-Type: application/json"
//curl -X POST "http://192.168.8.152/json" -d '{"nrOfLeds":2000}' -H "Content-Type: application/json"

//set ws var and create AsyncCallbackJsonWebHandler , currently for /json
bool setupJsonHandlers(const char * uri, const char * (*processFunc)(JsonVariant &));

void addResponse(const char * id, const char * key, const char * value);
Expand All @@ -66,9 +67,10 @@ class SysModWeb:public Module {

void clientsToJson(JsonArray array, bool nameOnly = false, const char * filter = nullptr);

//gets the right responseDoc, depending on which task you are in
//gets the right responseDoc, depending on which task you are in, alternative for requestJSONBufferLock
JsonDocument * getResponseDoc();

//Currently only WLED style state and info
static void serveJson(AsyncWebServerRequest *request);

static unsigned long wsSendBytesCounter;
Expand Down
21 changes: 11 additions & 10 deletions src/User/UserModInstances.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ struct AppData {
uint8_t fx;
uint8_t palette;
uint8_t projection;
};
}; // 4 bytes

struct SysData {
unsigned long upTime;
uint8_t type;
uint8_t syncGroups;
uint16_t dmxChannel;
};
}; //8 bytes

struct NodeInfo {
IPAddress ip;
Expand All @@ -53,8 +53,8 @@ struct UDPWLEDMessage {
//compatible with WLED nodes as it only interprets first 44 bytes
struct UDPStarModMessage {
UDPWLEDMessage header; // 44 bytes
SysData sys;
AppData app;
SysData sys; //44
AppData app; //52
char body[1460 - sizeof(UDPWLEDMessage) - sizeof(SysData) - sizeof(AppData)];
};

Expand Down Expand Up @@ -149,7 +149,7 @@ class UserModInstances:public Module {
web->addResponse(var["id"], "label", "Show");
});

ui->initNumber(parentVar, "syncGroups", 0, 0, 99, false, [](JsonObject var) { //uiFun
ui->initNumber(parentVar, "syncGroups", 0, 0, 255, false, [](JsonObject var) { //uiFun
web->addResponse(var["id"], "comment", "0=no sync");
}, [](JsonObject var) { //chFun
ui->valChangedForInstancesTemp = true;
Expand Down Expand Up @@ -222,9 +222,9 @@ class UserModInstances:public Module {
uint8_t *udpIn = (uint8_t *)&udpSyncMessage;
notifierUdp.read(udpIn, packetSize);

for (int i=0; i<40; i++) {
Serial.printf("%d: %d\n", i, udpIn[i]);
}
// for (int i=0; i<40; i++) {
// Serial.printf("%d: %d\n", i, udpIn[i]);
// }

USER_PRINTF(" %d %d p:%d\n", udpSyncMessage.bri, udpSyncMessage.mainsegMode, packetSize);

Expand Down Expand Up @@ -336,14 +336,15 @@ class UserModInstances:public Module {
starModMessage.app.fx = mdl->getValue("fx");
starModMessage.app.palette = mdl->getValue("palette");
starModMessage.app.projection = mdl->getValue("projection");
// strncpy(starModMessage.body, "Effect x, Projection y, Leds begin..end", 1404-1);

updateNode(starModMessage); //temp? to show own node in list as instance is not catching it's own udp message...

IPAddress broadcastIP(255, 255, 255, 255);
if (0 != instanceUDP.beginPacket(broadcastIP, instanceUDPPort)) { // WLEDMM beginPacket == 0 --> error
USER_PRINTF("sendSysInfoUDP %s s:%d p:%d i:%d\n", (uint8_t*)&starModMessage, sizeof(UDPStarModMessage), instanceUDPPort, ip[3]);
// for (size_t x = 0; x < sizeof(UDPWLEDMessage); x++) {
// char* xx = (char*)&udpMessage;
// for (size_t x = 0; x < sizeof(UDPWLEDMessage) + sizeof(SysData) + sizeof(AppData); x++) {
// char* xx = (char*)&starModMessage;
// Serial.printf("%d: %d - %c\n", x, xx[x], xx[x]);
// }

Expand Down
Loading

0 comments on commit 583bcb9

Please sign in to comment.