[Commands] Add flag to be a bit more tolerant in last argument parsing

A lot of people were running into issues with some commands no longer working after the changes of strict rules parsing.

This flag in the advanced settings may help out a bit.
Also the logs are made a bit more elaborate to describe the issue.
This commit is contained in:
Gijs Noorlander
2019-12-04 11:54:41 +01:00
parent 701001d3e6
commit 099a2071c7
13 changed files with 85 additions and 20 deletions
+35 -8
View File
@@ -42,15 +42,31 @@ bool checkNrArguments(const char *cmd, const char *Line, int nrArguments) {
log += Line;
} else {
// Check for one more argument than allowed, since we apparently have one.
for (int i = 0; i <= nrArguments; ++i) {
if (i < nrArguments) {
log += F(" arg");
bool done = false;
int i = 1;
while (!done) {
String parameter;
if (i == nrArguments) {
parameter = tolerantParseStringKeepCase(Line, i+ 1);
done = true;
} else {
log += F(" extraArg");
parameter = parseStringKeepCase(Line, i + 1);
}
log += String(i + 1);
log += '=';
log += parseString(Line, i + 2);
done = parameter.length() == 0;
if (!done) {
if (i <= nrArguments) {
if (Settings.TolerantLastArgParse() && i == nrArguments) {
log += F(" (fixed)");
}
log += F(" Arg");
} else {
log += F(" ExtraArg");
}
log += String(i);
log += '=';
log += parameter;
}
++i;
}
}
log += F(" lineLength=");
@@ -60,6 +76,17 @@ bool checkNrArguments(const char *cmd, const char *Line, int nrArguments) {
log += Line;
log += '_';
addLog(LOG_LEVEL_ERROR, log);
if (!Settings.TolerantLastArgParse()) {
log = F("Command not executed!");
} else {
log = F("Command executed, but may fail.");
}
log += F(" See: https://github.com/letscontrolit/ESPEasy/issues/2724");
addLog(LOG_LEVEL_ERROR, log);
}
if (Settings.TolerantLastArgParse()) {
return true;
}
return false;
}
@@ -138,7 +165,7 @@ bool executeInternalCommand(const char *cmd, struct EventStruct *event, const ch
case 'l': {
COMMAND_CASE( "let", Command_Rules_Let, 2); // Rules.h
COMMAND_CASE( "load", Command_Settings_Load, 0); // Settings.h
COMMAND_CASE( "logentry", Command_logentry, 2); // Diagnostic.h
COMMAND_CASE( "logentry", Command_logentry, 1); // Diagnostic.h
COMMAND_CASE("logportstatus", Command_logPortStatus, 0); // Diagnostic.h
COMMAND_CASE( "lowmem", Command_Lowmem, 0); // Diagnostic.h
break;
+3 -1
View File
@@ -60,7 +60,9 @@
#define DEFAULT_WIFI_NONE_SLEEP false // When set, the wifi will be set to no longer sleep (more power
// used and need reboot to reset mode)
#define DEFAULT_GRATUITOUS_ARP false // When set, the node will send periodical gratuitous ARP
// packets to announce itself.
// packets to announce itself.
#define DEFAULT_TOLERANT_LAST_ARG_PARSE false // When set, the last argument of some commands will be parsed to the end of the line
// See: https://github.com/letscontrolit/ESPEasy/issues/2724
// --- Default Controller ------------------------------------------------------------------------------
#define DEFAULT_CONTROLLER false // true or false enabled or disabled, set 1st controller
+1
View File
@@ -158,6 +158,7 @@ String parseString(const String& string, byte indexFind);
String parseStringKeepCase(const String& string, byte indexFind);
String parseStringToEnd(const String& string, byte indexFind);
String parseStringToEndKeepCase(const String& string, byte indexFind);
String tolerantParseStringKeepCase(const String& string, byte indexFind);
int parseCommandArgumentInt(const String& string, unsigned int argc);
+2
View File
@@ -476,6 +476,8 @@ bool remoteConfig(struct EventStruct *event, const String& string)
if (parseString(string, 2) == F("task"))
{
String configTaskName = parseStringKeepCase(string, 3);
// FIXME TD-er: This command is not using the tolerance setting
// tolerantParseStringKeepCase(Line, 4);
String configCommand = parseStringToEndKeepCase(string, 4);
if ((configTaskName.length() == 0) || (configCommand.length() == 0)) {
+8
View File
@@ -436,6 +436,14 @@ String parseStringToEndKeepCase(const String& string, byte indexFind) {
return stripQuotes(result);
}
String tolerantParseStringKeepCase(const String& string, byte indexFind)
{
if (Settings.TolerantLastArgParse()) {
return parseStringToEndKeepCase(string, indexFind);
}
return parseStringKeepCase(string, indexFind);
}
// escapes special characters in strings for use in html-forms
void htmlEscape(String& html)
{
+3
View File
@@ -65,6 +65,7 @@ void handle_advanced() {
Settings.Latitude = getFormItemFloat(F("latitude"));
Settings.Longitude = getFormItemFloat(F("longitude"));
Settings.OldRulesEngine(isFormItemChecked(F("oldrulesengine")));
Settings.TolerantLastArgParse(isFormItemChecked(F("tolerantargparse")));
Settings.ForceWiFi_bg_mode(isFormItemChecked(getInternalLabel(LabelType::FORCE_WIFI_BG)));
Settings.WiFiRestart_connection_lost(isFormItemChecked(getInternalLabel(LabelType::RESTART_WIFI_LOST_CONN)));
Settings.EcoPowerMode(isFormItemChecked(getInternalLabel(LabelType::CPU_ECO_MODE)));
@@ -89,6 +90,8 @@ void handle_advanced() {
addFormCheckBox(F("Rules"), F("userules"), Settings.UseRules);
addFormCheckBox(F("Old Engine"), F("oldrulesengine"), Settings.OldRulesEngine());
addFormCheckBox(F("Tolerant last parameter"), F("tolerantargparse"), Settings.TolerantLastArgParse());
addFormNote(F("Perform less strict parsing on last argument of some commands (e.g. publish and sendToHttp)"));
addFormSubHeader(F("Controller Settings"));
+1 -1
View File
@@ -145,7 +145,7 @@ String Command_Debug(struct EventStruct *event, const char *Line)
String Command_logentry(struct EventStruct *event, const char *Line)
{
// FIXME TD-er: Add an extra optional parameter to set log level.
addLog(LOG_LEVEL_INFO, parseStringKeepCase(Line, 2));
addLog(LOG_LEVEL_INFO, tolerantParseStringKeepCase(Line, 2));
return return_command_success();
}
+5 -4
View File
@@ -13,9 +13,8 @@
String Command_HTTP_SendToHTTP(struct EventStruct *event, const char* Line)
{
if (WiFiConnected()) {
String strLine = Line;
String host = parseString(strLine, 2);
const int port = parseCommandArgumentInt(strLine, 2);
String host = parseString(Line, 2);
const int port = parseCommandArgumentInt(Line, 2);
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("SendToHTTP: Host: ");
log += host;
@@ -24,7 +23,9 @@ String Command_HTTP_SendToHTTP(struct EventStruct *event, const char* Line)
addLog(LOG_LEVEL_DEBUG, log);
}
if (!port < 0 || port > 65535) return return_command_failed();
String path = parseStringToEndKeepCase(strLine, 4);
// FIXME TD-er: This is not using the tolerant settings option.
// String path = tolerantParseStringKeepCase(Line, 4);
String path = parseStringToEndKeepCase(Line, 4);
#ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log = F("SendToHTTP: Path: ");
+1 -1
View File
@@ -52,7 +52,7 @@ String Command_MQTT_Publish(struct EventStruct *event, const char *Line)
if (enabledMqttController >= 0) {
// Command structure: Publish,<topic>,<value>
String topic = parseStringKeepCase(Line, 2);
String value = parseStringKeepCase(Line, 3);
String value = tolerantParseStringKeepCase(Line, 3);
addLog(LOG_LEVEL_DEBUG, String(F("Publish: ")) + topic + value);
if ((topic.length() > 0) && (value.length() > 0)) {
+6 -5
View File
@@ -31,7 +31,7 @@ String Command_UPD_SendTo(struct EventStruct *event, const char *Line)
int destUnit = parseCommandArgumentInt(Line, 1);
if ((destUnit > 0) && (destUnit < 255))
{
String eventName = parseStringKeepCase(Line, 3);
String eventName = tolerantParseStringKeepCase(Line, 3);
SendUDPCommand(destUnit, eventName.c_str(), eventName.length());
}
return return_command_success();
@@ -40,12 +40,13 @@ String Command_UPD_SendTo(struct EventStruct *event, const char *Line)
String Command_UDP_SendToUPD(struct EventStruct *event, const char *Line)
{
if (WiFiConnected()) {
String strLine = Line;
String ip = parseString(strLine, 2);
int port = parseCommandArgumentInt(strLine, 2);
String ip = parseString(Line, 2);
int port = parseCommandArgumentInt(Line, 2);
if (port < 0 || port > 65535) return return_command_failed();
String message = parseStringToEndKeepCase(strLine, 4);
// FIXME TD-er: This command is not using the tolerance setting
// tolerantParseStringKeepCase(Line, 4);
String message = parseStringToEndKeepCase(Line, 4);
IPAddress UDP_IP;
if (UDP_IP.fromString(ip)) {
+4
View File
@@ -84,6 +84,10 @@
#ifndef DEFAULT_GRATUITOUS_ARP
#define DEFAULT_GRATUITOUS_ARP false // When set, the node will send periodical gratuitous ARP packets to announce itself.
#endif
#ifndef DEFAULT_TOLERANT_LAST_ARG_PARSE
#define DEFAULT_TOLERANT_LAST_ARG_PARSE false // When set, the last argument of some commands will be parsed to the end of the line
// See: https://github.com/letscontrolit/ESPEasy/issues/2724
#endif
// --- Default Controller ------------------------------------------------------------------------------
#ifndef DEFAULT_CONTROLLER
+11
View File
@@ -91,6 +91,16 @@ void SettingsStruct_tmpl<N_TASKS>::gratuitousARP(bool value) {
setBitToUL(VariousBits1, 8, !value);
}
template<unsigned int N_TASKS>
bool SettingsStruct_tmpl<N_TASKS>::TolerantLastArgParse() {
return getBitFromUL(VariousBits1, 9);
}
template<unsigned int N_TASKS>
void SettingsStruct_tmpl<N_TASKS>::TolerantLastArgParse(bool value) {
setBitToUL(VariousBits1, 9, value);
}
template<unsigned int N_TASKS>
void SettingsStruct_tmpl<N_TASKS>::validate() {
if (UDPPort > 65535) { UDPPort = 0; }
@@ -213,6 +223,7 @@ void SettingsStruct_tmpl<N_TASKS>::clearMisc() {
EcoPowerMode(DEFAULT_ECO_MODE);
WifiNoneSleep(DEFAULT_WIFI_NONE_SLEEP);
gratuitousARP(DEFAULT_GRATUITOUS_ARP);
TolerantLastArgParse(DEFAULT_TOLERANT_LAST_ARG_PARSE);
}
template<unsigned int N_TASKS>
+5
View File
@@ -42,6 +42,11 @@ class SettingsStruct_tmpl
bool gratuitousARP();
void gratuitousARP(bool value);
// Be a bit more tolerant when parsing the last argument of a command.
// See: https://github.com/letscontrolit/ESPEasy/issues/2724
bool TolerantLastArgParse();
void TolerantLastArgParse(bool value);
void validate();
bool networkSettingsEmpty() const;