JSON in/decrementing (#2258)

* Initial JSON in/decrementing

* Segment brightness in/decrement

* Update json-increment (#2290)

* Add Basic Overlay support to Usermods.

* Add seven segment overlay usermod

* Add seven_seg debug build

* Add scrolling message to seven seg um

* Fixed red color on IP address

* bh1750

* Add msg scroll. Add MQTT and Config support

* Add readme

* Restore platformio.inii

* Edit comments

* Add strip off refresh option in LED settings. (#2259)

* Add strip off refresh option in LED settings.
New strip initialization logic.
Minor code clen-up.

* Dev code removal.

* Missing ethernet include

* Renamed mainseg to selseg

* Fix for preset cycling bounds.

* "Preset 0" bugfix.

* Auto segments only if segments were not modified

Co-authored-by: cschwinne <dev.aircoookie@gmail.com>

* Exclude virtual busses from current calculation (#2262)

* Refactor string usage

* 0.13.0-b4

* Fix MQTT Null publish

* Additional Flash string concat

* Add AKST/AKDT

* UM RGB-Rotary-Encoder: Properly used PinOwner

* Cycling bugfix.

Co-authored-by: Gregory Schmidt <gregory.b.schmidt@hotmail.com>
Co-authored-by: Blaž Kristan <blaz@kristan-sp.si>
Co-authored-by: Caleb Mah <calebmah@gmail.com>
Co-authored-by: ezcGman <ich@andy-hofmann.com>

* Working JSON preset cycle

* Fix some Codacy style issues

Co-authored-by: Gregory Schmidt <gregory.b.schmidt@hotmail.com>
Co-authored-by: Blaž Kristan <blaz@kristan-sp.si>
Co-authored-by: Caleb Mah <calebmah@gmail.com>
Co-authored-by: ezcGman <ich@andy-hofmann.com>
This commit is contained in:
Christian Schwinne 2021-10-30 14:42:17 +02:00 committed by GitHub
parent b33e28835d
commit 00238247cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 62 additions and 31 deletions

View File

@ -638,10 +638,9 @@ void WS2812FX::resetSegments() {
} }
void WS2812FX::makeAutoSegments() { void WS2812FX::makeAutoSegments() {
if (autoSegments) { //make one segment per bus
uint16_t segStarts[MAX_NUM_SEGMENTS] = {0}; uint16_t segStarts[MAX_NUM_SEGMENTS] = {0};
uint16_t segStops [MAX_NUM_SEGMENTS] = {0}; uint16_t segStops [MAX_NUM_SEGMENTS] = {0};
if (autoSegments) { //make one segment per bus
uint8_t s = 0; uint8_t s = 0;
for (uint8_t i = 0; i < busses.getNumBusses(); i++) { for (uint8_t i = 0; i < busses.getNumBusses(); i++) {
Bus* b = busses.getBus(i); Bus* b = busses.getBus(i);

View File

@ -191,6 +191,7 @@ bool isAsterisksOnly(const char* str, byte maxLen);
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage); void handleSettingsSet(AsyncWebServerRequest *request, byte subPage);
bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply=true); bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply=true);
int getNumVal(const String* req, uint16_t pos); int getNumVal(const String* req, uint16_t pos);
void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255);
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255); bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255);
//udp.cpp //udp.cpp

View File

@ -6,6 +6,20 @@
* JSON API (De)serialization * JSON API (De)serialization
*/ */
bool getVal(JsonVariant elem, byte* val, byte vmin=0, byte vmax=255) {
if (elem.is<int>()) {
*val = elem;
return true;
} else if (elem.is<const char*>()) {
const char* str = elem;
size_t len = strnlen(str, 12);
if (len == 0 || len > 10) return false;
parseNumber(str, val, vmin, vmax);
return true;
}
return false; //key does not exist
}
void deserializeSegment(JsonObject elem, byte it, byte presetId) void deserializeSegment(JsonObject elem, byte it, byte presetId)
{ {
byte id = elem["id"] | it; byte id = elem["id"] | it;
@ -62,12 +76,10 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
} }
if (stop > start && seg.offset > len -1) seg.offset = len -1; if (stop > start && seg.offset > len -1) seg.offset = len -1;
int segbri = elem["bri"] | -1; byte segbri = 0;
if (segbri == 0) { if (getVal(elem["bri"], &segbri)) {
seg.setOption(SEG_OPTION_ON, 0, id); if (segbri > 0) seg.setOpacity(segbri, id);
} else if (segbri > 0) { seg.setOption(SEG_OPTION_ON, segbri, id);
seg.setOpacity(segbri, id);
seg.setOption(SEG_OPTION_ON, 1, id);
} }
bool on = elem["on"] | seg.getOption(SEG_OPTION_ON); bool on = elem["on"] | seg.getOption(SEG_OPTION_ON);
@ -210,7 +222,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
strip.applyToAllSelected = false; strip.applyToAllSelected = false;
bool stateResponse = root[F("v")] | false; bool stateResponse = root[F("v")] | false;
bri = root["bri"] | bri; getVal(root["bri"], &bri);
bool on = root["on"] | (bri > 0); bool on = root["on"] | (bri > 0);
if (!on != !bri) toggleOnOff(); if (!on != !bri) toggleOnOff();
@ -314,18 +326,18 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
usermods.readFromJsonState(root); usermods.readFromJsonState(root);
int ps = root[F("psave")] | -1; byte ps = root[F("psave")];
if (ps > 0) { if (ps > 0) {
savePreset(ps, true, nullptr, root); savePreset(ps, true, nullptr, root);
} else { } else {
ps = root[F("pdel")] | -1; //deletion ps = root[F("pdel")]; //deletion
if (ps > 0) { if (ps > 0) {
deletePreset(ps); deletePreset(ps);
} }
ps = root["ps"] | -1; //load preset (clears state request!)
if (ps >= 0) { if (getVal(root["ps"], &presetCycCurr, 1, 5)) { //load preset (clears state request!)
if (!presetId) unloadPlaylist(); //stop playlist if preset changed manually if (!presetId) unloadPlaylist(); //stop playlist if preset changed manually
applyPreset(ps, callMode); applyPreset(presetCycCurr, callMode);
return stateResponse; return stateResponse;
} }

View File

@ -519,20 +519,21 @@ int getNumVal(const String* req, uint16_t pos)
} }
//helper to get int value at a position in string //helper to get int value with in/decrementing support via ~ syntax
bool updateVal(const String* req, const char* key, byte* val, byte minv, byte maxv) void parseNumber(const char* str, byte* val, byte minv, byte maxv)
{ {
int pos = req->indexOf(key); if (str == nullptr || str[0] == '\0') return;
if (pos < 1) return false; if (str[0] == 'r') {*val = random8(minv,maxv); return;}
if (str[0] == '~') {
if (req->charAt(pos+3) == '~') { int out = atoi(str +1);
int out = getNumVal(req, pos+1);
if (out == 0) if (out == 0)
{ {
if (req->charAt(pos+4) == '-') { if (str[1] == '0') return;
*val = (int)(*val -1) < (int)minv ? maxv : min((int)maxv,(*val -1)); if (str[1] == '-')
{
*val = (int)(*val -1) < (int)minv ? maxv : min((int)maxv,(*val -1)); //-1, wrap around
} else { } else {
*val = (int)(*val +1) > (int)maxv ? minv : max((int)minv,(*val +1)); *val = (int)(*val +1) > (int)maxv ? minv : max((int)minv,(*val +1)); //+1, wrap around
} }
} else { } else {
out += *val; out += *val;
@ -542,8 +543,25 @@ bool updateVal(const String* req, const char* key, byte* val, byte minv, byte ma
} }
} else } else
{ {
*val = getNumVal(req, pos); byte p1 = atoi(str);
const char* str2 = strchr(str,'~'); //min/max range (for preset cycle, e.g. "1~5~")
if (str2) {
byte p2 = atoi(str2+1);
while (isdigit((str2+1)[0])) str2++;
parseNumber(str2+1, val, p1, p2);
} else {
*val = p1;
} }
}
}
bool updateVal(const String* req, const char* key, byte* val, byte minv, byte maxv)
{
int pos = req->indexOf(key);
if (pos < 1) return false;
if (req->length() < (unsigned int)(pos + 4)) return false;
parseNumber(req->c_str() + pos +3, val, minv, maxv);
return true; return true;
} }

View File

@ -479,6 +479,7 @@ void sendSysInfoUDP()
if (!udp2Connected) return; if (!udp2Connected) return;
IPAddress ip = Network.localIP(); IPAddress ip = Network.localIP();
if (!ip || ip == IPAddress(255,255,255,255)) ip = IPAddress(4,3,2,1);
// TODO: make a nice struct of it and clean up // TODO: make a nice struct of it and clean up
// 0: 1 byte 'binary token 255' // 0: 1 byte 'binary token 255'