Change command handling

* Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547)
 * Change command handling by moving buffers up in chain solving MQTTlog support (#6524)
 * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540)
This commit is contained in:
Theo Arends 2019-10-02 16:45:53 +02:00
parent 97de80bba1
commit 8c34b9edbd
3 changed files with 53 additions and 40 deletions

View File

@ -8,6 +8,9 @@
* Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE * Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE
* Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode
* Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531) * Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531)
* Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547)
* Change command handling by moving buffers up in chain solving MQTTlog support (#6524)
* Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540)
* *
* 6.6.0.13 20190922 * 6.6.0.13 20190922
* Add command EnergyReset4 x,x to initialize total usage for two tarrifs * Add command EnergyReset4 x,x to initialize total usage for two tarrifs

View File

@ -81,55 +81,61 @@ void ResponseCmndIdxChar(const char* value)
/********************************************************************************************/ /********************************************************************************************/
void ExecuteCommand(char *cmnd, uint32_t source) void ExecuteCommand(const char *cmnd, uint32_t source)
{ {
char *start; // cmnd: "status 0" = stopic "status" and svalue " 0"
char *token; // cmnd: "var1 =1" = stopic "var1" and svalue " =1"
// cmnd: "var1=1" = stopic "var1" and svalue "=1"
#ifdef USE_DEBUG_DRIVER #ifdef USE_DEBUG_DRIVER
ShowFreeMem(PSTR("ExecuteCommand")); ShowFreeMem(PSTR("ExecuteCommand"));
#endif #endif
ShowSource(source); ShowSource(source);
token = strtok(cmnd, " "); const char *pos = cmnd;
if (token != nullptr) { while (*pos && isspace(*pos)) {
start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble pos++; // Skip all spaces
if (start) { token = start +1; }
} }
uint32_t size = (token != nullptr) ? strlen(token) : 0;
char stopic[size +2]; // / + \0
snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == nullptr) ? "" : token);
token = strtok(nullptr, ""); const char *start = pos;
size = (token != nullptr) ? strlen(token) : 0; // Get a command. Commands can only use letters, digits and underscores
char svalue[size +1]; while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) {
strlcpy(svalue, (token == nullptr) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b if ('/' == *pos) { // Skip possible cmnd/sonoff/ preamble
CommandHandler(stopic, (uint8_t*)svalue, strlen(svalue)); start = pos + 1;
}
pos++;
}
if ('\0' == *start || pos <= start) {
return; // Did not find any command to execute
}
uint32_t size = pos - start;
char stopic[size + 2]; // with leader '/' and end '\0'
stopic[0] = '/';
memcpy(stopic+1, start, size);
stopic[size+1] = '\0';
char svalue[strlen(pos) +1]; // pos point to the start of parameters
strlcpy(svalue, pos, sizeof(svalue));
CommandHandler(stopic, svalue, strlen(svalue));
} }
/********************************************************************************************/ /********************************************************************************************/
// topic: /power1 data: toggle = Console command // topicBuf: /power1 dataBuf: toggle = Console command
// topic: cmnd/sonoff/power1 data: toggle = Mqtt command using topic // topicBuf: cmnd/sonoff/power1 dataBuf: toggle = Mqtt command using topic
// topic: cmnd/sonoffs/power1 data: toggle = Mqtt command using a group topic // topicBuf: cmnd/sonoffs/power1 dataBuf: toggle = Mqtt command using a group topic
// topic: cmnd/DVES_83BB10_fb/power1 data: toggle = Mqtt command using fallback topic // topicBuf: cmnd/DVES_83BB10_fb/power1 dataBuf: toggle = Mqtt command using fallback topic
void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len)
{ {
#ifdef USE_DEBUG_DRIVER #ifdef USE_DEBUG_DRIVER
ShowFreeMem(PSTR("CommandHandler")); ShowFreeMem(PSTR("CommandHandler"));
#endif #endif
char topicBuf[TOPSZ]; while (*dataBuf && isspace(*dataBuf)) {
strlcpy(topicBuf, topic, sizeof(topicBuf)); dataBuf++; // Skip leading spaces in data
data_len--;
uint32_t i = 0;
for (i = 0; i < data_len; i++) {
if (!isspace(data[i])) { break; } // Skip leading spaces in data
} }
data_len -= i;
char dataBuf[data_len+1];
memcpy(dataBuf, data +i, sizeof(dataBuf));
bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr);
@ -139,6 +145,7 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len)
char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type)
uint32_t i = 0;
uint32_t index = 1; uint32_t index = 1;
bool user_index = false; bool user_index = false;
if (type != nullptr) { if (type != nullptr) {
@ -156,7 +163,7 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len)
type[i] = '\0'; type[i] = '\0';
} }
DEBUG_CORE_LOG(PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf);
if (type != nullptr) { if (type != nullptr) {
Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}"));
@ -686,11 +693,9 @@ void CmndSetoption(void)
IrReceiveUpdateThreshold(); IrReceiveUpdateThreshold();
break; break;
#endif #endif
#ifdef USE_TUYA_MCU
case P_DIMMER_MAX: case P_DIMMER_MAX:
restart_flag = 2; // Need a restart to update GUI restart_flag = 2; // Need a restart to update GUI
break; break;
#endif
} }
} }
} }

View File

@ -251,7 +251,7 @@ bool MqttPublishLib(const char* topic, bool retained)
return result; return result;
} }
void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len)
{ {
#ifdef USE_DEBUG_DRIVER #ifdef USE_DEBUG_DRIVER
ShowFreeMem(PSTR("MqttDataHandler")); ShowFreeMem(PSTR("MqttDataHandler"));
@ -262,8 +262,8 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
// Do not execute multiple times if Prefix1 equals Prefix2 // Do not execute multiple times if Prefix1 equals Prefix2
if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) {
char *str = strstr(topic, Settings.mqtt_prefix[0]); char *str = strstr(mqtt_topic, Settings.mqtt_prefix[0]);
if ((str == topic) && mqtt_cmnd_publish) { if ((str == mqtt_topic) && mqtt_cmnd_publish) {
if (mqtt_cmnd_publish > 3) { if (mqtt_cmnd_publish > 3) {
mqtt_cmnd_publish -= 3; mqtt_cmnd_publish -= 3;
} else { } else {
@ -273,10 +273,15 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
} }
} }
data[data_len] = 0; // Save MQTT data ASAP as it's data is discarded by PubSubClient with next publish as used in MQTTlog
char topic[TOPSZ];
strlcpy(topic, mqtt_topic, sizeof(topic));
mqtt_data[data_len] = 0;
char data[data_len +1];
memcpy(data, mqtt_data, sizeof(data));
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topic, data_len, data); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " \"%s\", " D_DATA_SIZE " %d, " D_DATA " \"%s\""), topic, data_len, data);
// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(dataBuf); } // if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(data); }
// MQTT pre-processing // MQTT pre-processing
XdrvMailbox.index = strlen(topic); XdrvMailbox.index = strlen(topic);