Merge branch 'development' into release-7.1

This commit is contained in:
Theo Arends 2019-11-25 15:27:37 +01:00
commit 220c9ac150
6 changed files with 162 additions and 127 deletions

View File

@ -114,9 +114,8 @@ build_flags = -D NDEBUG
-Wl,-Map,firmware.map -Wl,-Map,firmware.map
[core_2_6_1] [core_2_6_1]
; *** Esp8266 core for Arduino version 2.6.1 (for Windows, most Linux variants and Mac) ; *** Esp8266 core for Arduino version 2.6.1
; *** custom setup until the core 2.6.1 version is official released from PlatformIO crew platform = https://github.com/platformio/platform-espressif8266.git#develop
platform = https://github.com/Jason2866/platform-espressif8266.git#core_2_6_1
build_flags = ${esp82xx_defaults.build_flags} build_flags = ${esp82xx_defaults.build_flags}
-Wl,-Teagle.flash.1m.ld -Wl,-Teagle.flash.1m.ld
-DBEARSSL_SSL_BASIC -DBEARSSL_SSL_BASIC

View File

@ -218,7 +218,8 @@
// (POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON) // (POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON)
#define APP_BLINKTIME 10 // [BlinkTime] Time in 0.1 Sec to blink/toggle power for relay 1 #define APP_BLINKTIME 10 // [BlinkTime] Time in 0.1 Sec to blink/toggle power for relay 1
#define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000) #define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000)
#define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec) #define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec),
#define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering
#define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time #define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time
#define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message
@ -289,7 +290,8 @@
// -- MQTT - TLS - AWS IoT ------------------------ // -- MQTT - TLS - AWS IoT ------------------------
// Using TLS starting with version v6.5.0.16 compilation will only work using Core 2.4.2 and 2.5.2. No longer supported: 2.3.0 // Using TLS starting with version v6.5.0.16 compilation will only work using Core 2.4.2 and 2.5.2. No longer supported: 2.3.0
//#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) //#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake)
// #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use (+2.2k code, +1.9k mem during connection handshake) // #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake)
// This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates
// #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) // #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem)
// #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem) // #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem)
// Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp' // Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp'

View File

@ -152,21 +152,13 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
"}" "}"
#endif // USE_SCRIPT_WEB_DISPLAY #endif // USE_SCRIPT_WEB_DISPLAY
#ifdef USE_JAVASCRIPT_ES6
"lb=(v,p)=>la(`&${v}=${p}`);"
"lc=(v,i,p)=>la(`&${v}${i}=${p}`);"
#else
"function lb(v,p){"
"la('&'+v+'='+p);"
"}"
"function lc(v,i,p){" "function lc(v,i,p){"
"if(v=='h'||v=='d'){" // Hue or Brightness changed so change Saturation colors too
"var sl=eb('sl4').value;"
"eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))';"
"}"
"la('&'+v+i+'='+p);" "la('&'+v+i+'='+p);"
"}" "}"
#endif // USE_JAVASCRIPT_ES6
"function ld(v,p){"
"eb('s').style.background='linear-gradient(to right,#fff,hsl('+p+',100%%,50%%))';"
"la('&'+v+'='+p);"
"}"
"wl(la);"; "wl(la);";
@ -379,12 +371,9 @@ const char HTTP_HEAD_STYLE3[] PROGMEM =
"<h2>%s</h2>"; "<h2>%s</h2>";
const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM = const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM =
"<div id='%s' class='r' style='background-image:linear-gradient(to right,%s,%s);'><input type='range' min='%d' max='%d' value='%d' onchange='lb(\"%c\",value)'></div>"; "<div id='%s' class='r' style='background-image:linear-gradient(to right,%s,%s);'>"
const char HTTP_MSG_SLIDER_HUE[] PROGMEM = "<input id='sl%d' type='range' min='%d' max='%d' value='%d' onchange='lc(\"%c\",%d,value)'>"
"<div class='r' style='background-image:linear-gradient(to right,#800,#f00 5%%,#ff0 20%%,#0f0 35%%,#0ff 50%%,#00f 65%%,#f0f 80%%,#f00 95%%,#800);'>" "</div>";
"<input type='range' min='1' max='359' value='%d' onchange='ld(\"u\",value)'></div>";
const char HTTP_MSG_SLIDER_CHANNEL[] PROGMEM =
"<div class='r' style='background-image:linear-gradient(to right,#000,%s);'><input type='range' min='1' max='100' value='%d' onchange='lc(\"d\",%d,value)'></div>";
const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
"<div><span class='p'>" D_CLOSE "</span><span class='q'>" D_OPEN "</span></div>" "<div><span class='p'>" D_CLOSE "</span><span class='q'>" D_OPEN "</span></div>"
"<div><input type='range' min='0' max='100' value='%d' onchange='lc(\"u\",%d,value)'></div>"; "<div><input type='range' min='0' max='100' value='%d' onchange='lc(\"u\",%d,value)'></div>";
@ -962,8 +951,6 @@ void HandleWifiLogin(void)
WSContentStop(); WSContentStop();
} }
void HandleRoot(void) void HandleRoot(void)
{ {
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page. if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page.
@ -1012,26 +999,64 @@ void HandleRoot(void)
uint8_t light_subtype = light_type &7; uint8_t light_subtype = light_type &7;
if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
// Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp));
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "a", "#fff", "#ff0", 153, 500, LightGetColorTemp(), 't'); // White to Yellow WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Cold Warm
"a", // a - Unique HTML id
"#fff", "#ff0", // White to Yellow
1, // sl1
153, 500, // Range color temperature
LightGetColorTemp(),
't', 0); // t0 - Value id releated to lc("t0", value) and WebGetArg("t0", tmp, sizeof(tmp));
} }
if (light_subtype > 2) { if (light_subtype > 2) {
uint16_t hue; uint16_t hue;
uint8_t sat; uint8_t sat;
uint8_t bri; LightGetHSB(&hue, &sat, nullptr);
LightGetHSB(&hue, &sat, &bri);
WSContentSend_P(HTTP_MSG_SLIDER_HUE, hue); // Hue WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Hue
snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); "b", // b - Unique HTML id
// Saturation "s" related to eb('s').style.background='linear-gradient(to right,#fff,hsl('+p+',100%%,50%%))'; "#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", // Hue colors
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "s", "#fff", stemp, 1, 100, changeUIntScale(sat, 0, 255, 0, 100), 'n'); 2, // sl2 - Unique range HTML id - Used as source for Saturation end color
1, 359, // Range valid Hue
hue,
'h', 0); // h0 - Value id
uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255);
char scolor[8];
snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); // Saturation start color from Black to White
uint8_t red, green, blue;
LightHsToRgb(hue, 255, &red, &green, &blue);
snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); // Saturation end color
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Saturation
"s", // s - Unique HTML id related to eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))';
scolor, stemp, // Brightness to max current color
3, // sl3 - Unique range HTML id - Not used
1, 100, // Range 1 to 100%
changeUIntScale(sat, 0, 255, 0, 100),
'n', 0); // n0 - Value id
} }
// Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp));
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "b", "#000", "#fff", 1, 100, Settings.light_dimmer, 'd'); // Black to White WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Brightness - Black to White
"c", // c - Unique HTML id
"#000", "#fff", // Black to White
4, // sl4 - Unique range HTML id - Used as source for Saturation begin color
1, 100, // Range 1 to 100%
Settings.light_dimmer,
'd', 0); // d0 - Value id is related to lc("d0", value) and WebGetArg("d0", tmp, sizeof(tmp));
} else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM } else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM
uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype;
stemp[0] = 'd'; stemp[1] = '0'; stemp[2] = '\0'; // d0
for (uint32_t i = 0; i < pwm_channels; i++) { for (uint32_t i = 0; i < pwm_channels; i++) {
uint8_t index = (pwm_channels < 3) ? i +3 : i; stemp[1]++; // d1 to d5 - Make unique ids
WSContentSend_P(HTTP_MSG_SLIDER_CHANNEL, "#fff", changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), i+1); // Dark to Light
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Channel brightness - Black to White
stemp, // d1 to d5 - Unique HTML id
"#000", "#fff", // Black to White
i+1, // sl1 to sl5 - Unique range HTML id - Not used
1, 100, // Range 1 to 100%
changeUIntScale(Settings.light_color[i], 0, 255, 0, 100),
'd', i+1); // d1 to d5 - Value id
} }
} // Settings.flag3.pwm_multi_channels } // Settings.flag3.pwm_multi_channels
} }
@ -1136,7 +1161,7 @@ bool HandleRootStatusRefresh(void)
} }
#endif // USE_SONOFF_IFAN #endif // USE_SONOFF_IFAN
} }
WebGetArg("d", tmp, sizeof(tmp)); // 0 - 100 Dimmer value WebGetArg("d0", tmp, sizeof(tmp)); // 0 - 100 Dimmer value
if (strlen(tmp)) { if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI); ExecuteWebCommand(svalue, SRC_WEBGUI);
@ -1150,17 +1175,17 @@ bool HandleRootStatusRefresh(void)
ExecuteWebCommand(svalue, SRC_WEBGUI); ExecuteWebCommand(svalue, SRC_WEBGUI);
} }
} }
WebGetArg("t", tmp, sizeof(tmp)); // 153 - 500 Color temperature WebGetArg("t0", tmp, sizeof(tmp)); // 153 - 500 Color temperature
if (strlen(tmp)) { if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI); ExecuteWebCommand(svalue, SRC_WEBGUI);
} }
WebGetArg("u", tmp, sizeof(tmp)); // 0 - 359 Hue value WebGetArg("h0", tmp, sizeof(tmp)); // 0 - 359 Hue value
if (strlen(tmp)) { if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI); ExecuteWebCommand(svalue, SRC_WEBGUI);
} }
WebGetArg("n", tmp, sizeof(tmp)); // 0 - 99 Saturation value WebGetArg("n0", tmp, sizeof(tmp)); // 0 - 99 Saturation value
if (strlen(tmp)) { if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI); ExecuteWebCommand(svalue, SRC_WEBGUI);

View File

@ -1173,7 +1173,7 @@ void LightInit(void)
light_controller.setCTRGBLinked(ct_rgb_linked); light_controller.setCTRGBLinked(ct_rgb_linked);
} }
if ((LST_SINGLE < Light.subtype) && Light.pwm_multi_channels) { if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) {
// we treat each PWM channel as an independant one, hence we switch to // we treat each PWM channel as an independant one, hence we switch to
light_controller.setPWMMultiChannel(true); light_controller.setPWMMultiChannel(true);
Light.device = devices_present - Light.subtype + 1; // adjust if we also have relays Light.device = devices_present - Light.subtype + 1; // adjust if we also have relays
@ -1257,6 +1257,10 @@ uint32_t LightGetHSB(uint16_t *hue,uint8_t *sat, uint8_t *bri) {
light_state.getHSB(hue, sat, bri); light_state.getHSB(hue, sat, bri);
} }
void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) {
light_state.HsToRgb(hue, sat, r_r, r_g, r_b);
}
// If SetOption68 is set, get the brightness for a specific device // If SetOption68 is set, get the brightness for a specific device
uint8_t LightGetBri(uint8_t device) { uint8_t LightGetBri(uint8_t device) {
uint8_t bri = 254; // default value if relay uint8_t bri = 254; // default value if relay
@ -1363,6 +1367,7 @@ void LightState(uint8_t append)
{ {
char scolor[LIGHT_COLOR_SIZE]; char scolor[LIGHT_COLOR_SIZE];
char scommand[33]; char scommand[33];
bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); // there are 2 power and dimmers for RGB and White
if (append) { if (append) {
ResponseAppend_P(PSTR(",")); ResponseAppend_P(PSTR(","));
@ -1370,8 +1375,18 @@ void LightState(uint8_t append)
Response_P(PSTR("{")); Response_P(PSTR("{"));
} }
if (!Light.pwm_multi_channels) { if (!Light.pwm_multi_channels) {
GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1 if (unlinked) {
ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power), light_state.getDimmer()); // RGB and W are unlinked, we display the second Power/Dimmer
ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"
",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"),
Light.device, GetStateText(Light.power & 1), Light.device, light_state.getDimmer(1),
Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), Light.device + 1, light_state.getDimmer(2));
} else {
GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1),
light_state.getDimmer());
}
if (Light.subtype > LST_SINGLE) { if (Light.subtype > LST_SINGLE) {
ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor));
@ -1423,8 +1438,7 @@ void LightState(uint8_t append)
} }
} }
void LightPreparePower(void) void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = only CT, 3 = both RGB and CT
{
#ifdef DEBUG_LIGHT #ifdef DEBUG_LIGHT
AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power);
#endif #endif
@ -1462,20 +1476,24 @@ void LightPreparePower(void)
} }
} else { } else {
// RGB // RGB
if (light_state.getBriRGB() && !(Light.power & 1)) { if (channels & 1) {
if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes if (light_state.getBriRGB() && !(Light.power & 1)) {
ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT);
}
} else if (!light_state.getBriRGB() && (Light.power & 1)) {
ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT);
} }
} else if (!light_state.getBri() && (Light.power & 1)) {
ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT);
} }
// White CT // White CT
if (light_state.getBriCT() && !(Light.power & 2)) { if (channels & 2) {
if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes if (light_state.getBriCT() && !(Light.power & 2)) {
ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT);
}
} else if (!light_state.getBriCT() && (Light.power & 2)) {
ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT);
} }
} else if (!light_state.getBri() && (Light.power & 2)) {
ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT);
} }
} }
#ifdef USE_DOMOTICZ #ifdef USE_DOMOTICZ
@ -1594,11 +1612,11 @@ void LightAnimate(void)
sleep = Settings.sleep; sleep = Settings.sleep;
} }
} else { } else {
#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP if (Settings.sleep > PWM_MAX_SLEEP) {
sleep = (LS_POWER == Settings.light_scheme) && (!Light.fade_running) ? Settings.sleep : 0; // If no animation then use sleep as is sleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth
#else } else {
sleep = 0; sleep = Settings.sleep; // or keep the current sleep if it's lower than 50
#endif // PWM_LIGHTSCHEME0_IGNORE_SLEEP }
switch (Settings.light_scheme) { switch (Settings.light_scheme) {
case LS_POWER: case LS_POWER:
light_controller.calcLevels(Light.new_color); light_controller.calcLevels(Light.new_color);
@ -2071,7 +2089,7 @@ void CmndSupportColor(void)
ResponseCmndIdxChar(scolor); ResponseCmndIdxChar(scolor);
} }
if (coldim) { if (coldim) {
LightPreparePower(); LightPreparePower(); // no parameter, recalculate Power for all channels
} }
} }
@ -2102,11 +2120,12 @@ void CmndWhite(void)
void CmndChannel(void) void CmndChannel(void)
{ {
if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) {
bool coldim = false; uint32_t light_index = XdrvMailbox.index - Light.device;
power_t coldim = 0; // bit flag to update
// Handle +/- special command // Handle +/- special command
if (1 == XdrvMailbox.data_len) { if (1 == XdrvMailbox.data_len) {
uint8_t channel = changeUIntScale(Light.current_color[XdrvMailbox.index - Light.device],0,255,0,100); uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100);
if ('+' == XdrvMailbox.data[0]) { if ('+' == XdrvMailbox.data[0]) {
XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10;
} else if ('-' == XdrvMailbox.data[0]) { } else if ('-' == XdrvMailbox.data[0]) {
@ -2116,23 +2135,28 @@ void CmndChannel(void)
// Set "Channel" directly - this allows Color and Direct PWM control to coexist // Set "Channel" directly - this allows Color and Direct PWM control to coexist
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
Light.current_color[XdrvMailbox.index - Light.device] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255);
if (Light.pwm_multi_channels) { if (Light.pwm_multi_channels) {
// if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes coldim = 1 << light_index; // change the specified channel
// Light.power = Light.power | (1 << (XdrvMailbox.index - Light.device)); // ask to turn on channel
// }
} else { } else {
// if we change channels 1,2,3 then turn off CT mode (unless non-linked) if (light_controller.isCTRGBLinked()) {
if ((XdrvMailbox.index <= 3) && (light_controller.isCTRGBLinked())) { // if we change channels 1,2,3 then turn off CT mode (unless non-linked)
Light.current_color[3] = Light.current_color[4] = 0; if ((light_index < 3) && (light_controller.isCTRGBLinked())) {
Light.current_color[3] = Light.current_color[4] = 0;
} else {
Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0;
}
coldim = 1;
} else {
if (light_index < 3) { coldim = 1; } // RGB
else { coldim = 2; } // CT
} }
} }
light_controller.changeChannels(Light.current_color); light_controller.changeChannels(Light.current_color);
coldim = true;
} }
ResponseCmndIdxNumber(changeUIntScale(Light.current_color[XdrvMailbox.index -1],0,255,0,100)); ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100));
if (coldim) { if (coldim) {
LightPreparePower(); LightPreparePower(coldim);
} }
} }
} }
@ -2179,7 +2203,7 @@ void CmndHsbColor(void)
} }
if (validHSB) { if (validHSB) {
light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); light_controller.changeHSB(HSB[0], HSB[1], HSB[2]);
LightPreparePower(); LightPreparePower(1);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR));
} }
} else { } else {
@ -2242,7 +2266,7 @@ void CmndColorTemperature(void)
} }
if ((XdrvMailbox.payload >= 153) && (XdrvMailbox.payload <= 500)) { // https://developers.meethue.com/documentation/core-concepts if ((XdrvMailbox.payload >= 153) && (XdrvMailbox.payload <= 500)) { // https://developers.meethue.com/documentation/core-concepts
light_controller.changeCTB(XdrvMailbox.payload, light_state.getBri()); light_controller.changeCTB(XdrvMailbox.payload, light_state.getBri());
LightPreparePower(); LightPreparePower(2);
} else { } else {
ResponseCmndNumber(ct); ResponseCmndNumber(ct);
} }
@ -2272,17 +2296,19 @@ void CmndDimmer(void)
if (light_controller.isCTRGBLinked()) { if (light_controller.isCTRGBLinked()) {
// normal state, linked RGB and CW // normal state, linked RGB and CW
light_controller.changeDimmer(XdrvMailbox.payload); light_controller.changeDimmer(XdrvMailbox.payload);
LightPreparePower();
} else { } else {
if (0 != XdrvMailbox.index) { if (0 != XdrvMailbox.index) {
light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index);
LightPreparePower(1 << (XdrvMailbox.index - 1)); // recalculate only the target dimmer
} else { } else {
// change both dimmers // change both dimmers
light_controller.changeDimmer(XdrvMailbox.payload, 1); light_controller.changeDimmer(XdrvMailbox.payload, 1);
light_controller.changeDimmer(XdrvMailbox.payload, 2); light_controller.changeDimmer(XdrvMailbox.payload, 2);
LightPreparePower();
} }
} }
Light.update = true; Light.update = true;
LightPreparePower();
} else { } else {
ResponseCmndNumber(dimmer); ResponseCmndNumber(dimmer);
} }

View File

@ -53,7 +53,11 @@ void LM75ADDetect(void)
{ {
for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) {
lm75ad_address = lm75ad_addresses[i]; lm75ad_address = lm75ad_addresses[i];
if (I2cActive(lm75ad_address)) { continue; } if (I2cActive(lm75ad_address)) {
continue; }
if (!I2cSetDevice(lm75ad_address)) {
break; // do not make the next step without a confirmed device on the bus
}
uint16_t buffer; uint16_t buffer;
if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) {
if (buffer == 0x4B00) { if (buffer == 0x4B00) {

View File

@ -31,58 +31,37 @@
#define MLX90614_TOBJ1 0x07 #define MLX90614_TOBJ1 0x07
#define MLX90614_TOBJ2 0x08 #define MLX90614_TOBJ2 0x08
bool mlx_ready = false; struct {
float obj_temp; union {
float amb_temp; uint16_t value;
uint32_t i2c_buf;
};
float obj_temp;
float amb_temp;
bool ready = false;
} mlx90614;
void MLX90614_Init(void) void MLX90614_Init(void)
{ {
if (!I2cSetDevice(I2_ADR_IRT)) { return; } if (!I2cSetDevice(I2_ADR_IRT)) { return; }
I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); I2cSetActiveFound(I2_ADR_IRT, "MLX90614");
mlx_ready = true; mlx90614.ready = true;
// not needed on tasmota
//Wire.begin();
//delay(500);
}
// return ir temp
// 0 = chip, 1 = object temperature
// * 0.02 - 273.15
uint16_t read_irtmp(uint8_t flag)
{
Wire.beginTransmission(I2_ADR_IRT);
if (!flag) {
Wire.write(MLX90614_TA);
} else {
Wire.write(MLX90614_TOBJ1);
}
Wire.endTransmission(false);
Wire.requestFrom(I2_ADR_IRT, 3);
uint8_t low = Wire.read();
uint8_t hig = Wire.read();
Wire.read();
uint16_t val = ((uint16_t)hig << 8) | low;
return val;
} }
void MLX90614_Every_Second(void) void MLX90614_Every_Second(void)
{ {
uint16_t uval = read_irtmp(1); mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1);
if (uval & 0x8000) { if (mlx90614.value & 0x8000) {
obj_temp = -999; mlx90614.obj_temp = -999;
} else { } else {
obj_temp = ((float)uval * 0.02) - 273.15; mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15;
} }
uval = read_irtmp(0); mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA);
if (uval & 0x8000) { if (mlx90614.value & 0x8000) {
amb_temp = -999; mlx90614.amb_temp = -999;
} else { } else {
amb_temp = ((float)uval * 0.02) - 273.15; mlx90614.amb_temp = ((float)mlx90614.value * 0.02) - 273.15;
} }
} }
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
@ -94,9 +73,9 @@ void MLX90614_Every_Second(void)
void MLX90614_Show(uint8_t json) void MLX90614_Show(uint8_t json)
{ {
char obj_tstr[16]; char obj_tstr[16];
dtostrfd(obj_temp, Settings.flag2.temperature_resolution, obj_tstr); dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr);
char amb_tstr[16]; char amb_tstr[16];
dtostrfd(amb_temp, Settings.flag2.temperature_resolution, amb_tstr); dtostrfd(mlx90614.amb_temp, Settings.flag2.temperature_resolution, amb_tstr);
if (json) { if (json) {
ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr); ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr);
@ -120,7 +99,7 @@ bool Xsns46(byte function)
if (FUNC_INIT == function) { if (FUNC_INIT == function) {
MLX90614_Init(); MLX90614_Init();
} }
else if (mlx_ready) { else if (mlx90614.ready) {
switch (function) { switch (function) {
case FUNC_EVERY_SECOND: case FUNC_EVERY_SECOND:
MLX90614_Every_Second(); MLX90614_Every_Second();