2019-10-17 11:20:26 +01:00
|
|
|
/*
|
2019-10-27 10:13:24 +00:00
|
|
|
xlgt_05_sonoff_l1.ino - Sonoff L1 led support for Tasmota
|
2019-10-17 11:20:26 +01:00
|
|
|
|
2021-01-01 12:44:04 +00:00
|
|
|
Copyright (C) 2021 Theo Arends
|
2019-10-17 11:20:26 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
#define SONOFF_L1_START_DELAY // Sync Nuvotron power state with Tasmota on power up
|
2021-09-01 10:14:30 +01:00
|
|
|
//#define SONOFF_L1_ALLOW_REMOTE_INTERRUPT // During schemes 2..4 or if fade is active
|
2020-11-09 14:04:22 +00:00
|
|
|
#define SONOFF_L1_DEBUG1 // Add send and receive logging
|
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
#define SONOFF_L1_BUSY 200 // Time in milliseconds to handle a serial request
|
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
#define SONOFF_L1_BUFFER_SIZE 170
|
2019-10-17 11:20:26 +01:00
|
|
|
|
|
|
|
#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 {
|
2021-01-28 16:52:17 +00:00
|
|
|
char *buffer;
|
2021-09-01 10:14:30 +01:00
|
|
|
uint32_t process_time = 0;
|
2019-10-17 11:20:26 +01:00
|
|
|
uint32_t unlock = 0;
|
2021-09-01 10:14:30 +01:00
|
|
|
uint32_t busy = SONOFF_L1_BUSY;
|
|
|
|
uint16_t sequence;
|
2020-11-08 17:03:35 +00:00
|
|
|
uint8_t color[3];
|
|
|
|
uint8_t dimmer;
|
|
|
|
uint8_t power;
|
2021-01-28 16:52:17 +00:00
|
|
|
uint8_t old_music_sync = 0;
|
|
|
|
uint8_t sensitive;
|
|
|
|
uint8_t speed;
|
2019-10-17 11:20:26 +01:00
|
|
|
} Snfl1;
|
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
const char kL1Commands[] PROGMEM = "L1|" // Prefix
|
2021-01-28 00:14:37 +00:00
|
|
|
"MusicSync";
|
|
|
|
|
|
|
|
void (* const L1Command[])(void) PROGMEM = {
|
|
|
|
&CmndMusicSync };
|
|
|
|
|
2019-10-17 11:20:26 +01:00
|
|
|
/********************************************************************************************/
|
|
|
|
|
2020-11-09 14:04:22 +00:00
|
|
|
#ifdef SONOFF_L1_START_DELAY
|
|
|
|
#include <Ticker.h>
|
|
|
|
Ticker SnfL1StartDelay;
|
|
|
|
|
|
|
|
void SnfL1SendDelayed(void) {
|
|
|
|
SnfL1Send();
|
|
|
|
}
|
2021-01-28 16:52:17 +00:00
|
|
|
#endif // SONOFF_L1_START_DELAY
|
2020-11-09 14:04:22 +00:00
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
#include <Ticker.h>
|
|
|
|
Ticker SnfL1Backlog;
|
|
|
|
|
|
|
|
void SnfL1SendBacklog(void) {
|
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: ++Exec backlog"));
|
|
|
|
|
|
|
|
SnfL1SetChannels(true);
|
|
|
|
}
|
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
void SnfL1Send(void) {
|
2020-11-09 14:04:22 +00:00
|
|
|
#ifdef SONOFF_L1_DEBUG1
|
2021-09-01 10:14:30 +01:00
|
|
|
AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Send '%s'"), Snfl1.buffer);
|
2020-11-09 14:04:22 +00:00
|
|
|
#endif
|
|
|
|
Serial.print(Snfl1.buffer);
|
|
|
|
Serial.write(0x1B);
|
|
|
|
Serial.flush();
|
2021-09-01 10:14:30 +01:00
|
|
|
|
|
|
|
Snfl1.process_time = millis();
|
|
|
|
Snfl1.unlock = Snfl1.process_time + Snfl1.busy; // Wait for 'AT+RESULT="sequence":"1630250830439"'
|
2020-11-09 14:04:22 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
void SnfL1SendOk(void) {
|
2021-01-28 16:52:17 +00:00
|
|
|
snprintf_P(Snfl1.buffer, SONOFF_L1_BUFFER_SIZE, PSTR("AT+SEND=ok"));
|
2020-11-09 14:04:22 +00:00
|
|
|
SnfL1Send();
|
|
|
|
}
|
2019-10-17 11:20:26 +01:00
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
bool SnfL1SerialInput(void) {
|
2020-10-30 11:29:48 +00:00
|
|
|
if (TasmotaGlobal.serial_in_byte != 0x1B) {
|
2020-11-09 14:04:22 +00:00
|
|
|
if (TasmotaGlobal.serial_in_byte_counter >= SONOFF_L1_BUFFER_SIZE) {
|
2020-10-29 11:21:24 +00:00
|
|
|
TasmotaGlobal.serial_in_byte_counter = 0;
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
2020-10-30 11:29:48 +00:00
|
|
|
if (TasmotaGlobal.serial_in_byte_counter || (!TasmotaGlobal.serial_in_byte_counter && ('A' == TasmotaGlobal.serial_in_byte))) { // A from AT
|
|
|
|
TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte;
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
} else {
|
2020-10-30 11:29:48 +00:00
|
|
|
TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = 0x00;
|
2019-10-17 11:20:26 +01:00
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
// AT+RESULT="sequence":"0458" = L1
|
|
|
|
// AT+RESULT="sequence":"0458","switch" = L1 lite - just returns part of receive buffer
|
|
|
|
// AT+RESULT="sequence":"1554682835320" = L1 both
|
|
|
|
// AT+UPDATE="sequence":"1554682835320","switch":"on","light_type":1,"colorR":0,"colorG":16,"colorB":0,"bright":6,"mode":1
|
2019-10-17 11:20:26 +01:00
|
|
|
// AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":0,"colorB":0,"bright":6,"mode":1,"speed":100,"sensitive":10
|
2020-11-09 14:04:22 +00:00
|
|
|
#ifdef SONOFF_L1_DEBUG1
|
2021-09-01 10:14:30 +01:00
|
|
|
AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd '%s'"), TasmotaGlobal.serial_in_buffer);
|
2020-11-09 14:04:22 +00:00
|
|
|
#endif
|
2020-10-30 11:29:48 +00:00
|
|
|
if (!strncmp(TasmotaGlobal.serial_in_buffer +3, "RESULT", 6)) {
|
2020-11-09 14:04:22 +00:00
|
|
|
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
2021-09-01 10:14:30 +01:00
|
|
|
Snfl1.busy = 500;
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
// Read sequence number and calculate time it took from send of same sequence
|
|
|
|
// this indicates Nuvoton processing speed (50-60 for L1, 30-40 for L1 lite)
|
|
|
|
// Important for constant color change schemes and fade
|
|
|
|
char *end_str;
|
|
|
|
char *string = TasmotaGlobal.serial_in_buffer +10;
|
|
|
|
char *token = strtok_r(string, ",", &end_str);
|
|
|
|
if (token) {
|
|
|
|
char* end_token;
|
|
|
|
char* token2 = strtok_r(token, ":", &end_token);
|
|
|
|
char* token3 = strtok_r(nullptr, ":", &end_token);
|
|
|
|
if (!strncmp(token2, "\"sequence\"", 10) && (strlen(token3) > 3)) {
|
|
|
|
token3 = token3 + strlen(token3) - 4; // Last three digits
|
|
|
|
if (Snfl1.sequence == atoi(token3)) {
|
|
|
|
Snfl1.busy = (millis() - Snfl1.process_time) + 30; // Add some scatter time
|
|
|
|
if (Snfl1.busy > SONOFF_L1_BUSY) {
|
|
|
|
Snfl1.busy = SONOFF_L1_BUSY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
Snfl1.busy = 80;
|
|
|
|
#endif // SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("Sl1: ++Busy %d"), Snfl1.busy);
|
|
|
|
|
|
|
|
SnfL1SendOk();
|
|
|
|
return true;
|
|
|
|
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
2020-10-30 11:29:48 +00:00
|
|
|
else if (!strncmp(TasmotaGlobal.serial_in_buffer +3, "UPDATE", 6)) {
|
2019-10-17 11:20:26 +01:00
|
|
|
char cmnd_dimmer[20];
|
|
|
|
char cmnd_color[20];
|
|
|
|
char *end_str;
|
2020-10-30 11:29:48 +00:00
|
|
|
char *string = TasmotaGlobal.serial_in_buffer +10;
|
2019-10-17 11:20:26 +01:00
|
|
|
char *token = strtok_r(string, ",", &end_str);
|
|
|
|
|
|
|
|
bool color_updated[3] = { false, false, false };
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
2021-01-23 16:10:06 +00:00
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd sequence %s"), token3);
|
2019-10-17 11:20:26 +01:00
|
|
|
|
|
|
|
token = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strncmp(token2, "\"switch\"", 8)) {
|
|
|
|
switch_state = !strncmp(token3, "\"on\"", 4) ? true : false;
|
|
|
|
|
2021-01-23 16:10:06 +00:00
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd switch %d (%d)"), switch_state, Light.power);
|
2019-10-17 11:20:26 +01:00
|
|
|
|
|
|
|
is_power_change = (switch_state != Light.power);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strncmp(token2, "\"color", 6)) {
|
|
|
|
char color_channel_name = token2[6];
|
|
|
|
int color_index;
|
2020-11-09 12:52:42 +00:00
|
|
|
switch(color_channel_name) {
|
2019-10-17 11:20:26 +01:00
|
|
|
case 'R': color_index = 0;
|
|
|
|
break;
|
|
|
|
case 'G': color_index = 1;
|
|
|
|
break;
|
|
|
|
case 'B': color_index = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int color_value = atoi(token3);
|
2020-11-08 17:03:35 +00:00
|
|
|
Snfl1.color[color_index] = color_value;
|
2020-11-09 12:52:42 +00:00
|
|
|
color_updated[color_index] = true;
|
2019-10-17 11:20:26 +01:00
|
|
|
|
|
|
|
bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2];
|
|
|
|
if (all_color_channels_updated) {
|
|
|
|
|
2021-01-23 16:10:06 +00:00
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd color R%d G%d B%d (R%d G%d B%d)"),
|
2020-11-09 12:52:42 +00:00
|
|
|
// Snfl1.color[0], Snfl1.color[1], Snfl1.color[2],
|
2021-06-11 17:14:12 +01:00
|
|
|
// Settings->light_color[0], Settings->light_color[1], Settings->light_color[2]);
|
2019-10-17 11:20:26 +01:00
|
|
|
|
2021-06-11 17:14:12 +01:00
|
|
|
is_color_change = (Light.power && (memcmp(Snfl1.color, Settings->light_color, 3) != 0));
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
2020-11-09 12:52:42 +00:00
|
|
|
snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), Snfl1.color[0], Snfl1.color[1], Snfl1.color[2]);
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strncmp(token2, "\"bright\"", 8)) {
|
|
|
|
uint8_t dimmer = atoi(token3);
|
|
|
|
|
2021-06-11 17:14:12 +01:00
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings->light_dimmer);
|
2019-10-17 11:20:26 +01:00
|
|
|
|
2021-06-11 17:14:12 +01:00
|
|
|
is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings->light_dimmer));
|
2019-10-17 11:20:26 +01:00
|
|
|
snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer);
|
|
|
|
}
|
|
|
|
|
2021-08-27 14:50:17 +01:00
|
|
|
else if (!strncmp(token2, "\"mode\"", 6)) {
|
|
|
|
uint8_t received_mode = atoi(token3);
|
|
|
|
Settings->sbflag1.sonoff_l1_music_sync = (SONOFF_L1_MODE_SYNC_TO_MUSIC == received_mode);
|
|
|
|
}
|
|
|
|
|
2019-10-17 11:20:26 +01:00
|
|
|
token = strtok_r(nullptr, ",", &end_str);
|
|
|
|
}
|
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
SnfL1SendOk();
|
|
|
|
|
2019-10-17 11:20:26 +01:00
|
|
|
if (is_power_change) {
|
2021-06-11 17:14:12 +01:00
|
|
|
if (Settings->light_scheme > 0) {
|
2019-10-17 11:20:26 +01:00
|
|
|
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"));
|
2020-11-09 16:15:48 +00:00
|
|
|
ExecuteCommand(cmnd_scheme, SRC_REMOTE);
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
}
|
2021-09-01 10:14:30 +01:00
|
|
|
// else {
|
|
|
|
ExecuteCommandPower(1, switch_state, SRC_REMOTE);
|
|
|
|
// }
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
else if (is_brightness_change) {
|
2020-11-09 16:15:48 +00:00
|
|
|
ExecuteCommand(cmnd_dimmer, SRC_REMOTE);
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
else if (Light.power && is_color_change) {
|
2021-06-11 17:14:12 +01:00
|
|
|
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
|
2019-10-17 11:20:26 +01:00
|
|
|
char cmnd_fade[20];
|
|
|
|
snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0"));
|
2020-11-09 16:15:48 +00:00
|
|
|
ExecuteCommand(cmnd_fade, SRC_REMOTE);
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
2021-06-11 17:14:12 +01:00
|
|
|
if (Settings->light_correction) { // Disable ledtable as RC button colors overrule and are immediate supressing ghost colors
|
2020-11-08 17:03:35 +00:00
|
|
|
char cmnd_fade[20];
|
|
|
|
snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_LEDTABLE " 0"));
|
2020-11-09 16:15:48 +00:00
|
|
|
ExecuteCommand(cmnd_fade, SRC_REMOTE);
|
2020-11-08 17:03:35 +00:00
|
|
|
}
|
2020-11-09 16:15:48 +00:00
|
|
|
ExecuteCommand(cmnd_color, SRC_REMOTE);
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-30 11:29:48 +00:00
|
|
|
TasmotaGlobal.serial_in_byte = 0;
|
2019-10-17 11:20:26 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************************************/
|
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
void SnfL1SetChannels(bool backlog) {
|
|
|
|
// Takes about 100ms at 9600 bps
|
|
|
|
|
|
|
|
if (!backlog) {
|
2020-11-08 17:03:35 +00:00
|
|
|
uint8_t power = Light.power;
|
|
|
|
bool power_changed = (Snfl1.power != power);
|
|
|
|
Snfl1.power = power;
|
|
|
|
|
2020-11-09 12:52:42 +00:00
|
|
|
uint8_t dimmer = light_state.getDimmer();
|
2020-11-08 17:03:35 +00:00
|
|
|
bool dimmer_changed = (Snfl1.dimmer != dimmer);
|
|
|
|
Snfl1.dimmer = dimmer;
|
|
|
|
|
2020-11-09 12:52:42 +00:00
|
|
|
uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic;
|
2020-11-08 17:03:35 +00:00
|
|
|
bool color_changed = false;
|
|
|
|
if (!power_changed) {
|
|
|
|
for (uint32_t i = 0; i < 3; i++) {
|
2021-09-01 10:14:30 +01:00
|
|
|
if (Snfl1.color[i] != scale_col[i]) {
|
|
|
|
color_changed = true;
|
2020-11-08 17:03:35 +00:00
|
|
|
}
|
|
|
|
Snfl1.color[i] = scale_col[i];
|
|
|
|
}
|
|
|
|
}
|
2021-09-01 10:14:30 +01:00
|
|
|
if (!power_changed && !dimmer_changed && !color_changed && (Snfl1.old_music_sync == Settings->sbflag1.sonoff_l1_music_sync)) { return; }
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TimeReached(Snfl1.unlock)) {
|
|
|
|
|
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: ++SC snd"));
|
2020-11-08 17:03:35 +00:00
|
|
|
|
2021-08-25 14:24:55 +01:00
|
|
|
uint32_t mode = (Settings->sbflag1.sonoff_l1_music_sync) ? SONOFF_L1_MODE_SYNC_TO_MUSIC : SONOFF_L1_MODE_COLORFUL;
|
2021-09-01 10:14:30 +01:00
|
|
|
Snfl1.sequence = millis()%1000;
|
2021-08-25 14:24:55 +01:00
|
|
|
snprintf_P(Snfl1.buffer, SONOFF_L1_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"),
|
2021-09-01 10:14:30 +01:00
|
|
|
LocalTime(), Snfl1.sequence,
|
2020-11-09 14:04:22 +00:00
|
|
|
Snfl1.power ? "on" : "off",
|
|
|
|
Snfl1.color[0], Snfl1.color[1], Snfl1.color[2],
|
|
|
|
Snfl1.dimmer,
|
2021-08-25 14:24:55 +01:00
|
|
|
mode);
|
|
|
|
if (SONOFF_L1_MODE_SYNC_TO_MUSIC == mode) {
|
|
|
|
snprintf_P(Snfl1.buffer, SONOFF_L1_BUFFER_SIZE, PSTR("%s,\"sensitive\":%d,\"speed\":%d"),
|
|
|
|
Snfl1.buffer,
|
|
|
|
Snfl1.sensitive,
|
|
|
|
Snfl1.speed);
|
|
|
|
}
|
2020-11-09 14:04:22 +00:00
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
#ifdef SONOFF_L1_START_DELAY
|
2020-11-09 14:04:22 +00:00
|
|
|
static bool first_call = true;
|
|
|
|
if (first_call) {
|
2020-12-26 14:12:46 +00:00
|
|
|
SnfL1StartDelay.once_ms(900, SnfL1SendDelayed); // Allow startup time for Nuvotron microcontroller
|
2020-11-09 14:04:22 +00:00
|
|
|
first_call = false;
|
2021-01-28 16:52:17 +00:00
|
|
|
} else
|
2020-11-09 14:04:22 +00:00
|
|
|
#endif // SONOFF_L1_START_DELAY
|
2021-01-28 16:52:17 +00:00
|
|
|
SnfL1Send();
|
2021-09-01 10:14:30 +01:00
|
|
|
} else {
|
|
|
|
if (Settings->light_scheme == 0) {
|
|
|
|
// Fix last fade state
|
|
|
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: ++SC bck"));
|
2019-10-17 11:20:26 +01:00
|
|
|
|
2021-09-01 10:14:30 +01:00
|
|
|
SnfL1Backlog.once_ms(SONOFF_L1_BUSY, SnfL1SendBacklog); // Set backlog
|
|
|
|
}
|
2020-11-09 14:04:22 +00:00
|
|
|
}
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
|
2021-08-27 15:39:18 +01:00
|
|
|
bool SnfL1SetChannelsFromFunc(void) {
|
|
|
|
static bool first_call = true;
|
|
|
|
if (first_call) {
|
|
|
|
first_call = false; // Allow MusicSync at init time
|
|
|
|
} else {
|
|
|
|
Settings->sbflag1.sonoff_l1_music_sync = 0; // Disable MusicSync on user color change
|
|
|
|
}
|
2021-09-01 10:14:30 +01:00
|
|
|
SnfL1SetChannels(false);
|
|
|
|
return true;
|
2021-08-27 15:39:18 +01:00
|
|
|
}
|
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
bool SnfL1ModuleSelected(void) {
|
2020-10-30 11:29:48 +00:00
|
|
|
if (SONOFF_L1 == TasmotaGlobal.module_type) {
|
2020-04-27 11:54:07 +01:00
|
|
|
if (PinUsed(GPIO_RXD) && PinUsed(GPIO_TXD)) {
|
2021-01-28 16:52:17 +00:00
|
|
|
Snfl1.buffer = (char*)malloc(SONOFF_L1_BUFFER_SIZE);
|
|
|
|
if (Snfl1.buffer) {
|
|
|
|
SetSerial(19200, TS_SERIAL_8N1);
|
|
|
|
|
|
|
|
Snfl1.power = !Light.power;
|
|
|
|
Snfl1.dimmer = !light_state.getDimmer();
|
2021-01-29 10:00:56 +00:00
|
|
|
Snfl1.sensitive = 5; // 1..10
|
|
|
|
Snfl1.speed = 50; // 1..100
|
2021-01-28 16:52:17 +00:00
|
|
|
|
|
|
|
TasmotaGlobal.light_type = LT_RGB;
|
|
|
|
TasmotaGlobal.light_driver = XLGT_05;
|
|
|
|
AddLog(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found"));
|
|
|
|
return true;
|
|
|
|
}
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-08 17:03:35 +00:00
|
|
|
return false;
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
|
2021-01-28 16:52:17 +00:00
|
|
|
void CmndMusicSync(void) {
|
|
|
|
// Format is L1MusicSync on/off/toggle, sensitivity, speed
|
2021-01-28 00:14:37 +00:00
|
|
|
// sensitivity 1..10, speed 1..100
|
2021-01-28 16:52:17 +00:00
|
|
|
if (XdrvMailbox.data_len > 0) {
|
2021-08-03 13:12:38 +01:00
|
|
|
Snfl1.old_music_sync = Settings->sbflag1.sonoff_l1_music_sync;
|
2021-01-28 16:52:17 +00:00
|
|
|
uint32_t parm[3] = { 0 };
|
|
|
|
ParseParameters(3, parm);
|
|
|
|
if (2 == parm[0]) {
|
2021-08-03 13:12:38 +01:00
|
|
|
Settings->sbflag1.sonoff_l1_music_sync ^= 1; // Toggle
|
2021-01-28 16:52:17 +00:00
|
|
|
} else {
|
2021-08-03 13:12:38 +01:00
|
|
|
Settings->sbflag1.sonoff_l1_music_sync = parm[0] & 1; // On or Off
|
2021-01-28 00:14:37 +00:00
|
|
|
}
|
2021-01-28 16:52:17 +00:00
|
|
|
if ((parm[1] > 0) && (parm[1] < 11)) {
|
|
|
|
Snfl1.sensitive = parm[1]; // 1..10
|
|
|
|
}
|
|
|
|
if ((parm[2] > 0) && (parm[2] < 101)) {
|
|
|
|
Snfl1.speed = parm[2]; // 1..100
|
|
|
|
}
|
2021-09-01 10:14:30 +01:00
|
|
|
SnfL1SetChannels(false);
|
2021-01-28 16:52:17 +00:00
|
|
|
}
|
|
|
|
Response_P(PSTR("{\"%s\":{\"Mode\":\"%s\",\"Sensitive\":%d,\"Speed\":%d}}"),
|
2021-08-03 13:12:38 +01:00
|
|
|
XdrvMailbox.command, GetStateText(Settings->sbflag1.sonoff_l1_music_sync), Snfl1.sensitive, Snfl1.speed);
|
2021-01-28 00:14:37 +00:00
|
|
|
}
|
2021-01-28 16:52:17 +00:00
|
|
|
|
2019-10-17 11:20:26 +01:00
|
|
|
/*********************************************************************************************\
|
|
|
|
* Interface
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2022-11-11 09:44:56 +00:00
|
|
|
bool Xlgt05(uint32_t function)
|
2019-10-17 11:20:26 +01:00
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
switch (function) {
|
|
|
|
case FUNC_SERIAL:
|
|
|
|
result = SnfL1SerialInput();
|
|
|
|
break;
|
|
|
|
case FUNC_SET_CHANNELS:
|
2021-08-27 15:39:18 +01:00
|
|
|
result = SnfL1SetChannelsFromFunc();
|
2019-10-17 11:20:26 +01:00
|
|
|
break;
|
|
|
|
case FUNC_MODULE_INIT:
|
2020-11-08 17:03:35 +00:00
|
|
|
result = SnfL1ModuleSelected();
|
2019-10-17 11:20:26 +01:00
|
|
|
break;
|
2021-01-28 00:14:37 +00:00
|
|
|
case FUNC_COMMAND:
|
|
|
|
result = DecodeCommand(kL1Commands, L1Command);
|
|
|
|
break;
|
2019-10-17 11:20:26 +01:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // USE_SONOFF_L1
|
|
|
|
#endif // USE_LIGHT
|