Added basic segment support

Updated Espalexa
This commit is contained in:
cschwinne 2019-06-20 14:40:12 +02:00
parent b224a67ea7
commit 117dc5288d
10 changed files with 248 additions and 133 deletions

View File

@ -3,10 +3,10 @@
#define NpbWrapper_h
//PIN CONFIGURATION
#define LEDPIN 5 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
//#define USE_APA102 // Uncomment for using APA102 LEDs.
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#define IR_PIN 4 //infrared pin (-1 to disable)
#define IR_PIN -1 //infrared pin (-1 to disable)
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)

View File

@ -42,12 +42,13 @@
/* each segment uses 37 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#define MAX_NUM_SEGMENTS 8
#define MAX_NUM_SEGMENTS 10
#define NUM_COLORS 3 /* number of colors per segment */
#define SEGMENT _segments[_segment_index]
#define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x])
#define SEGENV _segment_runtimes[_segment_index]
#define SEGLEN SEGMENT.length()
#define SEGACT SEGMENT.stop
#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGLEN
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
@ -190,7 +191,15 @@ class WS2812FX {
{
return ((options >> n) & 0x01);
}
inline uint16_t length()
bool isSelected()
{
return getOption(0);
}
bool isActive()
{
return stop > start;
}
uint16_t length()
{
return stop - start;
}
@ -289,11 +298,6 @@ class WS2812FX {
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
_brightness = DEFAULT_BRIGHTNESS;
_num_segments = 1;
_segments[0].mode = DEFAULT_MODE;
_segments[0].colors[0] = DEFAULT_COLOR;
_segments[0].start = 0;
_segments[0].speed = DEFAULT_SPEED;
currentPalette = CRGBPalette16(CRGB::Black);
targetPalette = CloudColors_p;
ablMilliampsMax = 850;
@ -301,7 +305,7 @@ class WS2812FX {
_locked = nullptr;
_modeUsesLock = false;
bus = new NeoPixelWrapper();
RESET_RUNTIME;
resetSegments();
}
void
@ -310,13 +314,12 @@ class WS2812FX {
blur(uint8_t),
fade_out(uint8_t r),
setMode(uint8_t m),
setMode(uint8_t segid, uint8_t m),
setSpeed(uint8_t s),
setIntensity(uint8_t i),
setPalette(uint8_t p),
setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setColor(uint32_t c),
setSecondaryColor(uint32_t c),
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setColor(uint8_t slot, uint32_t c),
setBrightness(uint8_t b),
driverModeCronixie(bool b),
setCronixieDigits(byte* d),
@ -337,22 +340,24 @@ class WS2812FX {
show(void);
bool
reverseMode = true,
reverseMode = false,
gammaCorrectBri = false,
gammaCorrectCol = true,
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p);
uint8_t
returnedSegment = 0,
paletteFade = 0,
paletteBlend = 0,
colorOrder = 0,
getBrightness(void),
getMode(void),
getSpeed(void),
getNumSegments(void),
getModeCount(void),
getPaletteCount(void),
getMaxSegments(void),
getFirstSelectedSegment(void),
getReturnedSegmentId(void),
gamma8(uint8_t),
get_random_wheel_index(uint8_t);
@ -506,7 +511,6 @@ class WS2812FX {
uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99;
uint8_t _num_segments = 1;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 21 bytes per element
// start, stop, speed, intensity, palette, mode, options, color[]
{ 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, {DEFAULT_COLOR}}

View File

@ -58,16 +58,19 @@ void WS2812FX::service() {
unsigned long now = millis(); // Be aware, millis() rolls over every 49 days
if (now - _lastShow < MIN_SHOW_DELAY) return;
bool doShow = false;
for(uint8_t i=0; i < _num_segments; i++)
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
{
_segment_index = i;
if(now > SEGENV.next_time || _triggered)
if (SEGMENT.isActive())
{
doShow = true;
handle_palette();
uint16_t delay = (this->*_mode[SEGMENT.mode])();
SEGENV.next_time = now + max(delay, MIN_SHOW_DELAY);
SEGENV.call++;
if(now > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
{
doShow = true;
handle_palette();
uint16_t delay = (this->*_mode[SEGMENT.mode])();
SEGENV.next_time = now + delay;
SEGENV.call++;
}
}
}
if(doShow) {
@ -249,14 +252,24 @@ void WS2812FX::trigger() {
_triggered = true;
}
void WS2812FX::setMode(uint8_t m) {
RESET_RUNTIME;
bool ua = modeUsesLock(_segments[0].mode) && !modeUsesLock(m);
if (m > MODE_COUNT - 1) m = MODE_COUNT - 1;
_segments[0].mode = m;
if (ua) unlockAll();
_modeUsesLock = modeUsesLock(_segments[0].mode);
setBrightness(_brightness);
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
if (segid >= MAX_NUM_SEGMENTS) return;
bool anyUsedLock = _modeUsesLock, anyUseLock = false;
if (m >= MODE_COUNT) m = MODE_COUNT - 1;
if (_segments[segid].mode != m)
{
_segment_runtimes[segid].reset();
_segments[segid].mode = m;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (modeUsesLock(_segments[i].mode)) anyUseLock = true;
}
if (anyUsedLock && !anyUseLock) unlockAll();
_modeUsesLock = anyUseLock;
}
uint8_t WS2812FX::getModeCount()
@ -271,42 +284,64 @@ uint8_t WS2812FX::getPaletteCount()
//TODO transitions
void WS2812FX::setMode(uint8_t m) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) setMode(i, m);
}
}
void WS2812FX::setSpeed(uint8_t s) {
_segments[0].speed = s;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) _segments[i].speed = s;
}
}
void WS2812FX::setIntensity(uint8_t in) {
_segments[0].intensity = in;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) _segments[i].intensity = in;
}
}
void WS2812FX::setPalette(uint8_t p) {
_segments[0].palette = p;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) _segments[i].palette = p;
}
}
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p) {
bool changed = false;
m = constrain(m, 0, MODE_COUNT - 1);
if (m != _segments[0].mode) { setMode(m); changed = true; }
if (s != _segments[0].speed) { setSpeed(s); changed = true; }
if (i != _segments[0].intensity) { setIntensity(i); changed = true; }
if (p != _segments[0].palette) { setPalette(p); changed = true; }
return changed;
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
uint8_t retSeg = getReturnedSegmentId();
Segment& seg = _segments[retSeg];
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected())
{
_segments[i].speed = s;
_segments[i].intensity = in;
_segments[i].palette = p;
setMode(i, m);
}
}
if (seg.mode != modePrev || seg.speed != speedPrev || seg.intensity != intensityPrev || seg.palette != palettePrev) return true;
return false;
}
void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
setColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
setColor(slot, ((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
}
void WS2812FX::setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
setSecondaryColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
}
void WS2812FX::setColor(uint32_t c) {
_segments[0].colors[0] = c;
}
void WS2812FX::setSecondaryColor(uint32_t c) {
_segments[0].colors[1] = c;
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
if (slot >= NUM_COLORS) return;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) _segments[i].colors[slot] = c;
}
}
void WS2812FX::setBrightness(uint8_t b) {
@ -316,27 +351,44 @@ void WS2812FX::setBrightness(uint8_t b) {
}
uint8_t WS2812FX::getMode(void) {
return _segments[0].mode;
return _segments[getReturnedSegmentId()].mode;
}
uint8_t WS2812FX::getSpeed(void) {
return _segments[0].speed;
return _segments[getReturnedSegmentId()].speed;
}
uint8_t WS2812FX::getBrightness(void) {
return _brightness;
}
uint8_t WS2812FX::getNumSegments(void) {
return _num_segments;
}
uint8_t WS2812FX::getMaxSegments(void) {
return MAX_NUM_SEGMENTS;
}
uint8_t WS2812FX::getFirstSelectedSegment(void)
{
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && _segments[i].isSelected()) return i;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) //if none selected, get first active
{
if (_segments[i].isActive()) return i;
}
return 0;
}
uint8_t WS2812FX::getReturnedSegmentId(void) {
if (returnedSegment >= MAX_NUM_SEGMENTS || !_segments[returnedSegment].isActive())
{
return getFirstSelectedSegment();
}
return returnedSegment;
}
uint32_t WS2812FX::getColor(void) {
return _segments[0].colors[0];
return _segments[getReturnedSegmentId()].colors[0];
}
uint32_t WS2812FX::getPixelColor(uint16_t i)
@ -392,6 +444,16 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) {
if (n >= MAX_NUM_SEGMENTS) return;
Segment& seg = _segments[n];
if (seg.start == i1 && seg.stop == i2) return;
if (seg.isActive() && modeUsesLock(seg.mode))
{
_modeUsesLock = false;
unlockRange(seg.start, seg.stop);
_modeUsesLock = true;
}
if (i2 <= i1) //disable segment
{
seg.stop = 0; return;
}
if (i1 < _length) seg.start = i1;
seg.stop = i2;
if (i2 > _length) seg.stop = _length;
@ -402,12 +464,12 @@ void WS2812FX::resetSegments() {
memset(_segments, 0, sizeof(_segments));
memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
_segment_index = 0;
_num_segments = 1;
_segments[0].mode = DEFAULT_MODE;
_segments[0].colors[0] = DEFAULT_COLOR;
_segments[0].start = 0;
_segments[0].speed = DEFAULT_SPEED;
_segments[0].stop = _length;
_segments[0].setOption(0, 1); //select
}
void WS2812FX::setIndividual(uint16_t i, uint32_t col)
@ -434,28 +496,28 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
void WS2812FX::lock(uint16_t i)
{
if (modeUsesLock(SEGMENT.mode)) return;
if (_modeUsesLock) return;
if (i >= 0 && i < _length) _locked[i] = true;
}
void WS2812FX::lockRange(uint16_t i, uint16_t i2)
{
if (modeUsesLock(SEGMENT.mode)) return;
if (_modeUsesLock) return;
for (uint16_t x = i; x < i2; x++)
{
if (i >= 0 && i < _length) _locked[i] = true;
if (x >= 0 && x < _length) _locked[i] = true;
}
}
void WS2812FX::unlock(uint16_t i)
{
if (modeUsesLock(SEGMENT.mode)) return;
if (_modeUsesLock) return;
if (i >= 0 && i < _length) _locked[i] = false;
}
void WS2812FX::unlockRange(uint16_t i, uint16_t i2)
{
if (modeUsesLock(SEGMENT.mode)) return;
if (_modeUsesLock) return;
for (uint16_t x = i; x < i2; x++)
{
if (x >= 0 && x < _length) _locked[x] = false;

View File

@ -10,7 +10,7 @@
*/
/*
* @title Espalexa library
* @version 2.4.2
* @version 2.4.3
* @author Christian Schwinne
* @license MIT
* @contributors d-999
@ -49,7 +49,7 @@
#include <WiFiUdp.h>
#ifdef ESPALEXA_DEBUG
#pragma message "Espalexa 2.4.2 debug mode"
#pragma message "Espalexa 2.4.3 debug mode"
#define EA_DEBUG(x) Serial.print (x)
#define EA_DEBUGLN(x) Serial.println (x)
#else
@ -121,11 +121,25 @@ private:
return "Plug";
}
//Workaround functions courtesy of Sonoff-Tasmota
uint32_t encodeLightId(uint8_t idx)
{
uint8_t mac[6];
WiFi.macAddress(mac);
uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (idx & 0xF);
return id;
}
uint32_t decodeLightId(uint32_t id) {
return id & 0xF;
}
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
String deviceJsonString(uint8_t deviceId)
{
if (deviceId < 1 || deviceId > currentDeviceCount) return "{}"; //error
EspalexaDevice* dev = devices[deviceId-1];
deviceId--;
if (deviceId >= currentDeviceCount) return "{}"; //error
EspalexaDevice* dev = devices[deviceId];
String json = "{\"state\":{\"on\":";
json += boolString(dev->getValue());
@ -149,8 +163,8 @@ private:
json += "\",\"name\":\"" + dev->getName();
json += "\",\"modelid\":\"" + modelidString(dev->getType());
json += "\",\"manufacturername\":\"Philips\",\"productname\":\"E" + String(static_cast<uint8_t>(dev->getType()));
json += "\",\"uniqueid\":\""+ WiFi.macAddress() +"-"+ (deviceId+1);
json += "\",\"swversion\":\"espalexa-2.4.2\"}";
json += "\",\"uniqueid\":\"" + String(encodeLightId(deviceId+1));
json += "\",\"swversion\":\"espalexa-2.4.3\"}";
return json;
}
@ -174,7 +188,7 @@ private:
}
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
res += "\r\nUptime: " + (String)millis();
res += "\r\n\r\nEspalexa library v2.4.2 by Christian Schwinne 2019";
res += "\r\n\r\nEspalexa library v2.4.3 by Christian Schwinne 2019";
server->send(200, "text/plain", res);
}
#endif
@ -219,15 +233,6 @@ private:
"<serialNumber>"+ escapedMac +"</serialNumber>"
"<UDN>uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"</UDN>"
"<presentationURL>index.html</presentationURL>"
"<iconList>"
" <icon>"
" <mimetype>image/png</mimetype>"
" <height>48</height>"
" <width>48</width>"
" <depth>24</depth>"
" <url>hue_logo_0.png</url>"
" </icon>"
"</iconList>"
"</device>"
"</root>";
@ -450,22 +455,27 @@ public:
{
server->send(200, "application/json", "[{\"success\":true}]"); //short valid response
int devId = req.substring(req.indexOf("lights")+7).toInt();
uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
EA_DEBUG("ls"); EA_DEBUGLN(devId);
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::none);
devId = decodeLightId(devId);
EA_DEBUGLN(devId);
devId--; //zero-based for devices array
if (devId >= currentDeviceCount) return true; //return if invalid ID
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::none);
if (body.indexOf("false")>0) //OFF command
{
devices[devId-1]->setValue(0);
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::off);
devices[devId-1]->doCallback();
devices[devId]->setValue(0);
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::off);
devices[devId]->doCallback();
return true;
}
if (body.indexOf("true") >0) //ON command
{
devices[devId-1]->setValue(devices[devId-1]->getLastValue());
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::on);
devices[devId]->setValue(devices[devId]->getLastValue());
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::on);
}
if (body.indexOf("bri") >0) //BRIGHTNESS command
@ -473,35 +483,35 @@ public:
uint8_t briL = body.substring(body.indexOf("bri") +5).toInt();
if (briL == 255)
{
devices[devId-1]->setValue(255);
devices[devId]->setValue(255);
} else {
devices[devId-1]->setValue(briL+1);
devices[devId]->setValue(briL+1);
}
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::bri);
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::bri);
}
if (body.indexOf("xy") >0) //COLOR command (XY mode)
{
devices[devId-1]->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat());
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::xy);
devices[devId]->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat());
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::xy);
}
if (body.indexOf("hue") >0) //COLOR command (HS mode)
{
devices[devId-1]->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt());
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::hs);
devices[devId]->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt());
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::hs);
}
if (body.indexOf("ct") >0) //COLOR TEMP command (white spectrum)
{
devices[devId-1]->setColor(body.substring(body.indexOf("ct") +4).toInt());
devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::ct);
devices[devId]->setColor(body.substring(body.indexOf("ct") +4).toInt());
devices[devId]->setPropertyChanged(EspalexaDeviceProperty::ct);
}
devices[devId-1]->doCallback();
devices[devId]->doCallback();
#ifdef ESPALEXA_DEBUG
if (devices[devId-1]->getLastChangedProperty() == EspalexaDeviceProperty::none)
if (devices[devId]->getLastChangedProperty() == EspalexaDeviceProperty::none)
EA_DEBUGLN("STATE REQ WITHOUT BODY (likely Content-Type issue #6)");
#endif
return true;
@ -519,7 +529,7 @@ public:
String jsonTemp = "{";
for (int i = 0; i<currentDeviceCount; i++)
{
jsonTemp += "\"" + String(i+1) + "\":";
jsonTemp += "\"" + String(encodeLightId(i+1)) + "\":";
jsonTemp += deviceJsonString(i+1);
if (i < currentDeviceCount-1) jsonTemp += ",";
}
@ -527,7 +537,14 @@ public:
server->send(200, "application/json", jsonTemp);
} else //client wants one light (devId)
{
server->send(200, "application/json", deviceJsonString(devId));
devId = decodeLightId(devId);
EA_DEBUGLN(devId);
if (devId > currentDeviceCount)
{
server->send(200, "application/json", "{}");
} else {
server->send(200, "application/json", deviceJsonString(devId));
}
}
return true;

View File

@ -98,7 +98,7 @@
//version code in format yymmddb (b = daily build)
#define VERSION 1905222
#define VERSION 1906061
char versionString[] = "0.8.4";
@ -491,6 +491,7 @@ bool oappendi(int i)
//boot starts here
void setup() {
pinMode(4, OUTPUT); digitalWrite(4, HIGH);
wledInit();
}

View File

@ -143,7 +143,7 @@ void wledInit()
void beginStrip()
{
// Initialize NeoPixel Strip and button
strip.setColor(0);
strip.setColor(0, 0);
strip.setBrightness(255);
#ifdef BTNPIN

View File

@ -34,7 +34,11 @@ void notify(byte callMode, bool followUp=false)
udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed;
udpOut[10] = col[3];
udpOut[11] = 5; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//compatibilityVersionByte:
//0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports tertiary color
udpOut[11] = 5;
udpOut[12] = colSec[0];
udpOut[13] = colSec[1];
udpOut[14] = colSec[2];
@ -43,6 +47,10 @@ void notify(byte callMode, bool followUp=false)
udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF;
udpOut[19] = effectPalette;
/*udpOut[20] = colTer[0];
udpOut[21] = colTer[1];
udpOut[22] = colTer[2];
udpOut[23] = colTer[3];*/
IPAddress broadcastIp;
broadcastIp = ~uint32_t(WiFi.subnetMask()) | uint32_t(WiFi.gatewayIP());
@ -177,11 +185,18 @@ void handleNotifications()
colSec[2] = udpIn[14];
colSec[3] = udpIn[15];
}
/*if (udpIn[11] > 5)
{
colTer[0] = udpIn[20];
colTer[1] = udpIn[21];
colTer[2] = udpIn[22];
colSec[3] = udpIn[23];
}*/
}
}
//apply effects from notification
if (receiveNotificationEffects || !someSel)
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
{
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
effectSpeed = udpIn[9];

View File

@ -35,8 +35,8 @@ void setAllLeds() {
colorRGBtoRGBW(colT);
colorRGBtoRGBW(colSecT);
}
strip.setColor(colT[0], colT[1], colT[2], colT[3]);
strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], colSecT[3]);
strip.setColor(0, colT[0], colT[1], colT[2], colT[3]);
strip.setColor(1, colSecT[0], colSecT[1], colSecT[2], colSecT[3]);
}

View File

@ -73,7 +73,7 @@ void initServer()
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request, JsonVariant &json) {
JsonObject& root = json.as<JsonObject>();
if (!root.success()){request->send(500, "application/json", "{\"error\":\"Parsing failed\"}"); return;}
deserializeState(root);
if (deserializeState(root)) { serveJson(request); return; } //if JSON contains "v" (verbose response)
request->send(200, "application/json", "{\"success\":true}");
});
server.addHandler(handler);

View File

@ -2,8 +2,10 @@
* JSON API (De)serialization
*/
void deserializeState(JsonObject& root)
bool deserializeState(JsonObject& root)
{
bool stateResponse = root["v"] | false;
bri = root["bri"] | bri;
bool on = root["on"] | (bri > 0);
@ -32,6 +34,9 @@ void deserializeState(JsonObject& root)
receiveNotifications = udpn["recv"] | receiveNotifications;
bool noNotification = udpn["nn"]; //send no notification just for this request
int timein = root["time"] | -1;
if (timein != -1) setTime(timein);
int it = 0;
JsonArray& segs = root["seg"];
for (JsonObject& elem : segs)
@ -40,14 +45,14 @@ void deserializeState(JsonObject& root)
if (id < strip.getMaxSegments())
{
WS2812FX::Segment& seg = strip.getSegment(id);
/*uint16_t start = elem["start"] | seg.start;
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);*/
strip.setSegment(id, start, stop);
JsonArray& colarr = elem["col"];
if (colarr.success())
@ -63,31 +68,37 @@ void deserializeState(JsonObject& root)
byte cp = colX.copyTo(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;
//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 (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];}
}
}
}
}
byte fx = elem["fx"] | seg.mode;
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(fx);
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
seg.speed = elem["sx"] | seg.speed;
seg.intensity = elem["ix"] | seg.intensity;
byte pal = elem["pal"] | seg.palette;
if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
seg.setOption(0, elem["sel"] | seg.getOption(0));
seg.setOption(1, elem["rev"] | seg.getOption(1));
seg.palette = elem["pal"] | seg.palette;
//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
effectCurrent = seg.mode;
effectSpeed = seg.speed;
effectIntensity = seg.intensity;
effectPalette = seg.palette;
if (id == 0) {
effectCurrent = seg.mode;
effectSpeed = seg.speed;
effectIntensity = seg.intensity;
effectPalette = seg.palette;
}
}
it++;
}
colorUpdated(noNotification ? 5:1);
return stateResponse;
}
void serializeState(JsonObject& root)
@ -110,15 +121,20 @@ void serializeState(JsonObject& root)
udpn["recv"] = receiveNotifications;
JsonArray& seg = root.createNestedArray("seg");
JsonObject& seg0 = seg.createNestedObject();
serializeSegment(seg0);
for (byte s = 0; s < strip.getMaxSegments(); s++)
{
WS2812FX::Segment sg = strip.getSegment(s);
if (sg.isActive())
{
JsonObject& seg0 = seg.createNestedObject();
serializeSegment(seg0, sg, s);
}
}
}
void serializeSegment(JsonObject& root)
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id)
{
WS2812FX::Segment seg = strip.getSegment(0);
//root["id"] = i;
root["id"] = id;
root["start"] = seg.start;
root["stop"] = seg.stop;
root["len"] = seg.stop - seg.start;
@ -139,7 +155,7 @@ void serializeSegment(JsonObject& root)
root["sx"] = seg.speed;
root["ix"] = seg.intensity;
root["pal"] = seg.palette;
root["sel"] = true; //seg.getOption(0);
root["sel"] = seg.isSelected();
root["rev"] = seg.getOption(1);
root["cln"] = -1;
}