Add optional SSE demo

This commit is contained in:
Theo Arends 2021-02-02 14:57:53 +01:00
parent f9ec44fb0b
commit f58d779b2b
7 changed files with 56 additions and 21 deletions

View File

@ -0,0 +1,21 @@
const char HTTP_SCRIPT_ROOT[] PROGMEM =
"function la(p){"
"if(typeof(EventSource)!==\"undefined\"){"
"var e=new EventSource('?m=1');"
"e.onmessage=function(event){"
"eb('l1').innerHTML=event.data.replace(/{t}/g,\"<table style='width:100%%'>\")"
".replace(/{s}/g,\"<tr><th>\")"
// ".replace(/{m}/g,\"</th><td>\")"
".replace(/{m}/g,\"</th><td style='width:20px;white-space:nowrap'>\")" // I want a right justified column with left justified text
".replace(/{e}/g,\"</td></tr>\")"
".replace(/{c}/g,\"%%'><div style='text-align:center;font-weight:\");"
"}"
"}"
"a=p||'';"
"clearTimeout(lt);"
"if(x!=null){x.abort()}" // Abort if no response within 2 seconds (happens on restart 1)
"x=new XMLHttpRequest();"
"x.open('GET','.?m=1'+a,true);" // ?m related to Webserver->hasArg("m")
"x.send();"
"lt=setTimeout(la,20000);" // 20s failure timeout
"}";

View File

@ -27,6 +27,9 @@
#define XDRV_01 1 #define XDRV_01 1
// Enable below demo feature only if defines USE_UNISHOX_COMPRESSION and USE_SCRIPT_WEB_DISPLAY are disabled
//#define USE_WEB_SSE
#ifndef WIFI_SOFT_AP_CHANNEL #ifndef WIFI_SOFT_AP_CHANNEL
#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by WifiManager web GUI #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by WifiManager web GUI
#endif #endif
@ -61,8 +64,6 @@ enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTACLIENT, UP
#endif #endif
#endif #endif
const char HTTP_SCRIPT_COUNTER[] PROGMEM = const char HTTP_SCRIPT_COUNTER[] PROGMEM =
"var cn=180;" // seconds "var cn=180;" // seconds
"function u(){" "function u(){"
@ -74,7 +75,6 @@ const char HTTP_SCRIPT_COUNTER[] PROGMEM =
"}" "}"
"wl(u);"; "wl(u);";
#ifdef USE_UNISHOX_COMPRESSION #ifdef USE_UNISHOX_COMPRESSION
#ifdef USE_SCRIPT_WEB_DISPLAY #ifdef USE_SCRIPT_WEB_DISPLAY
#include "./html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h" #include "./html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h"
@ -85,8 +85,12 @@ const char HTTP_SCRIPT_COUNTER[] PROGMEM =
#else #else
#ifdef USE_SCRIPT_WEB_DISPLAY #ifdef USE_SCRIPT_WEB_DISPLAY
#include "./html_uncompressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h" #include "./html_uncompressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h"
#else
#ifdef USE_WEB_SSE
#include "./html_uncompressed/HTTP_SCRIPT_ROOT_SSE_NO_WEB_DISPLAY.h"
#else #else
#include "./html_uncompressed/HTTP_SCRIPT_ROOT_NO_WEB_DISPLAY.h" #include "./html_uncompressed/HTTP_SCRIPT_ROOT_NO_WEB_DISPLAY.h"
#endif // USE_WEB_SSE
#endif #endif
#include "./html_uncompressed/HTTP_SCRIPT_ROOT_PART2.h" #include "./html_uncompressed/HTTP_SCRIPT_ROOT_PART2.h"
#endif #endif
@ -346,8 +350,8 @@ const char kButtonAction[] PROGMEM =
"md|wi|lg|co|tp|dl|rs"; "md|wi|lg|co|tp|dl|rs";
const char kButtonConfirm[] PROGMEM = D_CONFIRM_RESTART "|" D_CONFIRM_RESET_CONFIGURATION; const char kButtonConfirm[] PROGMEM = D_CONFIRM_RESTART "|" D_CONFIRM_RESET_CONFIGURATION;
enum CTypes { CT_HTML, CT_PLAIN, CT_XML, CT_JSON, CT_STREAM }; enum CTypes { CT_HTML, CT_PLAIN, CT_XML, CT_STREAM, CT_APP_JSON, CT_APP_STREAM };
const char kContentTypes[] PROGMEM = "text/html|text/plain|text/xml|application/json|application/octet-stream"; const char kContentTypes[] PROGMEM = "text/html|text/plain|text/xml|text/event-stream|application/json|application/octet-stream";
const char kLoggingOptions[] PROGMEM = D_SERIAL_LOG_LEVEL "|" D_WEB_LOG_LEVEL "|" D_MQTT_LOG_LEVEL "|" D_SYS_LOG_LEVEL; const char kLoggingOptions[] PROGMEM = D_SERIAL_LOG_LEVEL "|" D_WEB_LOG_LEVEL "|" D_MQTT_LOG_LEVEL "|" D_SYS_LOG_LEVEL;
const char kLoggingLevels[] PROGMEM = D_NONE "|" D_ERROR "|" D_INFO "|" D_DEBUG "|" D_MORE_DEBUG; const char kLoggingLevels[] PROGMEM = D_NONE "|" D_ERROR "|" D_INFO "|" D_DEBUG "|" D_MORE_DEBUG;
@ -1223,7 +1227,13 @@ bool HandleRootStatusRefresh(void)
ExecuteWebCommand(svalue, SRC_WEBGUI); ExecuteWebCommand(svalue, SRC_WEBGUI);
} }
#endif // USE_ZIGBEE #endif // USE_ZIGBEE
#ifdef USE_WEB_SSE
WSContentBegin(200, CT_STREAM);
WSContentSend_P(PSTR("data: "));
#else
WSContentBegin(200, CT_HTML); WSContentBegin(200, CT_HTML);
#endif // USE_WEB_SSE
WSContentSend_P(PSTR("{t}")); WSContentSend_P(PSTR("{t}"));
XsnsCall(FUNC_WEB_SENSOR); XsnsCall(FUNC_WEB_SENSOR);
XdrvCall(FUNC_WEB_SENSOR); XdrvCall(FUNC_WEB_SENSOR);
@ -1259,6 +1269,10 @@ bool HandleRootStatusRefresh(void)
} }
} }
#endif // USE_TUYA_MCU #endif // USE_TUYA_MCU
#ifdef USE_WEB_SSE
WSContentSend_P(PSTR("\n\n"));
#endif // USE_WEB_SSE
WSContentEnd(); WSContentEnd();
return true; return true;
@ -1990,7 +2004,7 @@ void HandleBackupConfiguration(void)
Webserver->sendHeader(F("Content-Disposition"), attachment); Webserver->sendHeader(F("Content-Disposition"), attachment);
WSSend(200, CT_STREAM, ""); WSSend(200, CT_APP_STREAM, "");
uint32_t cfg_crc32 = Settings.cfg_crc32; uint32_t cfg_crc32 = Settings.cfg_crc32;
Settings.cfg_crc32 = GetSettingsCrc32(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918) Settings.cfg_crc32 = GetSettingsCrc32(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918)
@ -2671,14 +2685,14 @@ void HandleHttpCommand(void)
WebGetArg(PSTR("password"), tmp2, sizeof(tmp2)); WebGetArg(PSTR("password"), tmp2, sizeof(tmp2));
if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) {
WSContentBegin(401, CT_JSON); WSContentBegin(401, CT_APP_JSON);
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}"));
WSContentEnd(); WSContentEnd();
return; return;
} }
} }
WSContentBegin(200, CT_JSON); WSContentBegin(200, CT_APP_JSON);
String svalue = Webserver->arg(F("cmnd")); String svalue = Webserver->arg(F("cmnd"));
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
uint32_t curridx = TasmotaGlobal.log_buffer_pointer; uint32_t curridx = TasmotaGlobal.log_buffer_pointer;

View File

@ -4926,7 +4926,7 @@ uint8_t DownloadFile(char *file) {
} }
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp); snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp);
Webserver->sendHeader(F("Content-Disposition"), attachment); Webserver->sendHeader(F("Content-Disposition"), attachment);
WSSend(200, CT_STREAM, ""); WSSend(200, CT_APP_STREAM, "");
uint8_t buff[512]; uint8_t buff[512];
uint16_t bread; uint16_t bread;
@ -5599,7 +5599,7 @@ void Script_Handle_Hue(String *path) {
response = FPSTR(sHUE_ERROR_JSON); response = FPSTR(sHUE_ERROR_JSON);
} }
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str());
WSSend(code, CT_JSON, response); WSSend(code, CT_APP_JSON, response);
if (resp) { if (resp) {
Run_Scripter(">E", 2, 0); Run_Scripter(">E", 2, 0);
} }

View File

@ -438,7 +438,7 @@ void HueNotImplemented(String *path)
{ {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str());
WSSend(200, CT_JSON, PSTR("{}")); WSSend(200, CT_APP_JSON, PSTR("{}"));
} }
void HueConfigResponse(String *response) void HueConfigResponse(String *response)
@ -457,7 +457,7 @@ void HueConfig(String *path)
{ {
String response = ""; String response = "";
HueConfigResponse(&response); HueConfigResponse(&response);
WSSend(200, CT_JSON, response); WSSend(200, CT_APP_JSON, response);
} }
// device is forced to CT mode instead of HSB // device is forced to CT mode instead of HSB
@ -680,7 +680,7 @@ void HueGlobalConfig(String *path) {
response += F("},\"groups\":{},\"schedules\":{},\"config\":"); response += F("},\"groups\":{},\"schedules\":{},\"config\":");
HueConfigResponse(&response); HueConfigResponse(&response);
response += F("}"); response += F("}");
WSSend(200, CT_JSON, response); WSSend(200, CT_APP_JSON, response);
} }
void HueAuthentication(String *path) void HueAuthentication(String *path)
@ -688,7 +688,7 @@ void HueAuthentication(String *path)
char response[38]; char response[38];
snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str());
WSSend(200, CT_JSON, response); WSSend(200, CT_APP_JSON, response);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Authentication Result (%s)"), response); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Authentication Result (%s)"), response);
} }
@ -996,7 +996,7 @@ void HueLights(String *path)
} }
exit: exit:
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str());
WSSend(code, CT_JSON, response); WSSend(code, CT_APP_JSON, response);
} }
void HueGroups(String *path) void HueGroups(String *path)
@ -1029,7 +1029,7 @@ void HueGroups(String *path)
} }
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups Result (%s)"), path->c_str()); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups Result (%s)"), path->c_str());
WSSend(200, CT_JSON, response); WSSend(200, CT_APP_JSON, response);
} }
void HandleHueApi(String *path) void HandleHueApi(String *path)

View File

@ -384,7 +384,7 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) {
response = msg[HUE_ERROR_JSON]; response = msg[HUE_ERROR_JSON];
} }
AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str());
WSSend(code, CT_JSON, response); WSSend(code, CT_APP_JSON, response);
free(buf); free(buf);
} }

View File

@ -625,7 +625,7 @@ uint8_t UfsDownloadFile(char *file) {
} }
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp); snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp);
Webserver->sendHeader(F("Content-Disposition"), attachment); Webserver->sendHeader(F("Content-Disposition"), attachment);
WSSend(200, CT_STREAM, ""); WSSend(200, CT_APP_STREAM, "");
uint8_t buff[512]; uint8_t buff[512];
uint32_t bread; uint32_t bread;
@ -696,7 +696,7 @@ void donload_task(void *path) {
} }
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp); snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"), cp);
Webserver->sendHeader(F("Content-Disposition"), attachment); Webserver->sendHeader(F("Content-Disposition"), attachment);
WSSend(200, CT_STREAM, ""); WSSend(200, CT_APP_STREAM, "");
uint8_t *buff = (uint8_t*)malloc(DOWNLOAD_SIZE); uint8_t *buff = (uint8_t*)malloc(DOWNLOAD_SIZE);
if (buff) { if (buff) {

View File

@ -490,7 +490,7 @@ void UBXsendHeader(void)
{ {
Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN);
Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx"));
WSSend(200, CT_STREAM, F( WSSend(200, CT_APP_STREAM, F(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n" "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n"
"<GPX version=\"1.1\" creator=\"TASMOTA\" xmlns=\"http://www.topografix.com/GPX/1/1\" \r\n" "<GPX version=\"1.1\" creator=\"TASMOTA\" xmlns=\"http://www.topografix.com/GPX/1/1\" \r\n"
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n"