Browse Source

Two channel CCT (#1732)

* add CCT support for 2 channel boards

* update webinterface description

* add 2 channel CCT to homeassistant and domoticz

* remove domoticz two channel cct support.
master
copyrights 5 years ago
committed by Max Prokhorov
parent
commit
9ceca44770
3 changed files with 47 additions and 17 deletions
  1. +2
    -0
      code/espurna/homeassistant.ino
  2. +43
    -15
      code/espurna/light.ino
  3. +2
    -2
      code/html/index.html

+ 2
- 0
code/espurna/homeassistant.ino View File

@ -104,6 +104,8 @@ void _haSendSwitch(unsigned char i, JsonObject& config) {
if (lightHasColor()) { if (lightHasColor()) {
config["rgb_state_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, false); config["rgb_state_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, false);
config["rgb_command_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, true); config["rgb_command_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, true);
}
if (lightUseCCT()) {
config["color_temp_command_topic"] = mqttTopic(MQTT_TOPIC_MIRED, true); config["color_temp_command_topic"] = mqttTopic(MQTT_TOPIC_MIRED, true);
} }


+ 43
- 15
code/espurna/light.ino View File

@ -88,6 +88,11 @@ void _setRGBInputValue(unsigned char red, unsigned char green, unsigned char blu
_light_channel[2].inputValue = constrain(blue, 0, LIGHT_MAX_VALUE);; _light_channel[2].inputValue = constrain(blue, 0, LIGHT_MAX_VALUE);;
} }
void _setCCTInputValue(unsigned char warm, unsigned char cold) {
_light_channel[0].inputValue = constrain(warm, 0, LIGHT_MAX_VALUE);
_light_channel[1].inputValue = constrain(cold, 0, LIGHT_MAX_VALUE);
}
void _generateBrightness() { void _generateBrightness() {
double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS; double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS;
@ -278,7 +283,21 @@ void _fromHSV(const char * hsv) {
// https://github.com/stelgenhof/AiLight // https://github.com/stelgenhof/AiLight
void _fromKelvin(unsigned long kelvin) { void _fromKelvin(unsigned long kelvin) {
if (!_light_has_color) return;
if (!_light_has_color) {
if(!_light_use_cct) return;
_light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);
// This change the range from 153-500 to 0-347 so we get a value between 0 and 1 in the end.
double factor = ((double) _light_mireds - (double) LIGHT_COLDWHITE_MIRED)/((double) LIGHT_WARMWHITE_MIRED - (double) LIGHT_COLDWHITE_MIRED);
unsigned char warm = round(factor * LIGHT_MAX_VALUE);
unsigned char cold = round(((double) 1.0 - factor) * LIGHT_MAX_VALUE);
_setCCTInputValue(warm, cold);
return;
}
_light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS); _light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);
@ -542,12 +561,15 @@ void _lightMQTTCallback(unsigned int type, const char * topic, const char * payl
mqttSubscribe(MQTT_TOPIC_BRIGHTNESS); mqttSubscribe(MQTT_TOPIC_BRIGHTNESS);
if (_light_has_color) { if (_light_has_color) {
mqttSubscribe(MQTT_TOPIC_MIRED);
mqttSubscribe(MQTT_TOPIC_KELVIN);
mqttSubscribe(MQTT_TOPIC_COLOR_RGB); mqttSubscribe(MQTT_TOPIC_COLOR_RGB);
mqttSubscribe(MQTT_TOPIC_COLOR_HSV); mqttSubscribe(MQTT_TOPIC_COLOR_HSV);
mqttSubscribe(MQTT_TOPIC_TRANSITION); mqttSubscribe(MQTT_TOPIC_TRANSITION);
} }
if (_light_has_color || _light_use_cct) {
mqttSubscribe(MQTT_TOPIC_MIRED);
mqttSubscribe(MQTT_TOPIC_KELVIN);
}
// Group color // Group color
if (mqtt_group_color.length() > 0) mqttSubscribeRaw(mqtt_group_color.c_str()); if (mqtt_group_color.length() > 0) mqttSubscribeRaw(mqtt_group_color.c_str());
@ -700,6 +722,10 @@ bool lightHasColor() {
return _light_has_color; return _light_has_color;
} }
bool lightUseCCT() {
return _light_use_cct;
}
void _lightComms(unsigned char mask) { void _lightComms(unsigned char mask) {
// Report color & brightness to MQTT broker // Report color & brightness to MQTT broker
@ -869,16 +895,16 @@ bool _lightWebSocketOnReceive(const char * key, JsonVariant& value) {
void _lightWebSocketStatus(JsonObject& root) { void _lightWebSocketStatus(JsonObject& root) {
if (_light_has_color) { if (_light_has_color) {
if (_light_use_cct) {
root["useCCT"] = _light_use_cct;
root["mireds"] = _light_mireds;
}
if (getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1) { if (getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1) {
root["rgb"] = lightColor(true); root["rgb"] = lightColor(true);
} else { } else {
root["hsv"] = lightColor(false); root["hsv"] = lightColor(false);
} }
} }
if (_light_use_cct) {
root["useCCT"] = _light_use_cct;
root["mireds"] = _light_mireds;
}
JsonArray& channels = root.createNestedArray("channels"); JsonArray& channels = root.createNestedArray("channels");
for (unsigned char id=0; id < _light_channel.size(); id++) { for (unsigned char id=0; id < _light_channel.size(); id++) {
channels.add(lightChannel(id)); channels.add(lightChannel(id));
@ -913,13 +939,15 @@ void _lightWebSocketOnAction(uint32_t client_id, const char * action, JsonObject
lightUpdate(true, true); lightUpdate(true, true);
} }
} }
if (_light_use_cct) {
if (strcmp(action, "mireds") == 0) {
_fromMireds(data["mireds"]);
lightUpdate(true, true);
}
}
} }
if (_light_use_cct) {
if (strcmp(action, "mireds") == 0) {
_fromMireds(data["mireds"]);
lightUpdate(true, true);
}
}
if (strcmp(action, "channel") == 0) { if (strcmp(action, "channel") == 0) {
if (data.containsKey("id") && data.containsKey("value")) { if (data.containsKey("id") && data.containsKey("value")) {
@ -1135,13 +1163,13 @@ void _lightConfigure() {
} }
_light_use_white = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1; _light_use_white = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
if (_light_use_white && (_light_channel.size() < 4)) {
if (_light_use_white && (_light_channel.size() < 4) && (_light_channel.size() != 2)) {
_light_use_white = false; _light_use_white = false;
setSetting("useWhite", _light_use_white); setSetting("useWhite", _light_use_white);
} }
_light_use_cct = getSetting("useCCT", LIGHT_USE_CCT).toInt() == 1; _light_use_cct = getSetting("useCCT", LIGHT_USE_CCT).toInt() == 1;
if (_light_use_cct && ((_light_channel.size() < 5) || !_light_use_white)) {
if (_light_use_cct && (((_light_channel.size() < 5) && (_light_channel.size() != 2)) || !_light_use_white)) {
_light_use_cct = false; _light_use_cct = false;
setSetting("useCCT", _light_use_cct); setSetting("useCCT", _light_use_cct);
} }


+ 2
- 2
code/html/index.html View File

@ -508,7 +508,7 @@
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useWhite" action="reload" tabindex="9" /></div> <div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useWhite" action="reload" tabindex="9" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div> <div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div> <div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Use forth dimmable channel as (cold) white light calculated out of the RGB values.<br />Will only work if the device has at least 4 dimmable channels.<br />Enabling this will render useless the "Channel 4" slider in the status page.<br />Reload the page to update the web interface.</div>
<div class="pure-u-1 pure-u-lg-3-4 hint">For 2 channels warm white and cold white lights or color lights to use forth dimmable channel as (cold) white light calculated out of the RGB values.<br />Will only work if the device has at least 4 dimmable channels.<br />Enabling this will render useless the "Channel 4" slider in the status page.<br />Reload the page to update the web interface.</div>
</div> </div>
<div class="pure-g"> <div class="pure-g">
@ -516,7 +516,7 @@
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useCCT" action="reload" tabindex="10" /></div> <div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useCCT" action="reload" tabindex="10" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div> <div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div> <div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Use fifth dimmable channel as warm white light and the forth dimmable channel as cold white.<br />Will only work if the device has at least 5 dimmable channels and "white channel" above is also ON.<br />Enabling this will render useless the "Channel 5" slider in the status page.<br />Reload the page to update the web interface.</div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Use a dimmable channel as warm white light and another dimmable channel as cold white light.<br />On devices with two dimmable channels the first use used for warm white light and the second for cold white light.<br />On color lights the fifth use used for warm white light and the fourth for cold white light.<br />Will only work if the device has exactly 2 dimmable channels or at least 5 dimmable channels and "white channel" above is also ON.<br />Enabling this will render useless the "Channel 5" slider in the status page.<br />Reload the page to update the web interface.</div>
</div> </div>
<div class="pure-g"> <div class="pure-g">


Loading…
Cancel
Save