Alexa and UDP sync CCT support

This commit is contained in:
cschwinne 2021-11-28 04:01:58 +01:00
parent 1973424e05
commit 11c7ffad4e
8 changed files with 66 additions and 31 deletions

View File

@ -434,6 +434,13 @@ board_build.ldscript = ${common.ldscript_2m512k}
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3 build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3
lib_deps = ${esp8266.lib_deps} lib_deps = ${esp8266.lib_deps}
[env:athom7w]
board = esp_wroom_02
platform = ${common.platform_wled_default}
board_build.ldscript = ${common.ldscript_2m512k}
build_flags = ${common.build_flags_esp8266} -D WLED_MAX_CCT_BLEND=0 -D BTNPIN=-1 -D IRPIN=-1 -D WLED_DISABLE_INFRARED
lib_deps = ${esp8266.lib_deps}
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# travis test board configurations # travis test board configurations
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -665,6 +665,7 @@ class WS2812FX {
applyToAllSelected = true, applyToAllSelected = true,
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p), setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p),
checkSegmentAlignment(void), checkSegmentAlignment(void),
hasCCTBus(void),
// return true if the strip is being sent pixel updates // return true if the strip is being sent pixel updates
isUpdating(void); isUpdating(void);

View File

@ -553,6 +553,20 @@ uint16_t WS2812FX::getLengthPhysical(void) {
return len; return len;
} }
bool WS2812FX::hasCCTBus(void) {
if (cctFromRgb && !correctWB) return false;
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
Bus *bus = busses.getBus(b);
if (bus == nullptr || bus->getLength()==0) break;
switch (bus->getType()) {
case TYPE_ANALOG_5CH:
case TYPE_ANALOG_2CH:
return true;
}
}
return false;
}
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) { void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
if (n >= MAX_NUM_SEGMENTS) return; if (n >= MAX_NUM_SEGMENTS) return;
Segment& seg = _segments[n]; Segment& seg = _segments[n];

View File

@ -73,17 +73,26 @@ void onAlexaChange(EspalexaDevice* dev)
if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white
{ {
uint16_t ct = espalexaDevice->getCt(); uint16_t ct = espalexaDevice->getCt();
if (strip.isRgbw) if (!ct) return;
{ uint16_t k = 1000000 / ct; //mireds to kelvin
if (strip.hasCCTBus()) {
uint8_t segid = strip.getMainSegmentId();
WS2812FX::Segment& seg = strip.getSegment(segid);
uint8_t cctPrev = seg.cct;
seg.setCCT(k, segid);
if (seg.cct != cctPrev) effectChanged = true; //send UDP
} else if (strip.isRgbw) {
switch (ct) { //these values empirically look good on RGBW switch (ct) { //these values empirically look good on RGBW
case 199: col[0]=255; col[1]=255; col[2]=255; col[3]=255; break; case 199: col[0]=255; col[1]=255; col[2]=255; col[3]=255; break;
case 234: col[0]=127; col[1]=127; col[2]=127; col[3]=255; break; case 234: col[0]=127; col[1]=127; col[2]=127; col[3]=255; break;
case 284: col[0]= 0; col[1]= 0; col[2]= 0; col[3]=255; break; case 284: col[0]= 0; col[1]= 0; col[2]= 0; col[3]=255; break;
case 350: col[0]=130; col[1]= 90; col[2]= 0; col[3]=255; break; case 350: col[0]=130; col[1]= 90; col[2]= 0; col[3]=255; break;
case 383: col[0]=255; col[1]=153; col[2]= 0; col[3]=255; break; case 383: col[0]=255; col[1]=153; col[2]= 0; col[3]=255; break;
default : colorKtoRGB(k, col);
} }
} else { } else {
colorCTtoRGB(ct, col); colorKtoRGB(k, col);
} }
} else { } else {
uint32_t color = espalexaDevice->getRGB(); uint32_t color = espalexaDevice->getRGB();

View File

@ -20,7 +20,7 @@
border-radius: var(--h); border-radius: var(--h);
font-size: 6vmin; font-size: 6vmin;
height: var(--h); height: var(--h);
width: 95%; width: calc(100% - 40px);
margin-top: 2vh; margin-top: 2vh;
} }
</style> </style>

View File

@ -12,7 +12,7 @@ const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,
// Autogenerated from wled00/data/settings.htm, do not edit!! // Autogenerated from wled00/data/settings.htm, do not edit!!
const char PAGE_settings[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>WLED Settings const char PAGE_settings[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>WLED Settings
</title><style> </title><style>
body{text-align:center;background:#222;height:100px;margin:0}html{--h:10.2vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:1px solid #333;border-radius:var(--h);font-size:6vmin;height:var(--h);width:95%%;margin-top:2vh} body{text-align:center;background:#222;height:100px;margin:0}html{--h:10.2vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:1px solid #333;border-radius:var(--h);font-size:6vmin;height:var(--h);width:calc(100%% - 40px);margin-top:2vh}
</style></head><body><form action="/"><button type="submit" id="b">Back</button> </style></head><body><form action="/"><button type="submit" id="b">Back</button>
</form><form action="/settings/wifi"><button type="submit">WiFi Setup</button> </form><form action="/settings/wifi"><button type="submit">WiFi Setup</button>
</form><form action="/settings/leds"><button type="submit">LED Preferences </form><form action="/settings/leds"><button type="submit">LED Preferences

View File

@ -86,7 +86,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on; if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
seg.setOption(SEG_OPTION_ON, on, id); seg.setOption(SEG_OPTION_ON, on, id);
uint8_t cctPrev = seg.cct;
seg.setCCT(elem["cct"] | seg.cct, id); seg.setCCT(elem["cct"] | seg.cct, id);
if (seg.cct != cctPrev && id == strip.getMainSegmentId()) effectChanged = true; //send UDP
JsonArray colarr = elem["col"]; JsonArray colarr = elem["col"];
if (!colarr.isNull()) if (!colarr.isNull())
@ -145,7 +147,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal); //if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED)); seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED)); seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR )); seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
//temporary, strip object gets updated via colorUpdated() //temporary, strip object gets updated via colorUpdated()
@ -385,10 +387,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
root["on"] = seg.getOption(SEG_OPTION_ON); root["on"] = seg.getOption(SEG_OPTION_ON);
byte segbri = seg.opacity; byte segbri = seg.opacity;
root["bri"] = (segbri) ? segbri : 255; root["bri"] = (segbri) ? segbri : 255;
uint16_t cct = seg.cct; root["cct"] = seg.cct;
if (cct >= 1900) cct = (cct - 1900) >> 5; //convert K to 0-255
if (cct > 255) cct = 255;
root["cct"] = cct;
if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name); //not good practice, but decreases required JSON buffer if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name); //not good practice, but decreases required JSON buffer
@ -505,23 +504,14 @@ void serializeInfo(JsonObject root)
leds[F("count")] = strip.getLengthTotal(); leds[F("count")] = strip.getLengthTotal();
leds[F("rgbw")] = strip.isRgbw; leds[F("rgbw")] = strip.isRgbw;
leds[F("wv")] = false; leds[F("wv")] = false;
leds["cct"] = correctWB; leds["cct"] = correctWB || strip.hasCCTBus();
for (uint8_t s = 0; s < busses.getNumBusses(); s++) { switch (Bus::getAutoWhiteMode()) {
Bus *bus = busses.getBus(s); case RGBW_MODE_MANUAL_ONLY:
if (bus == nullptr || bus->getLength()==0) break; case RGBW_MODE_DUAL:
switch (bus->getType()) { if (strip.isRgbw) leds[F("wv")] = true;
case TYPE_ANALOG_5CH: break;
case TYPE_ANALOG_2CH: }
if (!cctFromRgb) leds["cct"] = true;
break;
}
switch (Bus::getAutoWhiteMode()) {
case RGBW_MODE_MANUAL_ONLY:
case RGBW_MODE_DUAL:
if (bus->isRgbw()) leds[F("wv")] = true;
break;
}
}
leds[F("pwr")] = strip.currentMilliamps; leds[F("pwr")] = strip.currentMilliamps;
leds[F("fps")] = strip.getFps(); leds[F("fps")] = strip.getFps();
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;

View File

@ -4,7 +4,7 @@
* UDP sync notifier / Realtime / Hyperion / TPM2.NET * UDP sync notifier / Realtime / Hyperion / TPM2.NET
*/ */
#define WLEDPACKETSIZE 37 #define WLEDPACKETSIZE 39
#define UDP_IN_MAXSIZE 1472 #define UDP_IN_MAXSIZE 1472
#define PRESUMED_NETWORK_DELAY 3 //how many ms could it take on avg to reach the receiver? This will be added to transmitted times #define PRESUMED_NETWORK_DELAY 3 //how many ms could it take on avg to reach the receiver? This will be added to transmitted times
@ -25,6 +25,7 @@ void notify(byte callMode, bool followUp)
default: return; default: return;
} }
byte udpOut[WLEDPACKETSIZE]; byte udpOut[WLEDPACKETSIZE];
WS2812FX::Segment& mainseg = strip.getSegment(strip.getMainSegmentId());
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
udpOut[1] = callMode; udpOut[1] = callMode;
udpOut[2] = bri; udpOut[2] = bri;
@ -40,8 +41,8 @@ void notify(byte callMode, bool followUp)
//0: old 1: supports white 2: supports secondary color //0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette //3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet //6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
//9: supports sync groups, 37 byte packet //9: supports sync groups, 37 byte packet 10: supports CCT, 39 byte packet
udpOut[11] = 9; udpOut[11] = 10;
udpOut[12] = colSec[0]; udpOut[12] = colSec[0];
udpOut[13] = colSec[1]; udpOut[13] = colSec[1];
udpOut[14] = colSec[2]; udpOut[14] = colSec[2];
@ -50,7 +51,7 @@ void notify(byte callMode, bool followUp)
udpOut[17] = (transitionDelay >> 0) & 0xFF; udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF; udpOut[18] = (transitionDelay >> 8) & 0xFF;
udpOut[19] = effectPalette; udpOut[19] = effectPalette;
uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; uint32_t colTer = mainseg.colors[2];
udpOut[20] = (colTer >> 16) & 0xFF; udpOut[20] = (colTer >> 16) & 0xFF;
udpOut[21] = (colTer >> 8) & 0xFF; udpOut[21] = (colTer >> 8) & 0xFF;
udpOut[22] = (colTer >> 0) & 0xFF; udpOut[22] = (colTer >> 0) & 0xFF;
@ -77,6 +78,11 @@ void notify(byte callMode, bool followUp)
//sync groups //sync groups
udpOut[36] = syncGroups; udpOut[36] = syncGroups;
//Might be changed to Kelvin in the future, receiver code should handle that case
//0: byte 38 contains 0-255 value, 255: no valid CCT, 1-254: Kelvin value MSB
udpOut[37] = strip.hasCCTBus() ? 0 : 255; //check this is 0 for the next value to be significant
udpOut[38] = mainseg.cct;
IPAddress broadcastIp; IPAddress broadcastIp;
broadcastIp = ~uint32_t(Network.subnetMask()) | uint32_t(Network.gatewayIP()); broadcastIp = ~uint32_t(Network.subnetMask()) | uint32_t(Network.gatewayIP());
@ -260,6 +266,14 @@ void handleNotifications()
{ {
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
} }
if (version > 9 && version < 200 && udpIn[37] < 255) { //valid CCT/Kelvin value
uint8_t cct = udpIn[38];
if (udpIn[37] > 0) { //Kelvin
cct = (((udpIn[37] << 8) + udpIn[38]) - 1900) >> 5;
}
uint8_t segid = strip.getMainSegmentId();
strip.getSegment(segid).setCCT(cct, segid);
}
} }
} }