v5.12.0h - Add HSBColor and Channel commands

5.12.0h
 * Add PWM status to command State if PWM enabled (#2203)
 * Add
command HSBColor Hue,Sat,Bri (#1642, #2203)
 * Add command Channel
0..100 to control dimmer value for individual color channels (#2111,
#2203)
This commit is contained in:
Theo Arends 2018-03-20 16:28:18 +01:00
parent 2ba4d6fb47
commit 2c4b8a4a3b
5 changed files with 86 additions and 13 deletions

View File

@ -1,6 +1,9 @@
/* 5.12.0h
* Add support for Software Serial bridge using commands SerialDelimiter, SBaudrate and SSerialSend. Supports 8N1 and text only (#2190)
* Add support for Hardware Serial bridge using commands SerialDelimiter, Baudrate and SerialSend. Supports 8N1 and text only (#2182)
* Add PWM status to command State if PWM enabled (#2203)
* Add command HSBColor Hue,Sat,Bri (#1642, #2203)
* Add command Channel 0..100 to control dimmer value for individual color channels (#2111, #2203)
*
* 5.12.0f
* Add compile time support for WS2812 BRG and RBG led configurations to be defined in user_config.h (#1690)

View File

@ -63,6 +63,7 @@
#define D_JSON_GATEWAY "Gateway"
#define D_JSON_HEAPSIZE "Heap"
#define D_JSON_HIGH "High"
#define D_JSON_HSBCOLOR "HSBColor"
#define D_JSON_HUMIDITY "Humidity"
#define D_JSON_I2CSCAN_DEVICES_FOUND_AT "Device(s) found at"
#define D_JSON_I2CSCAN_UNKNOWN_ERROR_AT "Unknown error at"
@ -247,9 +248,11 @@
#define D_CMND_EXCEPTION "Exception"
// Commands xdrv_01_light.ino
#define D_CMND_CHANNEL "Channel"
#define D_CMND_COLOR "Color"
#define D_CMND_COLORTEMPERATURE "CT"
#define D_CMND_DIMMER "Dimmer"
#define D_CMND_HSBCOLOR "HSBColor"
#define D_CMND_LED "Led"
#define D_CMND_LEDTABLE "LedTable"
#define D_CMND_FADE "Fade"
@ -483,4 +486,4 @@ const char S_INFORMATION[] PROGMEM = D_INFORMATION;
const char S_RESTART[] PROGMEM = D_RESTART;
#endif // USE_WEBSERVER
#endif // _I18N_H_
#endif // _I18N_H_

View File

@ -737,15 +737,9 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
Settings.pwm_value[index -1] = payload;
analogWrite(pin[GPIO_PWM1 + index -1], bitRead(pwm_inverted, index -1) ? Settings.pwm_range - payload : payload);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PWM "\":{"));
bool first = true;
for (byte i = 0; i < MAX_PWMS; i++) {
if (pin[GPIO_PWM1 + i] < 99) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]);
first = false;
}
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"),mqtt_data);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{"));
MqttShowPWMState(); // Render the PWM status to MQTT
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
}
else if (CMND_PWMFREQUENCY == command_code) {
if ((1 == payload) || ((payload >= 100) && (payload <= 4000))) {
@ -1327,6 +1321,19 @@ void PublishStatus(uint8_t payload)
}
void MqttShowPWMState()
{
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data);
bool first = true;
for (byte i = 0; i < MAX_PWMS; i++) {
if (pin[GPIO_PWM1 + i] < 99) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]);
first = false;
}
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
}
void MqttShowState()
{
char stemp1[33];
@ -1345,6 +1352,11 @@ void MqttShowState()
}
}
if (pwm_present) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
MqttShowPWMState();
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"),
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str());
}

View File

@ -223,7 +223,7 @@ char* Unescape(char* buffer, uint16_t* size)
case 'f': che = '\f'; break; // 0C Formfeed
case 'n': che = '\n'; break; // 0A Linefeed (Newline)
case 'r': che = '\r'; break; // 0D Carriage return
// case 's': che = ' '; break; // 20 Space
case 's': che = ' '; break; // 20 Space
case 't': che = '\t'; break; // 09 Horizontal tab
case 'v': che = '\v'; break; // 0B Vertical tab
// case '?': che = '\?'; break; // 3F Question mark

View File

@ -55,10 +55,12 @@
enum LightCommands {
CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE,
CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION, CMND_WIDTH, CMND_UNDOCA };
CMND_PIXELS, CMND_ROTATION, CMND_SCHEME, CMND_SPEED, CMND_WAKEUP, CMND_WAKEUPDURATION,
CMND_WIDTH, CMND_CHANNEL, CMND_HSBCOLOR, CMND_UNDOCA };
const char kLightCommands[] PROGMEM =
D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LED "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|"
D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WIDTH "|UNDOCA" ;
D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|"
D_CMND_WIDTH "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ;
struct LRgbColor {
uint8_t R, G, B;
@ -535,6 +537,8 @@ void LightState(uint8_t append)
{
char scolor[25];
char scommand[33];
float hsb[3];
int16_t h,s,b;
if (append) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
@ -546,6 +550,15 @@ void LightState(uint8_t append)
mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer);
if (light_subtype > LST_SINGLE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
// Add status for HSB
LightGetHsb(&hsb[0],&hsb[1],&hsb[2]);
// Scale these percentages up to the numbers expected byt he client
h = round(hsb[0] * 360);
s = round(hsb[1] * 100);
b = round(hsb[2] * 100);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), mqtt_data, h,s,b);
}
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp());
@ -1053,6 +1066,48 @@ boolean LightCommand()
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor);
}
}
else if ((CMND_CHANNEL == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= light_subtype ) ) {
// Set "Channel" directly - this allows Color and Direct PWM control to coexist
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
uint8_t level = XdrvMailbox.payload;
light_current_color[XdrvMailbox.index-1] = round(level * 2.55);
LightSetColor();
coldim = true;
}
snprintf_P(scolor, 25, PSTR("%d"), round(light_current_color[XdrvMailbox.index -1] / 2.55));
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor);
}
else if ((CMND_HSBCOLOR == command_code) && ( light_subtype >= LST_RGB)) {
// Implement method to "direct set" color by HSB (HSB is passed comma separated, 0<H<360 0<S<100 0<B<100 )
uint16_t HSB[3];
bool validHSB = true;
for (int i = 0; i < 3; i++) {
char *substr;
if (0 == i) {
substr = strtok(XdrvMailbox.data, ",");
} else {
substr = strtok(NULL, ",");
}
if (substr != NULL) {
HSB[i] = atoi(substr);
} else {
validHSB = false;
}
}
if (validHSB) {
// Translate to fractional elements as required by LightHsbToRgb
// Keep the results <=1 in the event someone passes something
// out of range.
LightSetHsb(( (HSB[0]>360) ? (HSB[0] % 360) : HSB[0] ) /360.0,
( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0,
( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0,
0);
} else {
LightState(0);
}
}
#ifdef USE_WS2812 // ***********************************************************************
else if ((CMND_LED == command_code) && (LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) {
if (XdrvMailbox.data_len > 0) {