"), color);
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentButton(uint32_t title_index, bool show=true) {
char action[4];
char title[100]; // Large to accomodate UTF-16 as used by Russian
@@ -1003,11 +1046,15 @@ void WSContentButton(uint32_t title_index, bool show=true) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentSpaceButton(uint32_t title_index, bool show=true) {
WSContentSend_P(PSTR("
")); // 5px padding
WSContentButton(title_index, show);
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentSeparator(uint32_t state) {
// Send two column separator
static bool request = false;
@@ -1029,18 +1076,26 @@ void WSContentSeparator(uint32_t state) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentSend_Temp(const char *types, float f_temperature) {
WSContentSend_PD(HTTP_SNS_F_TEMP, types, Settings->flag2.temperature_resolution, &f_temperature, TempUnit());
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentSend_Voltage(const char *types, float f_voltage) {
WSContentSend_PD(HTTP_SNS_F_VOLTAGE, types, Settings->flag2.voltage_resolution, &f_voltage);
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentSend_CurrentMA(const char *types, float f_current) {
WSContentSend_PD(HTTP_SNS_F_CURRENT_MA, types, Settings->flag2.current_resolution, &f_current);
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentSend_THD(const char *types, float f_temperature, float f_humidity) {
WSContentSend_Temp(types, f_temperature);
@@ -1055,6 +1110,8 @@ void WSContentSend_THD(const char *types, float f_temperature, float f_humidity)
#endif // USE_HEAT_INDEX
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentEnd(void) {
WSContentFlush(); // Flush chunk buffer
_WSContentSend(""); // Signal end of chunked content
@@ -1064,6 +1121,8 @@ void WSContentEnd(void) {
#endif // defined(USE_MI_ESP32) && !defined(USE_BLE_ESP32)
}
+/*-------------------------------------------------------------------------------------------*/
+
void WSContentStop(void) {
if ( WifiIsInManagerMode() && (!Web.initial_config) ) {
if (WifiConfigCounter()) {
@@ -1139,8 +1198,23 @@ void WebRestart(uint32_t type) {
/*********************************************************************************************/
-void HandleWifiLogin(void)
-{
+uint32_t WebUseManagementSubmenu(void) {
+ static uint32_t management_count = 0;
+
+ if (!management_count) {
+ XdrvMailbox.index = 1;
+ XdrvXsnsCall(FUNC_WEB_ADD_CONSOLE_BUTTON);
+ XdrvCall(FUNC_WEB_ADD_MANAGEMENT_BUTTON);
+ management_count = XdrvMailbox.index;
+ }
+ return management_count -1;
+}
+
+/*********************************************************************************************\
+ * HandleRoot
+\*********************************************************************************************/
+
+void HandleWifiLogin(void) {
WSContentStart_P(PSTR(D_CONFIGURE_WIFI), false); // false means show page no matter if the client has or has not credentials
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_LOGIN);
@@ -1155,19 +1229,9 @@ void HandleWifiLogin(void)
WSContentStop();
}
-uint32_t WebUseManagementSubmenu(void) {
- static uint32_t management_count = 0;
-
- if (!management_count) {
- XdrvMailbox.index = 1;
- XdrvXsnsCall(FUNC_WEB_ADD_CONSOLE_BUTTON);
- XdrvCall(FUNC_WEB_ADD_MANAGEMENT_BUTTON);
- management_count = XdrvMailbox.index;
- }
- return management_count -1;
-}
-
#ifdef USE_LIGHT
+/*-------------------------------------------------------------------------------------------*/
+
void WebSliderColdWarm(void) {
Web.slider[0] = LightGetColorTemp();
WSContentSend_P(PSTR("
|
WSContentSeparatorI(1);
}
+/*-------------------------------------------------------------------------------------------*/
+
void HandleInformation(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
@@ -2883,7 +3000,9 @@ void HandleInformation(void) {
#endif // Not FIRMWARE_MINIMAL
-/*-------------------------------------------------------------------------------------------*/
+/*********************************************************************************************\
+ * HandleUpgradeFirmware
+\*********************************************************************************************/
#if defined(USE_ZIGBEE_EZSP) || defined(USE_TASMOTA_CLIENT) || defined(SHELLY_FW_UPGRADE) || defined(USE_RF_FLASH) || defined(USE_CCLOADER)
#define USE_WEB_FW_UPGRADE
@@ -2899,6 +3018,8 @@ struct {
bool ready;
} BUpload;
+/*-------------------------------------------------------------------------------------------*/
+
void BUploadInit(uint32_t file_type) {
Web.upload_file_type = file_type;
BUpload.spi_hex_size = 0;
@@ -2908,6 +3029,8 @@ void BUploadInit(uint32_t file_type) {
BUpload.ready = false;
}
+/*-------------------------------------------------------------------------------------------*/
+
uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) {
if (0 == BUpload.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
if (!ESP.flashEraseSector(BUpload.spi_sector_counter)) {
@@ -2931,6 +3054,8 @@ uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) {
#endif // USE_WEB_FW_UPGRADE
+/*-------------------------------------------------------------------------------------------*/
+
void HandleUpgradeFirmware(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
@@ -2954,6 +3079,8 @@ void HandleUpgradeFirmware(void) {
Web.upload_file_type = UPL_TASMOTA;
}
+/*-------------------------------------------------------------------------------------------*/
+
void HandleUpgradeFirmwareStart(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
@@ -2981,6 +3108,8 @@ void HandleUpgradeFirmwareStart(void) {
ExecuteWebCommand(command);
}
+/*-------------------------------------------------------------------------------------------*/
+
void HandleUploadDone(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
@@ -3029,6 +3158,8 @@ void HandleUploadDone(void) {
WSContentStop();
}
+/*-------------------------------------------------------------------------------------------*/
+
void UploadServices(uint32_t start_service) {
if (Web.upload_services_stopped != start_service) { return; }
Web.upload_services_stopped = !start_service;
@@ -3053,6 +3184,8 @@ void UploadServices(uint32_t start_service) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void HandleUploadLoop(void) {
// Based on ESP8266HTTPUpdateServer.cpp uses ESP8266WebServer Parsing.cpp and Cores Updater.cpp (Update)
static uint32_t upload_size;
@@ -3305,10 +3438,11 @@ void HandleUploadLoop(void) {
// Scheduler(); // Feed OsWatch timer to prevent restart on long uploads
}
-/*-------------------------------------------------------------------------------------------*/
+/*********************************************************************************************\
+ * HandlePreflightRequest
+\*********************************************************************************************/
-void HandlePreflightRequest(void)
-{
+void HandlePreflightRequest(void) {
#ifdef USE_CORS
HttpHeaderCors();
#endif
@@ -3317,9 +3451,11 @@ void HandlePreflightRequest(void)
WSSend(200, CT_HTML, "");
}
-/*-------------------------------------------------------------------------------------------*/
-
#ifdef ESP32
+/*********************************************************************************************\
+ * HandleSwitchBootPartition
+\*********************************************************************************************/
+
// Switch boot partition
//
// Parameter `u4` is either `fct` or `ota` to switch to factory or ota
@@ -3338,8 +3474,9 @@ static void WSReturnSimpleString(const char *msg) {
Webserver->send(200, "text/plain", msg);
}
-void HandleSwitchBootPartition(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void HandleSwitchBootPartition(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
char tmp1[8];
@@ -3393,10 +3530,11 @@ void HandleSwitchBootPartition(void)
}
#endif // ESP32
-/*-------------------------------------------------------------------------------------------*/
+/*********************************************************************************************\
+ * HandleHttpCommand
+\*********************************************************************************************/
-void HandleHttpCommand(void)
-{
+void HandleHttpCommand(void) {
if (!HttpCheckPriviledgedAccess(false)) { return; }
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND));
@@ -3451,10 +3589,11 @@ void HandleHttpCommand(void)
WSContentEnd();
}
-/*-------------------------------------------------------------------------------------------*/
+/*********************************************************************************************\
+ * HandleManagement
+\*********************************************************************************************/
-void HandleManagement(void)
-{
+void HandleManagement(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_MANAGEMENT));
@@ -3473,8 +3612,11 @@ void HandleManagement(void)
WSContentStop();
}
-void HandleConsole(void)
-{
+/*********************************************************************************************\
+ * HandleConsole
+\*********************************************************************************************/
+
+void HandleConsole(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
if (Webserver->hasArg(F("c2"))) { // Console refresh requested
@@ -3496,8 +3638,9 @@ void HandleConsole(void)
WSContentStop();
}
-void HandleConsoleRefresh(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void HandleConsoleRefresh(void) {
String svalue = Webserver->arg(F("c1"));
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str());
@@ -3529,8 +3672,7 @@ void HandleConsoleRefresh(void)
/********************************************************************************************/
-void HandleNotFound(void)
-{
+void HandleNotFound(void) {
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not found (%s)"), Webserver->uri().c_str());
#ifndef NO_CAPTIVE_PORTAL
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page.
@@ -3554,10 +3696,11 @@ void HandleNotFound(void)
}
}
+/********************************************************************************************/
+
#ifndef NO_CAPTIVE_PORTAL
/* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
-bool CaptivePortal(void)
-{
+bool CaptivePortal(void) {
// Possible hostHeader: connectivitycheck.gstatic.com or 192.168.4.1
if ((WifiIsInManagerMode()) && !ValidIpAddress(Webserver->hostHeader().c_str())) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED));
@@ -3571,7 +3714,9 @@ bool CaptivePortal(void)
}
#endif // NO_CAPTIVE_PORTAL
-/*********************************************************************************************/
+/*********************************************************************************************\
+ * Commands
+\*********************************************************************************************/
#ifndef FIRMWARE_MINIMAL
@@ -3579,12 +3724,13 @@ enum {QUERY_DEFAULT=0, QUERY_RUN};
int WebQuery(char *buffer, int query_function);
#ifdef USE_WEBRUN
+/*-------------------------------------------------------------------------------------------*/
+
char *WebRunBuffer = nullptr;
char *WebRunContext = nullptr;
bool WebRunMutex = false;
-void WebRunLoop(void)
-{
+void WebRunLoop(void) {
if (WebRunBuffer && !WebRunMutex && BACKLOG_EMPTY) {
WebRunMutex = true;
char *command = strtok_r(WebRunContext, "\n\r", &WebRunContext);
@@ -3600,8 +3746,9 @@ void WebRunLoop(void)
}
}
-void WebRunInit(const char *command_buffer)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void WebRunInit(const char *command_buffer) {
if (!WebRunBuffer) {
int len = strlen(command_buffer);
WebRunContext = WebRunBuffer = (char*)malloc(len+1);
@@ -3617,9 +3764,9 @@ void WebRunInit(const char *command_buffer)
}
#endif // #ifdef USE_WEBRUN
+/*-------------------------------------------------------------------------------------------*/
-int WebQuery(char *buffer, int query_function = 0)
-{
+int WebQuery(char *buffer, int query_function = 0) {
// http://192.168.1.1/path GET -> Sends HTTP GET http://192.168.1.1/path
// http://192.168.1.1/path POST {"some":"message"} -> Sends HTTP POST to http://192.168.1.1/path with body {"some":"message"}
// http://192.168.1.1/path PUT [Autorization: Bearer abcdxyz] potato -> Sends HTTP PUT to http://192.168.1.1/path with authorization header and body "potato"
@@ -3737,147 +3884,8 @@ int WebQuery(char *buffer, int query_function = 0)
return status;
}
-int WebSend(char *buffer)
-{
- // [tasmota] POWER1 ON --> Sends http://tasmota/cm?cmnd=POWER1 ON
- // [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON
- // [tasmota] /any/link/starting/with/a/slash.php?log=123 --> Sends http://tasmota/any/link/starting/with/a/slash.php?log=123
- // [tasmota,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://tasmota/any/link/starting/with/a/slash.php?log=123
- char *host;
- char *user;
- char *password;
- char *command;
- int status = WEBCMND_WRONG_PARAMETERS;
-
- // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON |
- host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON |
- if (host && command) {
- RemoveSpace(host); // host = |[192.168.178.86:80,admin:joker|
- host++; // host = |192.168.178.86:80,admin:joker| - Skip [
- host = strtok_r(host, ",", &user); // host = |192.168.178.86:80|, user = |admin:joker|
- String url = F("http://"); // url = |http://|
- url += host; // url = |http://192.168.178.86:80|
-
- command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123|
- if (command[0] != '/') {
- url += F("/cm?"); // url = |http://192.168.178.86/cm?|
- if (user) {
- user = strtok_r(user, ":", &password); // user = |admin|, password = |joker|
- if (user && password) {
- char userpass[200];
- snprintf_P(userpass, sizeof(userpass), PSTR("user=%s&password=%s&"), user, password);
- url += userpass; // url = |http://192.168.178.86/cm?user=admin&password=joker&|
- }
- }
- url += F("cmnd="); // url = |http://192.168.178.86/cm?cmnd=| or |http://192.168.178.86/cm?user=admin&password=joker&cmnd=|
- }
- url += UrlEncode(command); // url = |http://192.168.178.86/cm?cmnd=POWER1%20ON|
- url += F(" GET"); // url = |http://192.168.178.86/cm?cmnd=POWER1%20ON GET|
-
- DEBUG_CORE_LOG(PSTR("WEB: Uri '%s'"), url.c_str());
- status = WebQuery(const_cast(url.c_str()));
- }
- return status;
-}
-
-#ifdef USE_WEBGETCONFIG
-int WebGetConfig(char *buffer) {
- // http://user:password@server:port/path/%id%.dmp : %id% will be expanded to MAC address
-
- int status = WEBCMND_WRONG_PARAMETERS;
-
- RemoveSpace(buffer); // host = |[192.168.178.86:80,admin:joker|
- String url = ResolveToken(buffer);
-
- DEBUG_CORE_LOG(PSTR("WEB: Config Uri '%s'"), url.c_str());
-
-
-#if defined(ESP32) && defined(USE_WEBCLIENT_HTTPS)
- HTTPClientLight http;
- if (http.begin(UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON|
-#else // HTTP only
- WiFiClient http_client;
- HTTPClient http;
- if (http.begin(http_client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON|
-#endif
- int http_code = http.GET(); // Start connection and send HTTP header
- if (http_code > 0) { // http_code will be negative on error
- status = WEBCMND_DONE;
- if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) {
- WiFiClient *stream = http.getStreamPtr();
- int len = http.getSize();
- if (len <= sizeof(TSettings)) {
- len = sizeof(TSettings);
- }
- if (SettingsBufferAlloc(len)) {
- uint8_t *buff = settings_buffer;
- while (http.connected() && (len > 0)) {
- size_t size = stream->available();
- if (size) {
- int read = stream->readBytes(buff, len);
- len -= read;
- }
- delayMicroseconds(1);
- }
- if (len) {
- DEBUG_CORE_LOG(PSTR("WEB: Connection lost"));
- status = WEBCMND_CONNECTION_LOST;
- } else if (SettingsConfigRestore()) {
- AddLog(LOG_LEVEL_INFO, PSTR("WEB: Settings applied, restarting"));
- TasmotaGlobal.restart_flag = 2; // Always restart to re-enable disabled features during update
- } else {
- DEBUG_CORE_LOG(PSTR("WEB: Settings file invalid"));
- status = WEBCMND_INVALID_FILE;
- }
- } else {
- DEBUG_CORE_LOG(PSTR("WEB: Memory error (%d) or invalid file length (%d)"), settings_buffer, len);
- status = WEBCMND_MEMORY_ERROR;
- }
- } else {
- AddLog(LOG_LEVEL_DEBUG, PSTR("WEB: HTTP error %d"), http_code);
- status = (http_code == HTTP_CODE_NOT_FOUND) ? WEBCMND_FILE_NOT_FOUND : WEBCMND_OTHER_HTTP_ERROR;
- }
- } else {
- DEBUG_CORE_LOG(PSTR("WEB: Connection failed"));
- status = 2; // Connection failed
- }
- http.end(); // Clean up connection data
- } else {
- status = 3; // Host not found or connection error
- }
-
- return status;
-}
-#endif // USE_WEBGETCONFIG
-
-bool JsonWebColor(const char* dataBuf)
-{
- // Default (Dark theme)
- // {"WebColor":["#eaeaea","#252525","#4f4f4f","#000","#ddd","#65c115","#1f1f1f","#ff5661","#008000","#faffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#faffff","#999","#eaeaea","#08405e"]}
- // Default pre v7 (Light theme)
- // {"WebColor":["#000","#fff","#f2f2f2","#000","#fff","#000","#fff","#f00","#008000","#fff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#fff","#999","#000","#08405e"]} // {"WebColor":["#000000","#ffffff","#f2f2f2","#000000","#ffffff","#000000","#ffffff","#ff0000","#008000","#ffffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#ffffff","#999999","#000000","#08405e"]}
-
- JsonParser parser((char*) dataBuf);
- JsonParserObject root = parser.getRootObject();
- JsonParserArray arr = root[PSTR(D_CMND_WEBCOLOR)].getArray();
- if (arr) { // if arr is valid, i.e. json is valid, the key D_CMND_WEBCOLOR was found and the token is an arra
- uint32_t i = 0;
- for (auto color : arr) {
- if (i < COL_LAST) {
- WebHexCode(i, color.getStr());
- } else {
- break;
- }
- i++;
- }
- }
- return true;
-}
-
-/*********************************************************************************************\
- * Commands
-\*********************************************************************************************/
+/*-------------------------------------------------------------------------------------------*/
const char kWebCmndStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR "|"
#ifdef USE_WEBGETCONFIG
@@ -3951,8 +3959,9 @@ void CmndWebTime(void) {
}
#ifdef USE_EMULATION
-void CmndEmulation(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndEmulation(void) {
#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE)
#if defined(USE_EMULATION_WEMO) && defined(USE_EMULATION_HUE)
if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) {
@@ -3973,6 +3982,8 @@ void CmndEmulation(void)
#endif // USE_EMULATION
#ifdef USE_SENDMAIL
+/*-------------------------------------------------------------------------------------------*/
+
void CmndSendmail(void) {
if (XdrvMailbox.data_len > 0) {
uint8_t result = SendMail(XdrvMailbox.data);
@@ -3982,8 +3993,9 @@ void CmndSendmail(void) {
}
#endif // USE_SENDMAIL
-void CmndWebServer(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndWebServer(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings->webserver = XdrvMailbox.payload;
}
@@ -3995,8 +4007,9 @@ void CmndWebServer(void)
}
}
-void CmndWebPassword(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndWebPassword(void) {
bool show_asterisk = (2 == XdrvMailbox.index);
if (XdrvMailbox.data_len > 0) {
SettingsUpdateText(SET_WEBPWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data);
@@ -4011,24 +4024,72 @@ void CmndWebPassword(void)
}
}
-void CmndWeblog(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndWeblog(void) {
if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) {
Settings->weblog_level = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings->weblog_level);
}
-void CmndWebRefresh(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndWebRefresh(void) {
if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 65000)) {
Settings->web_refresh = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings->web_refresh);
}
-void CmndWebSend(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+int WebSend(char *buffer) {
+ // [tasmota] POWER1 ON --> Sends http://tasmota/cm?cmnd=POWER1 ON
+ // [192.168.178.86:80,admin:joker] POWER1 ON --> Sends http://hostname:80/cm?user=admin&password=joker&cmnd=POWER1 ON
+ // [tasmota] /any/link/starting/with/a/slash.php?log=123 --> Sends http://tasmota/any/link/starting/with/a/slash.php?log=123
+ // [tasmota,admin:joker] /any/link/starting/with/a/slash.php?log=123 --> Sends http://tasmota/any/link/starting/with/a/slash.php?log=123
+
+ char *host;
+ char *user;
+ char *password;
+ char *command;
+ int status = WEBCMND_WRONG_PARAMETERS;
+
+ // buffer = | [ 192.168.178.86 : 80 , admin : joker ] POWER1 ON |
+ host = strtok_r(buffer, "]", &command); // host = | [ 192.168.178.86 : 80 , admin : joker |, command = | POWER1 ON |
+ if (host && command) {
+ RemoveSpace(host); // host = |[192.168.178.86:80,admin:joker|
+ host++; // host = |192.168.178.86:80,admin:joker| - Skip [
+ host = strtok_r(host, ",", &user); // host = |192.168.178.86:80|, user = |admin:joker|
+ String url = F("http://"); // url = |http://|
+ url += host; // url = |http://192.168.178.86:80|
+
+ command = Trim(command); // command = |POWER1 ON| or |/any/link/starting/with/a/slash.php?log=123|
+ if (command[0] != '/') {
+ url += F("/cm?"); // url = |http://192.168.178.86/cm?|
+ if (user) {
+ user = strtok_r(user, ":", &password); // user = |admin|, password = |joker|
+ if (user && password) {
+ char userpass[200];
+ snprintf_P(userpass, sizeof(userpass), PSTR("user=%s&password=%s&"), user, password);
+ url += userpass; // url = |http://192.168.178.86/cm?user=admin&password=joker&|
+ }
+ }
+ url += F("cmnd="); // url = |http://192.168.178.86/cm?cmnd=| or |http://192.168.178.86/cm?user=admin&password=joker&cmnd=|
+ }
+ url += UrlEncode(command); // url = |http://192.168.178.86/cm?cmnd=POWER1%20ON|
+ url += F(" GET"); // url = |http://192.168.178.86/cm?cmnd=POWER1%20ON GET|
+
+ DEBUG_CORE_LOG(PSTR("WEB: Uri '%s'"), url.c_str());
+ status = WebQuery(const_cast(url.c_str()));
+ }
+ return status;
+}
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+void CmndWebSend(void) {
if (XdrvMailbox.data_len > 0) {
uint32_t result = WebSend(XdrvMailbox.data);
if (result != WEBCMND_VALID_RESPONSE) {
@@ -4038,6 +4099,8 @@ void CmndWebSend(void)
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndWebQuery(void) {
if (XdrvMailbox.data_len > 0) {
uint32_t result = WebQuery(XdrvMailbox.data);
@@ -4049,6 +4112,8 @@ void CmndWebQuery(void) {
}
#ifdef USE_WEBRUN
+/*-------------------------------------------------------------------------------------------*/
+
void CmndWebRun(void) {
if (XdrvMailbox.data_len > 0) {
uint32_t result = WebQuery(XdrvMailbox.data, QUERY_RUN);
@@ -4061,6 +4126,78 @@ void CmndWebRun(void) {
#endif // #ifdef USE_WEBRUN
#ifdef USE_WEBGETCONFIG
+/*-------------------------------------------------------------------------------------------*/
+
+int WebGetConfig(char *buffer) {
+ // http://user:password@server:port/path/%id%.dmp : %id% will be expanded to MAC address
+
+ int status = WEBCMND_WRONG_PARAMETERS;
+
+ RemoveSpace(buffer); // host = |[192.168.178.86:80,admin:joker|
+ String url = ResolveToken(buffer);
+
+ DEBUG_CORE_LOG(PSTR("WEB: Config Uri '%s'"), url.c_str());
+
+
+#if defined(ESP32) && defined(USE_WEBCLIENT_HTTPS)
+ HTTPClientLight http;
+ if (http.begin(UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON|
+#else // HTTP only
+ WiFiClient http_client;
+ HTTPClient http;
+ if (http.begin(http_client, UrlEncode(url))) { // UrlEncode(url) = |http://192.168.178.86/cm?cmnd=POWER1%20ON|
+#endif
+ int http_code = http.GET(); // Start connection and send HTTP header
+ if (http_code > 0) { // http_code will be negative on error
+ status = WEBCMND_DONE;
+ if (http_code == HTTP_CODE_OK || http_code == HTTP_CODE_MOVED_PERMANENTLY) {
+ WiFiClient *stream = http.getStreamPtr();
+ int len = http.getSize();
+ if (len <= sizeof(TSettings)) {
+ len = sizeof(TSettings);
+ }
+ if (SettingsBufferAlloc(len)) {
+ uint8_t *buff = settings_buffer;
+ while (http.connected() && (len > 0)) {
+ size_t size = stream->available();
+ if (size) {
+ int read = stream->readBytes(buff, len);
+ len -= read;
+ }
+ delayMicroseconds(1);
+ }
+ if (len) {
+ DEBUG_CORE_LOG(PSTR("WEB: Connection lost"));
+ status = WEBCMND_CONNECTION_LOST;
+ } else if (SettingsConfigRestore()) {
+ AddLog(LOG_LEVEL_INFO, PSTR("WEB: Settings applied, restarting"));
+ TasmotaGlobal.restart_flag = 2; // Always restart to re-enable disabled features during update
+ } else {
+ DEBUG_CORE_LOG(PSTR("WEB: Settings file invalid"));
+ status = WEBCMND_INVALID_FILE;
+ }
+ } else {
+ DEBUG_CORE_LOG(PSTR("WEB: Memory error (%d) or invalid file length (%d)"), settings_buffer, len);
+ status = WEBCMND_MEMORY_ERROR;
+ }
+ } else {
+ AddLog(LOG_LEVEL_DEBUG, PSTR("WEB: HTTP error %d"), http_code);
+ status = (http_code == HTTP_CODE_NOT_FOUND) ? WEBCMND_FILE_NOT_FOUND : WEBCMND_OTHER_HTTP_ERROR;
+ }
+ } else {
+ DEBUG_CORE_LOG(PSTR("WEB: Connection failed"));
+ status = 2; // Connection failed
+ }
+ http.end(); // Clean up connection data
+ } else {
+ status = 3; // Host not found or connection error
+ }
+
+ return status;
+}
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
void CmndWebGetConfig(void) {
// WebGetConfig http://myserver:8000/tasmota/conf/%id%.dmp where %id% is expanded to device mac address
// WebGetConfig http://myserver:8000/tasmota/conf/Config_demo_9.5.0.8.dmp
@@ -4072,8 +4209,35 @@ void CmndWebGetConfig(void) {
}
#endif // USE_WEBGETCONFIG
-void CmndWebColor(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+bool JsonWebColor(const char* dataBuf) {
+ // Default (Dark theme)
+ // {"WebColor":["#eaeaea","#252525","#4f4f4f","#000","#ddd","#65c115","#1f1f1f","#ff5661","#008000","#faffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#faffff","#999","#eaeaea","#08405e"]}
+ // Default pre v7 (Light theme)
+ // {"WebColor":["#000","#fff","#f2f2f2","#000","#fff","#000","#fff","#f00","#008000","#fff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#fff","#999","#000","#08405e"]}
+ // {"WebColor":["#000000","#ffffff","#f2f2f2","#000000","#ffffff","#000000","#ffffff","#ff0000","#008000","#ffffff","#1fa3ec","#0e70a4","#d43535","#931f1f","#47c266","#5aaf6f","#ffffff","#999999","#000000","#08405e"]}
+
+ JsonParser parser((char*) dataBuf);
+ JsonParserObject root = parser.getRootObject();
+ JsonParserArray arr = root[PSTR(D_CMND_WEBCOLOR)].getArray();
+ if (arr) { // if arr is valid, i.e. json is valid, the key D_CMND_WEBCOLOR was found and the token is an arra
+ uint32_t i = 0;
+ for (auto color : arr) {
+ if (i < COL_LAST) {
+ WebHexCode(i, color.getStr());
+ } else {
+ break;
+ }
+ i++;
+ }
+ }
+ return true;
+}
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+void CmndWebColor(void) {
if (XdrvMailbox.data_len > 0) {
if (strchr(XdrvMailbox.data, '{') == nullptr) { // If no JSON it must be parameter
if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= COL_LAST)) {
@@ -4096,8 +4260,9 @@ void CmndWebColor(void)
ResponseAppend_P(PSTR("]}"));
}
-void CmndWebSensor(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndWebSensor(void) {
if (XdrvMailbox.index < MAX_XSNS_DRIVERS) {
if (XdrvMailbox.payload >= 0) {
bitWrite(Settings->sensors[1][XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1);
@@ -4108,6 +4273,8 @@ void CmndWebSensor(void)
ResponseJsonEnd();
}
+/*-------------------------------------------------------------------------------------------*/
+
String *WebButton1732[16] = {0,};
void SetWebButton(uint8_t button_index, const char *text) {
@@ -4134,8 +4301,7 @@ const char* GetWebButton(uint8_t button_index) {
return empty;
}
-void CmndWebButton(void)
-{
+void CmndWebButton(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_BUTTON_TEXT)) {
if (!XdrvMailbox.usridx) {
ResponseCmndAll(SET_BUTTON1, MAX_BUTTON_TEXT);
@@ -4148,6 +4314,8 @@ void CmndWebButton(void)
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndWebCanvas(void) {
/*
WebCanvas allows GUI body canvas configuration using a color, "url" or "gradient".
@@ -4172,8 +4340,9 @@ void CmndWebCanvas(void) {
}
#ifdef USE_CORS
-void CmndCors(void)
-{
+/*-------------------------------------------------------------------------------------------*/
+
+void CmndCors(void) {
if (XdrvMailbox.data_len > 0) {
SettingsUpdateText(SET_CORS, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? CORS_DOMAIN : XdrvMailbox.data);
}
@@ -4187,8 +4356,7 @@ void CmndCors(void)
* Interface
\*********************************************************************************************/
-bool Xdrv01(uint32_t function)
-{
+bool Xdrv01(uint32_t function) {
bool result = false;
switch (function) {
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_75_dali.ino b/tasmota/tasmota_xdrv_driver/xdrv_75_dali.ino
index 252b6048e..ddc1c679a 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_75_dali.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_75_dali.ino
@@ -272,6 +272,8 @@
#define DALI_TOPIC "DALI"
#define D_PRFX_DALI "Dali"
+/*********************************************************************************************/
+
const char kDALICommands[] PROGMEM = D_PRFX_DALI "|" // Prefix
"|" D_CMND_POWER "|" D_CMND_DIMMER "|Target"
#ifdef USE_LIGHT
@@ -292,7 +294,6 @@ struct DALI {
uint32_t bit_cycles;
uint32_t last_activity;
uint32_t received_dali_data; // Data received from DALI bus
- uint32_t slider_update_time;
uint8_t pin_rx;
uint8_t pin_tx;
uint8_t max_short_address;
@@ -348,6 +349,8 @@ uint32_t DaliAddress2Target(uint32_t adr) {
}
*/
+/*-------------------------------------------------------------------------------------------*/
+
uint32_t DaliSaveState(uint32_t adr, uint32_t cmd) {
if (adr &0x01) { return 0; } // No address
int index = -1;
@@ -376,6 +379,8 @@ uint32_t DaliSaveState(uint32_t adr, uint32_t cmd) {
return index;
}
+/*-------------------------------------------------------------------------------------------*/
+
void DaliEnableRxInterrupt(void) {
Dali->available = false;
attachInterrupt(Dali->pin_rx, DaliReceiveData, (Dali->invert_rx) ? RISING : FALLING);
@@ -639,6 +644,8 @@ bool DaliSetPowerOnLevel(uint32_t adr, uint32_t v) {
return DaliSetValue(adr, DALI_QUERY_POWER_ON_LEVEL, DALI_SET_POWER_ON_LEVEL, v);
}
+/*-------------------------------------------------------------------------------------------*/
+
uint32_t DaliGearPresent(void) {
uint32_t count = 0;
for (uint32_t sa = 0; sa < Dali->max_short_address; sa++) { // Scanning 64 addresses takes about 2500 ms
@@ -649,6 +656,8 @@ uint32_t DaliGearPresent(void) {
return count;
}
+/*-------------------------------------------------------------------------------------------*/
+
void DaliInitLight(void) {
// Taken from Shelly Dali Dimmer ;-)
DaliSendData(DALI_DATA_TRANSFER_REGISTER0, DALI_INIT_FADE); // Fade x second
@@ -1002,6 +1011,8 @@ bool DaliJsonParse(void) {
return served;
}
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
void CmndDali(void) {
// Dali {"addr":254,"cmd":100} - Any address and/or command
// Dali 0|1 - Enable DALI receive probe
@@ -1031,6 +1042,8 @@ void CmndDaliTarget(void) {
ResponseCmndNumber(Dali->target);
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliPower(void) {
// DaliPower 0 - Broadcast power off
// DaliPower 1 - Broadcast power on to last dimmer state
@@ -1068,6 +1081,8 @@ void CmndDaliPower(void) {
ResponseDali(index);
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliDimmer(void) {
// DaliDimmer 0..100 - Broadcast set power off or dimmer state
// DaliDimmer0 0..100 - Broadcast set power off or dimmer state
@@ -1094,6 +1109,8 @@ void CmndDaliDimmer(void) {
ResponseDali(index);
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliGroup(void) {
// DaliGroup1 1,2 - Add device 1 and 2 to group 1
// DaliGroup1 -1,2 - Remove device 1 and 2 to group 1
@@ -1151,6 +1168,8 @@ void CmndDaliGroup(void) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliGear(void) {
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 64)) {
Dali->max_short_address = XdrvMailbox.payload;
@@ -1160,6 +1179,8 @@ void CmndDaliGear(void) {
ResponseAppend_P(PSTR("%d,\"Present\":%d}"), Dali->max_short_address, count);
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliSend(void) {
// Send command
// Setting bit 8 will repeat command once
@@ -1180,6 +1201,8 @@ void CmndDaliSend(void) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliQuery(void) {
// Send command and return response or -1 (no response within DALI_TIMEOUT)
// Setting bit 8 will repeat command once
@@ -1193,6 +1216,8 @@ void CmndDaliQuery(void) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliScan(void) {
// Scan short addresses
// DaliScan 1 - Reset and commission short addresses
@@ -1207,6 +1232,8 @@ void CmndDaliScan(void) {
}
}
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliGroupSliders(void) {
// DaliGroupSliders 0..16 - Add group sliders
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 16)) {
@@ -1217,6 +1244,8 @@ void CmndDaliGroupSliders(void) {
}
#ifdef USE_LIGHT
+/*-------------------------------------------------------------------------------------------*/
+
void CmndDaliLight(void) {
// DaliLight 0 - Disable light controls
// DaliLight 1 - Enable light controls
@@ -1259,6 +1288,8 @@ void DaliWebAddMainSlider(void) {
WSContentSend_P(PSTR(""));
}
+/*********************************************************************************************/
+
void DaliWebGetArg(void) {
char tmp[8]; // WebGetArg numbers only
char svalue[32]; // Command and number parameter
@@ -1283,41 +1314,29 @@ void DaliWebGetArg(void) {
ExecuteWebCommand(svalue);
}
}
-#endif // USE_WEBSERVER
-void DaliShow(bool json) {
- if (json) {
- ResponseAppend_P(PSTR(","));
- ResponseAppendDali(0);
-#ifdef USE_WEBSERVER
- } else {
- WSContentSend_P(PSTR("")); // Terminate current {t}
- WSContentSend_P(HTTP_MSG_EXEC_JAVASCRIPT); // "sbflag1.dali_light; i <= Settings->mbflag2.dali_group_sliders; i++) { // DaliLight 0/1, DaliGroupSliders
- WSContentSend_P(PSTR("eb('k75%d').style='background:#%06x';"),
- i, WebColor((Dali->power[i]) ? COL_BUTTON : COL_BUTTON_OFF));
- if (Dali->dimmer[i] != Dali->web_dimmer[i]) {
- if (0 == Dali->slider_update_time) {
- Dali->slider_update_time = slider_update_time + Settings->web_refresh; // Allow other users to sync screen
- }
- else if (slider_update_time > Dali->slider_update_time) {
- Dali->slider_update_time = 1; // Allow multiple updates
- Dali->web_dimmer[i] = Dali->dimmer[i];
- }
- WSContentSend_P(PSTR("eb('i75%d').value='%d';"),
- i, changeUIntScale(Dali->dimmer[i], 0, 254, 0, 100));
+/*********************************************************************************************/
+
+void DaliWebShow(void) {
+ WSContentSend_P(PSTR("")); // Terminate current {t}
+ WSContentSend_P(HTTP_MSG_EXEC_JAVASCRIPT); // "sbflag1.dali_light; i <= Settings->mbflag2.dali_group_sliders; i++) { // DaliLight 0/1, DaliGroupSliders
+ WSContentSend_P(PSTR("eb('k75%d').style='background:#%06x';"),
+ i, WebColor((Dali->power[i]) ? COL_BUTTON : COL_BUTTON_OFF));
+ if (Dali->dimmer[i] != Dali->web_dimmer[i]) {
+ if (WebUpdateSliderTime()) {
+ Dali->web_dimmer[i] = Dali->dimmer[i];
}
+ WSContentSend_P(PSTR("eb('i75%d').value='%d';"),
+ i, changeUIntScale(Dali->dimmer[i], 0, 254, 0, 100));
}
- if (1 == Dali->slider_update_time) {
- Dali->slider_update_time = 0;
- }
- WSContentSend_P(PSTR("\">{t}")); // Restart {t} =
- WSContentSeparator(3); // Don't print separator on next WSContentSeparator(1)
-#endif // USE_WEBSERVER
}
+ WSContentSend_P(PSTR("\">{t}")); // Restart {t} =
+ WSContentSeparator(3); // Don't print separator on next WSContentSeparator(1)
}
+#endif // USE_WEBSERVER
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
@@ -1345,11 +1364,12 @@ bool Xdrv75(uint32_t function) {
break;
#endif // USE_LIGHT
case FUNC_JSON_APPEND:
- DaliShow(true);
+ ResponseAppend_P(PSTR(","));
+ ResponseAppendDali(0);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
- DaliShow(false);
+ DaliWebShow();
break;
case FUNC_WEB_ADD_MAIN_BUTTON:
DaliWebAddMainSlider();
|
---|