mirror of https://github.com/arendst/Tasmota.git
Change Sonoff L1 support
This commit is contained in:
parent
c10c057c9b
commit
cd10e84ecf
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -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","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
|
|
Loading…
Reference in New Issue