v5.11.1f - Revert chunks (#1706)

5.11.1f
 * Revert chunked webserver pages as it fails on many browsers
due to chunks being too small (#1706)
 * Reduce initial console weblog
from 20 to 13 lines due to memory constraints
This commit is contained in:
arendst 2018-01-26 15:21:57 +01:00
parent cfdbe8af95
commit d66ef2347e
7 changed files with 66 additions and 133 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota ## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **5.11.1e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. Current version is **5.11.1f** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions ### ATTENTION All versions

View File

@ -1,4 +1,8 @@
/* 5.11.1e /* 5.11.1f
* Revert chunked webserver pages as it fails on many browsers due to chunks being too small (#1706)
* Reduce initial console weblog from 20 to 13 lines due to memory constraints
*
* 5.11.1e
* Replaced command Ina219Mode with command Sensor13 * Replaced command Ina219Mode with command Sensor13
* Add chunked webserver pages for large pages saving memory * Add chunked webserver pages for large pages saving memory
* Fix Non-English JSON temperature unit attachement * Fix Non-English JSON temperature unit attachement

View File

@ -90,7 +90,11 @@ typedef unsigned long power_t; // Power (Relay) type
#ifdef USE_MQTT_TLS #ifdef USE_MQTT_TLS
#define MAX_LOG_LINES 10 // Max number of lines in weblog #define MAX_LOG_LINES 10 // Max number of lines in weblog
#else #else
#define MAX_LOG_LINES 20 // Max number of lines in weblog #ifdef ARDUINO_ESP8266_RELEASE_2_3_0
#define MAX_LOG_LINES 20 // Max number of lines in weblog
#else
#define MAX_LOG_LINES 13 // Max number of lines in weblog (less due to more memory usage)
#endif
#endif #endif
#define MAX_BACKLOG 16 // Max number of commands in backlog (chk backlog_index and backlog_pointer code) #define MAX_BACKLOG 16 // Max number of commands in backlog (chk backlog_index and backlog_pointer code)
#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds #define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds

View File

@ -25,9 +25,10 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)" - Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/ ====================================================*/
#define VERSION 0x050B0105 // 5.11.1e #define VERSION 0x050B0106 // 5.11.1f
// Location specific includes // Location specific includes
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
#include "sonoff.h" // Enumeration used in user_config.h #include "sonoff.h" // Enumeration used in user_config.h
#include "user_config.h" // Fixed user configurable options #include "user_config.h" // Fixed user configurable options
#include "user_config_override.h" // Configuration overrides for user_config.h #include "user_config_override.h" // Configuration overrides for user_config.h

View File

@ -108,7 +108,7 @@ void WifiWpsStatusCallback(wps_cb_status status);
#define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string (6 x DS18x20 sensors) #define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string (6 x DS18x20 sensors)
#endif #endif
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) //#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
#ifndef ARDUINO_ESP8266_RELEASE #ifndef ARDUINO_ESP8266_RELEASE
#define ARDUINO_ESP8266_RELEASE "STAGED" #define ARDUINO_ESP8266_RELEASE "STAGED"
#endif #endif

View File

@ -414,6 +414,8 @@ void PollDnsWebserver()
} }
} }
/*********************************************************************************************/
void SetHeader() void SetHeader()
{ {
WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate"));
@ -424,8 +426,6 @@ void SetHeader()
#endif #endif
} }
/*********************************************************************************************/
void ShowPage(String &page, bool auth) void ShowPage(String &page, bool auth)
{ {
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) { if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
@ -453,57 +453,6 @@ void ShowPage(String &page)
/*********************************************************************************************/ /*********************************************************************************************/
void ShowPageStartChunk()
{
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), "");
}
void ShowPageChunk(String &page)
{
page.replace(F("{ha"), my_module.name);
page.replace(F("{h}"), Settings.friendlyname[0]);
if (HTTP_MANAGER == webserver_state) {
if (WifiConfigCounter()) {
page.replace(F("<body>"), F("<body onload='u()'>"));
page += FPSTR(HTTP_COUNTER);
}
}
WebServer->sendContent(page);
}
void ShowPageStart(String &page, bool auth)
{
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
return WebServer->requestAuthentication();
}
SetHeader();
ShowPageStartChunk();
ShowPageChunk(page);
}
void ShowPageStart(String &page)
{
ShowPageStart(page, true);
}
void ShowPageStopChunk()
{
WebServer->sendContent("");
WebServer->client().stop(); // Stop is needed because we sent no content length
}
void ShowPageEnd(String &page)
{
ShowPageChunk(page);
String endpart = FPSTR(HTTP_END);
endpart.replace(F("{mv"), my_version);
WebServer->sendContent(endpart);
ShowPageStopChunk();
}
/*********************************************************************************************/
void HandleWifiLogin() void HandleWifiLogin()
{ {
String page = FPSTR(HTTP_HEAD); String page = FPSTR(HTTP_HEAD);
@ -534,7 +483,6 @@ void HandleRoot()
} }
} else { } else {
char stemp[10]; char stemp[10];
char line[160];
String page = FPSTR(HTTP_HEAD); String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_MAIN_MENU)); page.replace(F("{v}"), FPSTR(S_MAIN_MENU));
page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_HEAD_STYLE);
@ -544,19 +492,19 @@ void HandleRoot()
if (devices_present) { if (devices_present) {
if (light_type) { if (light_type) {
if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) { if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) {
snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER1, LightGetColorTemp()); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER1, LightGetColorTemp());
page += line; page += mqtt_data;
} }
snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER2, Settings.light_dimmer); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MSG_SLIDER2, Settings.light_dimmer);
page += line; page += mqtt_data;
} }
page += FPSTR(HTTP_TABLE100); page += FPSTR(HTTP_TABLE100);
page += F("<tr>"); page += F("<tr>");
for (byte idx = 1; idx <= devices_present; idx++) { for (byte idx = 1; idx <= devices_present; idx++) {
snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx);
snprintf_P(line, sizeof(line), PSTR("<td style='width:%d%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>"),
100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : "");
page += line; page += mqtt_data;
} }
page += F("</tr></table>"); page += F("</tr></table>");
} }
@ -570,8 +518,8 @@ void HandleRoot()
} }
for (byte j = 0; j < 4; j++) { for (byte j = 0; j < 4; j++) {
idx++; idx++;
snprintf_P(line, sizeof(line), PSTR("<td style='width:25%'><button onclick='la(\"?k=%d\");'>%d</button></td>"), idx, idx); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:25%'><button onclick='la(\"?k=%d\");'>%d</button></td>"), idx, idx);
page += line; page += mqtt_data;
} }
} }
page += F("</tr></table>"); page += F("</tr></table>");
@ -605,23 +553,28 @@ void HandleAjaxStatusRefresh()
ExecuteCommand(svalue); ExecuteCommand(svalue);
} }
ShowPageStartChunk(); String page = "";
WebServer->sendContent(HTTP_TABLE100); mqtt_data[0] = '\0';
XsnsCall(FUNC_WEB_APPEND); XsnsCall(FUNC_WEB_APPEND);
WebServer->sendContent(PSTR("</table>")); if (strlen(mqtt_data)) {
page += FPSTR(HTTP_TABLE100);
page += mqtt_data;
page.replace(F("."), F(D_DECIMAL_SEPARATOR));
page += F("</table>");
}
if (devices_present) { if (devices_present) {
WebServer->sendContent(HTTP_TABLE100); page += FPSTR(HTTP_TABLE100);
WebServer->sendContent(PSTR("<tr>")); page += F("<tr>");
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
for (byte idx = 1; idx <= devices_present; idx++) { for (byte idx = 1; idx <= devices_present; idx++) {
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d{t}%s;font-size:%dpx'>%s</div></td>"), // {t} = %'><div style='text-align:center;font-weight: snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d{t}%s;font-size:%dpx'>%s</div></td>"), // {t} = %'><div style='text-align:center;font-weight:
100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
WebServer->sendContent(mqtt_data); page += mqtt_data;
} }
WebServer->sendContent(PSTR("</tr></table>")); page += F("</tr></table>");
} }
ShowPageStopChunk(); WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page);
} }
boolean HttpUser() boolean HttpUser()
@ -714,67 +667,57 @@ void HandleModuleConfiguration()
return; return;
} }
char stemp[20]; char stemp[20];
char line[160];
uint8_t midx; uint8_t midx;
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE);
String page = FPSTR(HTTP_HEAD); String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE));
ShowPageStart(page); page += FPSTR(HTTP_SCRIPT_MODULE1);
page = FPSTR(HTTP_SCRIPT_MODULE1);
for (byte i = 0; i < MAXMODULE; i++) { for (byte i = 0; i < MAXMODULE; i++) {
midx = pgm_read_byte(kNiceList + i); midx = pgm_read_byte(kNiceList + i);
snprintf_P(stemp, sizeof(stemp), kModules[midx].name); snprintf_P(stemp, sizeof(stemp), kModules[midx].name);
snprintf_P(line, sizeof(line), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp);
page += line; page += mqtt_data;
} }
page += FPSTR(HTTP_SCRIPT_MODULE3); page += FPSTR(HTTP_SCRIPT_MODULE3);
ShowPageChunk(page); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,99);o0=\""), Settings.module); // g99
page += mqtt_data;
snprintf_P(line, sizeof(line), PSTR("sk(%d,99);o0=\""), Settings.module); // g99
page = line;
mytmplt cmodule; mytmplt cmodule;
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule));
for (byte j = 0; j < GPIO_SENSOR_END; j++) { for (byte j = 0; j < GPIO_SENSOR_END; j++) {
if (!GetUsedInModule(j, cmodule.gp.io)) { if (!GetUsedInModule(j, cmodule.gp.io)) {
snprintf_P(stemp, sizeof(stemp), kSensors[j]); snprintf_P(stemp, sizeof(stemp), kSensors[j]);
snprintf_P(line, sizeof(line), HTTP_SCRIPT_MODULE2, j, j, stemp); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, j, j, stemp);
page += line; page += mqtt_data;
} }
} }
page += FPSTR(HTTP_SCRIPT_MODULE3); page += FPSTR(HTTP_SCRIPT_MODULE3);
ShowPageChunk(page);
page = FPSTR(HTTP_HEAD_STYLE); String part2 = FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_MODULE); part2 += FPSTR(HTTP_FORM_MODULE);
snprintf_P(stemp, sizeof(stemp), kModules[MODULE].name); snprintf_P(stemp, sizeof(stemp), kModules[MODULE].name);
page.replace(F("{mt"), stemp); part2.replace(F("{mt"), stemp);
page += F("<br/><table>"); part2 += F("<br/><table>");
String func = "";
for (byte i = 0; i < MAX_GPIO_PIN; i++) { for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (GPIO_USER == cmodule.gp.io[i]) { if (GPIO_USER == cmodule.gp.io[i]) {
snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(stemp, 3, PINS_WEMOS +i*2);
snprintf_P(line, sizeof(line), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:126px'><select id='g%d' name='g%d'></select></td></tr>"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:126px'><select id='g%d' name='g%d'></select></td></tr>"),
(WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i);
page += line; part2 += mqtt_data;
snprintf_P(line, sizeof(line), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16 snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16
func += line; page += mqtt_data;
} }
} }
func += F("}"); page += F("}");
ShowPageChunk(func); page += part2;
page.replace(F("<body>"), F("<body onload='sl()'>")); page.replace(F("<body>"), F("<body onload='sl()'>"));
page += F("</table>"); page += F("</table>");
ShowPageChunk(page); page += FPSTR(HTTP_FORM_END);
page = FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF); page += FPSTR(HTTP_BTN_CONF);
ShowPageEnd(page); ShowPage(page);
} }
void HandleWifiConfigurationWithScan() void HandleWifiConfigurationWithScan()
@ -1472,7 +1415,6 @@ void HandleHttpCommand()
} }
SetHeader(); SetHeader();
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message); WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message);
// WebServer->sendContent("");
} }
void HandleConsole() void HandleConsole()
@ -1517,10 +1459,8 @@ void HandleAjaxConsoleRefresh()
counter = atoi(WebServer->arg("c2").c_str()); counter = atoi(WebServer->arg("c2").c_str());
} }
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
WebServer->send(200, FPSTR(HDR_CTYPE_XML), "");
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<r><i>%d</i><j>%d</j><l>"), web_log_index, reset_web_log_flag); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<r><i>%d</i><j>%d</j><l>"), web_log_index, reset_web_log_flag);
WebServer->sendContent(mqtt_data); String message = F("}9"); // Cannot load mqtt_data here as <> will be encoded by replacements below
if (!reset_web_log_flag) { if (!reset_web_log_flag) {
counter = 99; counter = 99;
reset_web_log_flag = 1; reset_web_log_flag = 1;
@ -1533,23 +1473,24 @@ void HandleAjaxConsoleRefresh()
do { do {
if (web_log[counter].length()) { if (web_log[counter].length()) {
if (cflg) { if (cflg) {
WebServer->sendContent(PSTR("\n")); message += F("\n");
} else { } else {
cflg = 1; cflg = 1;
} }
web_log[counter].replace(F("<"), F("%3C")); // XML encoding to fix blank console log in concert with javascript decodeURIComponent message += web_log[counter];
web_log[counter].replace(F(">"), F("%3E"));
web_log[counter].replace(F("&"), F("%26"));
WebServer->sendContent(web_log[counter]);
} }
counter++; counter++;
if (counter > MAX_LOG_LINES -1) { if (counter > MAX_LOG_LINES -1) {
counter = 0; counter = 0;
} }
} while (counter != web_log_index); } while (counter != web_log_index);
message.replace(F("<"), F("%3C")); // XML encoding to fix blank console log in concert with javascript decodeURIComponent
message.replace(F(">"), F("%3E"));
message.replace(F("&"), F("%26"));
} }
WebServer->sendContent(PSTR("</l></r>")); message.replace(F("}9"), mqtt_data); // Save to load here
ShowPageStopChunk(); message += F("</l></r>");
WebServer->send(200, FPSTR(HDR_CTYPE_XML), message);
} }
void HandleInformation() void HandleInformation()

View File

@ -119,27 +119,10 @@ boolean XsnsCall(byte Function)
boolean result = false; boolean result = false;
for (byte x = 0; x < xsns_present; x++) { for (byte x = 0; x < xsns_present; x++) {
#ifdef USE_WEBSERVER
if (FUNC_WEB_APPEND == Function) {
mqtt_data[0] = '\0';
}
#endif // USE_WEBSERVER
result = xsns_func_ptr[x](Function); result = xsns_func_ptr[x](Function);
if (result) { if (result) {
break; break;
} }
#ifdef USE_WEBSERVER
if ((FUNC_WEB_APPEND == Function) && strlen(mqtt_data)) {
if (D_DECIMAL_SEPARATOR[0] != '.') {
for (int i = 0; i < strlen(mqtt_data); i++) {
if ('.' == mqtt_data[i]) {
mqtt_data[i] = D_DECIMAL_SEPARATOR[0];
}
}
}
WebServer->sendContent(mqtt_data);
}
#endif // USE_WEBSERVER
} }
return result; return result;