Integrated liveview

This commit is contained in:
cschwinne 2019-11-30 19:17:25 +01:00
parent 731550acb3
commit 0e8806eb2b
6 changed files with 176 additions and 66 deletions

View File

@ -367,7 +367,7 @@ class WS2812FX {
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);
uint8_t uint8_t
returnedSegment = 0, mainSegment = 0,
paletteFade = 0, paletteFade = 0,
paletteBlend = 0, paletteBlend = 0,
colorOrder = 0, colorOrder = 0,
@ -380,7 +380,7 @@ class WS2812FX {
getPaletteCount(void), getPaletteCount(void),
getMaxSegments(void), getMaxSegments(void),
getFirstSelectedSegment(void), getFirstSelectedSegment(void),
getReturnedSegmentId(void), getMainSegmentId(void),
gamma8(uint8_t), gamma8(uint8_t),
get_random_wheel_index(uint8_t); get_random_wheel_index(uint8_t);

View File

@ -331,7 +331,7 @@ void WS2812FX::setPalette(uint8_t p) {
} }
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) { bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
uint8_t retSeg = getReturnedSegmentId(); uint8_t retSeg = getMainSegmentId();
Segment& seg = _segments[retSeg]; Segment& seg = _segments[retSeg];
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette; uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
@ -370,11 +370,11 @@ void WS2812FX::setBrightness(uint8_t b) {
} }
uint8_t WS2812FX::getMode(void) { uint8_t WS2812FX::getMode(void) {
return _segments[getReturnedSegmentId()].mode; return _segments[getMainSegmentId()].mode;
} }
uint8_t WS2812FX::getSpeed(void) { uint8_t WS2812FX::getSpeed(void) {
return _segments[getReturnedSegmentId()].speed; return _segments[getMainSegmentId()].speed;
} }
uint8_t WS2812FX::getBrightness(void) { uint8_t WS2812FX::getBrightness(void) {
@ -398,20 +398,21 @@ uint8_t WS2812FX::getFirstSelectedSegment(void)
return 0; return 0;
} }
uint8_t WS2812FX::getReturnedSegmentId(void) { uint8_t WS2812FX::getMainSegmentId(void) {
if (returnedSegment >= MAX_NUM_SEGMENTS || !_segments[returnedSegment].isActive()) if (mainSegment >= MAX_NUM_SEGMENTS || !_segments[mainSegment].isActive())
{ {
return getFirstSelectedSegment(); return getFirstSelectedSegment();
} }
return returnedSegment; return mainSegment;
} }
uint32_t WS2812FX::getColor(void) { uint32_t WS2812FX::getColor(void) {
return _segments[getReturnedSegmentId()].colors[0]; return _segments[getMainSegmentId()].colors[0];
} }
uint32_t WS2812FX::getPixelColor(uint16_t i) uint32_t WS2812FX::getPixelColor(uint16_t i)
{ {
i = i * (_disableNLeds+1);
if (reverseMode) i = _length- 1 -i; if (reverseMode) i = _length- 1 -i;
if (IS_REVERSE) i = SEGMENT.stop -1 -i + SEGMENT.start; //reverse just individual segment if (IS_REVERSE) i = SEGMENT.stop -1 -i + SEGMENT.start; //reverse just individual segment
if (_skipFirstMode) i += LED_SKIP_AMOUNT; if (_skipFirstMode) i += LED_SKIP_AMOUNT;
@ -434,6 +435,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
default: return 0; default: return 0;
} }
} }
if (i >= _lengthRaw) return 0;
RgbwColor lColor = bus->GetPixelColorRgbw(i); RgbwColor lColor = bus->GetPixelColorRgbw(i);
byte r = lColor.R, g = lColor.G, b = lColor.B; byte r = lColor.R, g = lColor.G, b = lColor.B;
switch (colorOrder) switch (colorOrder)

59
wled00/data/liveview.htm Normal file
View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta charset="utf-8">
<meta name="theme-color" content="#222222">
<title>WLED Live Preview</title>
<style>
body {
margin: 0;
}
#canv {
background: black;
filter: brightness(175%);
width: 100%;
height: 100%;
position: absolute;
}
</style>
</head>
<body>
<div id="canv" />
<script>
update();
function update()
{
if (document.hidden) {
setTimeout(update, 250);
return;
}
fetch('/json/live')
.then(res => {
if (!res.ok) {
setTimeout(update, 2500);
}
return res.json();
})
.then(json => {
var str = "linear-gradient(90deg,";
var len = json.leds.length;
for (i = 0; i < len; i++) {
var leddata = json.leds[i];
if (leddata.length > 6) leddata = leddata.substring(2);
str += "#" + leddata;
if (i < len -1) str += ","
}
str += ")";
document.getElementById("canv").style.background = str;
setTimeout(update, 40);
})
.catch(function (error) {
setTimeout(update, 2500);
})
}
</script>
</body>
</html>

View File

@ -33,6 +33,24 @@ const char PAGE_welcome[] PROGMEM = "";
#endif #endif
//liveview
const char PAGE_liveview[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head>
<meta name=viewport content="width=device-width, initial-scale=1, minimum-scale=1">
<meta charset=utf-8>
<meta name=theme-color content=#222222>
<title>WLED Live Preview</title>
<style>body{margin:0}#canv{background:black;filter:brightness(175%);width:100%;height:100%;position:absolute}</style>
</head>
<body><div id=canv />
<script>update();function update()
{if(document.hidden){setTimeout(update,250);return;}
fetch('/json/live').then(res=>{if(!res.ok){setTimeout(update,2500);}
return res.json();}).then(json=>{var str="linear-gradient(90deg,";var len=json.leds.length;for(i=0;i<len;i++){var leddata=json.leds[i];if(leddata.length>6)leddata=leddata.substring(2);str+="#"+leddata;if(i<len-1)str+=","}
str+=")";document.getElementById("canv").style.background=str;setTimeout(update,40);}).catch(function(error){setTimeout(update,2500);})}</script>
</body></html>)=====";
/* /*
* favicon * favicon
*/ */

View File

@ -36,6 +36,10 @@ void initServer()
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "*"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "*"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "*");
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_liveview);
});
//settings page //settings page
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){ server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){

View File

@ -2,6 +2,64 @@
* JSON API (De)serialization * JSON API (De)serialization
*/ */
void deserializeSegment(JsonObject elem, byte it)
{
byte id = elem["id"] | it;
if (id < strip.getMaxSegments())
{
WS2812FX::Segment& seg = strip.getSegment(id);
uint16_t start = elem["start"] | seg.start;
int stop = elem["stop"] | -1;
if (stop < 0) {
uint16_t len = elem["len"];
stop = (len > 0) ? start + len : seg.stop;
}
strip.setSegment(id, start, stop);
JsonArray colarr = elem["col"];
if (!colarr.isNull())
{
for (uint8_t i = 0; i < 3; i++)
{
JsonArray colX = colarr[i];
if (colX.isNull()) break;
byte sz = colX.size();
if (sz > 0 && sz < 5)
{
int rgbw[] = {0,0,0,0};
byte cp = copyArray(colX, rgbw);
seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF)));
if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0;
if (id == 0) //temporary
{
if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];}
if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];}
}
}
}
}
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
seg.setOption(0, elem["sel"] | seg.getOption(0)); //selected
seg.setOption(1, elem["rev"] | seg.getOption(1)); //reverse
//int cln = seg_0["cln"];
//temporary, strip object gets updated via colorUpdated()
if (id == 0) {
effectCurrent = elem["fx"] | effectCurrent;
effectSpeed = elem["sx"] | effectSpeed;
effectIntensity = elem["ix"] | effectIntensity ;
effectPalette = elem["pal"] | effectPalette;
} else { //permanent
byte fx = elem["fx"] | seg.mode;
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
seg.speed = elem["sx"] | seg.speed;
seg.intensity = elem["ix"] | seg.intensity;
seg.palette = elem["pal"] | seg.palette;
}
}
}
bool deserializeState(JsonObject root) bool deserializeState(JsonObject root)
{ {
bool stateResponse = root["v"] | false; bool stateResponse = root["v"] | false;
@ -10,15 +68,18 @@ bool deserializeState(JsonObject root)
bool on = root["on"] | (bri > 0); bool on = root["on"] | (bri > 0);
if (!on != !bri) toggleOnOff(); if (!on != !bri) toggleOnOff();
if (root.containsKey("transition")) int tr = root["transition"] | -1;
if (tr >= 0)
{ {
transitionDelay = root["transition"]; transitionDelay = tr;
transitionDelay *= 100; transitionDelay *= 100;
} }
if (root.containsKey("tt"))
tr = root["tt"] | -1;
if (tr >= 0)
{ {
transitionDelayTemp = root["tt"]; transitionDelayTemp = tr;
transitionDelayTemp *= 100; transitionDelayTemp *= 100;
jsonTransitionOnce = true; jsonTransitionOnce = true;
} }
@ -44,65 +105,31 @@ bool deserializeState(JsonObject root)
if (timein != -1) setTime(timein); if (timein != -1) setTime(timein);
int it = 0; int it = 0;
JsonArray segs = root["seg"]; JsonVariant segVar = root["seg"];
for (JsonObject elem : segs) if (segVar.is<JsonObject>())
{ {
byte id = elem["id"] | it; int id = segVar["id"] | -1;
if (id < strip.getMaxSegments()) if (id < 0) { //set all selected segments
{ for (byte s = 0; s < strip.getMaxSegments(); s++)
WS2812FX::Segment& seg = strip.getSegment(id);
uint16_t start = elem["start"] | seg.start;
int stop = elem["stop"] | -1;
if (stop < 0) {
uint16_t len = elem["len"];
stop = (len > 0) ? start + len : seg.stop;
}
strip.setSegment(id, start, stop);
JsonArray colarr = elem["col"];
if (!colarr.isNull())
{ {
for (uint8_t i = 0; i < 3; i++) WS2812FX::Segment sg = strip.getSegment(s);
if (sg.isActive() && sg.isSelected())
{ {
JsonArray colX = colarr[i]; deserializeSegment(segVar, s);
if (colX.isNull()) break;
byte sz = colX.size();
if (sz > 0 && sz < 5)
{
int rgbw[] = {0,0,0,0};
byte cp = copyArray(colX, rgbw);
seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF)));
if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0;
if (id == 0) //temporary
{
if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];}
if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];}
}
}
} }
} }
} else { //set only the segment with the specified ID
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal); deserializeSegment(segVar, it);
seg.setOption(0, elem["sel"] | seg.getOption(0)); //selected }
seg.setOption(1, elem["rev"] | seg.getOption(1)); //reverse } else {
//int cln = seg_0["cln"]; JsonArray segs = segVar.as<JsonArray>();
//temporary, strip object gets updated via colorUpdated() for (JsonObject elem : segs)
if (id == 0) { {
effectCurrent = elem["fx"] | effectCurrent; deserializeSegment(elem, it);
effectSpeed = elem["sx"] | effectSpeed; it++;
effectIntensity = elem["ix"] | effectIntensity ;
effectPalette = elem["pal"] | effectPalette;
} else { //permanent
byte fx = elem["fx"] | seg.mode;
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
seg.speed = elem["sx"] | seg.speed;
seg.intensity = elem["ix"] | seg.intensity;
seg.palette = elem["pal"] | seg.palette;
}
} }
it++;
} }
colorUpdated(noNotification ? 5:1); colorUpdated(noNotification ? 5:1);
ps = root["psave"] | -1; ps = root["psave"] | -1;