mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-25 03:36:42 +00:00
Refactor backlog from String to char
This commit is contained in:
parent
90a4ae0ef5
commit
05014d48cf
@ -442,7 +442,7 @@ struct TasmotaGlobal_t {
|
|||||||
TSettings* Settings = nullptr;
|
TSettings* Settings = nullptr;
|
||||||
|
|
||||||
#include <LinkedList.h>
|
#include <LinkedList.h>
|
||||||
LinkedList<String> backlog; // Command backlog implemented with LinkedList
|
LinkedList<char*> backlog; // Command backlog implemented with LinkedList
|
||||||
#define BACKLOG_EMPTY (backlog.size() == 0)
|
#define BACKLOG_EMPTY (backlog.size() == 0)
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
@ -788,19 +788,19 @@ void BacklogLoop(void) {
|
|||||||
if (!BACKLOG_EMPTY && !TasmotaGlobal.backlog_mutex) {
|
if (!BACKLOG_EMPTY && !TasmotaGlobal.backlog_mutex) {
|
||||||
TasmotaGlobal.backlog_mutex = true;
|
TasmotaGlobal.backlog_mutex = true;
|
||||||
bool nodelay = false;
|
bool nodelay = false;
|
||||||
bool nodelay_detected = false;
|
|
||||||
String cmd;
|
|
||||||
do {
|
do {
|
||||||
cmd = backlog.shift();
|
char cmd[strlen(backlog.get(0))+1]; // Need to accomodate large commands like Template
|
||||||
nodelay_detected = !strncasecmp_P(cmd.c_str(), PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY));
|
BacklogHead(cmd);
|
||||||
if (nodelay_detected) { nodelay = true; }
|
if (!strncasecmp_P(cmd, PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY))) {
|
||||||
} while (!BACKLOG_EMPTY && nodelay_detected);
|
nodelay = true;
|
||||||
if (!nodelay_detected) {
|
} else {
|
||||||
ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG);
|
ExecuteCommand(cmd, SRC_BACKLOG);
|
||||||
}
|
if (nodelay || TasmotaGlobal.backlog_nodelay) {
|
||||||
if (nodelay || TasmotaGlobal.backlog_nodelay) {
|
TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler)
|
||||||
TasmotaGlobal.backlog_timer = millis(); // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler)
|
}
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
} while (!BACKLOG_EMPTY);
|
||||||
TasmotaGlobal.backlog_mutex = false;
|
TasmotaGlobal.backlog_mutex = false;
|
||||||
}
|
}
|
||||||
if (BACKLOG_EMPTY) {
|
if (BACKLOG_EMPTY) {
|
||||||
|
@ -493,82 +493,40 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) {
|
|||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
bool SetTimedCmnd(uint32_t time, const char *command) {
|
void BacklogAdd(const char* blcommand) {
|
||||||
uint32_t now = millis();
|
// Add object at end of list
|
||||||
// Try to use the same slot if command is already present
|
char* temp = (char*)malloc(strlen(blcommand)+1);
|
||||||
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
|
if (temp != nullptr) {
|
||||||
if (TasmotaGlobal.timed_cmnd[i].time != 0) {
|
strcpy(temp, blcommand);
|
||||||
if (!strcmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str())) {
|
backlog.add(temp);
|
||||||
// Stored command already present
|
|
||||||
TasmotaGlobal.timed_cmnd[i].time = now + time;
|
|
||||||
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag
|
|
||||||
TasmotaGlobal.timed_cmnd[i].time++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Try to find an empty slot and add command
|
|
||||||
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
|
|
||||||
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot
|
|
||||||
TasmotaGlobal.timed_cmnd[i].command = command;
|
|
||||||
TasmotaGlobal.timed_cmnd[i].time = now + time;
|
|
||||||
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag
|
|
||||||
TasmotaGlobal.timed_cmnd[i].time++;
|
|
||||||
}
|
|
||||||
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))) {
|
|
||||||
// Stored command starts with command
|
|
||||||
TasmotaGlobal.timed_cmnd[i].time = 0;
|
|
||||||
TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowTimedCmnd(const char *command) {
|
void BacklogInsert(uint32_t position, const char* blcommand) {
|
||||||
bool found = false;
|
// Add object at position in list
|
||||||
uint32_t now = millis();
|
char* temp = (char*)malloc(strlen(blcommand)+1);
|
||||||
Response_P(PSTR("{\"%s\":"), XdrvMailbox.command);
|
if (temp != nullptr) {
|
||||||
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
|
strcpy(temp, (char*)blcommand);
|
||||||
if (TasmotaGlobal.timed_cmnd[i].time != 0) {
|
backlog.add(position, temp);
|
||||||
if (!strncmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str(), strlen(command))) {
|
|
||||||
// Stored command starts with command
|
|
||||||
ResponseAppend_P(PSTR("%s"), (found) ? "," : "[");
|
|
||||||
found = true;
|
|
||||||
ResponseAppend_P(PSTR("{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), TasmotaGlobal.timed_cmnd[i].time - now, TasmotaGlobal.timed_cmnd[i].command.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
ResponseAppend_P(PSTR("]}"));
|
|
||||||
} else {
|
|
||||||
ResponseAppend_P(PSTR("\"" D_JSON_EMPTY "\"}"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoopTimedCmnd(void) {
|
void BacklogClear(void) {
|
||||||
uint32_t now = millis();
|
// Clear list
|
||||||
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
|
while (backlog.size()) {
|
||||||
if ((TasmotaGlobal.timed_cmnd[i].time > 0) && (now > TasmotaGlobal.timed_cmnd[i].time)) {
|
free(backlog.pop());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************/
|
char* BacklogHead(char* blcommand) {
|
||||||
|
// Remove first object from list
|
||||||
|
char* temp = backlog.shift();
|
||||||
|
strcpy(blcommand, temp);
|
||||||
|
free(temp);
|
||||||
|
return blcommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
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
|
||||||
@ -599,7 +557,7 @@ void CmndBacklog(void) {
|
|||||||
}
|
}
|
||||||
// Do not allow command Reset in backlog
|
// Do not allow command Reset in backlog
|
||||||
if ((*blcommand != '\0') && (strncasecmp_P(blcommand, PSTR(D_CMND_RESET), strlen(D_CMND_RESET)) != 0)) {
|
if ((*blcommand != '\0') && (strncasecmp_P(blcommand, PSTR(D_CMND_RESET), strlen(D_CMND_RESET)) != 0)) {
|
||||||
backlog.add(blcommand);
|
BacklogAdd(blcommand);
|
||||||
}
|
}
|
||||||
blcommand = strtok(nullptr, ";");
|
blcommand = strtok(nullptr, ";");
|
||||||
}
|
}
|
||||||
@ -608,11 +566,13 @@ void CmndBacklog(void) {
|
|||||||
TasmotaGlobal.backlog_timer = millis();
|
TasmotaGlobal.backlog_timer = millis();
|
||||||
} else {
|
} else {
|
||||||
bool blflag = BACKLOG_EMPTY;
|
bool blflag = BACKLOG_EMPTY;
|
||||||
backlog.clear();
|
BacklogClear();
|
||||||
ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED));
|
ResponseCmndChar(blflag ? PSTR(D_JSON_EMPTY) : PSTR(D_JSON_ABORTED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
void CmndJson(void) {
|
void CmndJson(void) {
|
||||||
// Json {"template":{"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18},"power":2,"HSBColor":"51,97,100","Channel":[100,85,3]}
|
// Json {"template":{"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18},"power":2,"HSBColor":"51,97,100","Channel":[100,85,3]}
|
||||||
//
|
//
|
||||||
@ -648,31 +608,6 @@ void CmndJson(void) {
|
|||||||
// {"template":"{\"NAME\":\"Dummy\",\"GPIO\":[320,0,321],\"FLAG\":0,\"BASE\":18}","power":2,"HSBColor":"51,97,100","Channel":[100,85,3]}
|
// {"template":"{\"NAME\":\"Dummy\",\"GPIO\":[320,0,321],\"FLAG\":0,\"BASE\":18}","power":2,"HSBColor":"51,97,100","Channel":[100,85,3]}
|
||||||
// Output:
|
// Output:
|
||||||
// template {"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18};power 2;HSBColor 51,97,100;Channel1 100;Channel2 85;Channel3 3
|
// template {"NAME":"Dummy","GPIO":[320,0,321],"FLAG":0,"BASE":18};power 2;HSBColor 51,97,100;Channel1 100;Channel2 85;Channel3 3
|
||||||
/*
|
|
||||||
String backlog;
|
|
||||||
for (auto command_key : root) {
|
|
||||||
const char *command = command_key.getStr();
|
|
||||||
JsonParserToken parameters = command_key.getValue();
|
|
||||||
if (parameters.isArray()) {
|
|
||||||
JsonParserArray parameter_arr = parameters.getArray();
|
|
||||||
uint32_t index = 1;
|
|
||||||
for (auto value : parameter_arr) {
|
|
||||||
backlog = command;
|
|
||||||
backlog += index++;
|
|
||||||
backlog += " ";
|
|
||||||
backlog += value.getStr(); // Channel1 100;Channel2 85;Channel3 3
|
|
||||||
ExecuteCommand((char*)backlog.c_str(), SRC_FILE);
|
|
||||||
}
|
|
||||||
} else if (parameters.isObject()) { // Should have been escaped
|
|
||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("JSN: Object"));
|
|
||||||
} else {
|
|
||||||
backlog = command;
|
|
||||||
backlog += " ";
|
|
||||||
backlog += parameters.getStr(); // HSBColor 51,97,100
|
|
||||||
ExecuteCommand((char*)backlog.c_str(), SRC_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
String backlog; // We might need a larger string than XdrvMailbox.data_len accomodating decoded arrays
|
String backlog; // We might need a larger string than XdrvMailbox.data_len accomodating decoded arrays
|
||||||
for (auto command_key : root) {
|
for (auto command_key : root) {
|
||||||
const char *command = command_key.getStr();
|
const char *command = command_key.getStr();
|
||||||
@ -751,6 +686,85 @@ void CmndPower(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
bool SetTimedCmnd(uint32_t time, const char *command) {
|
||||||
|
uint32_t now = millis();
|
||||||
|
// Try to use the same slot if command is already present
|
||||||
|
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
|
||||||
|
if (TasmotaGlobal.timed_cmnd[i].time != 0) {
|
||||||
|
if (!strcmp(command, TasmotaGlobal.timed_cmnd[i].command.c_str())) {
|
||||||
|
// Stored command already present
|
||||||
|
TasmotaGlobal.timed_cmnd[i].time = now + time;
|
||||||
|
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag
|
||||||
|
TasmotaGlobal.timed_cmnd[i].time++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Try to find an empty slot and add command
|
||||||
|
for (uint32_t i = 0; i < MAX_TIMED_CMND; i++) {
|
||||||
|
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Free slot
|
||||||
|
TasmotaGlobal.timed_cmnd[i].command = command;
|
||||||
|
TasmotaGlobal.timed_cmnd[i].time = now + time;
|
||||||
|
if (0 == TasmotaGlobal.timed_cmnd[i].time) { // Skip empty slot flag
|
||||||
|
TasmotaGlobal.timed_cmnd[i].time++;
|
||||||
|
}
|
||||||
|
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))) {
|
||||||
|
// Stored command starts with command
|
||||||
|
TasmotaGlobal.timed_cmnd[i].time = 0;
|
||||||
|
TasmotaGlobal.timed_cmnd[i].command = (const char*) nullptr; // Force deallocation of the String internal memory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowTimedCmnd(const char *command) {
|
||||||
|
bool found = false;
|
||||||
|
uint32_t now = millis();
|
||||||
|
Response_P(PSTR("{\"%s\":"), XdrvMailbox.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))) {
|
||||||
|
// Stored command starts with command
|
||||||
|
ResponseAppend_P(PSTR("%s"), (found) ? "," : "[");
|
||||||
|
found = true;
|
||||||
|
ResponseAppend_P(PSTR("{\"" D_JSON_REMAINING "\":%d,\"" D_JSON_COMMAND "\":\"%s\"}"), TasmotaGlobal.timed_cmnd[i].time - now, TasmotaGlobal.timed_cmnd[i].command.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
ResponseAppend_P(PSTR("]}"));
|
||||||
|
} else {
|
||||||
|
ResponseAppend_P(PSTR("\"" D_JSON_EMPTY "\"}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 CmndTimedPower(void) {
|
void CmndTimedPower(void) {
|
||||||
/*
|
/*
|
||||||
Allow timed power changes on a 50ms granularity
|
Allow timed power changes on a 50ms granularity
|
||||||
@ -801,6 +815,8 @@ void CmndTimedPower(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
void CmndStatusResponse(uint32_t index) {
|
void CmndStatusResponse(uint32_t index) {
|
||||||
static String all_status = (const char*) nullptr;
|
static String all_status = (const char*) nullptr;
|
||||||
|
|
||||||
|
@ -2070,14 +2070,14 @@ void ExecuteCommandBlock(const char * commands, int len)
|
|||||||
{
|
{
|
||||||
//Insert into backlog
|
//Insert into backlog
|
||||||
TasmotaGlobal.backlog_mutex = true;
|
TasmotaGlobal.backlog_mutex = true;
|
||||||
backlog.add(insertPosition, sCurrentCommand);
|
BacklogInsert(insertPosition, sCurrentCommand.c_str());
|
||||||
TasmotaGlobal.backlog_mutex = false;
|
TasmotaGlobal.backlog_mutex = false;
|
||||||
insertPosition++;
|
insertPosition++;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (sCurrentCommand.length() > 0) {
|
if (sCurrentCommand.length() > 0) {
|
||||||
//Insert into backlog
|
//Insert into backlog
|
||||||
backlog.add(insertPosition, sCurrentCommand);
|
BacklogInsert(insertPosition, sCurrentCommand.c_str());
|
||||||
insertPosition++;
|
insertPosition++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user