mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-26 20:26:32 +00:00
Add Sonoff L1 Music Sync control
Add command ``L1MusicSync <0|Off>|<1|On>|<2|Toggle>, 1..10, 1..100>`` to control Sonoff L1 Music Sync mode sensitivity and speed (#10722)
This commit is contained in:
parent
d8a769bfc5
commit
ac8d26982d
@ -11,6 +11,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Commands ``BuzzerActive``, ``BuzzerPwm`` as synonyms for ``SetOption67, 111`` respectively
|
- Commands ``BuzzerActive``, ``BuzzerPwm`` as synonyms for ``SetOption67, 111`` respectively
|
||||||
- Support for ESP32 ``Module 5`` Wireless Tag Eth01 (#9496)
|
- Support for ESP32 ``Module 5`` Wireless Tag Eth01 (#9496)
|
||||||
- Support trailing silence in buzzer tune (#10694)
|
- Support trailing silence in buzzer tune (#10694)
|
||||||
|
- Command ``L1MusicSync <0|Off>|<1|On>|<2|Toggle>, 1..10, 1..100>`` to control Sonoff L1 Music Sync mode sensitivity and speed (#10722)
|
||||||
|
- Commands ``Speed2`` and ``Fade2`` to control a once off speed and/or fade (#10730)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Maximum chars in ``AddLog_P`` logging restored from 128 to 700 (MAX_LOGSZ) to solve broken error messages
|
- Maximum chars in ``AddLog_P`` logging restored from 128 to 700 (MAX_LOGSZ) to solve broken error messages
|
||||||
|
@ -61,10 +61,12 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
|||||||
- Command ``CTRange`` to specify the visible CT range the bulb is capable of [#10311](https://github.com/arendst/Tasmota/issues/10311)
|
- Command ``CTRange`` to specify the visible CT range the bulb is capable of [#10311](https://github.com/arendst/Tasmota/issues/10311)
|
||||||
- Command ``RuleTimer0`` to access all RuleTimers at once [#10352](https://github.com/arendst/Tasmota/issues/10352)
|
- Command ``RuleTimer0`` to access all RuleTimers at once [#10352](https://github.com/arendst/Tasmota/issues/10352)
|
||||||
- Command ``VirtualCT`` to simulate or fine tune CT bulbs with 3,4,5 channels [#10311](https://github.com/arendst/Tasmota/issues/10311)
|
- Command ``VirtualCT`` to simulate or fine tune CT bulbs with 3,4,5 channels [#10311](https://github.com/arendst/Tasmota/issues/10311)
|
||||||
|
- Command ``L1MusicSync <0|Off>|<1|On>|<2|Toggle>, 1..10, 1..100>`` to control Sonoff L1 Music Sync mode sensitivity and speed [#10722](https://github.com/arendst/Tasmota/issues/10722)
|
||||||
- Command ``SetOption40 0..250`` to disable button functionality if activated for over 0.1 second re-introduced
|
- Command ``SetOption40 0..250`` to disable button functionality if activated for over 0.1 second re-introduced
|
||||||
- Command ``SetOption43 1..255`` to control Rotary step (#10407)
|
- Command ``SetOption43 1..255`` to control Rotary step (#10407)
|
||||||
- Command ``SetOption118 1`` to move ZbReceived from JSON message and into the subtopic replacing "SENSOR" default [#10353](https://github.com/arendst/Tasmota/issues/10353)
|
- Command ``SetOption118 1`` to move ZbReceived from JSON message and into the subtopic replacing "SENSOR" default [#10353](https://github.com/arendst/Tasmota/issues/10353)
|
||||||
- Command ``SetOption119 1`` to remove the device addr from json payload, can be used with zb_topic_fname where the addr is already known from the topic [#10355](https://github.com/arendst/Tasmota/issues/10355)
|
- Command ``SetOption119 1`` to remove the device addr from json payload, can be used with zb_topic_fname where the addr is already known from the topic [#10355](https://github.com/arendst/Tasmota/issues/10355)
|
||||||
|
- Commands ``Speed2`` and ``Fade2`` to control a once off speed and/or fade [#10730](https://github.com/arendst/Tasmota/issues/10730)
|
||||||
- Commands ``ChannelRemap``, ``MultiPWM``, ``AlexaCTRange``, ``PowerOnFade``, ``PWMCT``, ``WhiteBlend``, ``VirtualCT`` as synonyms for ``SetOption37, 68, 82, 91, 92, 105 and 106`` respectively
|
- Commands ``ChannelRemap``, ``MultiPWM``, ``AlexaCTRange``, ``PowerOnFade``, ``PWMCT``, ``WhiteBlend``, ``VirtualCT`` as synonyms for ``SetOption37, 68, 82, 91, 92, 105 and 106`` respectively
|
||||||
- Commands ``ZbNameKey``, ``ZbDeviceTopic``, ``ZbNoPrefix``, ``ZbEndpointSuffix``, ``ZbNoAutoBind``, ``ZbNameTopic`` as synonyms for ``SetOption83, 89, 100, 101, 110 and 112`` respectively
|
- Commands ``ZbNameKey``, ``ZbDeviceTopic``, ``ZbNoPrefix``, ``ZbEndpointSuffix``, ``ZbNoAutoBind``, ``ZbNameTopic`` as synonyms for ``SetOption83, 89, 100, 101, 110 and 112`` respectively
|
||||||
- Commands ``BuzzerActive``, ``BuzzerPwm`` as synonyms for ``SetOption67, 111`` respectively
|
- Commands ``BuzzerActive``, ``BuzzerPwm`` as synonyms for ``SetOption67, 111`` respectively
|
||||||
|
@ -25,11 +25,11 @@
|
|||||||
|
|
||||||
#define XLGT_05 5
|
#define XLGT_05 5
|
||||||
|
|
||||||
//#define SONOFF_L1_START_DELAY // Sync Nuvotron power state with Tasmota on power up
|
#define SONOFF_L1_START_DELAY // Sync Nuvotron power state with Tasmota on power up
|
||||||
//#define SONOFF_L1_ALLOW_REMOTE_INTERRUPT // During schemes 2..4
|
//#define SONOFF_L1_ALLOW_REMOTE_INTERRUPT // During schemes 2..4
|
||||||
#define SONOFF_L1_DEBUG1 // Add send and receive logging
|
#define SONOFF_L1_DEBUG1 // Add send and receive logging
|
||||||
|
|
||||||
#define SONOFF_L1_BUFFER_SIZE 140
|
#define SONOFF_L1_BUFFER_SIZE 170
|
||||||
|
|
||||||
#define SONOFF_L1_MODE_COLORFUL 1 // [Color key] Colorful (static color)
|
#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_GRADIENT 2 // [SMOOTH] Colorful Gradient
|
||||||
@ -45,19 +45,21 @@
|
|||||||
#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 // Sync to music [Speed 1- 100, sensitivity 1 - 10]
|
#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 // Sync to music [Speed 1- 100, sensitivity 1 - 10]
|
||||||
|
|
||||||
struct SNFL1 {
|
struct SNFL1 {
|
||||||
|
char *buffer;
|
||||||
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
||||||
uint32_t unlock = 0;
|
uint32_t unlock = 0;
|
||||||
bool receive_ready = true;
|
bool receive_ready = true;
|
||||||
#endif
|
|
||||||
#ifdef SONOFF_L1_START_DELAY
|
|
||||||
char buffer[SONOFF_L1_BUFFER_SIZE];
|
|
||||||
#endif
|
#endif
|
||||||
uint8_t color[3];
|
uint8_t color[3];
|
||||||
uint8_t dimmer;
|
uint8_t dimmer;
|
||||||
uint8_t power;
|
uint8_t power;
|
||||||
|
uint8_t old_music_sync = 0;
|
||||||
|
uint8_t music_sync = 0;
|
||||||
|
uint8_t sensitive;
|
||||||
|
uint8_t speed;
|
||||||
} Snfl1;
|
} Snfl1;
|
||||||
|
|
||||||
const char kL1Commands[] PROGMEM = "L1|" // prefix
|
const char kL1Commands[] PROGMEM = "L1|" // Prefix
|
||||||
"MusicSync";
|
"MusicSync";
|
||||||
|
|
||||||
void (* const L1Command[])(void) PROGMEM = {
|
void (* const L1Command[])(void) PROGMEM = {
|
||||||
@ -72,45 +74,24 @@ Ticker SnfL1StartDelay;
|
|||||||
void SnfL1SendDelayed(void) {
|
void SnfL1SendDelayed(void) {
|
||||||
SnfL1Send();
|
SnfL1Send();
|
||||||
}
|
}
|
||||||
|
#endif // SONOFF_L1_START_DELAY
|
||||||
|
|
||||||
void SnfL1Send(void)
|
void SnfL1Send(void) {
|
||||||
{
|
|
||||||
#ifdef SONOFF_L1_DEBUG1
|
#ifdef SONOFF_L1_DEBUG1
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), Snfl1.buffer);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), Snfl1.buffer);
|
||||||
#endif
|
#endif
|
||||||
Serial.print(Snfl1.buffer);
|
Serial.print(Snfl1.buffer);
|
||||||
Serial.write(0x1B);
|
Serial.write(0x1B);
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnfL1SerialSendOk(void)
|
void SnfL1SerialSendOk(void) {
|
||||||
{
|
snprintf_P(Snfl1.buffer, SONOFF_L1_BUFFER_SIZE, PSTR("AT+SEND=ok"));
|
||||||
snprintf_P(Snfl1.buffer, sizeof(Snfl1.buffer), PSTR("AT+SEND=ok"));
|
|
||||||
|
|
||||||
SnfL1Send();
|
SnfL1Send();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void SnfL1Send(const char *buffer)
|
|
||||||
{
|
|
||||||
#ifdef SONOFF_L1_DEBUG1
|
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Send %s"), buffer);
|
|
||||||
#endif
|
|
||||||
Serial.print(buffer);
|
|
||||||
Serial.write(0x1B);
|
|
||||||
Serial.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SnfL1SerialSendOk(void)
|
bool SnfL1SerialInput(void) {
|
||||||
{
|
|
||||||
char buffer[16];
|
|
||||||
snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok"));
|
|
||||||
|
|
||||||
SnfL1Send(buffer);
|
|
||||||
}
|
|
||||||
#endif // SONOFF_L1_START_DELAY
|
|
||||||
|
|
||||||
bool SnfL1SerialInput(void)
|
|
||||||
{
|
|
||||||
if (TasmotaGlobal.serial_in_byte != 0x1B) {
|
if (TasmotaGlobal.serial_in_byte != 0x1B) {
|
||||||
if (TasmotaGlobal.serial_in_byte_counter >= SONOFF_L1_BUFFER_SIZE) {
|
if (TasmotaGlobal.serial_in_byte_counter >= SONOFF_L1_BUFFER_SIZE) {
|
||||||
TasmotaGlobal.serial_in_byte_counter = 0;
|
TasmotaGlobal.serial_in_byte_counter = 0;
|
||||||
@ -125,7 +106,7 @@ bool SnfL1SerialInput(void)
|
|||||||
// AT+UPDATE="sequence":"34906","switch":"on","light_type":1,"colorR":0,"colorG":16,"colorB":0,"bright":6,"mode":1
|
// 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
|
// AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":0,"colorB":0,"bright":6,"mode":1,"speed":100,"sensitive":10
|
||||||
#ifdef SONOFF_L1_DEBUG1
|
#ifdef SONOFF_L1_DEBUG1
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), TasmotaGlobal.serial_in_buffer);
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), TasmotaGlobal.serial_in_buffer);
|
||||||
#endif
|
#endif
|
||||||
if (!strncmp(TasmotaGlobal.serial_in_buffer +3, "RESULT", 6)) {
|
if (!strncmp(TasmotaGlobal.serial_in_buffer +3, "RESULT", 6)) {
|
||||||
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
||||||
@ -246,8 +227,7 @@ bool SnfL1SerialInput(void)
|
|||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
bool SnfL1SetChannels(void)
|
bool SnfL1SetChannels(void) {
|
||||||
{
|
|
||||||
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
||||||
if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) {
|
if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) {
|
||||||
#endif
|
#endif
|
||||||
@ -269,34 +249,30 @@ bool SnfL1SetChannels(void)
|
|||||||
Snfl1.color[i] = scale_col[i];
|
Snfl1.color[i] = scale_col[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!power_changed && !dimmer_changed && !color_changed) { return true; }
|
if (!power_changed && !dimmer_changed && !color_changed && (Snfl1.old_music_sync == Snfl1.music_sync)) { return true; }
|
||||||
|
|
||||||
#ifdef SONOFF_L1_START_DELAY
|
uint32_t mode = SONOFF_L1_MODE_COLORFUL;
|
||||||
snprintf_P(Snfl1.buffer, sizeof(Snfl1.buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"),
|
if (Snfl1.music_sync) {
|
||||||
|
mode = SONOFF_L1_MODE_SYNC_TO_MUSIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,\"sensitive\":%d,\"speed\":%d"),
|
||||||
LocalTime(), millis()%1000,
|
LocalTime(), millis()%1000,
|
||||||
Snfl1.power ? "on" : "off",
|
Snfl1.power ? "on" : "off",
|
||||||
Snfl1.color[0], Snfl1.color[1], Snfl1.color[2],
|
Snfl1.color[0], Snfl1.color[1], Snfl1.color[2],
|
||||||
Snfl1.dimmer,
|
Snfl1.dimmer,
|
||||||
SONOFF_L1_MODE_COLORFUL);
|
mode,
|
||||||
|
Snfl1.sensitive,
|
||||||
|
Snfl1.speed);
|
||||||
|
|
||||||
|
#ifdef SONOFF_L1_START_DELAY
|
||||||
static bool first_call = true;
|
static bool first_call = true;
|
||||||
if (first_call) {
|
if (first_call) {
|
||||||
SnfL1StartDelay.once_ms(900, SnfL1SendDelayed); // Allow startup time for Nuvotron microcontroller
|
SnfL1StartDelay.once_ms(900, SnfL1SendDelayed); // Allow startup time for Nuvotron microcontroller
|
||||||
first_call = false;
|
first_call = false;
|
||||||
} else {
|
} else
|
||||||
SnfL1Send();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
char buffer[SONOFF_L1_BUFFER_SIZE];
|
|
||||||
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,
|
|
||||||
Snfl1.power ? "on" : "off",
|
|
||||||
Snfl1.color[0], Snfl1.color[1], Snfl1.color[2],
|
|
||||||
Snfl1.dimmer,
|
|
||||||
SONOFF_L1_MODE_COLORFUL);
|
|
||||||
|
|
||||||
SnfL1Send(buffer);
|
|
||||||
#endif // SONOFF_L1_START_DELAY
|
#endif // SONOFF_L1_START_DELAY
|
||||||
|
SnfL1Send();
|
||||||
|
|
||||||
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
#ifdef SONOFF_L1_ALLOW_REMOTE_INTERRUPT
|
||||||
Snfl1.unlock = millis() + 500; // Allow time for the RC
|
Snfl1.unlock = millis() + 500; // Allow time for the RC
|
||||||
@ -306,60 +282,53 @@ bool SnfL1SetChannels(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SnfL1ModuleSelected(void)
|
bool SnfL1ModuleSelected(void) {
|
||||||
{
|
|
||||||
if (SONOFF_L1 == TasmotaGlobal.module_type) {
|
if (SONOFF_L1 == TasmotaGlobal.module_type) {
|
||||||
if (PinUsed(GPIO_RXD) && PinUsed(GPIO_TXD)) {
|
if (PinUsed(GPIO_RXD) && PinUsed(GPIO_TXD)) {
|
||||||
SetSerial(19200, TS_SERIAL_8N1);
|
Snfl1.buffer = (char*)malloc(SONOFF_L1_BUFFER_SIZE);
|
||||||
|
if (Snfl1.buffer) {
|
||||||
|
SetSerial(19200, TS_SERIAL_8N1);
|
||||||
|
|
||||||
Snfl1.power = !Light.power;
|
Snfl1.power = !Light.power;
|
||||||
Snfl1.dimmer = !light_state.getDimmer();
|
Snfl1.dimmer = !light_state.getDimmer();
|
||||||
|
Snfl1.music_sync = 0;
|
||||||
|
Snfl1.sensitive = 1; // 1..10
|
||||||
|
Snfl1.speed = 1; // 1..100
|
||||||
|
|
||||||
TasmotaGlobal.light_type = LT_RGB;
|
TasmotaGlobal.light_type = LT_RGB;
|
||||||
TasmotaGlobal.light_driver = XLGT_05;
|
TasmotaGlobal.light_driver = XLGT_05;
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found"));
|
AddLog(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found"));
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SONOFF_L1_MODE_SYNC_TO_MUSIC
|
void CmndMusicSync(void) {
|
||||||
void SnfL1ModeMusic(uint32_t sensitive, uint32_t speed) {
|
// Format is L1MusicSync on/off/toggle, sensitivity, speed
|
||||||
char buffer[SONOFF_L1_BUFFER_SIZE];
|
|
||||||
snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"mode\":%d,\"sensitive\":%d,\"speed\":%d"),
|
|
||||||
LocalTime(), millis()%1000,
|
|
||||||
SONOFF_L1_MODE_SYNC_TO_MUSIC,
|
|
||||||
sensitive,
|
|
||||||
speed
|
|
||||||
);
|
|
||||||
|
|
||||||
SnfL1Send(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CmndMusicSync(void)
|
|
||||||
{
|
|
||||||
// Format is L1MusicSync sensitivity,speed
|
|
||||||
// sensitivity 1..10, speed 1..100
|
// sensitivity 1..10, speed 1..100
|
||||||
char *p;
|
if (XdrvMailbox.data_len > 0) {
|
||||||
strtok_r(XdrvMailbox.data, ",", &p);
|
Snfl1.old_music_sync = Snfl1.music_sync;
|
||||||
if (0 == XdrvMailbox.payload) {
|
uint32_t parm[3] = { 0 };
|
||||||
|
ParseParameters(3, parm);
|
||||||
|
if (2 == parm[0]) {
|
||||||
|
Snfl1.music_sync ^= 1; // Toggle
|
||||||
|
} else {
|
||||||
|
Snfl1.music_sync = parm[0] & 1; // On or Off
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
SnfL1SetChannels();
|
SnfL1SetChannels();
|
||||||
|
|
||||||
ResponseCmndDone();
|
|
||||||
}
|
|
||||||
else if (p != nullptr) {
|
|
||||||
uint32_t sen = strtol(XdrvMailbox.data, nullptr, 0);
|
|
||||||
uint32_t spd = strtol(p, nullptr, 0);
|
|
||||||
if ( (sen >= 0) && (sen <= 10) && (spd >= 0) && (spd <= 100) ) {
|
|
||||||
SnfL1ModeMusic(sen, spd);
|
|
||||||
ResponseCmndDone();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return; // error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Response_P(PSTR("{\"%s\":{\"Mode\":\"%s\",\"Sensitive\":%d,\"Speed\":%d}}"),
|
||||||
|
XdrvMailbox.command, GetStateText(Snfl1.music_sync), Snfl1.sensitive, Snfl1.speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user