diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7c3307cdb..ba41d1f6d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -11,6 +11,7 @@ * Add WebUI for multiple, independent PWM channels * Remove default DS18B20 driver and only support define DS18x20 (#6647) * Add support for PMS3003 dust particle sensor + * Change Sonoff L1 support by adding define USE_SONOFF_L1 * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index dd03de4b6..0e25ea3ed 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -315,7 +315,7 @@ #define USE_TUYA_MCU // Add support for Tuya Serial MCU #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) -#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) +#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer (+2k code) #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_BUZZER // Add support for a buzzer (+0k6 code) #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) @@ -330,6 +330,7 @@ #define USE_MY92X1 // Add support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) #define USE_SM2135 // Add support for SM2135 RGBCW led control as used in Action LSC (+0k6 code) +#define USE_SONOFF_L1 // Add support for Sonoff L1 led control // -- Counter input ------------------------------- #define USE_COUNTER // Enable inputs as counter (+0k8 code) diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 6ac4a6ac1..b9aaf1fb3 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -86,6 +86,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_DISCOVERY // Disable mDNS (+8k code or +23.5k code with core 2_5_x, +0.3k mem) // -- Optional modules ------------------------- +//#define ROTARY_V1 // Add support for MI Desk Lamp #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_TUYA_MCU // Add support for Tuya Serial MCU #ifndef TUYA_DIMMER_ID @@ -93,7 +94,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif //#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code) -//#define ROTARY_V1 // Add support for MI Desk Lamp #define USE_COUNTER // Enable counters #undef USE_ADC_VCC // Add Analog input on selected devices @@ -150,8 +150,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) -//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) -//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger @@ -167,6 +165,8 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DDSU666 // Add support for Chint DDSU666 Modbus energy monitor (+0k6 code) +//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) +//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #define USE_MAX31855 // Add support for MAX31855 K-Type thermocouple sensor using softSPI @@ -419,7 +419,6 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_WS2812 // Disable WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // -#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 76f5cb8d4..c5a8a4652 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -763,7 +763,7 @@ const uint8_t kModuleNiceList[] PROGMEM = { SONOFF_T13, SONOFF_LED, // Sonoff Light Devices SONOFF_BN, -#ifdef USE_PS_16_DZ +#ifdef USE_SONOFF_L1 SONOFF_L1, #endif SONOFF_B1, // Sonoff Light Bulbs diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index cf0740e72..9ba69feee 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -471,7 +471,9 @@ void GetFeatures(void) #ifdef USE_SONOFF_RF feature5 |= 0x00002000; // xdrv_06_snfbridge.ino #endif -// feature5 |= 0x00004000; +#ifdef USE_SONOFF_L1 + feature5 |= 0x00004000; +#endif // feature5 |= 0x00008000; // feature5 |= 0x00010000; diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 67771aa48..c9fdff640 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -1,5 +1,5 @@ /* - xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer and Sonoff L1 support for Sonoff-Tasmota + xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer support for Sonoff-Tasmota Copyright (C) 2019 Joel Stein and Theo Arends @@ -20,64 +20,46 @@ #ifdef USE_LIGHT #ifdef USE_PS_16_DZ /*********************************************************************************************\ - * PS 16 DZ Serial Dimmer and Sonoff L1 + * PS 16 DZ Serial Dimmer \*********************************************************************************************/ #define XDRV_19 19 -#define PS16DZ_BUFFER_SIZE 140 - -#define PS16DZ_SONOFF_L1_MODE_COLORFUL 1 // Colorful (static color) -#define PS16DZ_SONOFF_L1_MODE_COLORFUL_GRADIENT 2 // Colorful Gradient -#define PS16DZ_SONOFF_L1_MODE_COLORFUL_BREATH 3 // Colorful Breath -#define PS16DZ_SONOFF_L1_MODE_DIY_GRADIENT 4 // DIY Gradient (fade in and out) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_DIY_PULSE 5 // DIY Pulse (faster fade in and out) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_DIY_BREATH 6 // DIY Breath (toggle on/off) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_DIY_STROBE 7 // DIY Strobe (faster toggle on/off) [Speed 1- 100, color] -#define PS16DZ_SONOFF_L1_MODE_RGB_GRADIENT 8 // RGB Gradient -#define PS16DZ_SONOFF_L1_MODE_RGB_PULSE 9 // RGB Pulse -#define PS16DZ_SONOFF_L1_MODE_RGB_BREATH 10 // RGB Breath -#define PS16DZ_SONOFF_L1_MODE_RGB_STROBE 11 // RGB strobe -#define PS16DZ_SONOFF_L1_MODE_SYNC_TO_MUSIC 12 // Sync to music [Speed 1- 100, sensitivity 1 - 10] +#define PS16DZ_BUFFER_SIZE 80 #include TasmotaSerial *PS16DZSerial = nullptr; struct PS16DZ { - char *tx_buffer = nullptr; // Serial transmit buffer char *rx_buffer = nullptr; // Serial receive buffer int byte_counter = 0; - uint8_t color[3]; // Most recent serial sent/received values uint8_t dimmer = 0; - bool supports_color = false; - bool switch_state = false; } Ps16dz; /*********************************************************************************************\ * Internal Functions \*********************************************************************************************/ -void PS16DZSerialSendTxBuffer(void) +void PS16DZSerialSend(const char *tx_buffer) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), Ps16dz.tx_buffer); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Send %s"), tx_buffer); - PS16DZSerial->print(Ps16dz.tx_buffer); + PS16DZSerial->print(tx_buffer); PS16DZSerial->write(0x1B); PS16DZSerial->flush(); } -void PS16DZSerialSendOkCommand(void) +void PS16DZSerialSendOk(void) { - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+SEND=ok")); - PS16DZSerialSendTxBuffer(); + char tx_buffer[16]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); + PS16DZSerialSend(tx_buffer); } // Send a serial update command to the LED controller // For dimmer types: // AT+UPDATE="sequence":"1554682835320","switch":"on","bright":100 -// For color types: -// AT+UPDATE="sequence":"1554682835320","switch":"on","bright":100,"mode":1,"colorR":255,"colorG":46,"colorB":101,"light_types":1 void PS16DZSerialSendUpdateCommand(void) { uint8_t light_state_dimmer = light_state.getDimmer(); @@ -85,74 +67,17 @@ void PS16DZSerialSendUpdateCommand(void) light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), + char tx_buffer[80]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); - if (Ps16dz.supports_color) { - uint8_t light_state_rgb[3]; - light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); - - snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("%s,\"mode\":%d,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"light_types\":1"), - Ps16dz.tx_buffer, PS16DZ_SONOFF_L1_MODE_COLORFUL, light_state_rgb[0], light_state_rgb[1], light_state_rgb[2]); - } - PS16DZSerialSendTxBuffer(); + PS16DZSerialSend(tx_buffer); } /*********************************************************************************************\ * API Functions \*********************************************************************************************/ -bool PS16DZSerialSendUpdateCommandIfRequired(void) -{ - if (!PS16DZSerial) { return true; } - - bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); - bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); - - uint8_t light_state_rgb[3]; - light_state.getRGB(&light_state_rgb[0], &light_state_rgb[1], &light_state_rgb[2]); - bool is_color_change = (Ps16dz.supports_color && (memcmp(light_state_rgb, Ps16dz.color, 3) != 0)); - - if (is_switch_change || is_brightness_change || is_color_change) { - PS16DZSerialSendUpdateCommand(); - } - - return true; -} - -bool PS16DZModuleSelected(void) -{ - switch (my_module_type) - { - case PS_16_DZ: - devices_present++; - light_type = LT_SERIAL1; - break; - case SONOFF_L1: - devices_present++; - light_type = LT_PWM3; - break; - } - - return true; -} - -void PS16DZInit(void) -{ - Ps16dz.supports_color = (light_state.getColorMode() == LCM_RGB); - - Ps16dz.tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.tx_buffer != nullptr) { - Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.rx_buffer != nullptr) { - PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (PS16DZSerial->begin(19200)) { - if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } - } - } - } -} - void PS16DZSerialInput(void) { char scmnd[20]; @@ -171,18 +96,18 @@ void PS16DZSerialInput(void) Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; // AT+RESULT="sequence":"1554682835320" - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Received %s"), Ps16dz.rx_buffer); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Rcvd %s"), Ps16dz.rx_buffer); - if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { - // AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":255,"colorB":255,"bright":100,"mode":19,"speed":100,"sensitive":100 + if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { + + } + else if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { + // AT+UPDATE="switch":"on","bright":100 char *end_str; char *string = Ps16dz.rx_buffer+10; char *token = strtok_r(string, ",", &end_str); - bool color_updated[3] = { false, false, false }; - memcpy(Ps16dz.color, Settings.light_color, 3); bool is_switch_change = false; - bool is_color_change = false; bool is_brightness_change = false; while (token != nullptr) { @@ -191,43 +116,13 @@ void PS16DZSerialInput(void) char* token3 = strtok_r(nullptr, ":", &end_token); if (!strncmp(token2, "\"switch\"", 8)) { - Ps16dz.switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), Ps16dz.switch_state); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), switch_state); - is_switch_change = (Ps16dz.switch_state != power); + is_switch_change = (switch_state != power); if (is_switch_change) { - ExecuteCommandPower(1, Ps16dz.switch_state, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction - } - } - else if (!strncmp(token2, "\"color", 6)) { - - char color_channel_name = token2[6]; - int color_index; - switch(color_channel_name) - { - case 'R': color_index = 0; - break; - case 'G': color_index = 1; - break; - case 'B': color_index = 2; - break; - } - int color_value = atoi(token3); - Ps16dz.color[color_index] = color_value; - color_updated[color_index] = true; - - bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; - if (all_color_channels_updated) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Color R:%d, G:%d, B:%d"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); - - is_color_change = (memcmp(Ps16dz.color, Settings.light_color, 3) != 0); - } - - if (power && is_color_change) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), Ps16dz.color[0], Ps16dz.color[1], Ps16dz.color[2]); - ExecuteCommand(scmnd, SRC_SWITCH); + ExecuteCommandPower(1, switch_state, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } else if (!strncmp(token2, "\"bright\"", 8)) { @@ -249,11 +144,11 @@ void PS16DZSerialInput(void) token = strtok_r(nullptr, ",", &end_str); } - if (!is_color_change && !is_brightness_change) { + if (!is_brightness_change) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Update")); - PS16DZSerialSendOkCommand(); + PS16DZSerialSendOk(); } } else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { @@ -274,6 +169,39 @@ void PS16DZSerialInput(void) } } +bool PS16DZSerialSendUpdateCommandIfRequired(void) +{ + if (!PS16DZSerial) { return true; } + + bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); + bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); + + if (is_switch_change || is_brightness_change) { + PS16DZSerialSendUpdateCommand(); + } + + return true; +} + +void PS16DZInit(void) +{ + Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); + if (Ps16dz.rx_buffer != nullptr) { + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } + } +} + +bool PS16DZModuleSelected(void) +{ + devices_present++; + light_type = LT_SERIAL1; + + return true; +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -282,20 +210,20 @@ bool Xdrv19(uint8_t function) { bool result = false; - if ((PS_16_DZ == my_module_type) || (SONOFF_L1 == my_module_type)) { + if (PS_16_DZ == my_module_type) { switch (function) { case FUNC_LOOP: if (PS16DZSerial) { PS16DZSerialInput(); } break; - case FUNC_MODULE_INIT: - result = PS16DZModuleSelected(); + case FUNC_SET_DEVICE_POWER: + case FUNC_SET_CHANNELS: + result = PS16DZSerialSendUpdateCommandIfRequired(); break; case FUNC_INIT: PS16DZInit(); break; - case FUNC_SET_DEVICE_POWER: - case FUNC_SET_CHANNELS: - result = PS16DZSerialSendUpdateCommandIfRequired(); + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); break; } } diff --git a/sonoff/xlgt_05_sonoff_l1.ino b/sonoff/xlgt_05_sonoff_l1.ino new file mode 100644 index 000000000..b0661a594 --- /dev/null +++ b/sonoff/xlgt_05_sonoff_l1.ino @@ -0,0 +1,258 @@ +/* + xlgt_05_sonoff_l1.ino - Sonoff L1 led support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_LIGHT +#ifdef USE_SONOFF_L1 +/*********************************************************************************************\ + * Sonoff L1 +\*********************************************************************************************/ + +#define XLGT_05 5 + +#define SONOFF_L1_BUFFER_SIZE 140 + +#define SONOFF_L1_MODE_COLORFUL 1 // [Color key] Colorful (static color) +#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 // [SMOOTH] Colorful Gradient +#define SONOFF_L1_MODE_COLORFUL_BREATH 3 // [FADE] Colorful Breath +#define SONOFF_L1_MODE_DIY_GRADIENT 4 // DIY Gradient (fade in and out) [Speed 1- 100, color] +#define SONOFF_L1_MODE_DIY_PULSE 5 // DIY Pulse (faster fade in and out) [Speed 1- 100, color] +#define SONOFF_L1_MODE_DIY_BREATH 6 // DIY Breath (toggle on/off) [Speed 1- 100, color] +#define SONOFF_L1_MODE_DIY_STROBE 7 // DIY Strobe (faster toggle on/off) [Speed 1- 100, color] +#define SONOFF_L1_MODE_RGB_GRADIENT 8 // RGB Gradient +#define SONOFF_L1_MODE_RGB_PULSE 9 // [STROBE] RGB Pulse +#define SONOFF_L1_MODE_RGB_BREATH 10 // RGB Breath +#define SONOFF_L1_MODE_RGB_STROBE 11 // [FLASH] RGB strobe +#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 // Sync to music [Speed 1- 100, sensitivity 1 - 10] + +struct SNFL1 { + uint32_t unlock = 0; + bool receive_ready = true; +} Snfl1; + +/********************************************************************************************/ + +void SnfL1Send(const char *buffer) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), buffer); + + Serial.print(buffer); + Serial.write(0x1B); + Serial.flush(); +} + +void SnfL1SerialSendOk(void) +{ + char buffer[16]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok")); + + SnfL1Send(buffer); +} + +bool SnfL1SerialInput(void) +{ + if (serial_in_byte != 0x1B) { + if (serial_in_byte_counter >= 140) { + serial_in_byte_counter = 0; + } + if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { // A from AT + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + } else { + serial_in_buffer[serial_in_byte_counter++] = 0x00; + + // AT+RESULT="sequence":"1554682835320" + // AT+UPDATE="sequence":"34906","switch":"on","light_type":1,"colorR":0,"colorG":16,"colorB":0,"bright":6,"mode":1 + // AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":0,"colorB":0,"bright":6,"mode":1,"speed":100,"sensitive":10 + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), serial_in_buffer); + + if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { + Snfl1.receive_ready = true; + } + else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { + char cmnd_dimmer[20]; + char cmnd_color[20]; + char *end_str; + char *string = serial_in_buffer +10; + char *token = strtok_r(string, ",", &end_str); + + bool color_updated[3] = { false, false, false }; + uint8_t current_color[3]; + memcpy(current_color, Settings.light_color, 3); + + bool switch_state = false; + bool is_power_change = false; + bool is_color_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"sequence\"", 10)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd sequence %s"), token3); + + token = nullptr; + } + + else if (!strncmp(token2, "\"switch\"", 8)) { + switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd switch %d (%d)"), switch_state, Light.power); + + is_power_change = (switch_state != Light.power); + } + + else if (!strncmp(token2, "\"color", 6)) { + char color_channel_name = token2[6]; + int color_index; + switch(color_channel_name) + { + case 'R': color_index = 0; + break; + case 'G': color_index = 1; + break; + case 'B': color_index = 2; + break; + } + int color_value = atoi(token3); + current_color[color_index] = color_value; + color_updated[color_index] = true; + + bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; + if (all_color_channels_updated) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd color R%d G%d B%d (R%d G%d B%d)"), + current_color[0], current_color[1], current_color[2], + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + + is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); + } + snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), current_color[0], current_color[1], current_color[2]); + } + + else if (!strncmp(token2, "\"bright\"", 8)) { + uint8_t dimmer = atoi(token3); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings.light_dimmer); + + is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); + snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); + } + + token = strtok_r(nullptr, ",", &end_str); + } + + if (is_power_change) { + if (Settings.light_scheme > 0) { + if (!switch_state) { // If power off RC button pressed stop schemes + char cmnd_scheme[20]; + snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0")); + ExecuteCommand(cmnd_scheme, SRC_SWITCH); + } + } else { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (is_brightness_change) { + ExecuteCommand(cmnd_dimmer, SRC_SWITCH); + } + else if (Light.power && is_color_change) { + if (0 == Settings.light_scheme) { // Fix spurious color receptions when scheme > 0 + if (Settings.light_fade) { // Disable fade as RC button colors overrule and are immediate supressing ghost colors + char cmnd_fade[20]; + snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0")); + ExecuteCommand(cmnd_fade, SRC_SWITCH); + } + ExecuteCommand(cmnd_color, SRC_SWITCH); + } + } + } + + SnfL1SerialSendOk(); + + return true; + } + serial_in_byte = 0; + return false; +} + +/********************************************************************************************/ + +bool SnfL1SetChannels(void) +{ + if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) { + + uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic; + + char buffer[140]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"), + LocalTime(), millis()%1000, + Light.power ? "on" : "off", + scale_col[0], scale_col[1], scale_col[2], + light_state.getDimmer(), + SONOFF_L1_MODE_COLORFUL); + + SnfL1Send(buffer); + + Snfl1.unlock = millis() + 500; // Allow time for the RC + Snfl1.receive_ready = false; + } + return true; +} + +void SnfL1ModuleSelected(void) +{ + if (SONOFF_L1 == my_module_type) { + if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { + Settings.flag.mqtt_serial = 0; + baudrate = 19200; + + light_type = LT_RGB; + light_flg = XLGT_05; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xlgt05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SERIAL: + result = SnfL1SerialInput(); + break; + case FUNC_SET_CHANNELS: + result = SnfL1SetChannels(); + break; + case FUNC_MODULE_INIT: + SnfL1ModuleSelected(); + break; + } + return result; +} + +#endif // USE_SONOFF_L1 +#endif // USE_LIGHT \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index 39e2b96e3..1cb86a0b9 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -170,9 +170,9 @@ a_features = [[ "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" ],[ "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M", - "USE_INA226","USE_A4988_STEPPER","USE_DDS2382","USE_SM2135", + "USE_INA226","USE_A4988_Stepper","USE_DDS2382","USE_SM2135", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", - "USE_SONOFF_SC","USE_SONOFF_RF","","", + "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","", "","","","", "","","","", "","","","",