\").replace(/}2/g,\" | \");"
- "eb('i').innerHTML=s;"
- "}"
- "";
-const char HTTP_MSG_SLIDER1[] PROGMEM =
- " " D_COLDLIGHT "" D_WARMLIGHT " "
- "";
-const char HTTP_MSG_SLIDER2[] PROGMEM =
- "" D_DARKLIGHT "" D_BRIGHTLIGHT " "
- "";
-const char HTTP_MSG_RSTRT[] PROGMEM =
- "
" D_DEVICE_WILL_RESTART " ";
-const char HTTP_BTN_MENU1[] PROGMEM =
-#ifndef BE_MINIMAL
- " "
- " "
-#endif
- " "
- " ";
-const char HTTP_BTN_RSTRT[] PROGMEM =
- " ";
-const char HTTP_BTN_MENU_MODULE[] PROGMEM =
- " ";
-#if defined(USE_TIMERS) && defined(USE_TIMERS_WEB)
-const char HTTP_BTN_MENU_TIMER[] PROGMEM =
- " ";
-#endif // USE_TIMERS and USE_TIMERS_WEB
-const char HTTP_BTN_MENU_WIFI[] PROGMEM =
- " ";
-const char HTTP_BTN_MENU_MQTT[] PROGMEM =
- " "
-#ifdef USE_DOMOTICZ
- " "
-#endif // USE_DOMOTICZ
- "";
-const char HTTP_BTN_MENU4[] PROGMEM =
-#ifdef USE_KNX
-#ifdef USE_KNX_WEB_MENU
- " "
-#endif // USE_KNX_WEB_MENU
-#endif // USE_KNX
- " "
- " "
- " "
- " "
- " "
- " ";
-const char HTTP_BTN_MAIN[] PROGMEM =
- "
";
-const char HTTP_FORM_LOGIN[] PROGMEM =
- "";
-const char HTTP_BTN_CONF[] PROGMEM =
- "
";
-const char HTTP_FORM_MODULE[] PROGMEM =
- " |
---|
- // }2 = |
- String func = FPSTR(HTTP_SCRIPT_INFO_BEGIN);
- func += F("");
- func += F(D_PROGRAM_VERSION "}2"); func += my_version;
- 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 %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();
- uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present;
- if (SONOFF_IFAN02 == Settings.module) { maxfn = 1; }
- for (byte i = 0; i < maxfn; i++) {
- func += F("}1" D_FRIENDLY_NAME " "); func += i +1; func += F("}2"); func += 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 (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();
- }
- 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();
- }
-
- func += F("}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_CLIENT " & " D_FALLBACK_TOPIC "}2"); func += mqtt_client;
- func += F("}1" D_MQTT_USER "}2"); func += Settings.mqtt_user;
- func += F("}1" D_MQTT_TOPIC "}2"); func += Settings.mqtt_topic;
- func += F("}1" D_MQTT_GROUP_TOPIC "}2"); func += Settings.mqtt_grptopic;
- GetTopic_P(stopic, CMND, mqtt_topic, "");
- func += F("}1" D_MQTT_FULL_TOPIC "}2"); func += stopic;
-
- } else {
- func += F("}1" D_MQTT "}2" D_DISABLED);
- }
-
- 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);
- }
-#else
- func += F(D_DISABLED);
-#endif // USE_EMULATION
-
- func += F("}1" D_MDNS_DISCOVERY "}2");
-#ifdef USE_DISCOVERY
- func += F(D_ENABLED);
- func += F("}1" D_MDNS_ADVERTISE "}2");
-#ifdef WEBSERVER_ADVERTISE
- func += F(D_WEB_SERVER);
-#else
- func += F(D_DISABLED);
-#endif // WEBSERVER_ADVERTISE
-#else
- func += F(D_DISABLED);
-#endif // USE_DISCOVERY
-
- func += F("}1}2 "); // Empty line
- func += F("}1" D_ESP_CHIP_ID "}2"); func += String(ESP.getChipId());
- func += F("}1" D_FLASH_CHIP_ID "}2"); func += String(ESP.getFlashChipId());
- 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);
- page.replace(F(""), F(""));
-
- // page += F("");
- page += FPSTR(HTTP_BTN_MAIN);
- ShowPage(page);
-}
-#endif // Not BE_MINIMAL
-
-void HandleUpgradeFirmware()
-{
- if (HttpUser()) { return; }
- if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- 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);
-
- upload_error = 0;
- upload_file_type = UPL_TASMOTA;
-}
-
-void HandleUpgradeFirmwareStart()
-{
- if (HttpUser()) { return; }
- if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- char svalue[100];
-
- AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED));
- WifiConfigCounter();
-
- char tmp[100];
- WebGetArg("o", tmp, sizeof(tmp));
- if (strlen(tmp)) {
- snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_OTAURL " %s"), tmp);
- ExecuteWebCommand(svalue, SRC_WEBGUI);
- }
-
- String page = FPSTR(HTTP_HEAD);
- page.replace(F("{v}"), FPSTR(S_INFORMATION));
- page += FPSTR(HTTP_HEAD_STYLE);
- page += F("" D_UPGRADE_STARTED " ... ");
- page += FPSTR(HTTP_MSG_RSTRT);
- page += FPSTR(HTTP_BTN_MAIN);
- ShowPage(page);
-
- snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_UPGRADE " 1"));
- ExecuteWebCommand(svalue, SRC_WEBGUI);
-}
-
-void HandleUploadDone()
-{
- if (HttpUser()) { return; }
- if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPLOAD_DONE));
-
- char error[100];
-
- WifiConfigCounter();
- restart_flag = 0;
- MqttRetryCounter(0);
-
- String page = FPSTR(HTTP_HEAD);
- page.replace(F("{v}"), FPSTR(S_INFORMATION));
- page += FPSTR(HTTP_HEAD_STYLE);
- page += F("" D_UPLOAD " " D_FAILED "
");
- switch (upload_error) {
- case 1: strncpy_P(error, PSTR(D_UPLOAD_ERR_1), sizeof(error)); break;
- case 2: strncpy_P(error, PSTR(D_UPLOAD_ERR_2), sizeof(error)); break;
- case 3: strncpy_P(error, PSTR(D_UPLOAD_ERR_3), sizeof(error)); break;
- case 4: strncpy_P(error, PSTR(D_UPLOAD_ERR_4), sizeof(error)); break;
- case 5: strncpy_P(error, PSTR(D_UPLOAD_ERR_5), sizeof(error)); break;
- case 6: strncpy_P(error, PSTR(D_UPLOAD_ERR_6), sizeof(error)); break;
- case 7: strncpy_P(error, PSTR(D_UPLOAD_ERR_7), sizeof(error)); break;
- case 8: strncpy_P(error, PSTR(D_UPLOAD_ERR_8), sizeof(error)); break;
- case 9: strncpy_P(error, PSTR(D_UPLOAD_ERR_9), sizeof(error)); break;
-#ifdef USE_RF_FLASH
- case 10: strncpy_P(error, PSTR(D_UPLOAD_ERR_10), sizeof(error)); break;
- case 11: strncpy_P(error, PSTR(D_UPLOAD_ERR_11), sizeof(error)); break;
- case 12: strncpy_P(error, PSTR(D_UPLOAD_ERR_12), sizeof(error)); break;
- case 13: strncpy_P(error, PSTR(D_UPLOAD_ERR_13), sizeof(error)); break;
-#endif
- default:
- snprintf_P(error, sizeof(error), PSTR(D_UPLOAD_ERROR_CODE " %d"), upload_error);
- }
- page += 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);
- 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);
-}
-
-void HandleUploadLoop()
-{
- // Based on ESP8266HTTPUpdateServer.cpp uses ESP8266WebServer Parsing.cpp and Cores Updater.cpp (Update)
- boolean _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level);
-
- if (HTTP_USER == webserver_state) { return; }
- if (upload_error) {
- if (UPL_TASMOTA == upload_file_type) { Update.end(); }
- return;
- }
-
- HTTPUpload& upload = WebServer->upload();
-
- if (UPLOAD_FILE_START == upload.status) {
- restart_flag = 60;
- if (0 == upload.filename.c_str()[0]) {
- upload_error = 1; // No file selected
- return;
- }
- SettingsSave(1); // Free flash for upload
- snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str());
- AddLog(LOG_LEVEL_INFO);
- if (UPL_SETTINGS == upload_file_type) {
- if (!SettingsBufferAlloc()) {
- upload_error = 2; // Not enough space
- return;
- }
- } else {
- MqttRetryCounter(60);
-#ifdef USE_EMULATION
- UdpDisconnect();
-#endif // USE_EMULATION
-#ifdef USE_ARILUX_RF
- AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine
-#endif // USE_ARILUX_RF
- if (Settings.flag.mqtt_enabled) MqttDisconnect();
- uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
- if (!Update.begin(maxSketchSpace)) { //start with max available size
-
-// if (_serialoutput) Update.printError(Serial);
-// if (Update.getError() == UPDATE_ERROR_BOOTSTRAP) {
-// if (_serialoutput) Serial.println("Device still in UART update mode, perform powercycle");
-// }
-
- upload_error = 2; // Not enough space
- return;
- }
- }
- upload_progress_dot_count = 0;
- } else if (!upload_error && (UPLOAD_FILE_WRITE == upload.status)) {
- if (0 == upload.totalSize) {
- if (UPL_SETTINGS == upload_file_type) {
- config_block_count = 0;
- }
- else {
-#ifdef USE_RF_FLASH
- if ((SONOFF_BRIDGE == Settings.module) && (upload.buf[0] == ':')) { // Check if this is a RF bridge FW file
- Update.end(); // End esp8266 update session
- upload_file_type = UPL_EFM8BB1;
-
- upload_error = SnfBrUpdateInit();
- if (upload_error != 0) { return; }
- } else
-#endif // USE_RF_FLASH
- {
- if (upload.buf[0] != 0xE9) {
- upload_error = 3; // Magic byte is not 0xE9
- return;
- }
- uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4);
- if(bin_flash_size > ESP.getFlashChipRealSize()) {
- upload_error = 4; // Program flash size is larger than real flash size
- return;
- }
- upload.buf[2] = 3; // Force DOUT - ESP8285
- }
- }
- }
- if (UPL_SETTINGS == upload_file_type) {
- if (!upload_error) {
- if (upload.currentSize > (sizeof(Settings) - (config_block_count * HTTP_UPLOAD_BUFLEN))) {
- upload_error = 9; // File too large
- return;
- }
- memcpy(settings_buffer + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize);
- config_block_count++;
- }
- }
-#ifdef USE_RF_FLASH
- else if (UPL_EFM8BB1 == upload_file_type) {
- if (efm8bb1_update != NULL) { // We have carry over data since last write, i. e. a start but not an end
- ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize);
- free(efm8bb1_update);
- efm8bb1_update = NULL;
- if (result != 0) {
- upload_error = abs(result); // 2 = Not enough space, 8 = File invalid
- return;
- }
- }
- ssize_t result = rf_search_and_write(upload.buf, upload.currentSize);
- if (result < 0) {
- upload_error = abs(result);
- return;
- } else if (result > 0) {
- if (result > upload.currentSize) {
- // Offset is larger than the buffer supplied, this should not happen
- upload_error = 9; // File too large - Failed to decode RF firmware
- return;
- }
- // A remnant has been detected, allocate data for it plus a null termination byte
- size_t remnant_sz = upload.currentSize - result;
- efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1);
- if (efm8bb1_update == NULL) {
- upload_error = 2; // Not enough space - Unable to allocate memory to store new RF firmware
- return;
- }
- memcpy(efm8bb1_update, upload.buf + result, remnant_sz);
- // Add null termination at the end of of remnant buffer
- efm8bb1_update[remnant_sz] = '\0';
- }
- }
-#endif // USE_RF_FLASH
- else { // firmware
- if (!upload_error && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) {
- upload_error = 5; // Upload buffer miscompare
- return;
- }
- if (_serialoutput) {
- Serial.printf(".");
- upload_progress_dot_count++;
- if (!(upload_progress_dot_count % 80)) { Serial.println(); }
- }
- }
- } else if(!upload_error && (UPLOAD_FILE_END == upload.status)) {
- if (_serialoutput && (upload_progress_dot_count % 80)) {
- Serial.println();
- }
- if (UPL_SETTINGS == upload_file_type) {
- if (config_xor_on_set) {
- for (uint16_t i = 2; i < sizeof(Settings); i++) {
- settings_buffer[i] ^= (config_xor_on_set +i);
- }
- }
- bool valid_settings = false;
- unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8];
- if (buffer_version > 0x06000000) {
- uint16_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2];
- uint16_t buffer_crc = settings_buffer[15] << 8 | settings_buffer[14];
- uint16_t crc = 0;
- for (uint16_t i = 0; i < buffer_size; i++) {
- if ((i < 14) || (i > 15)) { crc += settings_buffer[i]*(i+1); } // Skip crc
- }
- valid_settings = (buffer_crc == crc);
- } else {
- valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN);
- }
- if (valid_settings) {
- SettingsDefaultSet2();
- memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16);
- Settings.version = buffer_version; // Restore version and auto upgrade after restart
- SettingsBufferFree();
- } else {
- upload_error = 8; // File invalid
- return;
- }
- }
-#ifdef USE_RF_FLASH
- else if (UPL_EFM8BB1 == upload_file_type) {
- // RF FW flash done
- upload_file_type = UPL_TASMOTA;
- }
-#endif // USE_RF_FLASH
- else {
- if (!Update.end(true)) { // true to set the size to the current progress
- if (_serialoutput) { Update.printError(Serial); }
- upload_error = 6; // Upload failed. Enable logging 3
- return;
- }
- }
- if (!upload_error) {
- snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize);
- AddLog(LOG_LEVEL_INFO);
- }
- } else if (UPLOAD_FILE_ABORTED == upload.status) {
- restart_flag = 0;
- MqttRetryCounter(0);
- upload_error = 7; // Upload aborted
- if (UPL_TASMOTA == upload_file_type) { Update.end(); }
- }
- delay(0);
-}
-
-void HandlePreflightRequest()
-{
- WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*"));
- WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST"));
- WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("authorization"));
- WebServer->send(200, FPSTR(HDR_CTYPE_HTML), "");
-}
-
-void HandleHttpCommand()
-{
- if (HttpUser()) { return; }
-// if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog
-
- AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND));
-
- uint8_t valid = 1;
- if (Settings.web_password[0] != 0) {
- char tmp1[100];
- WebGetArg("user", tmp1, sizeof(tmp1));
- char tmp2[100];
- WebGetArg("password", tmp2, sizeof(tmp2));
- if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = 0; }
- }
-
- String message = F("{\"" D_RSLT_WARNING "\":\"");
- if (valid) {
- byte curridx = web_log_index;
- WebGetArg("cmnd", svalue, sizeof(svalue));
- if (strlen(svalue)) {
- ExecuteWebCommand(svalue, SRC_WEBCOMMAND);
-
- if (web_log_index != curridx) {
- byte counter = curridx;
- message = F("{");
- do {
- char* tmp;
- size_t len;
- GetLog(counter, &tmp, &len);
- if (len) {
- // [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
- char* JSON = (char*)memchr(tmp, '{', len);
- if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
- if (message.length() > 1) { message += F(","); }
- size_t JSONlen = len - (JSON - tmp);
- strlcpy(mqtt_data, JSON +1, JSONlen -2);
- message += mqtt_data;
- }
- }
- counter++;
- if (!counter) counter++; // Skip 0 as it is not allowed
- } while (counter != web_log_index);
- message += F("}");
- } else {
- message += F(D_ENABLE_WEBLOG_FOR_RESPONSE "\"}");
- }
- } else {
- message += F(D_ENTER_COMMAND " cmnd=\"}");
- }
- } else {
- message += F(D_NEED_USER_AND_PASSWORD "\"}");
- }
- SetHeader();
- WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message);
-}
-
-void HandleConsole()
-{
- if (HttpUser()) { return; }
- if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- 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_HEAD_STYLE);
- page.replace(F(""), FPSTR(HTTP_SCRIPT_CONSOL));
- page.replace(F(""), F(""));
- page += FPSTR(HTTP_FORM_CMND);
- page += FPSTR(HTTP_BTN_MAIN);
- ShowPage(page);
-}
-
-void HandleAjaxConsoleRefresh()
-{
- if (HttpUser()) { return; }
- if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- char svalue[INPUT_BUFFER_SIZE]; // Large to serve Backlog
- byte cflg = 1;
- byte counter = 0; // Initial start, should never be 0 again
-
- WebGetArg("c1", svalue, sizeof(svalue));
- if (strlen(svalue)) {
- snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_COMMAND "%s"), svalue);
- AddLog(LOG_LEVEL_INFO);
- ExecuteWebCommand(svalue, SRC_WEBCONSOLE);
- }
-
- WebGetArg("c2", svalue, sizeof(svalue));
- if (strlen(svalue)) { counter = atoi(svalue); }
-
- byte last_reset_web_log_flag = reset_web_log_flag;
- String message = F("}9"); // Cannot load mqtt_data here as <> will be encoded by replacements below
- if (!reset_web_log_flag) {
- counter = 0;
- reset_web_log_flag = 1;
- }
- if (counter != web_log_index) {
- if (!counter) {
- counter = web_log_index;
- cflg = 0;
- }
- do {
- char* tmp;
- size_t len;
- GetLog(counter, &tmp, &len);
- if (len) {
- if (cflg) {
- message += F("\n");
- } else {
- cflg = 1;
- }
- strlcpy(mqtt_data, tmp, len);
- message += mqtt_data;
- }
- counter++;
- if (!counter) { counter++; } // Skip 0 as it is not allowed
- } while (counter != web_log_index);
- // XML encoding to fix blank console log in concert with javascript decodeURIComponent
- message.replace(F("%"), F("%25")); // Needs to be done first as otherwise the % in %26 will also be converted
- message.replace(F("&"), F("%26"));
- message.replace(F("<"), F("%3C"));
- message.replace(F(">"), F("%3E"));
- }
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d%d"), web_log_index, last_reset_web_log_flag);
- message.replace(F("}9"), mqtt_data); // Save to load here
- message += F("");
- WebServer->send(200, FPSTR(HDR_CTYPE_XML), message);
-}
-
-void HandleRestart()
-{
- if (HttpUser()) { return; }
- if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
- AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART);
-
- String page = FPSTR(HTTP_HEAD);
- page.replace(F("{v}"), FPSTR(S_RESTART));
- page += FPSTR(HTTP_HEAD_STYLE);
- page += FPSTR(HTTP_MSG_RSTRT);
- if (HTTP_MANAGER == webserver_state) {
- webserver_state = HTTP_ADMIN;
- } else {
- page += FPSTR(HTTP_BTN_MAIN);
- }
- ShowPage(page);
-
- ShowWebSource(SRC_WEBGUI);
- restart_flag = 2;
-}
-
-/********************************************************************************************/
-
-void HandleNotFound()
-{
-// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_HTTP "Not fount (%s)"), WebServer->uri().c_str());
-// AddLog(LOG_LEVEL_DEBUG);
-
- if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page.
-
-#ifdef USE_EMULATION
- String path = WebServer->uri();
- if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) {
- HandleHueApi(&path);
- } else
-#endif // USE_EMULATION
- {
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"),
- WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args());
- 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();
- WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), mqtt_data);
- }
-}
-
-/* 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. */
-boolean CaptivePortal()
-{
- if ((HTTP_MANAGER == webserver_state) && !ValidIpAddress(WebServer->hostHeader())) {
- AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED));
-
- WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true);
- WebServer->send(302, FPSTR(HDR_CTYPE_PLAIN), ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
- WebServer->client().stop(); // Stop is needed because we sent no content length
- return true;
- }
- return false;
-}
-
-/** Is this an IP? */
-boolean ValidIpAddress(String str)
-{
- for (uint16_t i = 0; i < str.length(); i++) {
- int c = str.charAt(i);
- if (c != '.' && (c < '0' || c > '9')) { return false; }
- }
- return true;
-}
-
-/*********************************************************************************************/
-
-String UrlEncode(const String& text)
-{
- const char hex[] = "0123456789ABCDEF";
-
- String encoded = "";
- int len = text.length();
- int i = 0;
- while (i < len) {
- char decodedChar = text.charAt(i++);
-
-/*
- if (('a' <= decodedChar && decodedChar <= 'z') ||
- ('A' <= decodedChar && decodedChar <= 'Z') ||
- ('0' <= decodedChar && decodedChar <= '9') ||
- ('=' == decodedChar)) {
- encoded += decodedChar;
- } else {
- encoded += '%';
- encoded += hex[decodedChar >> 4];
- encoded += hex[decodedChar & 0xF];
- }
-*/
- if (' ' == decodedChar) {
- encoded += '%';
- encoded += hex[decodedChar >> 4];
- encoded += hex[decodedChar & 0xF];
- } else {
- encoded += decodedChar;
- }
-
- }
- return encoded;
-}
-
-int WebSend(char *buffer)
-{
- // http://192.168.178.86:80/cm?user=admin&password=joker&cmnd=POWER1 ON
- // http://192.168.178.86:80/cm?cmnd=POWER1 ON
- // [192.168.178.86:80,admin:joker] POWER1 ON
-
- char *host;
- char *port;
- char *user;
- char *password;
- char *command;
- uint16_t nport = 80;
- int status = 1; // Wrong parameters
-
- host = strtok_r(buffer, "]", &command); // buffer = [192.168.178.86:80,admin:joker] POWER1 ON
- if (host && command) {
- host = LTrim(host);
- host++; // Skip [
- host = strtok_r(host, ",", &user); // host = 192.168.178.86:80,admin:joker > 192.168.178.86:80
- host = strtok_r(host, ":", &port); // host = 192.168.178.86:80 > 192.168.178.86
- if (user) {
- user = strtok_r(user, ":", &password); // user = admin:joker > admin
- }
-
-//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Buffer |%X|, Host |%X|, Port |%X|, User |%X|, Password |%X|, Command |%X|"), buffer, host, port, user, password, command);
-//AddLog(LOG_LEVEL_DEBUG);
-
- if (port) { nport = atoi(port); }
-
- String nuri = "";
- if (user && password) {
- nuri += F("user=");
- nuri += user;
- nuri += F("&password=");
- nuri += password;
- nuri += F("&");
- }
- nuri += F("cmnd=");
- nuri += LTrim(command);
- String uri = UrlEncode(nuri);
-
- IPAddress host_ip;
- if (WiFi.hostByName(host, host_ip)) {
- WiFiClient client;
-
- bool connected = false;
- byte retry = 2;
- while ((retry > 0) && !connected) {
- --retry;
- connected = client.connect(host_ip, nport);
- if (connected) break;
- }
-
- if (connected) {
- String url = F("GET /cm?");
- url += uri;
- url += F(" HTTP/1.1\r\n Host: ");
- url += IPAddress(host_ip).toString();
- if (port) {
- url += F(" \r\n Port: ");
- url += port;
- }
- url += F(" \r\n Connection: close\r\n\r\n");
-
-//snprintf_P(log_data, sizeof(log_data), PSTR("DBG: Url |%s|"), url.c_str());
-//AddLog(LOG_LEVEL_DEBUG);
-
- client.print(url.c_str());
- client.flush();
- client.stop();
- status = 0; // No error - Done
- } else {
- status = 2; // Connection failed
- }
- } else {
- status = 3; // Host not found
- }
- }
- return status;
-}
-
-/*********************************************************************************************/
-
-enum WebCommands { CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_WEBREFRESH, CMND_WEBSEND, CMND_EMULATION };
-const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ;
-const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ;
-
-bool WebCommand()
-{
- char command[CMDSZ];
- bool serviced = true;
-
- int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kWebCommands);
- if (-1 == command_code) {
- serviced = false; // Unknown command
- }
- if (CMND_WEBSERVER == command_code) {
- if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { Settings.webserver = XdrvMailbox.payload; }
- if (Settings.webserver) {
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"),
- (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str());
- } else {
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(0));
- }
- }
- else if (CMND_WEBPASSWORD == command_code) {
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) {
- strlcpy(Settings.web_password, (SC_CLEAR == Shortcut(XdrvMailbox.data)) ? "" : (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password));
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.web_password);
- } else {
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_ASTERIX, command);
- }
- }
- else if (CMND_WEBLOG == command_code) {
- if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { Settings.weblog_level = XdrvMailbox.payload; }
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.weblog_level);
- }
- else if (CMND_WEBREFRESH == command_code) {
- if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 10000)) { Settings.web_refresh = XdrvMailbox.payload; }
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.web_refresh);
- }
- else if (CMND_WEBSEND == command_code) {
- if (XdrvMailbox.data_len > 0) {
- uint8_t result = WebSend(XdrvMailbox.data);
- char stemp1[20];
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus));
- }
- }
-#ifdef USE_EMULATION
- else if (CMND_EMULATION == command_code) {
- if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) {
- Settings.flag2.emulation = XdrvMailbox.payload;
- restart_flag = 2;
- }
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.emulation);
- }
-#endif // USE_EMULATION
- else serviced = false; // Unknown command
-
- return serviced;
-}
-
-/*********************************************************************************************\
- * Interface
-\*********************************************************************************************/
-
-#define XDRV_02
-
-boolean Xdrv02(byte function)
-{
- boolean result = false;
-
- switch (function) {
- case FUNC_LOOP:
- PollDnsWebserver();
-#ifdef USE_EMULATION
- if (Settings.flag2.emulation) PollUdp();
-#endif // USE_EMULATION
- break;
- case FUNC_COMMAND:
- result = WebCommand();
- break;
- }
- return result;
-}
-#endif // USE_WEBSERVER
|
---|