Added basic segment support
Updated Espalexa
This commit is contained in:
parent
b224a67ea7
commit
117dc5288d
@ -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)
|
||||
|
||||
|
@ -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}}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user