Browse Source

Color transitions

fastled
Xose Pérez 7 years ago
parent
commit
97c52ed1a0
4 changed files with 2714 additions and 2688 deletions
  1. +4
    -0
      code/espurna/config/general.h
  2. BIN
      code/espurna/data/index.html.gz
  3. +187
    -165
      code/espurna/light.ino
  4. +2523
    -2523
      code/espurna/static/index.html.gz.h

+ 4
- 0
code/espurna/config/general.h View File

@ -546,6 +546,10 @@ PROGMEM const char* const custom_reset_string[] = {
#define LIGHT_USE_CSS 1 // Use CSS style to report colors (1=> "#FF0000", 0=> "255,0,0") #define LIGHT_USE_CSS 1 // Use CSS style to report colors (1=> "#FF0000", 0=> "255,0,0")
#define LIGHT_USE_RGB 0 // Use RGB color selector (1=> RGB, 0=> HSV) #define LIGHT_USE_RGB 0 // Use RGB color selector (1=> RGB, 0=> HSV)
#define LIGHT_USE_TRANSITIONS 1 // Transitions between colors
#define LIGHT_TRANSITION_STEP 10 // Time in millis between each transtion step
#define LIGHT_TRANSITION_STEPS 50 // Number of steps to acomplish transition
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// POWER METERING // POWER METERING
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


BIN
code/espurna/data/index.html.gz View File


+ 187
- 165
code/espurna/light.ino View File

@ -19,25 +19,36 @@ extern "C" {
} }
#endif #endif
Ticker colorTicker;
// -----------------------------------------------------------------------------
Ticker _light_save_ticker;
Ticker _light_transition_ticker;
typedef struct { typedef struct {
unsigned char pin; unsigned char pin;
bool reverse; bool reverse;
unsigned char value;
unsigned char shadow;
unsigned char value; // target or nominal value
unsigned char shadow; // represented value
double current; // transition value
} channel_t; } channel_t;
std::vector<channel_t> _channels;
bool _lightState = false;
unsigned int _brightness = LIGHT_MAX_BRIGHTNESS;
std::vector<channel_t> _light_channel;
bool _light_state = false;
bool _light_has_color = false;
bool _light_use_white = false;
bool _light_use_gamma = false;
unsigned long _light_steps_left = 0;
unsigned int _light_brightness = LIGHT_MAX_BRIGHTNESS;
#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
#include <my92xx.h> #include <my92xx.h>
my92xx * _my92xx; my92xx * _my92xx;
ARRAYINIT(unsigned char, _light_channel_map, MY92XX_MAPPING);
#endif #endif
// Gamma Correction lookup table (8 bit) // Gamma Correction lookup table (8 bit)
// TODO: move to PROGMEM // TODO: move to PROGMEM
const unsigned char gamma_table[] = {
const unsigned char _light_gamma_table[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6,
@ -63,14 +74,14 @@ const unsigned char gamma_table[] = {
void _fromLong(unsigned long value, bool brightness) { void _fromLong(unsigned long value, bool brightness) {
if (brightness) { if (brightness) {
_channels[0].value = (value >> 24) & 0xFF;
_channels[1].value = (value >> 16) & 0xFF;
_channels[2].value = (value >> 8) & 0xFF;
_brightness = (value & 0xFF) * LIGHT_MAX_BRIGHTNESS / 255;
_light_channel[0].value = (value >> 24) & 0xFF;
_light_channel[1].value = (value >> 16) & 0xFF;
_light_channel[2].value = (value >> 8) & 0xFF;
_light_brightness = (value & 0xFF) * LIGHT_MAX_BRIGHTNESS / 255;
} else { } else {
_channels[0].value = (value >> 16) & 0xFF;
_channels[1].value = (value >> 8) & 0xFF;
_channels[2].value = (value) & 0xFF;
_light_channel[0].value = (value >> 16) & 0xFF;
_light_channel[1].value = (value >> 8) & 0xFF;
_light_channel[2].value = (value) & 0xFF;
} }
} }
@ -83,7 +94,7 @@ void _fromRGB(const char * rgb) {
// if color begins with a # then assume HEX RGB // if color begins with a # then assume HEX RGB
if (p[0] == '#') { if (p[0] == '#') {
if (lightHasColor()) {
if (_light_has_color) {
++p; ++p;
unsigned long value = strtoul(p, NULL, 16); unsigned long value = strtoul(p, NULL, 16);
@ -96,7 +107,7 @@ void _fromRGB(const char * rgb) {
// it's a temperature in mireds // it's a temperature in mireds
} else if (p[0] == 'M') { } else if (p[0] == 'M') {
if (lightHasColor()) {
if (_light_has_color) {
unsigned long mireds = atol(p + 1); unsigned long mireds = atol(p + 1);
_fromMireds(mireds); _fromMireds(mireds);
} }
@ -104,7 +115,7 @@ void _fromRGB(const char * rgb) {
// it's a temperature in kelvin // it's a temperature in kelvin
} else if (p[0] == 'K') { } else if (p[0] == 'K') {
if (lightHasColor()) {
if (_light_has_color) {
unsigned long kelvin = atol(p + 1); unsigned long kelvin = atol(p + 1);
_fromKelvin(kelvin); _fromKelvin(kelvin);
} }
@ -114,19 +125,19 @@ void _fromRGB(const char * rgb) {
char * tok; char * tok;
unsigned char count = 0; unsigned char count = 0;
unsigned char channels = _channels.size();
unsigned char channels = _light_channel.size();
tok = strtok(p, ","); tok = strtok(p, ",");
while (tok != NULL) { while (tok != NULL) {
_channels[count].value = atoi(tok);
_light_channel[count].value = atoi(tok);
if (++count == channels) break; if (++count == channels) break;
tok = strtok(NULL, ","); tok = strtok(NULL, ",");
} }
// RGB but less than 3 values received // RGB but less than 3 values received
if (lightHasColor() && (count < 3)) {
_channels[1].value = _channels[0].value;
_channels[2].value = _channels[0].value;
if (_light_has_color && (count < 3)) {
_light_channel[1].value = _light_channel[0].value;
_light_channel[2].value = _light_channel[0].value;
} }
} }
@ -135,17 +146,17 @@ void _fromRGB(const char * rgb) {
void _toRGB(char * rgb, size_t len, bool applyBrightness) { void _toRGB(char * rgb, size_t len, bool applyBrightness) {
if (!lightHasColor()) return;
if (!_light_has_color) return;
float b = applyBrightness ? (float) _brightness / LIGHT_MAX_BRIGHTNESS : 1;
float b = applyBrightness ? (float) _light_brightness / LIGHT_MAX_BRIGHTNESS : 1;
unsigned long value = 0; unsigned long value = 0;
value += _channels[0].value * b;
value += _light_channel[0].value * b;
value <<= 8; value <<= 8;
value += _channels[1].value * b;
value += _light_channel[1].value * b;
value <<= 8; value <<= 8;
value += _channels[2].value * b;
value += _light_channel[2].value * b;
snprintf_P(rgb, len, PSTR("#%06X"), value); snprintf_P(rgb, len, PSTR("#%06X"), value);
@ -163,7 +174,7 @@ void _fromHSV(const char * hsv) {
char * ptr = (char *) hsv; char * ptr = (char *) hsv;
if (strlen(ptr) == 0) return; if (strlen(ptr) == 0) return;
if (!lightHasColor()) return;
if (!_light_has_color) return;
char * tok; char * tok;
unsigned char count = 0; unsigned char count = 0;
@ -189,56 +200,56 @@ void _fromHSV(const char * hsv) {
switch (int(h)) { switch (int(h)) {
case 0: case 0:
_channels[0].value = v;
_channels[1].value = t;
_channels[2].value = p;
_light_channel[0].value = v;
_light_channel[1].value = t;
_light_channel[2].value = p;
break; break;
case 1: case 1:
_channels[0].value = q;
_channels[1].value = v;
_channels[2].value = p;
_light_channel[0].value = q;
_light_channel[1].value = v;
_light_channel[2].value = p;
break; break;
case 2: case 2:
_channels[0].value = p;
_channels[1].value = v;
_channels[2].value = t;
_light_channel[0].value = p;
_light_channel[1].value = v;
_light_channel[2].value = t;
break; break;
case 3: case 3:
_channels[0].value = p;
_channels[1].value = q;
_channels[2].value = v;
_light_channel[0].value = p;
_light_channel[1].value = q;
_light_channel[2].value = v;
break; break;
case 4: case 4:
_channels[0].value = t;
_channels[1].value = p;
_channels[2].value = v;
_light_channel[0].value = t;
_light_channel[1].value = p;
_light_channel[2].value = v;
break; break;
case 5: case 5:
_channels[0].value = v;
_channels[1].value = p;
_channels[2].value = q;
_light_channel[0].value = v;
_light_channel[1].value = p;
_light_channel[2].value = q;
break; break;
default: default:
_channels[0].value = 0;
_channels[1].value = 0;
_channels[2].value = 0;
_light_channel[0].value = 0;
_light_channel[1].value = 0;
_light_channel[2].value = 0;
break; break;
} }
_brightness = LIGHT_MAX_BRIGHTNESS;
_light_brightness = LIGHT_MAX_BRIGHTNESS;
} }
void _toHSV(char * hsv, size_t len) { void _toHSV(char * hsv, size_t len) {
if (!lightHasColor()) return;
if (!_light_has_color) return;
double min, max; double min, max;
double h, s, v; double h, s, v;
double r = (double) _channels[0].value / 255.0;
double g = (double) _channels[1].value / 255.0;
double b = (double) _channels[2].value / 255.0;
double r = (double) _light_channel[0].value / 255.0;
double g = (double) _light_channel[1].value / 255.0;
double b = (double) _light_channel[2].value / 255.0;
min = (r < g) ? r : g; min = (r < g) ? r : g;
min = (min < b) ? min : b; min = (min < b) ? min : b;
@ -281,14 +292,14 @@ void _toHSV(char * hsv, size_t len) {
void _toLong(char * color, size_t len, bool applyBrightness) { void _toLong(char * color, size_t len, bool applyBrightness) {
if (!lightHasColor()) return;
if (!_light_has_color) return;
float b = applyBrightness ? (float) _brightness / LIGHT_MAX_BRIGHTNESS : 1;
float b = applyBrightness ? (float) _light_brightness / LIGHT_MAX_BRIGHTNESS : 1;
snprintf_P(color, len, PSTR("%d,%d,%d"), snprintf_P(color, len, PSTR("%d,%d,%d"),
(int) (_channels[0].value * b),
(int) (_channels[1].value * b),
(int) (_channels[2].value * b)
(int) (_light_channel[0].value * b),
(int) (_light_channel[1].value * b),
(int) (_light_channel[2].value * b)
); );
} }
@ -302,7 +313,7 @@ void _toLong(char * color, size_t len) {
void _fromKelvin(unsigned long kelvin) { void _fromKelvin(unsigned long kelvin) {
// Check we have RGB channels // Check we have RGB channels
if (!lightHasColor()) return;
if (!_light_has_color) return;
// Calculate colors // Calculate colors
unsigned int red = (kelvin <= 66) unsigned int red = (kelvin <= 66)
@ -318,9 +329,9 @@ void _fromKelvin(unsigned long kelvin) {
: 138.5177312231 * log(kelvin - 10) - 305.0447927307); : 138.5177312231 * log(kelvin - 10) - 305.0447927307);
// Save values // Save values
_channels[0].value = constrain(red, 0, LIGHT_MAX_VALUE);
_channels[1].value = constrain(green, 0, LIGHT_MAX_VALUE);
_channels[2].value = constrain(blue, 0, LIGHT_MAX_VALUE);
_light_channel[0].value = constrain(red, 0, LIGHT_MAX_VALUE);
_light_channel[1].value = constrain(green, 0, LIGHT_MAX_VALUE);
_light_channel[2].value = constrain(blue, 0, LIGHT_MAX_VALUE);
} }
@ -333,8 +344,8 @@ void _fromMireds(unsigned long mireds) {
unsigned int _toPWM(unsigned long value, bool bright, bool gamma, bool reverse) { unsigned int _toPWM(unsigned long value, bool bright, bool gamma, bool reverse) {
value = constrain(value, 0, LIGHT_MAX_VALUE); value = constrain(value, 0, LIGHT_MAX_VALUE);
if (bright) value *= ((float) _brightness / LIGHT_MAX_BRIGHTNESS);
if (gamma) value = gamma_table[value];
if (bright) value *= ((float) _light_brightness / LIGHT_MAX_BRIGHTNESS);
if (gamma) value = _light_gamma_table[value];
if (LIGHT_MAX_VALUE != LIGHT_LIMIT_PWM) value = map(value, 0, LIGHT_MAX_VALUE, 0, LIGHT_LIMIT_PWM); if (LIGHT_MAX_VALUE != LIGHT_LIMIT_PWM) value = map(value, 0, LIGHT_MAX_VALUE, 0, LIGHT_LIMIT_PWM);
if (reverse) value = LIGHT_LIMIT_PWM - value; if (reverse) value = LIGHT_LIMIT_PWM - value;
return value; return value;
@ -342,11 +353,11 @@ unsigned int _toPWM(unsigned long value, bool bright, bool gamma, bool reverse)
// Returns a PWM valule for the given channel ID // Returns a PWM valule for the given channel ID
unsigned int _toPWM(unsigned char id) { unsigned int _toPWM(unsigned char id) {
if (id < _channels.size()) {
bool isColor = lightHasColor() && (id < 3);
if (id < _light_channel.size()) {
bool isColor = _light_has_color && (id < 3);
bool bright = isColor; bool bright = isColor;
bool gamma = isColor & (getSetting("useGamma", LIGHT_USE_GAMMA).toInt() == 1);
return _toPWM(_channels[id].shadow, bright, gamma, _channels[id].reverse);
bool gamma = isColor & _light_use_gamma;
return _toPWM(_light_channel[id].shadow, bright, gamma, _light_channel[id].reverse);
} }
return 0; return 0;
} }
@ -357,23 +368,34 @@ unsigned int _toPWM(unsigned char id) {
void _shadow() { void _shadow() {
for (unsigned int i=0; i < _channels.size(); i++) {
_channels[i].shadow = _lightState ? _channels[i].value : 0;
// Transitions
unsigned char target;
for (unsigned int i=0; i < _light_channel.size(); i++) {
target = _light_state ? _light_channel[i].value : 0;
if (_light_steps_left == 0) {
_light_channel[i].current = target;
} else {
double difference = (double) (target - _light_channel[i].current) / (_light_steps_left + 1);
_light_channel[i].current = _light_channel[i].current + difference;
}
_light_channel[i].shadow = _light_channel[i].current;
} }
if (lightHasColor()) {
bool useWhite = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
// Update transition ticker
if (_light_steps_left == 0) {
_light_transition_ticker.detach();
} else {
_light_steps_left--;
}
if (_lightState && useWhite && (_channels.size() > 3)) {
if (_channels[0].shadow == _channels[1].shadow && _channels[1].shadow == _channels[2].shadow ) {
_channels[3].shadow = _channels[0].shadow * ((float) _brightness / LIGHT_MAX_BRIGHTNESS);
_channels[2].shadow = 0;
_channels[1].shadow = 0;
_channels[0].shadow = 0;
}
// Use white channel for same RGB
if (_light_use_white && _light_has_color) {
if (_light_channel[0].shadow == _light_channel[1].shadow && _light_channel[1].shadow == _light_channel[2].shadow ) {
_light_channel[3].shadow = _light_channel[0].shadow * ((float) _light_brightness / LIGHT_MAX_BRIGHTNESS);
_light_channel[2].shadow = 0;
_light_channel[1].shadow = 0;
_light_channel[0].shadow = 0;
} }
} }
} }
@ -383,24 +405,22 @@ void _lightProviderUpdate() {
_shadow(); _shadow();
#ifdef LIGHT_ENABLE_PIN #ifdef LIGHT_ENABLE_PIN
digitalWrite(LIGHT_ENABLE_PIN, _lightState);
digitalWrite(LIGHT_ENABLE_PIN, _light_state);
#endif #endif
#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX #if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
ARRAYINIT(unsigned char, channels, MY92XX_MAPPING);
for (unsigned char i=0; i<_channels.size(); i++) {
_my92xx->setChannel(channels[i], _toPWM(i));
for (unsigned char i=0; i<_light_channel.size(); i++) {
_my92xx->setChannel(_light_channel_map[i], _toPWM(i));
} }
_my92xx->setState(_lightState);
_my92xx->setState(true);
_my92xx->update(); _my92xx->update();
#endif #endif
#if LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER #if LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER
for (unsigned int i=0; i < _channels.size(); i++) {
for (unsigned int i=0; i < _light_channel.size(); i++) {
pwm_set_duty(_toPWM(i), i); pwm_set_duty(_toPWM(i), i);
} }
pwm_start(); pwm_start();
@ -414,18 +434,18 @@ void _lightProviderUpdate() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void _lightColorSave() { void _lightColorSave() {
for (unsigned int i=0; i < _channels.size(); i++) {
setSetting("ch", i, _channels[i].value);
for (unsigned int i=0; i < _light_channel.size(); i++) {
setSetting("ch", i, _light_channel[i].value);
} }
setSetting("brightness", _brightness);
setSetting("brightness", _light_brightness);
saveSettings(); saveSettings();
} }
void _lightColorRestore() { void _lightColorRestore() {
for (unsigned int i=0; i < _channels.size(); i++) {
_channels[i].value = getSetting("ch", i, i==0 ? 255 : 0).toInt();
for (unsigned int i=0; i < _light_channel.size(); i++) {
_light_channel[i].value = getSetting("ch", i, i==0 ? 255 : 0).toInt();
} }
_brightness = getSetting("brightness", LIGHT_MAX_BRIGHTNESS).toInt();
_light_brightness = getSetting("brightness", LIGHT_MAX_BRIGHTNESS).toInt();
lightUpdate(false, false); lightUpdate(false, false);
} }
@ -439,7 +459,7 @@ void _lightMQTTCallback(unsigned int type, const char * topic, const char * payl
if (type == MQTT_CONNECT_EVENT) { if (type == MQTT_CONNECT_EVENT) {
if (lightHasColor()) {
if (_light_has_color) {
mqttSubscribe(MQTT_TOPIC_BRIGHTNESS); mqttSubscribe(MQTT_TOPIC_BRIGHTNESS);
mqttSubscribe(MQTT_TOPIC_MIRED); mqttSubscribe(MQTT_TOPIC_MIRED);
mqttSubscribe(MQTT_TOPIC_KELVIN); mqttSubscribe(MQTT_TOPIC_KELVIN);
@ -483,14 +503,14 @@ void _lightMQTTCallback(unsigned int type, const char * topic, const char * payl
// Brightness // Brightness
if (t.equals(MQTT_TOPIC_BRIGHTNESS)) { if (t.equals(MQTT_TOPIC_BRIGHTNESS)) {
_brightness = constrain(atoi(payload), 0, LIGHT_MAX_BRIGHTNESS);
_light_brightness = constrain(atoi(payload), 0, LIGHT_MAX_BRIGHTNESS);
lightUpdate(true, mqttForward()); lightUpdate(true, mqttForward());
} }
// Channel // Channel
if (t.startsWith(MQTT_TOPIC_CHANNEL)) { if (t.startsWith(MQTT_TOPIC_CHANNEL)) {
unsigned int channelID = t.substring(strlen(MQTT_TOPIC_CHANNEL)+1).toInt(); unsigned int channelID = t.substring(strlen(MQTT_TOPIC_CHANNEL)+1).toInt();
if (channelID >= _channels.size()) {
if (channelID >= _light_channel.size()) {
DEBUG_MSG_P(PSTR("[LIGHT] Wrong channelID (%d)\n"), channelID); DEBUG_MSG_P(PSTR("[LIGHT] Wrong channelID (%d)\n"), channelID);
return; return;
} }
@ -506,7 +526,7 @@ void lightMQTT() {
char buffer[12]; char buffer[12];
if (lightHasColor()) {
if (_light_has_color) {
// Color // Color
if (getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1) { if (getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1) {
@ -520,14 +540,14 @@ void lightMQTT() {
mqttSend(MQTT_TOPIC_COLOR_HSV, buffer); mqttSend(MQTT_TOPIC_COLOR_HSV, buffer);
// Brightness // Brightness
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _brightness);
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _light_brightness);
mqttSend(MQTT_TOPIC_BRIGHTNESS, buffer); mqttSend(MQTT_TOPIC_BRIGHTNESS, buffer);
} }
// Channels // Channels
for (unsigned int i=0; i < _channels.size(); i++) {
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _channels[i].value);
for (unsigned int i=0; i < _light_channel.size(); i++) {
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _light_channel[i].value);
mqttSend(MQTT_TOPIC_CHANNEL, i, buffer); mqttSend(MQTT_TOPIC_CHANNEL, i, buffer);
} }
@ -540,21 +560,26 @@ void lightMQTT() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
unsigned char lightChannels() { unsigned char lightChannels() {
return _channels.size();
return _light_channel.size();
} }
bool lightHasColor() { bool lightHasColor() {
bool useColor = getSetting("useColor", LIGHT_USE_COLOR).toInt() == 1;
return useColor && (_channels.size() > 2);
return _light_has_color;
} }
unsigned char lightWhiteChannels() { unsigned char lightWhiteChannels() {
return _channels.size() % 3;
return _light_channel.size() % 3;
} }
void lightUpdate(bool save, bool forward) { void lightUpdate(bool save, bool forward) {
_lightProviderUpdate();
#if LIGHT_USE_TRANSITIONS
_light_steps_left = LIGHT_TRANSITION_STEPS;
_light_transition_ticker.attach_ms(LIGHT_TRANSITION_STEP, _lightProviderUpdate);
#else
_light_steps_left = 0;
_lightProviderUpdate();
#endif
// Report color & brightness to MQTT broker // Report color & brightness to MQTT broker
#if MQTT_SUPPORT #if MQTT_SUPPORT
@ -563,35 +588,12 @@ void lightUpdate(bool save, bool forward) {
// Report color to WS clients (using current brightness setting) // Report color to WS clients (using current brightness setting)
#if WEB_SUPPORT #if WEB_SUPPORT
{
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["colorVisible"] = 1;
root["useColor"] = getSetting("useColor", LIGHT_USE_COLOR).toInt() == 1;
root["useWhite"] = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
root["useGamma"] = getSetting("useGamma", LIGHT_USE_GAMMA).toInt() == 1;
if (lightHasColor()) {
bool useRGB = getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1;
if (useRGB) {
root["rgb"] = lightColor(true);
root["brightness"] = lightBrightness();
} else {
root["hsv"] = lightColor(false);
}
}
JsonArray& channels = root.createNestedArray("channels");
for (unsigned char id=0; id < lightChannels(); id++) {
channels.add(lightChannel(id));
}
String output;
root.printTo(output);
wsSend(output.c_str());
}
wsSend(_lightWebSocketOnSend);
#endif #endif
#if LIGHT_SAVE_ENABLED #if LIGHT_SAVE_ENABLED
// Delay saving to EEPROM 5 seconds to avoid wearing it out unnecessarily // Delay saving to EEPROM 5 seconds to avoid wearing it out unnecessarily
if (save) colorTicker.once(LIGHT_SAVE_DELAY, _lightColorSave);
if (save) _light_save_ticker.once(LIGHT_SAVE_DELAY, _lightColorSave);
#endif #endif
}; };
@ -603,11 +605,11 @@ void lightSave() {
#endif #endif
void lightState(bool state) { void lightState(bool state) {
_lightState = state;
_light_state = state;
} }
bool lightState() { bool lightState() {
return _lightState;
return _light_state;
} }
void lightColor(const char * color, bool rgb) { void lightColor(const char * color, bool rgb) {
@ -642,28 +644,28 @@ String lightColor() {
} }
unsigned int lightChannel(unsigned char id) { unsigned int lightChannel(unsigned char id) {
if (id <= _channels.size()) {
return _channels[id].value;
if (id <= _light_channel.size()) {
return _light_channel[id].value;
} }
return 0; return 0;
} }
void lightChannel(unsigned char id, unsigned int value) { void lightChannel(unsigned char id, unsigned int value) {
if (id <= _channels.size()) {
_channels[id].value = constrain(value, 0, LIGHT_MAX_VALUE);
if (id <= _light_channel.size()) {
_light_channel[id].value = constrain(value, 0, LIGHT_MAX_VALUE);
} }
} }
unsigned int lightBrightness() { unsigned int lightBrightness() {
return _brightness;
return _light_brightness;
} }
void lightBrightness(int b) { void lightBrightness(int b) {
_brightness = constrain(b, 0, LIGHT_MAX_BRIGHTNESS);
_light_brightness = constrain(b, 0, LIGHT_MAX_BRIGHTNESS);
} }
void lightBrightnessStep(int steps) { void lightBrightnessStep(int steps) {
lightBrightness(_brightness + steps * LIGHT_STEP);
lightBrightness(_light_brightness + steps * LIGHT_STEP);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -674,13 +676,13 @@ void lightBrightnessStep(int steps) {
void _lightWebSocketOnSend(JsonObject& root) { void _lightWebSocketOnSend(JsonObject& root) {
root["colorVisible"] = 1; root["colorVisible"] = 1;
root["useColor"] = getSetting("useColor", LIGHT_USE_COLOR).toInt() == 1;
root["useWhite"] = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
root["useGamma"] = getSetting("useGamma", LIGHT_USE_GAMMA).toInt() == 1;
root["useColor"] = _light_has_color;
root["useWhite"] = _light_use_white;
root["useGamma"] = _light_use_gamma;
root["useCSS"] = getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1; root["useCSS"] = getSetting("useCSS", LIGHT_USE_CSS).toInt() == 1;
bool useRGB = getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1; bool useRGB = getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1;
root["useRGB"] = useRGB; root["useRGB"] = useRGB;
if (lightHasColor()) {
if (_light_has_color) {
if (useRGB) { if (useRGB) {
root["rgb"] = lightColor(true); root["rgb"] = lightColor(true);
root["brightness"] = lightBrightness(); root["brightness"] = lightBrightness();
@ -696,11 +698,10 @@ void _lightWebSocketOnSend(JsonObject& root) {
void _lightWebSocketOnAction(const char * action, JsonObject& data) { void _lightWebSocketOnAction(const char * action, JsonObject& data) {
if (lightHasColor()) {
if (_light_has_color) {
if (strcmp(action, "color") == 0) { if (strcmp(action, "color") == 0) {
if (data.containsKey("rgb")) { if (data.containsKey("rgb")) {
Serial.printf(data["rgb"]);
lightColor(data["rgb"], true); lightColor(data["rgb"], true);
lightUpdate(true, true); lightUpdate(true, true);
} }
@ -728,7 +729,7 @@ void _lightWebSocketOnAction(const char * action, JsonObject& data) {
void _lightAPISetup() { void _lightAPISetup() {
// API entry points (protected with apikey) // API entry points (protected with apikey)
if (lightHasColor()) {
if (_light_has_color) {
// DEPRECATE // DEPRECATE
apiRegister(MQTT_TOPIC_COLOR, MQTT_TOPIC_COLOR, apiRegister(MQTT_TOPIC_COLOR, MQTT_TOPIC_COLOR,
@ -771,7 +772,7 @@ void _lightAPISetup() {
apiRegister(MQTT_TOPIC_BRIGHTNESS, MQTT_TOPIC_BRIGHTNESS, apiRegister(MQTT_TOPIC_BRIGHTNESS, MQTT_TOPIC_BRIGHTNESS,
[](char * buffer, size_t len) { [](char * buffer, size_t len) {
snprintf_P(buffer, len, PSTR("%d"), _brightness);
snprintf_P(buffer, len, PSTR("%d"), _light_brightness);
}, },
[](const char * payload) { [](const char * payload) {
lightBrightness(atoi(payload)); lightBrightness(atoi(payload));
@ -846,6 +847,24 @@ unsigned long getIOFunc(unsigned long gpio) {
#endif #endif
void _lightConfigure() {
_light_has_color = getSetting("useColor", LIGHT_USE_COLOR).toInt() == 1;
if (_light_has_color && (_light_channel.size() < 3)) {
_light_has_color = false;
setSetting("useColor", _light_has_color);
}
_light_use_white = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
if (_light_use_white && (_light_channel.size() < 4)) {
_light_use_white = false;
setSetting("useWhite", _light_use_white);
}
_light_use_gamma = getSetting("useGamma", LIGHT_USE_GAMMA).toInt() == 1;
}
void lightSetup() { void lightSetup() {
#ifdef LIGHT_ENABLE_PIN #ifdef LIGHT_ENABLE_PIN
@ -856,7 +875,7 @@ void lightSetup() {
_my92xx = new my92xx(MY92XX_MODEL, MY92XX_CHIPS, MY92XX_DI_PIN, MY92XX_DCKI_PIN, MY92XX_COMMAND); _my92xx = new my92xx(MY92XX_MODEL, MY92XX_CHIPS, MY92XX_DI_PIN, MY92XX_DCKI_PIN, MY92XX_COMMAND);
for (unsigned char i=0; i<LIGHT_CHANNELS; i++) { for (unsigned char i=0; i<LIGHT_CHANNELS; i++) {
_channels.push_back((channel_t) {0, false, 0});
_light_channel.push_back((channel_t) {0, false, 0, 0, 0});
} }
#endif #endif
@ -864,33 +883,33 @@ void lightSetup() {
#if LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER #if LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER
#ifdef LIGHT_CH1_PIN #ifdef LIGHT_CH1_PIN
_channels.push_back((channel_t) {LIGHT_CH1_PIN, LIGHT_CH1_INVERSE, 0});
_light_channel.push_back((channel_t) {LIGHT_CH1_PIN, LIGHT_CH1_INVERSE, 0, 0, 0});
#endif #endif
#ifdef LIGHT_CH2_PIN #ifdef LIGHT_CH2_PIN
_channels.push_back((channel_t) {LIGHT_CH2_PIN, LIGHT_CH2_INVERSE, 0});
_light_channel.push_back((channel_t) {LIGHT_CH2_PIN, LIGHT_CH2_INVERSE, 0, 0, 0});
#endif #endif
#ifdef LIGHT_CH3_PIN #ifdef LIGHT_CH3_PIN
_channels.push_back((channel_t) {LIGHT_CH3_PIN, LIGHT_CH3_INVERSE, 0});
_light_channel.push_back((channel_t) {LIGHT_CH3_PIN, LIGHT_CH3_INVERSE, 0, 0, 0});
#endif #endif
#ifdef LIGHT_CH4_PIN #ifdef LIGHT_CH4_PIN
_channels.push_back((channel_t) {LIGHT_CH4_PIN, LIGHT_CH4_INVERSE, 0});
_light_channel.push_back((channel_t) {LIGHT_CH4_PIN, LIGHT_CH4_INVERSE, 0, 0, 0});
#endif #endif
#ifdef LIGHT_CH5_PIN #ifdef LIGHT_CH5_PIN
_channels.push_back((channel_t) {LIGHT_CH5_PIN, LIGHT_CH5_INVERSE, 0});
_light_channel.push_back((channel_t) {LIGHT_CH5_PIN, LIGHT_CH5_INVERSE, 0, 0, 0});
#endif #endif
uint32 pwm_duty_init[PWM_CHANNEL_NUM_MAX]; uint32 pwm_duty_init[PWM_CHANNEL_NUM_MAX];
uint32 io_info[PWM_CHANNEL_NUM_MAX][3]; uint32 io_info[PWM_CHANNEL_NUM_MAX][3];
for (unsigned int i=0; i < _channels.size(); i++) {
for (unsigned int i=0; i < _light_channel.size(); i++) {
pwm_duty_init[i] = 0; pwm_duty_init[i] = 0;
io_info[i][0] = getIOMux(_channels[i].pin);
io_info[i][1] = getIOFunc(_channels[i].pin);
io_info[i][2] = _channels[i].pin;
pinMode(_channels[i].pin, OUTPUT);
io_info[i][0] = getIOMux(_light_channel[i].pin);
io_info[i][1] = getIOFunc(_light_channel[i].pin);
io_info[i][2] = _light_channel[i].pin;
pinMode(_light_channel[i].pin, OUTPUT);
} }
pwm_init(LIGHT_MAX_PWM, pwm_duty_init, PWM_CHANNEL_NUM_MAX, io_info); pwm_init(LIGHT_MAX_PWM, pwm_duty_init, PWM_CHANNEL_NUM_MAX, io_info);
pwm_start(); pwm_start();
@ -899,17 +918,21 @@ void lightSetup() {
#endif #endif
DEBUG_MSG_P(PSTR("[LIGHT] LIGHT_PROVIDER = %d\n"), LIGHT_PROVIDER); DEBUG_MSG_P(PSTR("[LIGHT] LIGHT_PROVIDER = %d\n"), LIGHT_PROVIDER);
DEBUG_MSG_P(PSTR("[LIGHT] Number of channels: %d\n"), _channels.size());
DEBUG_MSG_P(PSTR("[LIGHT] Number of channels: %d\n"), _light_channel.size());
_lightColorRestore(); _lightColorRestore();
_lightConfigure();
#if WEB_SUPPORT #if WEB_SUPPORT
_lightAPISetup(); _lightAPISetup();
wsOnSendRegister(_lightWebSocketOnSend); wsOnSendRegister(_lightWebSocketOnSend);
wsOnActionRegister(_lightWebSocketOnAction); wsOnActionRegister(_lightWebSocketOnAction);
#if LIGHT_SAVE_ENABLED == 0
wsOnAfterParseRegister(lightSave);
#endif
wsOnAfterParseRegister([]() {
#if LIGHT_SAVE_ENABLED == 0
lightSave();
#endif
_lightConfigure();
});
#endif #endif
#if MQTT_SUPPORT #if MQTT_SUPPORT
@ -921,5 +944,4 @@ void lightSetup() {
void lightLoop(){ void lightLoop(){
} }
#endif // LIGHT_PROVIDER != LIGHT_PROVIDER_NONE #endif // LIGHT_PROVIDER != LIGHT_PROVIDER_NONE

+ 2523
- 2523
code/espurna/static/index.html.gz.h
File diff suppressed because it is too large
View File


Loading…
Cancel
Save