From d790b1cfcaf2abc4f880f615d7903a54481266be Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:16:07 +0100 Subject: [PATCH 1/3] 6.4.1.20 Webserver uses chunks 6.4.1.20 20190304 * Changed webserver content handling from single String to small Chunks increasing RAM --- sonoff/_changelog.ino | 5 +- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 865 ++++++++++++++++++----------------- sonoff/xdrv_02_mqtt.ino | 46 +- sonoff/xdrv_07_domoticz.ino | 53 +-- sonoff/xdrv_09_timers.ino | 96 ++-- sonoff/xdrv_11_knx.ino | 200 +++----- sonoff/xsns_34_hx711.ino | 39 +- 8 files changed, 633 insertions(+), 673 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3690ecf4a..f5606578a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.4.1.19 20190222 +/* 6.4.1.20 20190304 + * Changed webserver content handling from single String to small Chunks increasing RAM + * + * 6.4.1.19 20190222 * Add command SetOption37 for RGBCW color mapping (#5326) * Add Korean language translations (#5344) * Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373) diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index d4bfa230b..6dc3c6f38 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06040113 +#define VERSION 0x06040114 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index cbd52ccee..40f8f7fbf 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -27,6 +27,8 @@ #define XDRV_01 1 +#define CHUNKED_BUFFER_SIZE 400 // Chunk buffer size + #ifndef WIFI_SOFT_AP_CHANNEL #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI #endif @@ -49,7 +51,7 @@ const char HTTP_HEAD[] PROGMEM = "" "" "" - "{h} - {v}" + "%s - %s" ""; + "window.onload=u;"; const char HTTP_SCRIPT_ROOT[] PROGMEM = "function la(p){" @@ -76,17 +77,17 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "a=p;" "clearTimeout(lt);" "}" - "if(x!=null){x.abort();}" // Abort if no response within Settings.web_refresh milliseconds (happens on restart 1) + "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){" - "var s=x.responseText.replace(/{t}/g,\"\").replace(/{s}/g,\"\").replace(/{c}/g,\"%'>
\").replace(/{s}/g,\"
\").replace(/{c}/g,\"%%'>
hasArg("m") "x.send();" - "lt=setTimeout(la,{a});" // Settings.web_refresh + "lt=setTimeout(la,%d);" // Settings.web_refresh "}" "function lb(p){" "la('&d='+p);" // &d related to WebGetArg("d", tmp, sizeof(tmp)); @@ -129,7 +130,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.onreadystatechange=function(){" "if(x.readyState==4&&x.status==200){" "var z,d;" - "d=x.responseText.split(/\1/);" // Field separator + "d=x.responseText.split(/}1/);" // Field separator "id=d.shift();" "if(d.shift()==0){t.value='';}" "z=d.shift();" @@ -141,18 +142,18 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "x.open('GET','cs?c2='+id+o,true);" // Related to WebServer->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp)) "x.send();" "}" - "lt=setTimeout(l,{a});" + "lt=setTimeout(l,%d);" "return false;" "}" "window.onload=l;"; const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM = - "\2%d'>%s (%d\3"; // \2 and \3 are used in below os.replace + "}2%d'>%s (%d}3"; // }2 and }3 are used in below os.replace const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM = "var os;" "function sk(s,g){" // s = value, g = id and name - "var o=os.replace(/\2/g,\"
\").replace(/{m}/g,\"\").replace(/{e}/g,\"
\").replace(/{m}/g,\"\").replace(/{e}/g,\"
\").replace(/}2/g,\"\");" "eb('i').innerHTML=s;" "}" - "window.onload=i;" - ""; + "window.onload=i;"; -const char HTTP_HEAD_STYLE[] PROGMEM = +const char HTTP_HEAD_STYLE1[] PROGMEM = "" "" "" @@ -266,11 +268,12 @@ const char HTTP_HEAD_STYLE[] PROGMEM = #endif "
" #ifdef LANGUAGE_MODULE_NAME - "

" D_MODULE " {ha

" + "

" D_MODULE " %s

" #else - "

{ha " D_MODULE "

" + "

%s " D_MODULE "

" #endif - "

{h}

{j}
"; + "

%s

%s"; + const char HTTP_MSG_SLIDER1[] PROGMEM = "
" D_COLDLIGHT "" D_WARMLIGHT "
" "
"; @@ -333,61 +336,39 @@ const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = const char HTTP_FORM_MODULE[] PROGMEM = "
 " D_MODULE_PARAMETERS " " "
" - "

" D_MODULE_TYPE " ({mt)

"; + "

" D_MODULE_TYPE " (%s)

" + "
"; -const char HTTP_LNK_ITEM[] PROGMEM = - "
{v} ({w}) {i} {r}%
"; -const char HTTP_LNK_SCAN[] PROGMEM = - "
"; const char HTTP_FORM_WIFI[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "" - "

" D_AP1_SSID " (" STA_SSID1 ")

" + "

" D_AP1_SSID " (" STA_SSID1 ")

" "

" D_AP1_PASSWORD "

" - "

" D_AP2_SSID " (" STA_SSID2 ")

" + "

" D_AP2_SSID " (" STA_SSID2 ")

" "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (" WIFI_HOSTNAME ")

"; + "

" D_HOSTNAME " (%s)

"; const char HTTP_FORM_LOG1[] PROGMEM = "
 " D_LOGGING_PARAMETERS " " ""; const char HTTP_FORM_LOG2[] PROGMEM = - "

{b0 ({b1)

"; -const char HTTP_FORM_LOG3[] PROGMEM = - "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; + "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" + "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" + "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; const char HTTP_FORM_OTHER[] PROGMEM = "
 " D_OTHER_PARAMETERS " " "" "

" "
 " D_TEMPLATE " " - "

" - "

" D_ACTIVATE "

" + "

" + "

" D_ACTIVATE "

" "
" "
" "" D_WEB_ADMIN_PASSWORD "

" "
" - "" D_MQTT_ENABLE "
" + "" D_MQTT_ENABLE "
" "
"; - const char HTTP_FORM_OTHER2[] PROGMEM = - "" D_FRIENDLY_NAME " {1 ({2)

"; -#ifdef USE_EMULATION -const char HTTP_FORM_OTHER3a[] PROGMEM = - "

" // Keep close to Friendlynames so do not use
- "
 " D_EMULATION " 

"; -const char HTTP_FORM_OTHER3b[] PROGMEM = - "{3{4
"; // Different id only used for labels -const char HTTP_FORM_OTHER3c[] PROGMEM = - "

"; -#endif // USE_EMULATION const char HTTP_FORM_END[] PROGMEM = "
" @@ -401,30 +382,34 @@ const char HTTP_FORM_UPG[] PROGMEM = "
" "
 " D_UPGRADE_BY_WEBSERVER " " "" - "
" D_OTA_URL "

" + "
" D_OTA_URL "

" "
" "


" "
 " D_UPGRADE_BY_FILE_UPLOAD " "; const char HTTP_FORM_RST_UPG[] PROGMEM = "
" "

" - "
" + "
" "
" "
" ""; + const char HTTP_FORM_CMND[] PROGMEM = "


" "
" "
" // "
" ""; + const char HTTP_TABLE100[] PROGMEM = "
"; + const char HTTP_COUNTER[] PROGMEM = "
"; + const char HTTP_END[] PROGMEM = "
" - "" + "" "" "" ""; @@ -435,6 +420,11 @@ const char HTTP_DEVICE_STATE[] PROGMEM = "%s"); + WSContentSend(FPSTR(HTTP_TABLE100)); + WSContentSend(F("")); if (SONOFF_IFAN02 == my_module_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); - page += mqtt_data; + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); for (uint8_t i = 0; i < MAX_FAN_SPEED; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); - page += mqtt_data; + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); } } else { for (uint8_t idx = 1; idx <= devices_present; idx++) { snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_DEVICE_CONTROL, - 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); - page += mqtt_data; + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); } } - page += F("
" D_CONFIGURATION_SAVED "
"); - if (2 == type) { - page += F("
" D_TRYING_TO_CONNECT "
"); - } - page += F(""); - } - else { - page.replace(F("{v}"), FPSTR(S_RESTART)); - } - bool reset_only = (HTTP_MANAGER_RESET_ONLY == webserver_state); - page += FPSTR(HTTP_MSG_RSTRT); + WSContentStart((type) ? FPSTR(S_SAVE_CONFIGURATION) : FPSTR(S_RESTART), !reset_only); + WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD)); + WSContentSendStyle(); + if (type) { + WSContentSend(F("
" D_CONFIGURATION_SAVED "
")); + if (2 == type) { + WSContentSend(F("
" D_TRYING_TO_CONNECT "
")); + } + WSContentSend(F("
")); + } + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); if (HTTP_MANAGER == webserver_state || reset_only) { webserver_state = HTTP_ADMIN; } else { - page += FPSTR(HTTP_BTN_MAIN); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); } - ShowPage(page, !reset_only); + WSContentStop(); ShowWebSource(SRC_WEBGUI); restart_flag = 2; @@ -692,11 +777,10 @@ void WebRestart(uint8_t type) void HandleWifiLogin(void) { - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR( D_CONFIGURE_WIFI )); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_LOGIN); - ShowPage(page, false); // false means show page no matter if the client has or has not credentials + WSContentStart(FPSTR(D_CONFIGURE_WIFI), false); // false means show page no matter if the client has or has not credentials + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_LOGIN)); + WSContentStop(); } void HandleRoot(void) @@ -732,68 +816,60 @@ void HandleRoot(void) char stemp[5]; - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); - page += FPSTR(HTTP_SCRIPT_ROOT); - page += FPSTR(HTTP_HEAD_STYLE); + WSContentStart(FPSTR(S_MAIN_MENU)); + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); + WSContentSendStyle(); - page += F("
"); + WSContentSend(F("
")); if (devices_present) { if (light_type) { if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER1, LightGetColorTemp()); - page += mqtt_data; + WSContentSend_P(HTTP_MSG_SLIDER1, LightGetColorTemp()); } - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER2, Settings.light_dimmer); - page += mqtt_data; + WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer); } - page += FPSTR(HTTP_TABLE100); - page += F("
"); + WSContentSend(F("
")); } if (SONOFF_BRIDGE == my_module_type) { - page += FPSTR(HTTP_TABLE100); - page += F(""); + WSContentSend(FPSTR(HTTP_TABLE100)); + WSContentSend(F("")); uint8_t idx = 0; for (uint8_t i = 0; i < 4; i++) { - if (idx > 0) { page += F(""); } + if (idx > 0) { WSContentSend(F("")); } for (uint8_t j = 0; j < 4; j++) { idx++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); - page += mqtt_data; + WSContentSend_P(PSTR(""), idx, idx); // &k is related to WebGetArg("k", tmp, sizeof(tmp)); } } - page += F(""); + WSContentSend(F("")); } #ifndef FIRMWARE_MINIMAL mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); - page += String(mqtt_data); + WSContentSend(mqtt_data); #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { - page += FPSTR(HTTP_BTN_MENU1); - page += FPSTR(HTTP_BTN_RSTRT); + WSContentSend(FPSTR(HTTP_BTN_MENU1)); + WSContentSend(FPSTR(HTTP_BTN_RSTRT)); } - ShowPage(page); + WSContentStop(); } bool HandleRootStatusRefresh(void) @@ -874,19 +950,6 @@ bool HandleRootStatusRefresh(void) return true; } -bool HttpCheckPriviledgedAccess(bool autorequestauth = true) -{ - if (HTTP_USER == webserver_state) { - HandleRoot(); - return false; - } - if (autorequestauth && !WebAuthenticate()) { - WebServer->requestAuthentication(); - return false; - } - return true; -} - /*-------------------------------------------------------------------------------------------*/ #ifndef FIRMWARE_MINIMAL @@ -897,21 +960,20 @@ void HandleConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_BTN_MENU_MODULE); + WSContentStart(FPSTR(S_CONFIGURATION)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_BTN_MENU_MODULE)); mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_BUTTON); XsnsCall(FUNC_WEB_ADD_BUTTON); - page += String(mqtt_data); + WSContentSend(mqtt_data); - page += FPSTR(HTTP_BTN_MENU4); - page += FPSTR(HTTP_BTN_RESET); - page += FPSTR(HTTP_BTN_MENU5); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentSend(FPSTR(HTTP_BTN_MENU4)); + WSContentSend(FPSTR(HTTP_BTN_RESET)); + WSContentSend(FPSTR(HTTP_BTN_MENU5)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } /*-------------------------------------------------------------------------------------------*/ @@ -930,7 +992,7 @@ void HandleTemplateConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; - for (uint8_t i = 0; i < MAXMODULE; i++) { // "\2'%d'>%s (%d)\3" - "\2'0'>Sonoff Basic (1)\3" + for (uint8_t i = 0; i < MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" uint8_t midx = pgm_read_byte(kModuleNiceList + i); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); page += mqtt_data; @@ -950,12 +1012,12 @@ void HandleTemplateConfiguration(void) Settings.module = module_save; String page = AnyModuleName(module); // NAME: Generic - page += F("\1"); // Field separator + page += F("}1"); // Field separator - for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: \2'0'>None (0)\3\2'17'>Button1 (17)\3... + for (uint8_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3... if (1 == i) { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); // \2'255'>User (255)\3 + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); // }2'255'>User (255)}3 page += mqtt_data; } @@ -964,14 +1026,14 @@ void HandleTemplateConfiguration(void) page += mqtt_data; } - mqtt_data[0] = '\1'; // Field separator - mqtt_data[1] = '\0'; // Char eot + page += F("}1"); // Field separator + mqtt_data[0] = '\0'; for (uint8_t i = 0; i < sizeof(cmodule); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", cmodule.io[i]); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\1%d\1%d"), mqtt_data, flag, Settings.user_template_base); // FLAG: 1 BASE: 17 + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}1%d}1%d"), mqtt_data, flag, Settings.user_template_base); // FLAG: 1 BASE: 17 page += mqtt_data; WSSend(200, CT_PLAIN, page); @@ -980,25 +1042,25 @@ void HandleTemplateConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_TEMPLATE)); - page += FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE); - page += FPSTR(HTTP_SCRIPT_TEMPLATE); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_TEMPLATE); - page += F("
"); + WSContentStart(FPSTR(S_CONFIGURE_TEMPLATE)); + WSContentSend(FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE)); + WSContentSend(FPSTR(HTTP_SCRIPT_TEMPLATE)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_TEMPLATE)); + + WSContentSend(F("
")); for (uint8_t i = 0; i < 17; i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("" D_GPIO "%d"), + if ((i < 6) || ((i > 8) && (i != 11))) { // Ignore flash pins GPIO06, 7, 8 and 11 + WSContentSend_P(PSTR("" D_GPIO "%d"), (0==i)?" style='width:74px'":"", i, ((9==i)||(10==i))? "ESP8285" :"", (0==i)?" style='width:176px'":"", i, i); - page += mqtt_data; } } - page += F("
%s
%s
"); - page += FPSTR(HTTP_FORM_TEMPLATE_FLAG); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend(F("")); + + WSContentSend(FPSTR(HTTP_FORM_TEMPLATE_FLAG)); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void TemplateSaveSettings(void) @@ -1054,7 +1116,7 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { String page = ""; uint8_t vidx = 0; - for (uint8_t i = 0; i <= MAXMODULE; i++) { // "\2'%d'>%s (%d)\3" - "\2'255'>UserTemplate (0)\3" - "\2'0'>Sonoff Basic (1)\3" + for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" if (0 == i) { midx = USER_MODULE; vidx = 0; @@ -1084,34 +1146,28 @@ void HandleModuleConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); - page += FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE); - page += FPSTR(HTTP_SCRIPT_MODULE1); - page.replace(F("}4"), String(Settings.module)); + WSContentStart(FPSTR(S_CONFIGURE_MODULE)); + WSContentSend(FPSTR(HTTP_SCRIPT_MODULE_TEMPLATE)); + WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 - page += mqtt_data; + WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16 } } - page += FPSTR(HTTP_SCRIPT_MODULE2); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_MODULE); - page.replace(F("{mt"), AnyModuleName(MODULE)); - page += F("
"); + WSContentSend(FPSTR(HTTP_SCRIPT_MODULE2)); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); for (uint8_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), + WSContentSend_P(PSTR(""), (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); - page += mqtt_data; } } - page += F("
%s " D_GPIO "%d %s
%s " D_GPIO "%d %s
"); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend(F("")); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void ModuleSaveSettings(void) @@ -1168,10 +1224,9 @@ void HandleWifiConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_WIFI)); - page += FPSTR(HTTP_SCRIPT_WIFI); - page += FPSTR(HTTP_HEAD_STYLE); + WSContentStart(FPSTR(S_CONFIGURE_WIFI)); + WSContentSend(FPSTR(HTTP_SCRIPT_WIFI)); + WSContentSendStyle(); if (HTTP_MANAGER_RESET_ONLY != webserver_state) { if (WebServer->hasArg("scan")) { @@ -1183,8 +1238,8 @@ void HandleWifiConfiguration(void) if (0 == n) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - page += FPSTR(S_NO_NETWORKS_FOUND); - page += F(". " D_REFRESH_TO_SCAN_AGAIN "."); + WSContentSend(FPSTR(S_NO_NETWORKS_FOUND)); + WSContentSend(F(". " D_REFRESH_TO_SCAN_AGAIN ".")); } else { //sort networks int indices[n]; @@ -1225,7 +1280,7 @@ void HandleWifiConfiguration(void) int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); if (minimum_signal_quality == -1 || minimum_signal_quality < quality) { - String item = FPSTR(HTTP_LNK_ITEM); + String item = F("
{v} ({w}) {i} {r}%
"); String rssiQ; rssiQ += quality; item.replace(F("{v}"), htmlEscape(WiFi.SSID(indices[i]))); @@ -1233,35 +1288,33 @@ void HandleWifiConfiguration(void) item.replace(F("{r}"), rssiQ); uint8_t auth = WiFi.encryptionType(indices[i]); item.replace(F("{i}"), (ENC_TYPE_WEP == auth) ? F(D_WEP) : (ENC_TYPE_TKIP == auth) ? F(D_WPA_PSK) : (ENC_TYPE_CCMP == auth) ? F(D_WPA2_PSK) : (ENC_TYPE_AUTO == auth) ? F(D_AUTO) : F("")); - page += item; + WSContentSend(item); delay(0); } else { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SKIPPING_LOW_QUALITY)); } } - page += "
"; + WSContentSend(F("
")); } } else { - page += FPSTR(HTTP_LNK_SCAN); + WSContentSend(F("
" D_SCAN_FOR_WIFI_NETWORKS "

")); } - page += FPSTR(HTTP_FORM_WIFI); - page.replace(F("{h1"), Settings.hostname); - page.replace(F("{s1"), Settings.sta_ssid[0]); - page.replace(F("{s2"), Settings.sta_ssid[1]); - page += FPSTR(HTTP_FORM_END); + // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception + WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); + WSContentSend(FPSTR(HTTP_FORM_END)); } + if (WifiIsInManagerMode()) { - page += FPSTR(HTTP_BTN_RSTRT); + WSContentSend(FPSTR(HTTP_BTN_RSTRT)); #ifndef FIRMWARE_MINIMAL - page += FPSTR(HTTP_BTN_RESET); -#endif // FIRMWARE_MINIMAL + WSContentSend(FPSTR(HTTP_BTN_RESET)); +#endif // FIRMWARE_MINIMAL } else { - page += FPSTR(HTTP_BTN_CONF); + WSContentSend(FPSTR(HTTP_BTN_CONF)); } -// ShowPage(page); - ShowPage(page, !(WifiIsInManagerMode())); + WSContentStop(); } void WifiSaveSettings(void) @@ -1300,58 +1353,40 @@ void HandleLoggingConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_LOGGING)); - page += FPSTR(HTTP_HEAD_STYLE); - - page += FPSTR(HTTP_FORM_LOG1); + WSContentStart(FPSTR(S_CONFIGURE_LOGGING)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_LOG1)); + char stemp1[32]; + char stemp2[32]; + uint8_t dlevel[3] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE }; for (uint8_t idx = 0; idx < 3; idx++) { - page += FPSTR(HTTP_FORM_LOG2); - switch (idx) { - case 0: - page.replace(F("{b0"), F(D_SERIAL_LOG_LEVEL)); - page.replace(F("{b1"), STR(SERIAL_LOG_LEVEL)); - page.replace(F("{b2"), F("ls")); - for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { - page.replace("{a" + String(i), (i == Settings.seriallog_level) ? F(" selected ") : F(" ")); - } - break; - case 1: - page.replace(F("{b0"), F(D_WEB_LOG_LEVEL)); - page.replace(F("{b1"), STR(WEB_LOG_LEVEL)); - page.replace(F("{b2"), F("lw")); - for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { - page.replace("{a" + String(i), (i == Settings.weblog_level) ? F(" selected ") : F(" ")); - } - break; - case 2: - page.replace(F("{b0"), F(D_SYS_LOG_LEVEL)); - page.replace(F("{b1"), STR(SYS_LOG_LEVEL)); - page.replace(F("{b2"), F("ll")); - for (uint8_t i = LOG_LEVEL_NONE; i < LOG_LEVEL_ALL; i++) { - page.replace("{a" + String(i), (i == Settings.syslog_level) ? F(" selected ") : F(" ")); - } - break; + uint8_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:Settings.syslog_level; + WSContentSend_P(PSTR("

%s (%s)

")); } - page += FPSTR(HTTP_FORM_LOG3); - page.replace(F("{l2"), Settings.syslog_host); - page.replace(F("{l3"), String(Settings.syslog_port)); - page.replace(F("{l4"), String(Settings.tele_period)); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void LoggingSaveSettings(void) { char tmp[sizeof(Settings.syslog_host)]; // Max length is currently 33 - WebGetArg("ls", tmp, sizeof(tmp)); + WebGetArg("l0", tmp, sizeof(tmp)); Settings.seriallog_level = (!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp); - WebGetArg("lw", tmp, sizeof(tmp)); + WebGetArg("l1", tmp, sizeof(tmp)); Settings.weblog_level = (!strlen(tmp)) ? WEB_LOG_LEVEL : atoi(tmp); - WebGetArg("ll", tmp, sizeof(tmp)); + WebGetArg("l2", tmp, sizeof(tmp)); Settings.syslog_level = (!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp); syslog_level = Settings.syslog_level; syslog_timer = 0; @@ -1383,42 +1418,41 @@ void HandleOtherConfiguration(void) return; } - char stemp[sizeof(Settings.friendlyname[0])]; // Max length is currently 33 + WSContentStart(FPSTR(S_CONFIGURE_OTHER)); + WSContentSendStyle(); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_OTHER)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_OTHER); TemplateJson(); - page.replace(F("{t1"), mqtt_data); - page.replace(F("{t2"), (USER_MODULE == Settings.module) ? F(" checked disabled") : F("")); - page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F("")); + char stemp[strlen(mqtt_data) +1]; + strlcpy(stemp, mqtt_data, sizeof(stemp)); // Get JSON template + WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? " checked disabled" : "", (Settings.flag.mqtt_enabled) ? " checked" : ""); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { - page += FPSTR(HTTP_FORM_OTHER2); - page.replace(F("{1"), String(i +1)); - snprintf_P(stemp, sizeof(stemp), PSTR(FRIENDLY_NAME"%d"), i +1); - page.replace(F("{2"), (i) ? stemp : FRIENDLY_NAME); - page.replace(F("{3"), Settings.friendlyname[i]); + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i +1); + WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), + i +1, + (i) ? stemp : "", + i, i, + (i) ? stemp : "", + Settings.friendlyname[i]); } #ifdef USE_EMULATION - page += FPSTR(HTTP_FORM_OTHER3a); + WSContentSend(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint8_t i = 0; i < EMUL_MAX; i++) { - page += FPSTR(HTTP_FORM_OTHER3b); - page.replace(F("{1"), String(i)); - page.replace(F("{2"), (i == Settings.flag2.emulation) ? F(" checked") : F("")); - page.replace(F("{3"), (i == EMUL_NONE) ? F(D_NONE) : (i == EMUL_WEMO) ? F(D_BELKIN_WEMO) : F(D_HUE_BRIDGE)); - page.replace(F("{4"), (i == EMUL_NONE) ? F("") : (i == EMUL_WEMO) ? F(" " D_SINGLE_DEVICE) : F(" " D_MULTI_DEVICE)); + WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels + i, i, + (i == Settings.flag2.emulation) ? " checked" : "", + GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), + (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); } - page += FPSTR(HTTP_FORM_OTHER3c); + WSContentSend(PSTR("

")); #endif // USE_EMULATION - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void OtherSaveSettings(void) @@ -1436,7 +1470,7 @@ void OtherSaveSettings(void) #endif // USE_EMULATION snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); for (uint8_t i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i +1); + snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); WebGetArg(webindex, tmp, sizeof(tmp)); snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); @@ -1509,13 +1543,12 @@ void HandleResetConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_RESET_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_CONFIGURATION_RESET "
"); - page += FPSTR(HTTP_MSG_RSTRT); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page, HTTP_MANAGER_RESET_ONLY != webserver_state); + WSContentStart(FPSTR(S_RESET_CONFIGURATION), (HTTP_MANAGER_RESET_ONLY != webserver_state)); + WSContentSendStyle(); + WSContentSend(F("
" D_CONFIGURATION_RESET "
")); + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); char command[CMDSZ]; snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); @@ -1528,14 +1561,12 @@ void HandleRestoreConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTORE_CONFIGURATION); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_RESTORE_CONFIGURATION)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_RST); - page += FPSTR(HTTP_FORM_RST_UPG); - page.replace(F("{r1"), F(D_RESTORE)); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentStart(FPSTR(S_RESTORE_CONFIGURATION)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_RST)); + WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); upload_error = 0; upload_file_type = UPL_SETTINGS; @@ -1553,113 +1584,91 @@ void HandleInformation(void) int freeMem = ESP.getFreeHeap(); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_INFORMATION)); - page += FPSTR(HTTP_HEAD_STYLE); - // page += F("
 Information "); - - page += F(""); - page += F("
"); - + WSContentStart(FPSTR(S_INFORMATION)); // Save 1k of code space replacing table html with javascript replace codes // }1 = // }2 = - String func = FPSTR(HTTP_SCRIPT_INFO_BEGIN); - func += F("
"); - func += F(D_PROGRAM_VERSION "}2"); func += my_version; func += my_image; - func += F("}1" D_BUILD_DATE_AND_TIME "}2"); func += GetBuildDateAndTime(); - func += F("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/"); func += String(ESP.getSdkVersion()); - func += F("}1" D_UPTIME "}2"); func += GetUptime(); - snprintf_P(stopic, sizeof(stopic), PSTR(" at 0x%X"), GetSettingsAddress()); - func += F("}1" D_FLASH_WRITE_COUNT "}2"); func += String(Settings.save_flag); func += stopic; - func += F("}1" D_BOOT_COUNT "}2"); func += String(Settings.bootcount); - func += F("}1" D_RESTART_REASON "}2"); func += GetResetReason(); + WSContentSend(FPSTR(HTTP_SCRIPT_INFO_BEGIN)); + WSContentSend_P(PSTR("
")); + WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), my_version, my_image); + WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); + WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_ESP8266_RELEASE "/%s"), ESP.getSdkVersion()); + WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); + WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); + WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount); + WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str()); uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; if (SONOFF_IFAN02 == my_module_type) { maxfn = 1; } for (uint8_t i = 0; i < maxfn; i++) { - func += F("}1" D_FRIENDLY_NAME " "); func += i +1; func += F("}2"); func += Settings.friendlyname[i]; + WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]); } - - func += F("}1}2 "); // Empty line - func += F("}1" D_AP); func += String(Settings.sta_active +1); - func += F(" " D_SSID " (" D_RSSI ")}2"); func += Settings.sta_ssid[Settings.sta_active]; func += F(" ("); func += WifiGetRssiAsQuality(WiFi.RSSI()); func += F("%)"); - func += F("}1" D_HOSTNAME "}2"); func += my_hostname; - if (mdns_begun) { func += F(".local"); } + WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI())); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (mdns_begun) ? ".local" : ""); if (static_cast(WiFi.localIP()) != 0) { - func += F("}1" D_IP_ADDRESS "}2"); func += WiFi.localIP().toString(); - func += F("}1" D_GATEWAY "}2"); func += IPAddress(Settings.ip_address[1]).toString(); - func += F("}1" D_SUBNET_MASK "}2"); func += IPAddress(Settings.ip_address[2]).toString(); - func += F("}1" D_DNS_SERVER "}2"); func += IPAddress(Settings.ip_address[3]).toString(); - func += F("}1" D_MAC_ADDRESS "}2"); func += WiFi.macAddress(); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str()); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.macAddress().c_str()); } if (static_cast(WiFi.softAPIP()) != 0) { - func += F("}1" D_AP " " D_IP_ADDRESS "}2"); func += WiFi.softAPIP().toString(); - func += F("}1" D_AP " " D_GATEWAY "}2"); func += WiFi.softAPIP().toString(); - func += F("}1" D_AP " " D_MAC_ADDRESS "}2"); func += WiFi.softAPmacAddress(); + WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), WiFi.softAPIP().toString().c_str()); + WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); } - - func += F("}1}2 "); // Empty line + WSContentSend_P(PSTR("}1}2 ")); // Empty line if (Settings.flag.mqtt_enabled) { - func += F("}1" D_MQTT_HOST "}2"); func += Settings.mqtt_host; - func += F("}1" D_MQTT_PORT "}2"); func += String(Settings.mqtt_port); - func += F("}1" D_MQTT_USER "}2"); func += Settings.mqtt_user; - func += F("}1" D_MQTT_CLIENT "}2"); func += mqtt_client; - func += F("}1" D_MQTT_TOPIC "}2"); func += Settings.mqtt_topic; - func += F("}1" D_MQTT_GROUP_TOPIC "}2"); func += Settings.mqtt_grptopic; - func += F("}1" D_MQTT_FULL_TOPIC "}2"); func += GetTopic_P(stopic, CMND, mqtt_topic, ""); - func += F("}1" D_MQTT " " D_FALLBACK_TOPIC "}2"); func += GetFallbackTopic_P(stopic, CMND, ""); + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host); + WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); + WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user); + WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); + WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); + WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); + WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); + WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, CMND, "")); } else { - func += F("}1" D_MQTT "}2" D_DISABLED); + WSContentSend_P(PSTR("}1" D_MQTT "}2" D_DISABLED)); } + WSContentSend_P(PSTR("}1}2 ")); // Empty line - func += F("}1}2 "); // Empty line - func += F("}1" D_EMULATION "}2"); #ifdef USE_EMULATION - if (EMUL_WEMO == Settings.flag2.emulation) { - func += F(D_BELKIN_WEMO); - } - else if (EMUL_HUE == Settings.flag2.emulation) { - func += F(D_HUE_BRIDGE); - } - else { - func += F(D_NONE); - } + WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings.flag2.emulation, kEmulationOptions)); #else - func += F(D_DISABLED); + WSContentSend_P(PSTR("}1" D_EMULATION "}2" D_DISABLED)); #endif // USE_EMULATION - func += F("}1" D_MDNS_DISCOVERY "}2"); + #ifdef USE_DISCOVERY + WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings.flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); if (Settings.flag3.mdns_enabled) { - func += F(D_ENABLED); - func += F("}1" D_MDNS_ADVERTISE "}2"); #ifdef WEBSERVER_ADVERTISE - func += F(D_WEB_SERVER); + WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_WEB_SERVER)); #else - func += F(D_DISABLED); + WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_DISABLED)); #endif // WEBSERVER_ADVERTISE - } else { - func += F(D_DISABLED); } #else - func += F(D_DISABLED); + WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2" D_DISABLED)); #endif // USE_DISCOVERY - func += F("}1}2 "); // Empty line - func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId()); - snprintf_P(stopic, sizeof(stopic), PSTR("0x%06X"), ESP.getFlashChipId()); - func += F("}1" D_FLASH_CHIP_ID "}2"); func += stopic; - func += F("}1" D_FLASH_CHIP_SIZE "}2"); func += String(ESP.getFlashChipRealSize() / 1024); func += F("kB"); - func += F("}1" D_PROGRAM_FLASH_SIZE "}2"); func += String(ESP.getFlashChipSize() / 1024); func += F("kB"); - func += F("}1" D_PROGRAM_SIZE "}2"); func += String(ESP.getSketchSize() / 1024); func += F("kB"); - func += F("}1" D_FREE_PROGRAM_SPACE "}2"); func += String(ESP.getFreeSketchSpace() / 1024); func += F("kB"); - func += F("}1" D_FREE_MEMORY "}2"); func += String(freeMem / 1024); func += F("kB"); - func += F("
"); - func += FPSTR(HTTP_SCRIPT_INFO_END); - page.replace(F(""), func); + WSContentSend_P(PSTR("}1}2 ")); // Empty line + WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP.getChipId()); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP.getSketchSize() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%dkB"), ESP.getFreeSketchSpace() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%dkB"), freeMem / 1024); + WSContentSend_P(PSTR("
")); - // page += F("
"); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentSend(FPSTR(HTTP_SCRIPT_INFO_END)); + WSContentSendStyle(); + // WSContentSend(F("
 Information ")); + WSContentSend_P(PSTR("" + "
")); + // WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } #endif // Not FIRMWARE_MINIMAL @@ -1671,15 +1680,12 @@ void HandleUpgradeFirmware(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_FIRMWARE_UPGRADE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_FIRMWARE_UPGRADE)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_UPG); - page.replace(F("{o1"), Settings.ota_url); - page += FPSTR(HTTP_FORM_RST_UPG); - page.replace(F("{r1"), F(D_UPGRADE)); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentStart(FPSTR(S_FIRMWARE_UPGRADE)); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); + WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); upload_error = 0; upload_file_type = UPL_TASMOTA; @@ -1701,14 +1707,13 @@ void HandleUpgradeFirmwareStart(void) ExecuteWebCommand(command, SRC_WEBGUI); } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_INFORMATION)); - page += FPSTR(HTTP_SCRIPT_RELOAD_OTA); - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_UPGRADE_STARTED " ...
"); - page += FPSTR(HTTP_MSG_RSTRT); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentStart(FPSTR(S_INFORMATION)); + WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD_OTA)); + WSContentSendStyle(); + WSContentSend(F("
" D_UPGRADE_STARTED " ...
")); + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); ExecuteWebCommand(command, SRC_WEBGUI); @@ -1726,15 +1731,14 @@ void HandleUploadDone(void) restart_flag = 0; MqttRetryCounter(0); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_INFORMATION)); + WSContentStart(FPSTR(S_INFORMATION)); if (!upload_error) { - page += FPSTR(HTTP_SCRIPT_RELOAD_OTA); // Refesh main web ui after OTA upgrade + WSContentSend(FPSTR(HTTP_SCRIPT_RELOAD_OTA)); // Refesh main web ui after OTA upgrade } - page += FPSTR(HTTP_HEAD_STYLE); - page += F("
" D_UPLOAD " " D_UPLOAD " " D_FAILED "

"); + WSContentSend(F("red'>" D_FAILED "


")); #ifdef USE_RF_FLASH if (upload_error < 14) { #else @@ -1744,20 +1748,20 @@ void HandleUploadDone(void) } else { snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error); } - page += error; + WSContentSend(error); snprintf_P(log_data, sizeof(log_data), PSTR(D_UPLOAD ": %s"), error); AddLog(LOG_LEVEL_DEBUG); stop_flash_rotate = Settings.flag.stop_flash_rotate; } else { - page += F("green'>" D_SUCCESSFUL "
"); - page += FPSTR(HTTP_MSG_RSTRT); + WSContentSend(F("green'>" D_SUCCESSFUL "
")); + WSContentSend(FPSTR(HTTP_MSG_RSTRT)); ShowWebSource(SRC_WEBGUI); restart_flag = 2; // Always restart to re-enable disabled features during update } SettingsBufferFree(); - page += F("

"); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } void HandleUploadLoop(void) @@ -2016,7 +2020,7 @@ void HandleHttpCommand(void) } else { message += F(D_NEED_USER_AND_PASSWORD "\"}"); } - SetHeader(); + WSHeaderSend(); WSSend(200, CT_JSON, message); } @@ -2033,13 +2037,12 @@ void HandleConsole(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONSOLE); - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONSOLE)); - page += FPSTR(HTTP_SCRIPT_CONSOL); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_CMND); - page += FPSTR(HTTP_BTN_MAIN); - ShowPage(page); + WSContentStart(FPSTR(S_CONSOLE)); + WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_CMND)); + WSContentSend(FPSTR(HTTP_BTN_MAIN)); + WSContentStop(); } void HandleConsoleRefresh(void) @@ -2060,7 +2063,7 @@ void HandleConsoleRefresh(void) bool last_reset_web_log_flag = reset_web_log_flag; // mqtt_data used as scratch space - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d\1%d\1"), web_log_index, last_reset_web_log_flag); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d}1%d}1"), web_log_index, last_reset_web_log_flag); String message = mqtt_data; if (!reset_web_log_flag) { counter = 0; @@ -2089,7 +2092,7 @@ void HandleConsoleRefresh(void) if (!counter) { counter++; } // Skip log index 0 as it is not allowed } while (counter != web_log_index); } - message += F("\1"); + message += F("}1"); WSSend(200, CT_PLAIN, message); } @@ -2114,7 +2117,7 @@ void HandleNotFound(void) for (uint8_t i = 0; i < WebServer->args(); i++) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s %s: %s\n"), mqtt_data, WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); } - SetHeader(); + WSHeaderSend(); WSSend(404, CT_PLAIN, mqtt_data); } } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 8721b42b2..d5ad9f4b5 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -900,16 +900,17 @@ const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT; const char HTTP_BTN_MENU_MQTT[] PROGMEM = "

"; -const char HTTP_FORM_MQTT[] PROGMEM = +const char HTTP_FORM_MQTT1[] PROGMEM = "
 " D_MQTT_PARAMETERS " " "
" - "

" D_HOST " (" MQTT_HOST ")

" - "

" D_PORT " (" STR(MQTT_PORT) ")

" - "

" D_CLIENT " ({m0)

" - "

" D_USER " (" MQTT_USER ")

" + "

" D_HOST " (" MQTT_HOST ")

" + "

" D_PORT " (" STR(MQTT_PORT) ")

" + "

" D_CLIENT " (%s)

"; +const char HTTP_FORM_MQTT2[] PROGMEM = + "

" D_USER " (" MQTT_USER ")

" "

" D_PASSWORD "

" - "

" D_TOPIC " = %topic% (" MQTT_TOPIC ")

" - "

" D_FULL_TOPIC " (" MQTT_FULLTOPIC ")

"; + "

" D_TOPIC " = %%topic%% (" MQTT_TOPIC ")

" + "

" D_FULL_TOPIC " (%s)

"; void HandleMqttConfiguration(void) { @@ -923,23 +924,24 @@ void HandleMqttConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT)); - page += FPSTR(HTTP_HEAD_STYLE); - - page += FPSTR(HTTP_FORM_MQTT); char str[sizeof(Settings.mqtt_client)]; - page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client))); - page.replace(F("{m1"), Settings.mqtt_host); - page.replace(F("{m2"), String(Settings.mqtt_port)); - page.replace(F("{m3"), Settings.mqtt_client); - page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user); - page.replace(F("{m6"), Settings.mqtt_topic); - page.replace(F("{m7"), Settings.mqtt_fulltopic); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentStart(FPSTR(S_CONFIGURE_MQTT)); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MQTT1, + Settings.mqtt_host, + Settings.mqtt_port, + Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)), + MQTT_CLIENT_ID, + Settings.mqtt_client); + WSContentSend_P(HTTP_FORM_MQTT2, + (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, + Settings.mqtt_topic, + MQTT_FULLTOPIC, MQTT_FULLTOPIC, + Settings.mqtt_fulltopic); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void MqttSaveSettings(void) diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 65711cd68..c12203d2f 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -439,14 +439,14 @@ const char HTTP_FORM_DOMOTICZ[] PROGMEM = "
" ""; const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM = - "" - ""; + "" + ""; const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM = - ""; + ""; const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM = - ""; + ""; const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM = - ""; + ""; void HandleDomoticzConfiguration(void) { @@ -462,35 +462,30 @@ void HandleDomoticzConfiguration(void) char stemp[32]; - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_DOMOTICZ)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_DOMOTICZ); + WSContentStart(FPSTR(S_CONFIGURE_DOMOTICZ)); + WSContentSendStyle(); + WSContentSend(FPSTR(HTTP_FORM_DOMOTICZ)); for (int i = 0; i < MAX_DOMOTICZ_IDX; i++) { if (i < devices_present) { - page += FPSTR(HTTP_FORM_DOMOTICZ_RELAY); - page.replace("{2", String((int)Settings.domoticz_relay_idx[i])); - page.replace("{3", String((int)Settings.domoticz_key_idx[i])); + WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY, + i +1, i, i, Settings.domoticz_relay_idx[i], + i +1, i, i, Settings.domoticz_key_idx[i]); } if (pin[GPIO_SWT1 +i] < 99) { - page += FPSTR(HTTP_FORM_DOMOTICZ_SWITCH); - page.replace("{4", String((int)Settings.domoticz_switch_idx[i])); + WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH, + i +1, i, i, Settings.domoticz_switch_idx[i]); } - page.replace("{1", String(i +1)); if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { break; } } for (int i = 0; i < DZ_MAX_SENSORS; i++) { - page += FPSTR(HTTP_FORM_DOMOTICZ_SENSOR); - page.replace("{1", String(i +1)); - page.replace("{2", GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors)); - page.replace("{5", String((int)Settings.domoticz_sensor_idx[i])); + WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR, + i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, i, Settings.domoticz_sensor_idx[i]); } - page += FPSTR(HTTP_FORM_DOMOTICZ_TIMER); - page.replace("{6", String((int)Settings.domoticz_update_timer)); - page += F("
" D_DOMOTICZ_IDX " {1
" D_DOMOTICZ_KEY_IDX " {1
" D_DOMOTICZ_IDX " %d
" D_DOMOTICZ_KEY_IDX " %d
" D_DOMOTICZ_SWITCH_IDX " {1
" D_DOMOTICZ_SWITCH_IDX " %d
" D_DOMOTICZ_SENSOR_IDX " {1 {2
" D_DOMOTICZ_SENSOR_IDX " %d %s
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ")
"); - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer); + WSContentSend(F("")); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void DomoticzSaveSettings(void) @@ -500,19 +495,19 @@ void DomoticzSaveSettings(void) char tmp[100]; for (uint8_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_key_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); } ssensor_indices[0] = '\0'; for (uint8_t i = 0; i < DZ_MAX_SENSORS; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i +1); + snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i); WebGetArg(stemp, tmp, sizeof(tmp)); Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp); snprintf_P(ssensor_indices, sizeof(ssensor_indices), PSTR("%s%s%d"), ssensor_indices, (strlen(ssensor_indices)) ? "," : "", Settings.domoticz_sensor_idx[i]); diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 3c3b1f376..7bc55ff63 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -519,7 +519,7 @@ const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER; const char HTTP_BTN_MENU_TIMER[] PROGMEM = "

"; -const char HTTP_TIMER_SCRIPT[] PROGMEM = +const char HTTP_TIMER_SCRIPT1[] PROGMEM = "var pt=[],ct=99;" "function qs(s){" // Alias to save code space "return document.querySelector(s);" @@ -528,8 +528,9 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "var o=document.createElement('option');" "o.textContent=i;" "q.appendChild(o);" - "}" + "}"; #ifdef USE_SUNRISE +const char HTTP_TIMER_SCRIPT2[] PROGMEM = "function gt(){" // Set hours and minutes according to mode "var m,p,q;" "m=qs('input[name=\"rd\"]:checked').value;" // Get mode @@ -558,8 +559,9 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "qs('#dr').disabled='disabled';" "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" // Create hours select options "}" - "}" + "}"; #endif +const char HTTP_TIMER_SCRIPT3[] PROGMEM = "function st(){" // Save parameters to hidden area "var i,l,m,n,p,s;" "m=0;s=0;" @@ -570,7 +572,7 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "m=qs('input[name=\"rd\"]:checked').value;" // Check mode "s|=(qs('input[name=\"rd\"]:checked').value<<29);" // Get mode #endif - "if(}1>0){" + "if(%d>0){" "i=qs('#d1').selectedIndex;if(i>=0){s|=(i<<23);}" // Get output "s|=(qs('#p1').selectedIndex<<27);" // Get action "}else{" @@ -587,7 +589,8 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "s|=((qs('#mw').selectedIndex)&0x0F)<<11;" // Get window minutes "pt[ct]=s;" "eb('t0').value=pt.join();" // Save parameters from array to hidden area - "}" + "}"; +const char HTTP_TIMER_SCRIPT4[] PROGMEM = "function ot(t,e){" // Select tab and update elements "var i,n,o,p,q,s;" "if(ct<99){st();}" // Save changes @@ -602,23 +605,24 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = #else "p=s&0x7FF;" // Get time "q=Math.floor(p/60);if(q<10){q='0'+q;}qs('#ho').value=q;" // Set hours - "q=p%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes + "q=p%%60;if(q<10){q='0'+q;}qs('#mi').value=q;" // Set minutes #endif "q=(s>>11)&0xF;if(q<10){q='0'+q;}qs('#mw').value=q;" // Set window minutes "for(i=0;i<7;i++){p=(s>>(16+i))&1;eb('w'+i).checked=p;}" // Set weekdays - "if(}1>0){" + "if(%d>0){" "p=(s>>23)&0xF;qs('#d1').value=p+1;" // Set output "p=(s>>27)&3;qs('#p1').selectedIndex=p;" // Set action "}" "p=(s>>15)&1;eb('r0').checked=p;" // Set repeat "p=(s>>31)&1;eb('a0').checked=p;" // Set arm - "}" + "}"; +const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs - "if(}1>0){" // Create Output and Action drop down boxes + "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" "o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" // Create offset direction select options #ifdef USE_RULES @@ -628,48 +632,52 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = #endif "}else{" "eb('oa').innerHTML=\"" D_TIMER_ACTION " " D_RULE "\";" // No outputs but rule is allowed - "}" + "}"; +const char HTTP_TIMER_SCRIPT6[] PROGMEM = #ifdef USE_SUNRISE "o=qs('#dr');ce('+',o);ce('-',o);" // Create offset direction select options #endif "o=qs('#ho');for(i=0;i<=23;i++){ce((i<10)?('0'+i):i,o);}" // Create hours select options "o=qs('#mi');for(i=0;i<=59;i++){ce((i<10)?('0'+i):i,o);}" // Create minutes select options "o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" // Create window minutes select options - "o=qs('#d1');for(i=0;i<}1;i++){ce(i+1,o);}" // Create outputs + "o=qs('#d1');for(i=0;i<%d;i++){ce(i+1,o);}" // Create outputs "var a='" D_DAY3LIST "';" "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\" \"}" "eb('ds').innerHTML=s;" // Create weekdays "eb('dP').click();" // Get the element with id='dP' and click on it - "}"; + "}" + "window.onload=it;"; const char HTTP_TIMER_STYLE[] PROGMEM = - ".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}" // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE (transparent won't work) - ""; -const char HTTP_FORM_TIMER[] PROGMEM = + ".tl{float:left;border-radius:0;border:1px solid #f2f2f2;padding:1px;width:6.25%;}"; // Border color needs to be the same as Fieldset background color from HTTP_HEAD_STYLE1 (transparent won't work) +const char HTTP_FORM_TIMER1[] PROGMEM = "
" " " D_TIMER_PARAMETERS " " "
" - "
" D_TIMER_ENABLE "


" + "
" D_TIMER_ENABLE "


" "



" "

" "
" "" D_TIMER_ARM " " "" D_TIMER_REPEAT "" "

" - "
" + "
"; #ifdef USE_SUNRISE - "
" // 299 used in page.replace(F("299") +const char HTTP_FORM_TIMER3[] PROGMEM = + "
" "" D_TIMER_TIME "
" - "" D_SUNRISE " (}8)
" - "" D_SUNSET " (}9)
" + "" D_SUNRISE " (%s)
" + "" D_SUNSET " (%s)
" "
" "

" "" - " " + " "; #else - "" D_TIMER_TIME " " +const char HTTP_FORM_TIMER3[] PROGMEM = + "" D_TIMER_TIME " "; #endif // USE_SUNRISE +const char HTTP_FORM_TIMER4[] PROGMEM = "" " " D_HOUR_MINUTE_SEPARATOR " " "" @@ -690,28 +698,30 @@ void HandleTimerConfiguration(void) return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(S_CONFIGURE_TIMER)); - page += FPSTR(HTTP_TIMER_SCRIPT); - page += FPSTR(HTTP_HEAD_STYLE); - page.replace(F(""), FPSTR(HTTP_TIMER_STYLE)); - page += FPSTR(HTTP_FORM_TIMER); - page.replace(F("{e0"), (Settings.flag3.timers_enable) ? F(" checked") : F("")); - for (uint8_t i = 0; i < MAX_TIMERS; i++) { - if (i > 0) { page += F(","); } - page += String(Settings.timer[i].data); - } - page += FPSTR(HTTP_FORM_TIMER1); - page.replace(F("}1"), String(devices_present)); + WSContentStart(FPSTR(S_CONFIGURE_TIMER)); + WSContentSend(FPSTR(HTTP_TIMER_SCRIPT1)); #ifdef USE_SUNRISE - page.replace(F("}8"), GetSun(0)); // Add Sunrise - page.replace(F("}9"), GetSun(1)); // Add Sunset - page.replace(F("299"), String(100 + (strlen(D_SUNSET) *12))); // Fix string length to keep radios centered + WSContentSend(FPSTR(HTTP_TIMER_SCRIPT2)); #endif // USE_SUNRISE - page += FPSTR(HTTP_FORM_END); - page += F(""); // Init elements and select first tab/button - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); + WSContentSendStyle(FPSTR(HTTP_TIMER_STYLE)); + WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); + for (uint8_t i = 0; i < MAX_TIMERS; i++) { + WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data); + } + WSContentSend(FPSTR(HTTP_FORM_TIMER2)); +#ifdef USE_SUNRISE + WSContentSend_P(HTTP_FORM_TIMER3, 100 + (strlen(D_SUNSET) *12), GetSun(0).c_str(), GetSun(1).c_str()); +#else + WSContentSend(FPSTR(HTTP_FORM_TIMER3)); +#endif // USE_SUNRISE + WSContentSend(FPSTR(HTTP_FORM_TIMER4)); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void TimerSaveSettings(void) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 461094162..9f3e6d344 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -755,13 +755,14 @@ const char HTTP_BTN_MENU_KNX[] PROGMEM = "

"; const char HTTP_FORM_KNX[] PROGMEM = - "
 " D_KNX_PARAMETERS " " - "
" + "
" + " " D_KNX_PARAMETERS " " + "" "
" "" D_KNX_PHYSICAL_ADDRESS " " - " . " - " . " - "" + " . " + " . " + "" "

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" "{nop}"; + ""; const char HTTP_FORM_KNX_GA[] PROGMEM = - " / " - " / " - " "; + " / " + " / " + " "; const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM = - "

" - ""; + "

" + "
"; const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM = - "" - ""; + "" + ""; const char HTTP_FORM_KNX3[] PROGMEM = "
{optex} -> GAfnum / GAarea / GAfdef
%s -> %d / %d / %d

" @@ -801,8 +802,8 @@ const char HTTP_FORM_KNX4[] PROGMEM = "-> -> "); - page += FPSTR(HTTP_FORM_KNX_GA); - page.replace(F("GAfnum"), F("GA_FNUM")); - page.replace(F("GAarea"), F("GA_AREA")); - page.replace(F("GAfdef"), F("GA_FDEF")); - page.replace(F("GAfnum"), F("GA_FNUM")); - page.replace(F("GAarea"), F("GA_AREA")); - page.replace(F("GAfdef"), F("GA_FDEF")); - page += FPSTR(HTTP_FORM_KNX_ADD_BTN); - page.replace(F("{btnval}"), String(1)); - if (Settings.knx_GA_registered < MAX_KNX_GA) { - page.replace(F("btndis"), F(" ")); - } - else - { - page.replace(F("btndis"), F("disabled")); - } - page.replace(F("fncbtnadd"), F("GAwarning")); - for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - if ( Settings.knx_GA_param[i] ) - { - page += FPSTR(HTTP_FORM_KNX_ADD_TABLE_ROW); - page.replace(F("{opval}"), String(i+1)); - page.replace(F("{optex}"), String(device_param_ga[Settings.knx_GA_param[i]-1])); - KNX_addr.value = Settings.knx_GA_addr[i]; - page.replace(F("GAfnum"), String(KNX_addr.ga.area)); - page.replace(F("GAarea"), String(KNX_addr.ga.line)); - page.replace(F("GAfdef"), String(KNX_addr.ga.member)); - } - } - - page += FPSTR(HTTP_FORM_KNX3); - page += FPSTR(HTTP_FORM_KNX_GA); - page.replace(F("GAfnum"), F("CB_FNUM")); - page.replace(F("GAarea"), F("CB_AREA")); - page.replace(F("GAfdef"), F("CB_FDEF")); - page.replace(F("GAfnum"), F("CB_FNUM")); - page.replace(F("GAarea"), F("CB_AREA")); - page.replace(F("GAfdef"), F("CB_FDEF")); - page += FPSTR(HTTP_FORM_KNX4); - uint8_t j; - for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) - { - // Check How many Relays are available and add: RelayX and TogleRelayX - if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } - if ( i == 8 ) { j = 0; } - if ( device_param[j].show ) - { - page += FPSTR(HTTP_FORM_KNX_OPT); - page.replace(F("{vop}"), String(device_param[i].type)); - page.replace(F("{nop}"), String(device_param_cb[i])); - } - } - page += F(" "); - page += FPSTR(HTTP_FORM_KNX_ADD_BTN); - page.replace(F("{btnval}"), String(2)); - if (Settings.knx_CB_registered < MAX_KNX_CB) { - page.replace(F("btndis"), F(" ")); - } - else - { - page.replace(F("btndis"), F("disabled")); - } - page.replace(F("fncbtnadd"), F("CBwarning")); - - for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - if ( Settings.knx_CB_param[i] ) - { - page += FPSTR(HTTP_FORM_KNX_ADD_TABLE_ROW2); - page.replace(F("{opval}"), String(i+1)); - page.replace(F("{optex}"), String(device_param_cb[Settings.knx_CB_param[i]-1])); - KNX_addr.value = Settings.knx_CB_addr[i]; - page.replace(F("GAfnum"), String(KNX_addr.ga.area)); - page.replace(F("GAarea"), String(KNX_addr.ga.line)); - page.replace(F("GAfdef"), String(KNX_addr.ga.member)); - } - } - page += F("
"); - page += F("
"); - page += FPSTR(HTTP_BTN_CONF); - - page.replace( F(""), + WSContentStart(FPSTR(S_CONFIGURE_KNX)); + WSContentSend( F("function GAwarning()" "{" "var GA_FNUM = eb('GA_FNUM');" @@ -995,9 +891,63 @@ void HandleKNXConfiguration(void) "if ( CB_FNUM != null && CB_FNUM.value == '0' && CB_AREA.value == '0' && CB_FDEF.value == '0' ) {" "alert('" D_KNX_WARNING "');" "}" - "}" - "") ); - ShowPage(page); + "}")); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member); + if ( Settings.flag.knx_enabled ) { WSContentSend(F(" checked")); } + WSContentSend(FPSTR(HTTP_FORM_KNX1)); + if ( Settings.flag.knx_enable_enhancement ) { WSContentSend(F(" checked")); } + + WSContentSend(FPSTR(HTTP_FORM_KNX2)); + for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) + { + if ( device_param[i].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_ga[i]); + } + } + WSContentSend(F(" -> ")); + WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_FNUM", "GA_AREA", "GA_AREA", "GA_FDEF", "GA_FDEF"); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); + for (uint8_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + if ( Settings.knx_GA_param[i] ) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); + } + } + + WSContentSend(FPSTR(HTTP_FORM_KNX3)); + WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_FNUM", "CB_AREA", "CB_AREA", "CB_FDEF", "CB_FDEF"); + WSContentSend(FPSTR(HTTP_FORM_KNX4)); + + uint8_t j; + for (uint8_t i = 0; i < KNX_MAX_device_param ; i++) + { + // Check How many Relays are available and add: RelayX and TogleRelayX + if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } + if ( i == 8 ) { j = 0; } + if ( device_param[j].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); + } + } + WSContentSend(F(" ")); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); + + for (uint8_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + if ( Settings.knx_CB_param[i] ) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); + } + } + WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 148f7f860..f019625fc 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -382,14 +382,14 @@ const char HTTP_BTN_MENU_HX711[] PROGMEM = const char HTTP_FORM_HX711[] PROGMEM = "
 " D_CALIBRATION " " "
" - "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" "
" "
" "


" "
 " D_HX711_PARAMETERS " " "
" - "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; void HandleHxAction(void) { @@ -403,41 +403,38 @@ void HandleHxAction(void) return; } - char tmp[100]; + char stemp1[20]; if (WebServer->hasArg("reset")) { - snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 1")); // Reset - ExecuteWebCommand(tmp, SRC_WEBGUI); + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); // Reset + ExecuteWebCommand(stemp1, SRC_WEBGUI); HandleRoot(); // Return to main screen return; } if (WebServer->hasArg("calibrate")) { - WebGetArg("p1", tmp, sizeof(tmp)); - Settings.weight_reference = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 1000); + WebGetArg("p1", stemp1, sizeof(stemp1)); + Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToDouble(stemp1) * 1000); HxLogUpdates(); - snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 2")); // Start calibration - ExecuteWebCommand(tmp, SRC_WEBGUI); + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); // Start calibration + ExecuteWebCommand(stemp1, SRC_WEBGUI); HandleRoot(); // Return to main screen return; } - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), FPSTR(D_CONFIGURE_HX711)); - page += FPSTR(HTTP_HEAD_STYLE); - page += FPSTR(HTTP_FORM_HX711); - dtostrfd((float)Settings.weight_reference / 1000, 3, tmp); - page.replace("{1", String(tmp)); - dtostrfd((float)Settings.weight_item / 10000, 4, tmp); - page.replace("{2", String(tmp)); - - page += FPSTR(HTTP_FORM_END); - page += FPSTR(HTTP_BTN_CONF); - ShowPage(page); + WSContentStart(FPSTR(D_CONFIGURE_HX711)); + WSContentSendStyle(); + dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); + char stemp2[20]; + dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); + WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); + WSContentSend(FPSTR(HTTP_FORM_END)); + WSContentSend(FPSTR(HTTP_BTN_CONF)); + WSContentStop(); } void HxSaveSettings(void) From b393cdc9f1d5784d1855084c260b157ce9022216 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:32:23 +0100 Subject: [PATCH 2/3] Replace menu button list Replace menu button list --- sonoff/xdrv_01_webserver.ino | 4 ---- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 4 ++-- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xsns_34_hx711.ino | 4 ++-- 6 files changed, 7 insertions(+), 11 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 40f8f7fbf..bb2af46e9 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -859,10 +859,8 @@ void HandleRoot(void) } #ifndef FIRMWARE_MINIMAL - mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); - WSContentSend(mqtt_data); #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { @@ -964,10 +962,8 @@ void HandleConfiguration(void) WSContentSendStyle(); WSContentSend(FPSTR(HTTP_BTN_MENU_MODULE)); - mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_BUTTON); XsnsCall(FUNC_WEB_ADD_BUTTON); - WSContentSend(mqtt_data); WSContentSend(FPSTR(HTTP_BTN_MENU4)); WSContentSend(FPSTR(HTTP_BTN_RESET)); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d5ad9f4b5..d2874f490 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -990,7 +990,7 @@ bool Xdrv02(uint8_t function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_MQTT)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index c12203d2f..a90245e08 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -536,7 +536,7 @@ bool Xdrv07(uint8_t function) switch (function) { #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_DOMOTICZ)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 7bc55ff63..cfc18904a 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -764,9 +764,9 @@ bool Xdrv09(uint8_t function) #ifdef USE_TIMERS_WEB case FUNC_WEB_ADD_BUTTON: #ifdef USE_RULES - strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); #else - if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data) - strlen(mqtt_data) -1); } + if (devices_present) { WSContentSend(FPSTR(HTTP_BTN_MENU_TIMER)); } #endif // USE_RULES break; case FUNC_WEB_ADD_HANDLER: diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 9f3e6d344..d39001250 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1249,7 +1249,7 @@ bool Xdrv11(uint8_t function) #ifdef USE_WEBSERVER #ifdef USE_KNX_WEB_MENU case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_KNX)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/kn", HandleKNXConfiguration); diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index f019625fc..5057b8c47 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -492,10 +492,10 @@ bool Xsns34(uint8_t function) break; #ifdef USE_HX711_GUI case FUNC_WEB_ADD_MAIN_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_MAIN_HX711)); break; case FUNC_WEB_ADD_BUTTON: - strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data) - strlen(mqtt_data) -1); + WSContentSend(FPSTR(HTTP_BTN_MENU_HX711)); break; case FUNC_WEB_ADD_HANDLER: WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); From 58fe50d81a49735ac2e8531c8f2eae5aa4112c96 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 7 Mar 2019 18:18:30 +0100 Subject: [PATCH 3/3] Update webserver layout Update webserver layout --- .github/ISSUE_TEMPLATE/Bug_report.md | 54 ++++++++---- .github/ISSUE_TEMPLATE/Custom.md | 43 ++++++--- .github/PULL_REQUEST_TEMPLATE.md | 10 +++ .github/stale.yml | 6 +- CODE_OF_CONDUCT.md | 76 ++++++++++++++++ CONTRIBUTING.md | 63 ++++++++++++++ SUPPORT.md | 22 +++++ sonoff/my_user_config.h | 6 +- sonoff/support.ino | 52 +++++++---- sonoff/xdrv_01_webserver.ino | 125 +++++++++++++++------------ sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_07_domoticz.ino | 2 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xdrv_11_knx.ino | 2 +- sonoff/xsns_34_hx711.ino | 2 +- 15 files changed, 355 insertions(+), 112 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SUPPORT.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index ad522ec4e..a0ab5e7e3 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -4,39 +4,61 @@ about: Create a report to help us improve --- -**IMPORTANT NOTICE** -If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + -**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** + + + + + + + + -**Describe the bug** +### BUG DESCRIPTION _A clear and concise description of what the bug is._ -_Also, make sure these boxes are checked [x] before submitting your issue - Thank you!_ -- [ ] _Searched the problem in issues and in the wiki_ -- [ ] _Hardware used_ : -- [ ] _Development/Compiler/Upload tools used_ : -- [ ] _If a pre-compiled release or development binary was used, which one?_ : -- [ ] _You have tried latest release or development binaries?_ : -- [ ] _Provide the output of command_``status 0`` : +### REQUESTED INFORMATION +_Make sure these boxes are checked before submitting your issue. Thank you_ + +**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** + +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) +- [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) +- [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) +- [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) +- [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) +- [ ] Device used (i.e. Sonoff Basic) : _____ +- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?) +- [ ] Development IDE - Compiler / Upload tools used : ____ / ____ +- [ ] Provide the output of command ``status 0`` : ``` -STATUS 0 OUTPUT HERE - DO NOT DELETE THE MARKERS ABOVE AND BELOW THIS LINE +STATUS 0 OUTPUT HERE: + + +``` +- [ ] Provide the output of console when you experience your issue if apply : +_(Please use_ ``weblog 4`` _for more debug information)_ +``` +CONSOLE OUTPUT HERE: + + ``` -**To Reproduce** +### TO REPRODUCE _Steps to reproduce the behavior:_ -**Expected behavior** +### EXPECTED BEHAVIOUR _A clear and concise description of what you expected to happen._ -**Screenshots** +### SCREENSHOTS _If applicable, add screenshots to help explain your problem._ -**Additional context** +### ADDITIONAL CONTEXT _Add any other context about the problem here._ diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index 4d1eba459..44bd847cb 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -4,24 +4,47 @@ about: Users Troubleshooting Help --- -**IMPORTANT NOTICE** -If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses. + + + + + + + + + + + + + +### ISSUE DESCRIPTION - TROUBLESHOOTING +_A clear description of what the issue is and be as extensive as possible_ + + +### REQUESTED INFORMATION +_Make sure these boxes are checked before submitting your issue. Thank you_ **FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** -Make sure these boxes are checked [x] before submitting your issue - Thank you! - +- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) - [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) -- [ ] Development/Compiler/Upload tools used : -- [ ] Hardware used : -- [ ] If a pre-compiled release or development binary was used, which one? : -- [ ] You have tried latest release or development binaries? : +- [ ] Device used (i.e. Sonoff Basic) : _____ +- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?) +- [ ] Development IDE - Compiler / Upload tools used : ____ / ____ - [ ] Provide the output of command ``status 0`` : ``` -STATUS 0 OUTPUT HERE -``` +STATUS 0 OUTPUT HERE: + +``` +- [ ] Provide the output of console when you experience your issue if apply : +_(Please use_ ``weblog 4`` _for more debug information)_ +``` +CONSOLE OUTPUT HERE: + + +``` **(Please, remember to close the issue when the problem has been addressed)** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..aea7cd816 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +## Description: + +**Related issue (if applicable):** fixes # + +## Checklist: + - [ ] The pull request is done against the dev branch + - [ ] Only relevant files were touched (Also beware if your editor has auto-formatting feature enabled) + - [ ] Only one feature/fix was added per PR. + - [ ] The code change is tested and works. + - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** diff --git a/.github/stale.yml b/.github/stale.yml index 88c5f7c21..484010321 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,9 +1,9 @@ # Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 45 +daysUntilStale: 25 # Number of days of inactivity before a stale Issue or Pull Request is closed. # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 15 +daysUntilClose: 5 # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable exemptLabels: @@ -37,4 +37,4 @@ closeComment: > limitPerRun: 30 # Limit to only `issues` or `pulls` -only: issues +#only: issues diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..1408ce048 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at https://sidweb.nl/cms3/en/contact. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..7cfcdfadb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,63 @@ +# Contributing to Sonoff-Tasmota + +**Any contribution helps our team and makes Tasmota better for the entire community!** + +Everybody is welcome and invited to contribute to Sonoff-Tasmota Project by: + +* Testing newly released features and reporting issues. +* Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) +* Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Contributing) + +This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. + +## Opening New Issues + +**Issue tracker is NOT a general discussion forum!** +1. Opening an issue means that a problem exists in the code and should be addressed by the project contributors. +2. When opening an issue, it is required to fill out the presented template. The requested information is important! If the template is ignored or insufficient info about the issue is provided, the issue may be closed. +3. Questions of type "How do I..." or "Can you please help me with..." or "Can Tasmota do..." WILL NOT be handled here. Such questions should be directed at a discussion forum or to the Tasmota Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. +4. Issues about topics already handled in the documentation will be closed in a similar manner. +5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself. +6. Issues with accompanied investigation that shows the root of the problem should be given priority. +7. Duplicate issues will be closed. + +## Triaging of Issues/PR's + +1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. +2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. +3. Issues that are accepted should be marked with appropriate labels. +4. Issues that could impact functionality for many users should be considered severe. +5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. +6. Issues with feature requests should be discussed for viability/desirability. +7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. +8. Feature requests that are not accompanied by a PR: + * could be closed immediately (denied). + * could be closed after some predetermined period of time (left as candidate for somebody to pick up). +9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 30 days by the STALE bot. + +## Pull requests + +A Pull Request (PR) is the process where code modifications are managed in GitHub. + +The process is straight-forward. + + - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) + - Fork the Sonoff-Tasmota Repository [git repository](https://github.com/arendst/Sonoff-Tasmota). + - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. + - Ensure tests work. + - Create a Pull Request against the [**dev**](https://github.com/arendst/Sonoff-Tasmota/tree/dev) branch of Sonoff-Tasmota. + +1. All pull requests must be done against the dev branch. +2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). +3. Only one feature/fix should be added per PR. +4. If adding a new functionality (new hardware, new library support) not related to an existing component move it to it's own modules (.ino file). +5. PRs that don't compile (break Travis) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. +6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. +7. All pull requests should consider updates to the documentation. +8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. +9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. +10. Pull requests that don't meet the above will be denied and closed. + + + + diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 000000000..46fa03ebc --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,22 @@ +# Sonoff-Tasmota Support + +If you're looking for support on **Sonoff-Tasmota** there are some options available: + +### Documentation: + +* [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it. +* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For information on common problems and solutions. +* [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota. + +### Support's Community: + +* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. +* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. +* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues. + +### Developers' Community: + +* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. +* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. +* [Troubleshooting](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. +* [Issue a question](https://github.com/arendst/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index e8d900ebe..b5c52ff81 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -280,8 +280,8 @@ // -- Rules --------------------------------------- #define USE_RULES // Add support for rules (+4k4 code) - #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) - #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) +// #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) +// #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // -- Internal Analog input ----------------------- #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices @@ -291,7 +291,7 @@ //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) #define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) // #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors -// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 +// #define DS18B20_INTERNAL_PULLUP // Use INPUT_PULLUP internal pullup resistors for single DS18B20 // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) diff --git a/sonoff/support.ino b/sonoff/support.ino index 8bb9d1dea..67f53d451 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -160,28 +160,33 @@ double CharToDouble(const char *str) char strbuf[24]; strlcpy(strbuf, str, sizeof(strbuf)); - char *pt; - double left = atoi(strbuf); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } // Trim leading spaces + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } // Skip any sign + + double left = 0; + if (*pt != '.') { + left = atoi(pt); // Get left part + while (isdigit(*pt)) { pt++; } // Skip number + } + double right = 0; - short len = 0; - pt = strtok (strbuf, "."); - if (pt) { - pt = strtok (NULL, "."); - if (pt) { - right = atoi(pt); - len = strlen(pt); - double fac = 1; - while (len) { - fac /= 10.0; - len--; - } - // pow is also very large - //double fac=pow(10,-len); - right *= fac; + if (*pt == '.') { + pt++; + right = atoi(pt); // Decimal part + while (isdigit(*pt)) { + pt++; + right /= 10.0; } } + double result = left + right; - if (left < 0) { result = left - right; } + if (sign < 0) { + return -result; // Add negative sign + } return result; } @@ -1274,6 +1279,17 @@ void AddLog_P(uint8_t loglevel, const char *formatP, const char *formatP2) AddLog(loglevel); } +void AddLog_P2(uint8_t loglevel, PGM_P formatP, ...) +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + AddLog(loglevel); +} + void AddLogBuffer(uint8_t loglevel, uint8_t *buffer, int count) { snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index bb2af46e9..8df9529b4 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -283,10 +283,11 @@ const char HTTP_MSG_SLIDER2[] PROGMEM = const char HTTP_MSG_RSTRT[] PROGMEM = "
" D_DEVICE_WILL_RESTART "

"; -const char HTTP_BTN_MENU1[] PROGMEM = +const char HTTP_BTN_CONF[] PROGMEM = "
" + ""; +const char HTTP_BTN_MENU1[] PROGMEM = #ifndef FIRMWARE_MINIMAL - "
" "

" #endif "
" @@ -297,30 +298,30 @@ const char HTTP_BTN_RSTRT[] PROGMEM = const char HTTP_BTN_MENU_MODULE[] PROGMEM = "

" "

"; -const char HTTP_BTN_RESET[] PROGMEM = - "
" - "
"; const char HTTP_BTN_MENU4[] PROGMEM = "

" "

" "

"; + +const char HTTP_BTN_RESET[] PROGMEM = + "
" + "
"; const char HTTP_BTN_MENU5[] PROGMEM = "

" "

"; + const char HTTP_BTN_MAIN[] PROGMEM = "
" "
"; const char HTTP_FORM_LOGIN[] PROGMEM = + "
" "
" - "
" D_USER "

" - "
" D_PASSWORD "

" + "

" D_USER "

" + "

" D_PASSWORD "

" "
" - "
"; - -const char HTTP_BTN_CONF[] PROGMEM = - "
" - "
"; + "" + "
"; const char HTTP_FORM_TEMPLATE[] PROGMEM = "
 " D_TEMPLATE_PARAMETERS " " @@ -481,37 +482,32 @@ void StartWebserver(int type, IPAddress ipweb) if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } if (!webserver_state) { if (!WebServer) { - WebServer = new ESP8266WebServer((HTTP_MANAGER==type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); + WebServer = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); WebServer->on("/", HandleRoot); WebServer->onNotFound(HandleNotFound); + WebServer->on("/up", HandleUpgradeFirmware); + WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA + WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); + WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); + WebServer->on("/cs", HandleConsole); + WebServer->on("/cm", HandleHttpCommand); #ifndef FIRMWARE_MINIMAL + WebServer->on("/cn", HandleConfiguration); + WebServer->on("/md", HandleModuleConfiguration); + WebServer->on("/wi", HandleWifiConfiguration); + WebServer->on("/lg", HandleLoggingConfiguration); + WebServer->on("/tp", HandleTemplateConfiguration); + WebServer->on("/co", HandleOtherConfiguration); + WebServer->on("/dl", HandleBackupConfiguration); + WebServer->on("/rs", HandleRestoreConfiguration); WebServer->on("/rt", HandleResetConfiguration); -#endif // FIRMWARE_MINIMAL - if (HTTP_MANAGER_RESET_ONLY != type) { - WebServer->on("/up", HandleUpgradeFirmware); - WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA - WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); - WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cs", HandleConsole); - WebServer->on("/cm", HandleHttpCommand); -#ifndef FIRMWARE_MINIMAL - WebServer->on("/cn", HandleConfiguration); - WebServer->on("/md", HandleModuleConfiguration); - WebServer->on("/wi", HandleWifiConfiguration); - WebServer->on("/lg", HandleLoggingConfiguration); - WebServer->on("/tp", HandleTemplateConfiguration); - WebServer->on("/co", HandleOtherConfiguration); - WebServer->on("/dl", HandleBackupConfiguration); - WebServer->on("/rs", HandleRestoreConfiguration); - WebServer->on("/rt", HandleResetConfiguration); - WebServer->on("/in", HandleInformation); + WebServer->on("/in", HandleInformation); #ifdef USE_EMULATION - HueWemoAddHandlers(); + HueWemoAddHandlers(); #endif // USE_EMULATION - XdrvCall(FUNC_WEB_ADD_HANDLER); - XsnsCall(FUNC_WEB_ADD_HANDLER); + XdrvCall(FUNC_WEB_ADD_HANDLER); + XsnsCall(FUNC_WEB_ADD_HANDLER); #endif // Not FIRMWARE_MINIMAL - } } reset_web_log_flag = false; WebServer->begin(); // Web server start @@ -727,7 +723,7 @@ void WSContentSendStyle() WSContentSendStyle(F("")); } -void WSContentStop(void) +void WSContentEnd(void) { if (WifiIsInManagerMode()) { if (WifiConfigCounter()) { @@ -767,7 +763,7 @@ void WebRestart(uint8_t type) } else { WSContentSend(FPSTR(HTTP_BTN_MAIN)); } - WSContentStop(); + WSContentEnd(); ShowWebSource(SRC_WEBGUI); restart_flag = 2; @@ -780,7 +776,16 @@ void HandleWifiLogin(void) WSContentStart(FPSTR(D_CONFIGURE_WIFI), false); // false means show page no matter if the client has or has not credentials WSContentSendStyle(); WSContentSend(FPSTR(HTTP_FORM_LOGIN)); - WSContentStop(); + + if (WifiIsInManagerMode()) { + WSContentSend(F("
")); + WSContentSend(FPSTR(HTTP_BTN_RSTRT)); +#ifndef FIRMWARE_MINIMAL + WSContentSend(FPSTR(HTTP_BTN_RESET)); +#endif // FIRMWARE_MINIMAL + } + + WSContentEnd(); } void HandleRoot(void) @@ -864,10 +869,15 @@ void HandleRoot(void) #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == webserver_state) { +#ifndef FIRMWARE_MINIMAL + WSContentSend(FPSTR(HTTP_BTN_CONF)); +#else + WSContentSend(F("
")); +#endif // Not FIRMWARE_MINIMAL WSContentSend(FPSTR(HTTP_BTN_MENU1)); WSContentSend(FPSTR(HTTP_BTN_RSTRT)); } - WSContentStop(); + WSContentEnd(); } bool HandleRootStatusRefresh(void) @@ -969,7 +979,7 @@ void HandleConfiguration(void) WSContentSend(FPSTR(HTTP_BTN_RESET)); WSContentSend(FPSTR(HTTP_BTN_MENU5)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } /*-------------------------------------------------------------------------------------------*/ @@ -1056,7 +1066,7 @@ void HandleTemplateConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_TEMPLATE_FLAG)); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void TemplateSaveSettings(void) @@ -1163,7 +1173,7 @@ void HandleModuleConfiguration(void) WSContentSend(F("")); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void ModuleSaveSettings(void) @@ -1210,7 +1220,7 @@ String htmlEscape(String s) void HandleWifiConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); @@ -1220,7 +1230,7 @@ void HandleWifiConfiguration(void) return; } - WSContentStart(FPSTR(S_CONFIGURE_WIFI)); + WSContentStart(FPSTR(S_CONFIGURE_WIFI), !WifiIsInManagerMode()); WSContentSend(FPSTR(HTTP_SCRIPT_WIFI)); WSContentSendStyle(); @@ -1303,6 +1313,7 @@ void HandleWifiConfiguration(void) } if (WifiIsInManagerMode()) { + WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_BTN_RSTRT)); #ifndef FIRMWARE_MINIMAL WSContentSend(FPSTR(HTTP_BTN_RESET)); @@ -1310,7 +1321,7 @@ void HandleWifiConfiguration(void) } else { WSContentSend(FPSTR(HTTP_BTN_CONF)); } - WSContentStop(); + WSContentEnd(); } void WifiSaveSettings(void) @@ -1371,7 +1382,7 @@ void HandleLoggingConfiguration(void) WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void LoggingSaveSettings(void) @@ -1448,7 +1459,7 @@ void HandleOtherConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void OtherSaveSettings(void) @@ -1535,16 +1546,16 @@ void HandleBackupConfiguration(void) void HandleResetConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESET_CONFIGURATION); - WSContentStart(FPSTR(S_RESET_CONFIGURATION), (HTTP_MANAGER_RESET_ONLY != webserver_state)); + WSContentStart(FPSTR(S_RESET_CONFIGURATION), !WifiIsInManagerMode()); WSContentSendStyle(); WSContentSend(F("
" D_CONFIGURATION_RESET "
")); WSContentSend(FPSTR(HTTP_MSG_RSTRT)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); char command[CMDSZ]; snprintf_P(command, sizeof(command), PSTR(D_CMND_RESET " 1")); @@ -1562,7 +1573,7 @@ void HandleRestoreConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_RST)); WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); upload_error = 0; upload_file_type = UPL_SETTINGS; @@ -1664,7 +1675,7 @@ void HandleInformation(void) "
")); // WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } #endif // Not FIRMWARE_MINIMAL @@ -1681,7 +1692,7 @@ void HandleUpgradeFirmware(void) WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); upload_error = 0; upload_file_type = UPL_TASMOTA; @@ -1709,7 +1720,7 @@ void HandleUpgradeFirmwareStart(void) WSContentSend(F("
" D_UPGRADE_STARTED " ...
")); WSContentSend(FPSTR(HTTP_MSG_RSTRT)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); snprintf_P(command, sizeof(command), PSTR(D_CMND_UPGRADE " 1")); ExecuteWebCommand(command, SRC_WEBGUI); @@ -1757,7 +1768,7 @@ void HandleUploadDone(void) SettingsBufferFree(); WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } void HandleUploadLoop(void) @@ -2038,7 +2049,7 @@ void HandleConsole(void) WSContentSendStyle(); WSContentSend(FPSTR(HTTP_FORM_CMND)); WSContentSend(FPSTR(HTTP_BTN_MAIN)); - WSContentStop(); + WSContentEnd(); } void HandleConsoleRefresh(void) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d2874f490..ea0cc01e5 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -941,7 +941,7 @@ void HandleMqttConfiguration(void) Settings.mqtt_fulltopic); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void MqttSaveSettings(void) diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index a90245e08..ec4e4f142 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -485,7 +485,7 @@ void HandleDomoticzConfiguration(void) WSContentSend(F("")); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void DomoticzSaveSettings(void) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index cfc18904a..094fbcd96 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -721,7 +721,7 @@ void HandleTimerConfiguration(void) WSContentSend(FPSTR(HTTP_FORM_TIMER4)); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void TimerSaveSettings(void) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index d39001250..379f01157 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -947,7 +947,7 @@ void HandleKNXConfiguration(void) WSContentSend(F("
")); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } } diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 5057b8c47..2de8b985a 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -434,7 +434,7 @@ void HandleHxAction(void) WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); WSContentSend(FPSTR(HTTP_FORM_END)); WSContentSend(FPSTR(HTTP_BTN_CONF)); - WSContentStop(); + WSContentEnd(); } void HxSaveSettings(void)