From 054764944d89609c4aff0149606a019fd5871a45 Mon Sep 17 00:00:00 2001 From: Ewoud Date: Thu, 30 May 2024 20:40:33 +0200 Subject: [PATCH] StarLink updates: use sys->now SysModInstances: - rename timebase to now in SysData and UDPWLEDSyncMessage and in table - updateInstance: timebase stuff only within groups SysModSystem - loop: calc now = millis() + timebase; SysModModel - add Coord3D isOutofBounds --- src/Sys/SysModInstances.h | 229 +++++++++++++++++++------------------- src/Sys/SysModModel.h | 3 + src/Sys/SysModSystem.cpp | 4 +- tools/misc.txt | 21 +++- 4 files changed, 139 insertions(+), 118 deletions(-) diff --git a/src/Sys/SysModInstances.h b/src/Sys/SysModInstances.h index cff3abf8..22a2705f 100644 --- a/src/Sys/SysModInstances.h +++ b/src/Sys/SysModInstances.h @@ -25,7 +25,7 @@ struct DMX { //additional data not in wled header struct SysData { unsigned long upTime; - uint32_t timebase; //25 + uint32_t now; //25 uint8_t timeSource; //29 uint32_t tokiTime; //30 in sec uint16_t tokiMs; //34 @@ -70,7 +70,7 @@ struct UDPStarMessage { char jsonString[1460 - sizeof(UDPWLEDMessage) - sizeof(SysData)]; }; -//WLED syncmessage +//WLED syncmessage 1193 bytes struct UDPWLEDSyncMessage { //see notify( in WLED byte protocol; //0 byte callMode; //1 @@ -90,7 +90,7 @@ struct UDPWLEDSyncMessage { //see notify( in WLED byte palette; //19 byte col2[4]; //20 byte followUp; //24 - byte timebase[4]; //25 + byte now[4]; //25 byte timeSource; //29 byte tokiTime[4]; //30 byte tokiMs[2]; //34 @@ -204,13 +204,13 @@ class SysModInstances:public SysModule { return true; default: return false; }}); - ui->initNumber(tableVar, "insTB", UINT16_MAX, 0, (unsigned long)-1, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun + ui->initNumber(tableVar, "insNow", UINT16_MAX, 0, (unsigned long)-1, true, [this](JsonObject var, unsigned8 rowNr, unsigned8 funType) { switch (funType) { //varFun case f_ValueFun: for (forUnsigned8 rowNrL = 0; rowNrL < instances.size() && (rowNr == UINT8_MAX || rowNrL == rowNr); rowNrL++) - mdl->setValue(var, instances[rowNrL].sysData.timebase, rowNrL); + mdl->setValue(var, instances[rowNrL].sysData.now / 1000, rowNrL); return true; case f_UIFun: - ui->setLabel(var, "TB"); + ui->setLabel(var, "Now"); return true; default: return false; }}); @@ -400,70 +400,76 @@ class SysModInstances:public SysModule { if (packetSize > 0) { // IPAddress remoteIp = notifierUdp.remoteIP(); - // ppf("handleNotifications sync ...%d %d\n", notifierUdp.remoteIP()[3], packetSize); - - UDPWLEDSyncMessage wledSyncMessage; - byte *udpIn = (byte *)&wledSyncMessage; - notifierUdp.read(udpIn, packetSize); - - // for (int i=0; i<40; i++) { - // Serial.printf("%d: %d\n", i, udpIn[i]); - // } - - ppf(" %d %d p:%d\n", wledSyncMessage.bri, wledSyncMessage.mainsegMode, packetSize); - - InstanceInfo *instance = findInstance(notifierUdp.remoteIP()); //if not exist, created - - instance->sysData.upTime = (wledSyncMessage.timebase[0] * 256*256*256 + 256*256*wledSyncMessage.timebase[1] + 256*wledSyncMessage.timebase[2] + wledSyncMessage.timebase[3]) / 1000; - instance->sysData.timebase = (wledSyncMessage.timebase[0] << 24) | (wledSyncMessage.timebase[1] << 16) | (wledSyncMessage.timebase[2] << 8) | (wledSyncMessage.timebase[3]); - instance->sysData.timeSource = wledSyncMessage.timeSource; - instance->sysData.tokiTime = (wledSyncMessage.tokiTime[0] << 24) | (wledSyncMessage.tokiTime[1] << 16) | (wledSyncMessage.tokiTime[2] << 8) | (wledSyncMessage.tokiTime[3]); - instance->sysData.tokiMs = (wledSyncMessage.tokiMs[0] << 8) | (wledSyncMessage.tokiMs[1]); - - //don't update toki for WLED ATM - - // uint32_t t = instance->sysData.timebase; - // t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay - // t -= millis(); - // sys->timebase = t; - // // timebaseUpdated = true; - - // Toki::Time tm; - // tm.sec = instance->sysData.tokiTime; - // tm.ms = instance->sysData.tokiMs; - // if (instance->sysData.timeSource > sys->toki.getTimeSource()) { //if sender's time source is more accurate - // sys->toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay - // uint8_t ts = TOKI_TS_UDP; - // if (instance->sysData.timeSource > 99) ts = TOKI_TS_UDP_NTP; - // else if (instance->sysData.timeSource >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC; - // sys->toki.setTime(tm, ts); - // } else if (/*timebaseUpdated && */ sys->toki.getTimeSource() > 99) { //if we both have good times, get a more accurate timebase - // Toki::Time myTime = sys->toki.getTime(); - // uint32_t diff = sys->toki.msDifference(tm, myTime); - // sys->timebase -= PRESUMED_NETWORK_DELAY; //no need to presume, use difference between NTP times at send and receive points - // if (sys->toki.isLater(tm, myTime)) { - // sys->timebase += diff; - // } else { - // sys->timebase -= diff; - // } - // } - - instance->jsonData["bri"] = wledSyncMessage.bri; - instance->jsonData["fx"] = wledSyncMessage.mainsegMode; //tbd: rowNr - instance->jsonData["pal"] = wledSyncMessage.palette; //tbd: rowNr - - // for (size_t x = 0; x < packetSize; x++) { - // char xx = (char)udpIn[x]; - // Serial.print(xx); - // } - // Serial.println(); - - ppf("insTbl handleNotifications %d\n", notifierUdp.remoteIP()[3]); - for (JsonObject childVar: mdl->varChildren("insTbl")) - ui->callVarFun(childVar, UINT8_MAX, f_ValueFun); //rowNr //instance - instances.begin() + if (packetSize == sizeof(UDPWLEDSyncMessage)) { //1193 bytes + + ppf("handleNotifications WLED sync ...%d %d %d\n", notifierUdp.remoteIP()[3], packetSize, sizeof(UDPWLEDSyncMessage)); + + UDPWLEDSyncMessage wledSyncMessage; + byte *udpIn = (byte *)&wledSyncMessage; + notifierUdp.read(udpIn, packetSize); + + // for (int i=0; i<40; i++) { + // Serial.printf("%d: %d\n", i, udpIn[i]); + // } + + ppf(" %d %d p:%d\n", wledSyncMessage.bri, wledSyncMessage.mainsegMode, packetSize); + + InstanceInfo *instance = findInstance(notifierUdp.remoteIP()); //if not exist, created + + // instance->sysData.upTime = (wledSyncMessage.now[0] * 256*256*256 + 256*256*wledSyncMessage.now[1] + 256*wledSyncMessage.now[2] + wledSyncMessage.now[3]) / 1000; + instance->sysData.upTime = (wledSyncMessage.now[0] << 24) | (wledSyncMessage.now[1] << 16) | (wledSyncMessage.now[2] << 8) | (wledSyncMessage.now[3]); + instance->sysData.now = (wledSyncMessage.now[0] << 24) | (wledSyncMessage.now[1] << 16) | (wledSyncMessage.now[2] << 8) | (wledSyncMessage.now[3]); + instance->sysData.timeSource = wledSyncMessage.timeSource; + instance->sysData.tokiTime = (wledSyncMessage.tokiTime[0] << 24) | (wledSyncMessage.tokiTime[1] << 16) | (wledSyncMessage.tokiTime[2] << 8) | (wledSyncMessage.tokiTime[3]); + instance->sysData.tokiMs = (wledSyncMessage.tokiMs[0] << 8) | (wledSyncMessage.tokiMs[1]); + + //don't update toki for WLED ATM + + // uint32_t t = instance->sysData.now; + // t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay + // t -= millis(); + // sys->timebase = t; + // // timebaseUpdated = true; + + // Toki::Time tm; + // tm.sec = instance->sysData.tokiTime; + // tm.ms = instance->sysData.tokiMs; + // if (instance->sysData.timeSource > sys->toki.getTimeSource()) { //if sender's time source is more accurate + // sys->toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay + // uint8_t ts = TOKI_TS_UDP; + // if (instance->sysData.timeSource > 99) ts = TOKI_TS_UDP_NTP; + // else if (instance->sysData.timeSource >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC; + // sys->toki.setTime(tm, ts); + // } else if (/*timebaseUpdated && */ sys->toki.getTimeSource() > 99) { //if we both have good times, get a more accurate timebase + // Toki::Time myTime = sys->toki.getTime(); + // uint32_t diff = sys->toki.msDifference(tm, myTime); + // sys->timebase -= PRESUMED_NETWORK_DELAY; //no need to presume, use difference between NTP times at send and receive points + // if (sys->toki.isLater(tm, myTime)) { + // sys->timebase += diff; + // } else { + // sys->timebase -= diff; + // } + // } + + instance->jsonData["bri"] = wledSyncMessage.bri; + instance->jsonData["fx"] = wledSyncMessage.mainsegMode; //tbd: rowNr + instance->jsonData["pal"] = wledSyncMessage.palette; //tbd: rowNr + + // for (size_t x = 0; x < packetSize; x++) { + // char xx = (char)udpIn[x]; + // Serial.print(xx); + // } + // Serial.println(); + + ppf("insTbl handleNotifications %d\n", notifierUdp.remoteIP()[3]); + for (JsonObject childVar: mdl->varChildren("insTbl")) + ui->callVarFun(childVar, UINT8_MAX, f_ValueFun); //rowNr //instance - instances.begin() - web->recvUDPCounter++; - web->recvUDPBytes+=packetSize; + web->recvUDPCounter++; + web->recvUDPBytes+=packetSize; + } + else + ppf("dev WLED sync massage not size %d\n", sizeof(UDPWLEDSyncMessage)); return; } @@ -591,7 +597,7 @@ class SysModInstances:public SysModule { starMessage.header.version = VERSION; starMessage.sysData.type = (strcmp(_INIT(TOSTRING(APP)), "StarBase")==0)?1:(strcmp(_INIT(TOSTRING(APP)), "StarLeds")==0)?2:3; //1=StarBase,2=StarLeds, 3=StarFork starMessage.sysData.upTime = millis()/1000; - starMessage.sysData.timebase = millis() + sys->timebase; + starMessage.sysData.now = millis() + sys->timebase; //similar to now starMessage.sysData.timeSource = sys->toki.getTimeSource(); starMessage.sysData.tokiTime = sys->toki.getTime().sec; starMessage.sysData.tokiMs = sys->toki.getTime().ms; @@ -718,58 +724,57 @@ class SysModInstances:public SysModule { instance.sysData = udpStarMessage.sysData; if (instance.ip != WiFi.localIP()) { //send from localIP will be done after updateInstance + char group1[32]; + char group2[32]; + if (groupOfName(instance.name, group1) && groupOfName(mdl->getValue("name"), group2) && strcmp(group1, group2) == 0) { + + uint32_t t = instance.sysData.now; + t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay + t -= millis(); + sys->timebase = t; + // timebaseUpdated = true; + + Toki::Time tm; + tm.sec = instance.sysData.tokiTime; + tm.ms = instance.sysData.tokiMs; + if (instance.sysData.timeSource > sys->toki.getTimeSource() || sys->toki.getTimeSource() == TOKI_TS_NONE) { //if sender's time source is more accurate + sys->toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay + uint8_t ts = TOKI_TS_UDP; //5 + if (instance.sysData.timeSource > 99) ts = TOKI_TS_UDP_NTP; //110 + else if (instance.sysData.timeSource >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC; //20 + sys->toki.setTime(tm, ts); + } else if (/*timebaseUpdated && */ sys->toki.getTimeSource() > 99) { //if we both have good times, get a more accurate timebase + Toki::Time myTime = sys->toki.getTime(); + uint32_t diff = sys->toki.msDifference(tm, myTime); + sys->timebase -= PRESUMED_NETWORK_DELAY; //no need to presume, use difference between NTP times at send and receive points + if (sys->toki.isLater(tm, myTime)) { + sys->timebase += diff; + } else { + sys->timebase -= diff; + } + } - uint32_t t = instance.sysData.timebase; - t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay - t -= millis(); - sys->timebase = t; - // timebaseUpdated = true; - - Toki::Time tm; - tm.sec = instance.sysData.tokiTime; - tm.ms = instance.sysData.tokiMs; - if (instance.sysData.timeSource > sys->toki.getTimeSource() || sys->toki.getTimeSource() == TOKI_TS_NONE) { //if sender's time source is more accurate - sys->toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay - uint8_t ts = TOKI_TS_UDP; //5 - if (instance.sysData.timeSource > 99) ts = TOKI_TS_UDP_NTP; //110 - else if (instance.sysData.timeSource >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC; //20 - sys->toki.setTime(tm, ts); - } else if (/*timebaseUpdated && */ sys->toki.getTimeSource() > 99) { //if we both have good times, get a more accurate timebase - Toki::Time myTime = sys->toki.getTime(); - uint32_t diff = sys->toki.msDifference(tm, myTime); - sys->timebase -= PRESUMED_NETWORK_DELAY; //no need to presume, use difference between NTP times at send and receive points - if (sys->toki.isLater(tm, myTime)) { - sys->timebase += diff; - } else { - sys->timebase -= diff; + //set instance.jsonData from new string + JsonDocument newData; + DeserializationError error = deserializeJson(newData, udpStarMessage.jsonString); + if (error || !newData.is()) { + // ppf("dev updateInstance json failed ip:%d e:%s\n", instance.ip[3], error.c_str(), udpStarMessage.jsonString); + //failed because some instances not on latest firmware, so turned off temporarily (tbd/wip) } - } - sys->now = millis() + sys->timebase; - - //set instance.jsonData from new string - JsonDocument newData; - DeserializationError error = deserializeJson(newData, udpStarMessage.jsonString); - if (error || !newData.is()) { - // ppf("dev updateInstance json failed ip:%d e:%s\n", instance.ip[3], error.c_str(), udpStarMessage.jsonString); - //failed because some instances not on latest firmware, so turned off temporarily (tbd/wip) - } - else { - //check if instance belongs to the same group + else { + //check if instance belongs to the same group - char group1[32]; - char group2[32]; - if (groupOfName(instance.name, group1) && groupOfName(mdl->getValue("name"), group2) && strcmp(group1, group2) == 0) { for (JsonPair pair: newData.as()) { // ppf("updateInstance sync from i:%s k:%s v:%s\n", instance.name, pair.key().c_str(), pair.value().as().c_str()); mdl->setValueJV(pair.key().c_str(), pair.value()); } + instance.jsonData = newData; // deepcopy: https://github.com/bblanchon/ArduinoJson/issues/1023 + // ppf("updateInstance json ip:%d", instance.ip[3]); + // print->printJson(" d:", instance.jsonData); } - instance.jsonData = newData; // deepcopy: https://github.com/bblanchon/ArduinoJson/issues/1023 - // ppf("updateInstance json ip:%d", instance.ip[3]); - // print->printJson(" d:", instance.jsonData); } - } + } //same group } //only update cell in instbl! diff --git a/src/Sys/SysModModel.h b/src/Sys/SysModModel.h index c2ec7754..cad6a16f 100644 --- a/src/Sys/SysModModel.h +++ b/src/Sys/SysModModel.h @@ -119,6 +119,9 @@ struct Coord3D { Coord3D delta = (*this-rhs); return sqrt((delta.x)*(delta.x) + (delta.y)*(delta.y) + (delta.z)*(delta.z)); } + bool isOutofBounds(Coord3D rhs) { + return x < 0 || y < 0 || z < 0 || x >= rhs.x || y >= rhs.y || z >= rhs.z; + } }; //used to sort keys of jsonobjects diff --git a/src/Sys/SysModSystem.cpp b/src/Sys/SysModSystem.cpp index 8c0739b2..c27439de 100644 --- a/src/Sys/SysModSystem.cpp +++ b/src/Sys/SysModSystem.cpp @@ -225,11 +225,13 @@ void SysModSystem::loop() { // SysModule::loop(); loopCounter++; + now = millis() + timebase; } + void SysModSystem::loop1s() { mdl->setUIValueV("upTime", "%lu s", millis()/1000); mdl->setUIValueV("now", "%lu s", now/1000); - mdl->setUIValueV("timeBase", "%lu s", timebase/1000); + mdl->setUIValueV("timeBase", "%lu s", (nowsetUIValueV("loops", "%lu /s", loopCounter); loopCounter = 0; diff --git a/tools/misc.txt b/tools/misc.txt index 8ce2fec0..7d117015 100644 --- a/tools/misc.txt +++ b/tools/misc.txt @@ -5,7 +5,7 @@ git log v0.14.1-beta.30..HEAD --pretty=format:'%ad,%<(20)%an,%s' --date=short Copy System Modules from MoonModules/StarLeds to upstream (as should only be modified in upstream) ============================================================ -cd /Users/ewoudwijma/Developer/GitHub/MoonModules/StarLeds +cd ~/Developer/GitHub/MoonModules/StarLeds ls ../../ewowi/StarBase/src/Sys cp ./src/Sys/* ../../ewowi/StarBase/src/Sys cp ./tools/* ../../ewowi/StarBase/tools @@ -67,10 +67,21 @@ ls -tU remove sound for f in (I*.mov|sort -d) ; do ffmpeg -i $PWD/$f -c copy -an $PWD/$f.nosound.mov; done -Update instance -curl -s -F "update=@/Users/ewoudwijma/Developer/GitHub/ewowi/StarBase/.pio/build/esp32dev/firmware.bin" 192.168.8.189/update - - +Update instances + +for i in 166 132 117 107 125 246 152 +do + echo upgrade 192.168.168.$i + curl -s -F "update=@/Users/ewoudwijma/Downloads/StarLeds_24053018_esp32dev.bin" 192.168.8.$i/update + curl -X POST "http://192.168.8.$i/json" -d '{"reboot":true}' -H "Content-Type: application/json" +done + +for i in 239 143 111 +do + echo upgrade 192.168.168.$i + curl -s -F "update=@/Users/ewoudwijma/Downloads/StarLeds_24053018_lolin_s2_mini.bin" 192.168.8.$i/update + curl -X POST "http://192.168.8.$i/json" -d '{"reboot":true}' -H "Content-Type: application/json" +done FileCreateDate for png files