Add command ``TimedPower``

Add command ``TimedPower<index> <milliseconds>[,ON|OFF|TOGGLE|BLINK]`` executes ``Power<index> [ON|OFF|TOGGLE|BLINK] `` and after <millisecond> executes ``Power<index> [OFF|ON|TOGGLE|OFF]``
This commit is contained in:
Theo Arends 2024-01-15 23:58:33 +01:00
parent 5e84d57c2a
commit 789fd1e055
6 changed files with 89 additions and 2 deletions

View File

@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file.
- ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381) - ESP32 MI BLE support for Xiaomi LYWSD02MMC (#20381)
- LVGL option to add `lv.keyboard` extra widget (#20496) - LVGL option to add `lv.keyboard` extra widget (#20496)
- GUI sensor separators (#20495) - GUI sensor separators (#20495)
- Command ``TimedPower<index> <milliseconds>[,ON|OFF|TOGGLE|BLINK]`` executes ``Power<index> [ON|OFF|TOGGLE|BLINK] `` and after <millisecond> executes ``Power<index> [OFF|ON|TOGGLE|OFF]``
### Breaking Changed ### Breaking Changed

View File

@ -118,6 +118,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
## Changelog v13.3.0.3 ## Changelog v13.3.0.3
### Added ### Added
- Command ``TimedPower<index> <milliseconds>[,ON|OFF|TOGGLE|BLINK]`` executes ``Power<index> [ON|OFF|TOGGLE|BLINK] `` and after <millisecond> executes ``Power<index> [OFF|ON|TOGGLE|OFF]``
- Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213) - Support for CST816S touch interface [#20213](https://github.com/arendst/Tasmota/issues/20213)
- Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247) - Support for Sonoff Basic R4 Magic Switch [#20247](https://github.com/arendst/Tasmota/issues/20247)
- Display of active drivers using command ``status 4`` - Display of active drivers using command ``status 4``

View File

@ -275,6 +275,7 @@
#define D_STATUS13_SHUTTER "SHT" #define D_STATUS13_SHUTTER "SHT"
#define D_CMND_STATE "State" #define D_CMND_STATE "State"
#define D_CMND_POWER "Power" #define D_CMND_POWER "Power"
#define D_CMND_TIMEDPOWER "TimedPower"
#define D_CMND_FANSPEED "FanSpeed" #define D_CMND_FANSPEED "FanSpeed"
#define D_CMND_POWERONSTATE "PowerOnState" #define D_CMND_POWERONSTATE "PowerOnState"
#define D_CMND_PULSETIME "PulseTime" #define D_CMND_PULSETIME "PulseTime"

View File

@ -222,6 +222,7 @@ const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads
const uint8_t MAX_BACKLOG = 30; // Max number of commands in backlog const uint8_t MAX_BACKLOG = 30; // Max number of commands in backlog
const uint32_t MIN_BACKLOG_DELAY = 200; // Minimal backlog delay in mSeconds const uint32_t MIN_BACKLOG_DELAY = 200; // Minimal backlog delay in mSeconds
const uint8_t MAX_TIMED_CMND = 16; // Max number of timed commands
const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate
const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate

View File

@ -292,6 +292,11 @@ HardwareSerial TasConsole = Serial; // Only serial interface
char EmptyStr[1] = { 0 }; // Provide a pointer destination to an empty char string char EmptyStr[1] = { 0 }; // Provide a pointer destination to an empty char string
typedef struct {
uint32_t time;
String command;
} tTimedCmnd;
struct TasmotaGlobal_t { struct TasmotaGlobal_t {
uint32_t global_update; // Timestamp of last global temperature and humidity update uint32_t global_update; // Timestamp of last global temperature and humidity update
uint32_t baudrate; // Current Serial baudrate uint32_t baudrate; // Current Serial baudrate
@ -411,6 +416,7 @@ struct TasmotaGlobal_t {
uint8_t backlog_pointer; // Command backlog pointer uint8_t backlog_pointer; // Command backlog pointer
String backlog[MAX_BACKLOG]; // Command backlog buffer String backlog[MAX_BACKLOG]; // Command backlog buffer
#endif #endif
tTimedCmnd timed_cmnd[MAX_TIMED_CMND]; // Timed command buffer
#ifdef MQTT_DATA_STRING #ifdef MQTT_DATA_STRING
String mqtt_data; // Buffer filled by Response functions String mqtt_data; // Buffer filled by Response functions
@ -851,6 +857,7 @@ void Scheduler(void) {
static uint32_t state_50msecond = 0; // State 50msecond timer static uint32_t state_50msecond = 0; // State 50msecond timer
if (TimeReached(state_50msecond)) { if (TimeReached(state_50msecond)) {
SetNextTimeInterval(state_50msecond, 50); SetNextTimeInterval(state_50msecond, 50);
LoopTimedCmnd();
#ifdef ROTARY_V1 #ifdef ROTARY_V1
RotaryHandler(); RotaryHandler();
#endif // ROTARY_V1 #endif // ROTARY_V1

View File

@ -23,7 +23,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
// Other commands // Other commands
D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_RESTART "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_RESTART "|"
#ifndef FIRMWARE_MINIMAL_ONLY #ifndef FIRMWARE_MINIMAL_ONLY
D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_TIMEDPOWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|"
D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|"
D_CMND_SO "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_SO "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|"
D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|"
@ -63,7 +63,7 @@ SO_SYNONYMS(kTasmotaSynonyms,
void (* const TasmotaCommand[])(void) PROGMEM = { void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, &CmndSeriallog, &CmndRestart, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, &CmndSeriallog, &CmndRestart,
#ifndef FIRMWARE_MINIMAL_ONLY #ifndef FIRMWARE_MINIMAL_ONLY
&CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndBacklog, &CmndDelay, &CmndPower, &CmndTimedPower, &CmndStatus, &CmndState, &CmndSleep,
&CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata,
&CmndSetoption, &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, &CmndSetoption, &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution,
&CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution,
@ -493,6 +493,46 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) {
/********************************************************************************************/ /********************************************************************************************/
bool SetTimedCmnd(uint32_t time, const char *command) {
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot
TasmotaGlobal.timed_cmnd[i].time = millis() + time;
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag
TasmotaGlobal.timed_cmnd[i].time++;
}
TasmotaGlobal.timed_cmnd[i].command = command;
return true;
}
}
AddLog(LOG_LEVEL_INFO, PSTR("TIM: No more timer slots left"));
return false;
}
void ResetTimedCmnd(const char *command) {
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
if (TasmotaGlobal.timed_cmnd[i].time != 0) {
if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) {
TasmotaGlobal.timed_cmnd[i].time = 0;
TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory
}
}
}
}
void LoopTimedCmnd(void) {
uint32_t now = millis();
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
if ((TasmotaGlobal.timed_cmnd[i].time > 0) && (now > TasmotaGlobal.timed_cmnd[i].time)) {
TasmotaGlobal.timed_cmnd[i].time = 0;
String cmd = TasmotaGlobal.timed_cmnd[i].command;
TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory
ExecuteCommand((char*)cmd.c_str(), SRC_TIMER);
}
}
}
/********************************************************************************************/
void CmndBacklog(void) { void CmndBacklog(void) {
// Backlog command1;command2;.. Execute commands in sequence with a delay in between set with SetOption34 // Backlog command1;command2;.. Execute commands in sequence with a delay in between set with SetOption34
// Backlog0 command1;command2;.. Execute commands in sequence with no delay // Backlog0 command1;command2;.. Execute commands in sequence with no delay
@ -695,6 +735,42 @@ void CmndPower(void)
} }
} }
void CmndTimedPower(void) {
/*
TimedPower<index> <milliseconds>[,0|1|2|3]
TimedPower0 3000 - Turn all power on and then off after 3 seconds
TimedPower1 2000 - Turn power1 on and then off after 2 seconds
TimedPower2 2000,0 - Turn power2 off and then on after 2 seconds
TimedPower1 2200,1 - Turn power1 on and then off after 2.2 seconds
TimedPower2 2000,2 - Toggle power2 and then toggle again after 2 seconds
TimedPower2 2500,3 - Blink power2 and then turn off after 2.5 seconds
*/
if ((XdrvMailbox.index >= 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) {
if (XdrvMailbox.data_len > 0) {
uint32_t parm[2] = { 0, 0 };
uint32_t parms = ParseParameters(2, parm);
uint32_t time = parm[0];
uint32_t start_state = 1; // Default on
if (2 == parms) {
start_state = parm[1] & 0x03; // 0,1,2,3
}
const uint8_t contra_state[] = { 1, 0, 2, 0 };
uint32_t end_state = contra_state[start_state];
char cmnd[32];
snprintf_P(cmnd, sizeof(cmnd), PSTR(D_CMND_POWER "%d %d"), XdrvMailbox.index, end_state);
if (SetTimedCmnd(time, cmnd)) {
XdrvMailbox.payload = start_state;
CmndPower();
}
} else {
// Remove all POWER timed command
ResetTimedCmnd(D_CMND_POWER);
ResponseCmndDone();
}
}
}
void CmndStatusResponse(uint32_t index) { void CmndStatusResponse(uint32_t index) {
static String all_status = (const char*) nullptr; static String all_status = (const char*) nullptr;