From 1da8f94a05262f6e0878b9f619d24eac08e349fe Mon Sep 17 00:00:00 2001 From: andrethomas Date: Mon, 18 Feb 2019 21:52:22 +0200 Subject: [PATCH 1/4] Introduce Reset 6 --- sonoff/sonoff.ino | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e54c23260..058631a15 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1309,7 +1309,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) case 2: case 3: case 4: - case 5: + case 5 ... 6: restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; @@ -2084,14 +2084,33 @@ void Every250mSeconds(void) } } if (restart_flag && (backlog_pointer == backlog_index)) { - if ((214 == restart_flag) || (215 == restart_flag)) { + if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { char storage[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)]; + char storage_mqtt_host[sizeof(Settings.mqtt_host)]; + uint16_t storage_mqtt_port; + char storage_mqtt_user[sizeof(Settings.mqtt_user)]; + char storage_mqtt_pwd[sizeof(Settings.mqtt_pwd)]; + char storage_mqtt_topic[sizeof(Settings.mqtt_topic)]; memcpy(storage, Settings.sta_ssid, sizeof(storage)); // Backup current SSIDs and Passwords - if (215 == restart_flag) { + if (216 == restart_flag) { + memcpy(storage_mqtt_host, Settings.mqtt_host, sizeof(Settings.mqtt_host)); + storage_mqtt_port = Settings.mqtt_port; + memcpy(storage_mqtt_user, Settings.mqtt_user, sizeof(Settings.mqtt_user)); + memcpy(storage_mqtt_pwd, Settings.mqtt_pwd, sizeof(Settings.mqtt_pwd)); + memcpy(storage_mqtt_topic, Settings.mqtt_topic, sizeof(Settings.mqtt_topic)); + } + if ((215 == restart_flag) || (216 == restart_flag)) { SettingsErase(0); // Erase all flash from program end to end of physical flash } SettingsDefault(); memcpy(Settings.sta_ssid, storage, sizeof(storage)); // Restore current SSIDs and Passwords + if (216 == restart_flag) { // Restore the mqtt host, port, username and password + memcpy(Settings.mqtt_host, storage_mqtt_host, sizeof(Settings.mqtt_host)); + Settings.mqtt_port = storage_mqtt_port; + memcpy(Settings.mqtt_user, storage_mqtt_user, sizeof(Settings.mqtt_user)); + memcpy(Settings.mqtt_pwd, storage_mqtt_pwd, sizeof(Settings.mqtt_pwd)); + memcpy(Settings.mqtt_topic, storage_mqtt_topic, sizeof(Settings.mqtt_topic)); + } restart_flag = 2; } else if (213 == restart_flag) { From 32c1e2d13c9b6fc28a7a5fd80e0a5d1fdb614b03 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Feb 2019 10:48:19 +0100 Subject: [PATCH 2/4] Tuning uptime and add utctime Tuning uptime and add utctime --- sonoff/sonoff.ino | 5 +---- sonoff/support_rtc.ino | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 058631a15..55d218456 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1306,10 +1306,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) restart_flag = 211; snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING); break; - case 2: - case 3: - case 4: - case 5 ... 6: + case 2 ... 6: restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 5c9f9e2b4..e13dd540e 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -181,19 +181,16 @@ uint32_t UpTime(void) } } +uint32_t GetMinutesUptime(void) +{ + return (UpTime() / 60); +} + String GetUptime(void) { return GetDuration(UpTime()); } -uint32_t GetMinutesUptime(void) -{ - TIME_T ut; - BreakTime(UpTime(), ut); - - return (ut.days *1440) + (ut.hour *60) + ut.minute; -} - uint32_t GetMinutesPastMidnight(void) { uint32_t minutes = 0; @@ -326,6 +323,11 @@ uint32_t RuleToTime(TimeRule r, int yr) return t; } +uint32_t UtcTime(void) +{ + return utc_time; +} + uint32_t LocalTime(void) { return local_time; From 06c97c4e1954c7243493768b84bb7952eea0b158 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Feb 2019 12:51:38 +0100 Subject: [PATCH 3/4] Fix command WebSend Fix command WebSend intermittent results (#5273) --- sonoff/_changelog.ino | 1 + sonoff/xdrv_01_webserver.ino | 89 +++++++++++++++++------------------- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index a08bea0fc..0549b2576 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -8,6 +8,7 @@ * Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections * Add property MqttCount to status 6 message representing number of Mqtt re-connections * Add property Downtime to state and status 11 message representing the duration of wifi connection loss + * Fix command WebSend intermittent results (#5273) * * 6.4.1.16 20190211 * Initial support for online template change using command Template or GUI Configure Other (#5177) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index c78a47c57..46b6ca6eb 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2146,23 +2146,22 @@ String UrlEncode(const String& text) int WebSend(char *buffer) { - /* [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON - * [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON - * [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 - * [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 - */ + // [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON + // [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON + // [sonoff] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 + // [sonoff,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://sonoff/any/link/starting/with/a/slash.php?log=123 char *host; char *port; char *user; char *password; char *command; - uint16_t nport = 80; int status = 1; // Wrong parameters // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON | host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON | if (host && command) { + String url = F("http:"); // url = |http:| host = Trim(host); // host = |[ 192.168.178.86 : 80 , admin : joker| host++; // host = | 192.168.178.86 : 80 , admin : joker| - Skip [ host = strtok_r(host, ",", &user); // host = | 192.168.178.86 : 80 |, user = | admin : joker| @@ -2170,66 +2169,62 @@ int WebSend(char *buffer) host = Trim(host); // host = |192.168.178.86| if (port) { port = Trim(port); // port = |80| - nport = atoi(port); + url += port; // url = |http:80| } + url += F("//"); // url = |http://| or |http:80//| + url += host; // url = |http://192.168.178.86| + if (user) { user = strtok_r(user, ":", &password); // user = | admin |, password = | joker| user = Trim(user); // user = |admin| if (password) { password = Trim(password); } // password = |joker| } + command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123| - - String nuri = ""; if (command[0] != '/') { - nuri = "/cm?"; + url += F("/cm?"); // url = |http://192.168.178.86/cm?| if (user && password) { - nuri += F("user="); - nuri += user; - nuri += F("&password="); - nuri += password; - nuri += F("&"); + url += F("user="); // url = |http://192.168.178.86/cm?user=| + url += user; // url = |http://192.168.178.86/cm?user=admin| + url += F("&password="); // url = |http://192.168.178.86/cm?user=admin&password=| + url += password; // url = |http://192.168.178.86/cm?user=admin&password=joker| + url += F("&"); // url = |http://192.168.178.86/cm?user=admin&password=joker&| } - nuri += F("cmnd="); + url += F("cmnd="); // url = |http://192.168.178.86/cm?cmnd=| or |http://192.168.178.86/cm?user=admin&password=joker&cmnd=| } - nuri += command; - String uri = UrlEncode(nuri); + url += command; // url = |http://192.168.178.86/cm?cmnd=POWER1 ON| - IPAddress host_ip; - if (WiFi.hostByName(host, host_ip)) { - WiFiClient client; - - bool connected = false; - uint8_t retry = 2; - while ((retry > 0) && !connected) { - --retry; - connected = client.connect(host_ip, nport); - if (connected) break; - } - - if (connected) { - String url = F("GET "); - url += uri; - url += F(" HTTP/1.1\r\nHost: "); -// url += IPAddress(host_ip).toString(); - url += host; // https://tools.ietf.org/html/rfc7230#section-5.4 (#4331) - if (port) { - url += F(":"); - url += port; - } - url += F("\r\nConnection: close\r\n\r\n"); - -//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str()); +//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Uri |%s|"), url.c_str()); //AddLog(LOG_LEVEL_DEBUG); - client.print(url.c_str()); - client.flush(); - client.stop(); + HTTPClient http; + if (http.begin(UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON| + int http_code = http.GET(); // Start connection and send HTTP header + if (http_code > 0) { // http_code will be negative on error + if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) { +/* + // Return received data to the user - Adds 900+ bytes to the code + String result = http.getString(); // File found at server - may need lot of ram or trigger out of memory! + uint16_t j = 0; + for (uint16_t i = 0; i < result.length(); i++) { + char text = result.charAt(i); + if (text > 31) { // Remove control characters like linefeed + mqtt_data[j] = result.charAt(i); + j++; + if (j == sizeof(mqtt_data) -2) { break; } + } + } + mqtt_data[j] = '\0'; + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); +*/ + } status = 0; // No error - Done } else { status = 2; // Connection failed } + http.end(); } else { - status = 3; // Host not found + status = 3; // Host not found or connection error } } return status; From 280dd25a8b65aa0f58ec1719ba290ec3d3cd7bcf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 19 Feb 2019 14:49:15 +0100 Subject: [PATCH 4/4] Optimize RAM for expression Optimize RAM for expression and add two more constant variables (#5275) --- sonoff/support_rtc.ino | 4 +-- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_10_rules.ino | 56 +++++++++++++++++++-------------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index e13dd540e..35f9b61e9 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -181,7 +181,7 @@ uint32_t UpTime(void) } } -uint32_t GetMinutesUptime(void) +uint32_t MinutesUptime(void) { return (UpTime() / 60); } @@ -191,7 +191,7 @@ String GetUptime(void) return GetDuration(UpTime()); } -uint32_t GetMinutesPastMidnight(void) +uint32_t MinutesPastMidnight(void) { uint32_t minutes = 0; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 1b0f480fb..3c3b1f376 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -232,7 +232,7 @@ String GetSun(uint8_t dawn) return String(stime); } -uint16_t GetSunMinutes(uint8_t dawn) +uint16_t SunMinutes(uint8_t dawn) { uint8_t hour[2]; uint8_t minute[2]; diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 9603e549b..08c6c362b 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -185,11 +185,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } snprintf_P(stemp, sizeof(stemp), PSTR("%%TIME%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetMinutesPastMidnight()); + rule_param = String(MinutesPastMidnight()); } snprintf_P(stemp, sizeof(stemp), PSTR("%%UPTIME%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetMinutesUptime()); + rule_param = String(MinutesUptime()); } snprintf_P(stemp, sizeof(stemp), PSTR("%%TIMESTAMP%%")); if (rule_param.startsWith(stemp)) { @@ -198,11 +198,11 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) #if defined(USE_TIMERS) && defined(USE_SUNRISE) snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNRISE%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetSunMinutes(0)); + rule_param = String(SunMinutes(0)); } snprintf_P(stemp, sizeof(stemp), PSTR("%%SUNSET%%")); if (rule_param.startsWith(stemp)) { - rule_param = String(GetSunMinutes(1)); + rule_param = String(SunMinutes(1)); } #endif // USE_TIMERS and USE_SUNRISE rule_param.toUpperCase(); @@ -347,12 +347,12 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1); commands.replace(stemp, Settings.mems[i]); } - commands.replace(F("%time%"), String(GetMinutesPastMidnight())); - commands.replace(F("%uptime%"), String(GetMinutesUptime())); + commands.replace(F("%time%"), String(MinutesPastMidnight())); + commands.replace(F("%uptime%"), String(MinutesUptime())); commands.replace(F("%timestamp%"), GetDateAndTime(DT_LOCAL).c_str()); #if defined(USE_TIMERS) && defined(USE_SUNRISE) - commands.replace(F("%sunrise%"), String(GetSunMinutes(0))); - commands.replace(F("%sunset%"), String(GetSunMinutes(1))); + commands.replace(F("%sunrise%"), String(SunMinutes(0))); + commands.replace(F("%sunset%"), String(SunMinutes(1))); #endif // USE_TIMERS and USE_SUNRISE char command[commands.length() +1]; @@ -505,8 +505,8 @@ void RulesEvery50ms(void) json_event[0] = '\0'; switch (i) { case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(json_event)); break; - case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), GetMinutesPastMidnight()); break; - case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), GetMinutesPastMidnight()); break; + case 1: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Initialized\":%d}}"), MinutesPastMidnight()); break; + case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), MinutesPastMidnight()); break; case 3: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break; case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break; case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break; @@ -549,7 +549,7 @@ void RulesEverySecond(void) if (RtcTime.valid) { if ((uptime > 60) && (RtcTime.minute != rules_last_minute)) { // Execute from one minute after restart every minute only once rules_last_minute = RtcTime.minute; - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), GetMinutesPastMidnight()); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), MinutesPastMidnight()); RulesProcessEvent(json_event); } } @@ -625,7 +625,7 @@ bool findNextNumber(char * &pNumber, double &value) */ bool findNextVariableValue(char * &pVarname, double &value) { - bool succeed = false; + bool succeed = true; value = 0; String sVarName = ""; while (*pVarname) { @@ -637,32 +637,32 @@ bool findNextVariableValue(char * &pVarname, double &value) } } sVarName.toUpperCase(); - if (sVarName.startsWith("VAR")) { + if (sVarName.startsWith(F("VAR"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_VARS) { value = CharToDouble(vars[index -1]); - succeed = true; } - } else if (sVarName.startsWith("MEM")) { + } else if (sVarName.startsWith(F("MEM"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_MEMS) { value = CharToDouble(Settings.mems[index -1]); - succeed = true; } - } else if (sVarName.equals("TIME")) { - value = GetMinutesPastMidnight(); - succeed = true; - } else if (sVarName.equals("UPTIME")) { - value = GetMinutesUptime(); - succeed = true; + } else if (sVarName.equals(F("TIME"))) { + value = MinutesPastMidnight(); + } else if (sVarName.equals(F("UPTIME"))) { + value = MinutesUptime(); + } else if (sVarName.equals(F("UTCTIME"))) { + value = UtcTime(); + } else if (sVarName.equals(F("LOCALTIME"))) { + value = LocalTime(); #if defined(USE_TIMERS) && defined(USE_SUNRISE) - } else if (sVarName.equals("SUNRISE")) { - value = GetSunMinutes(0); - succeed = true; - } else if (sVarName.equals("SUNSET")) { - value = GetSunMinutes(1); - succeed = true; + } else if (sVarName.equals(F("SUNRISE"))) { + value = SunMinutes(0); + } else if (sVarName.equals(F("SUNSET"))) { + value = SunMinutes(1); #endif + } else { + succeed = false; } return succeed;