From 76c102c09c4b7532e56b22fd1380a50f9bf942fc Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 27 Jul 2018 12:17:34 +0200 Subject: [PATCH 1/3] Support send / receive of binary serial data --- sonoff/settings.h | 2 +- sonoff/settings.ino | 4 ++-- sonoff/sonoff.ino | 27 ++++++++++++++++++++------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index e527d74b7..9abfa9fb9 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -48,7 +48,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t not_power_linked : 1; // bit 20 (v5.11.1f) uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i) uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f) - uint32_t rules_enabled : 1; // bit 23 (v5.12.0j) - free since v5.14.0b + uint32_t mqtt_serial_raw : 1; // bit 23 (vTDB) uint32_t rules_once : 1; // bit 24 (v5.12.0k) - free since v5.14.0b uint32_t knx_enabled : 1; // bit 25 (v5.12.0l) KNX uint32_t device_index_enable : 1; // bit 26 (v5.13.1a) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index d5541298d..10fbd10ed 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -756,7 +756,7 @@ void SettingsDelta() } if (Settings.version < 0x050E0002) { for (byte i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; } - Settings.rule_enabled = Settings.flag.rules_enabled; + Settings.rule_enabled = Settings.flag.mqtt_serial_raw; Settings.rule_once = Settings.flag.rules_once; } if (Settings.version < 0x06000000) { @@ -778,7 +778,7 @@ void SettingsDelta() } } if (Settings.version < 0x06000003) { - Settings.flag.rules_enabled = 0; + Settings.flag.mqtt_serial_raw = 0; Settings.flag.rules_once = 0; Settings.flag3.data = 0; } diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 7b63160fb..a302d65fe 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -915,15 +915,19 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200); } - else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 3)) { + else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 4)) { SetSeriallog(LOG_LEVEL_NONE); Settings.flag.mqtt_serial = 1; + Settings.flag.mqtt_serial_raw = (4 == index)?1:0; if (data_len > 0) { if (1 == index) { Serial.printf("%s\n", dataBuf); } - else if (2 == index) { - Serial.printf("%s", dataBuf); + else if (2 == index || 4 == index) { + for (int i=0; i 127) { // binary data... + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data... serial_in_byte_counter = 0; Serial.flush(); return; @@ -2190,8 +2194,9 @@ void SerialInput() } } } else { - if (serial_in_byte) { - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { + if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && + ((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; serial_polling_window = millis(); } else { @@ -2231,7 +2236,15 @@ void SerialInput() if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); + if (!Settings.flag.mqtt_serial_raw) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); + for (int i=0; i Date: Sat, 28 Jul 2018 12:30:47 +0200 Subject: [PATCH 2/3] Fix unsecure main webpage update Fix unsecure main webpage update --- sonoff/xdrv_02_webserver.ino | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 46699d757..bcc8b9173 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -29,6 +29,8 @@ uint8_t *efm8bb1_update = NULL; #endif // USE_RF_FLASH +#define D_TASMOTA_TOKEN "Tasmota-Token" + enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; const char HTTP_HEAD[] PROGMEM = @@ -57,7 +59,7 @@ const char HTTP_HEAD[] PROGMEM = "eb('p1').focus();" "}" "function lx(){" - "if(to==0){" + "if(to==1){" "if(tp<30){" "tp++;" "lt=setTimeout(lx,33);" // Wait for token from server @@ -74,21 +76,22 @@ const char HTTP_HEAD[] PROGMEM = "eb('l1').innerHTML=s;" "}" "};" - "x.open('GET','ay?t='+to+pc,true);" // Async request + "x.open('GET','ay'+pc,true);" // Async request + "x.setRequestHeader('" D_TASMOTA_TOKEN "',to);" "x.send();" // Perform command if available and get updated information "pc='';" "lt=setTimeout(la,2345-(tp*33));" "}" "function la(p){" "if(la.arguments.length==1){" - "pc='&'+p;" + "pc='?'+p;" "clearTimeout(lt);" "}else{pc='';}" - "to=0;tp=0;" + "to=1;tp=0;" "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) "x=new XMLHttpRequest();" "x.onreadystatechange=function(){" - "if(x.readyState==4&&x.status==200){to=x.responseText;}else{to=0;}" + "if(x.readyState==4&&x.status==200){to=x.getResponseHeader('" D_TASMOTA_TOKEN "');}else{to=1;}" "};" "x.open('GET','az',true);" // Async request "x.send();" // Get token from server @@ -344,6 +347,8 @@ const char HDR_CTYPE_XML[] PROGMEM = "text/xml"; const char HDR_CTYPE_JSON[] PROGMEM = "application/json"; const char HDR_CTYPE_STREAM[] PROGMEM = "application/octet-stream"; +const char HDR_TASMOTA_TOKEN[] PROGMEM = D_TASMOTA_TOKEN; + #define DNS_PORT 53 enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER}; @@ -359,7 +364,7 @@ uint8_t upload_progress_dot_count; uint8_t config_block_count = 0; uint8_t config_xor_on = 0; uint8_t config_xor_on_set = CONFIG_FILE_XOR; -long ajax_token = 0; +long ajax_token = 1; // Helper function to avoid code duplication (saves 4k Flash) static void WebGetArg(const char* arg, char* out, size_t max) @@ -631,9 +636,15 @@ void HandleToken() { char token[11]; - ajax_token = random(0x7FFFFFFF); + ajax_token = random(2, 0x7FFFFFFF); snprintf_P(token, sizeof(token), PSTR("%u"), ajax_token); + SetHeader(); + WebServer->sendHeader(FPSTR(HDR_TASMOTA_TOKEN), token); + snprintf_P(token, sizeof(token), PSTR("%u"), random(0x7FFFFFFF)); WebServer->send(200, FPSTR(HDR_CTYPE_HTML), token); + + const char* header_key[] = { D_TASMOTA_TOKEN }; + WebServer->collectHeaders(header_key, 1); } void HandleAjaxStatusRefresh() @@ -641,16 +652,13 @@ void HandleAjaxStatusRefresh() char svalue[80]; char tmp[100]; - WebGetArg("t", tmp, sizeof(tmp)); - char *p = tmp; - long ajax_token_received = strtol(p, &p, 10); - if (ajax_token_received != ajax_token) { + if (WebServer->header(FPSTR(HDR_TASMOTA_TOKEN)).toInt() != ajax_token) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND)); SetHeader(); WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), mqtt_data); return; } - ajax_token = 0; + ajax_token = 1; WebGetArg("o", tmp, sizeof(tmp)); if (strlen(tmp)) { @@ -1986,7 +1994,7 @@ int WebSend(char *buffer) /*********************************************************************************************/ enum WebCommands { CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_WEBSEND, CMND_EMULATION }; -const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ; +const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ; const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ; bool WebCommand() From da7dadae211412d5a45924a41cbedabc593b50b5 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Sat, 28 Jul 2018 15:06:31 +0200 Subject: [PATCH 3/3] Add rule triggers Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359) --- sonoff/_changelog.ino | 1 + sonoff/settings.h | 8 ++++---- sonoff/support.ino | 20 ++++++++++++++++---- sonoff/xdrv_10_rules.ino | 2 ++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 37c6b4e36..062f22a99 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,5 @@ /* 6.1.1c + * Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359) * Fix unsecure main webpage update * Add Turkish language file (#3332) * Fix command TimeDst/TimeStd invalid JSON (#3322) diff --git a/sonoff/settings.h b/sonoff/settings.h index e527d74b7..d94bcf0c3 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -155,7 +155,7 @@ typedef union { typedef union { uint8_t data; struct { - uint8_t pinmode : 3; // Enable INPUT + uint8_t pinmode : 3; // Enable INPUT uint8_t pullup : 1; // Enable internal weak pull-up resistor uint8_t b4 : 1; uint8_t b5 : 1; @@ -369,7 +369,7 @@ struct XDRVMAILBOX { char *data; } XdrvMailbox; -#define MAX_RULES_FLAG 5 // Number of bits used in RulesBitfield (tricky I know...) +#define MAX_RULES_FLAG 7 // Number of bits used in RulesBitfield (tricky I know...) typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull... uint16_t data; // Allow bit manipulation struct { @@ -378,8 +378,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint16_t time_set : 1; uint16_t mqtt_connected : 1; uint16_t mqtt_disconnected : 1; - uint16_t spare05 : 1; - uint16_t spare06 : 1; + uint16_t wifi_connected : 1; + uint16_t wifi_disconnected : 1; uint16_t spare07 : 1; uint16_t spare08 : 1; uint16_t spare09 : 1; diff --git a/sonoff/support.ino b/sonoff/support.ino index 13a9d4265..5cc9b0611 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1096,10 +1096,22 @@ void WifiBegin(uint8_t flag) AddLog(LOG_LEVEL_INFO); } +void WifiState(uint8_t state) +{ + if (state == global_state.wifi_down) { + if (state) { + rules_flag.wifi_connected = 1; + } else { + rules_flag.wifi_disconnected = 1; + } + } + global_state.wifi_down = state ^1; +} + void WifiCheckIp() { if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { - global_state.wifi_down = 0; + WifiState(1); wifi_counter = WIFI_CHECK_SEC; wifi_retry = wifi_retry_init; AddLog_P((wifi_status != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED)); @@ -1111,7 +1123,7 @@ void WifiCheckIp() } wifi_status = WL_CONNECTED; } else { - global_state.wifi_down = 1; + WifiState(0); uint8_t wifi_config_tool = Settings.sta_config; wifi_status = WiFi.status(); switch (wifi_status) { @@ -1222,7 +1234,7 @@ void WifiCheck(uint8_t param) WifiCheckIp(); } if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !wifi_config_type) { - global_state.wifi_down = 0; + WifiState(1); #ifdef BE_MINIMAL if (1 == RtcSettings.ota_loader) { RtcSettings.ota_loader = 0; @@ -1258,7 +1270,7 @@ void WifiCheck(uint8_t param) } #endif // USE_KNX } else { - global_state.wifi_down = 1; + WifiState(0); #if defined(USE_WEBSERVER) && defined(USE_EMULATION) UdpDisconnect(); #endif // USE_EMULATION diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 3296a9560..cc2ec65d6 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -432,6 +432,8 @@ void RulesEvery50ms() case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), GetMinutesPastMidnight()); 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; + case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break; } if (json_event[0]) { RulesProcessEvent(json_event);