"
+ "
");
+#endif // USE_EMULATION
+ page += FPSTR(HTTP_FORM_END);
+ page += FPSTR(HTTP_BTN_CONF);
+ showPage(page);
+}
+
+void handleDownload()
+{
+ if (httpUser()) {
+ return;
+ }
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Download config"));
+
+ uint8_t buffer[sizeof(sysCfg)];
+
+ WiFiClient myClient = webServer->client();
+ webServer->setContentLength(4096);
+
+ char attachment[100];
+ snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"),
+ sysCfg.friendlyname[0], Version);
+ webServer->sendHeader(F("Content-Disposition"), attachment);
+ webServer->send(200, FPSTR(HDR_CTYPE_STREAM), "");
+ memcpy(buffer, &sysCfg, sizeof(sysCfg));
+ buffer[0] = CONFIG_FILE_SIGN;
+ buffer[1] = (!CONFIG_FILE_XOR)?0:1;
+ if (buffer[1]) {
+ for (uint16_t i = 2; i < sizeof(buffer); i++) {
+ buffer[i] ^= (CONFIG_FILE_XOR +i);
+ }
+ }
+ myClient.write((const char*)buffer, sizeof(buffer));
+}
+
+void handleSave()
+{
+ if (httpUser()) {
+ return;
+ }
+
+ char log[LOGSZ +20];
+ char stemp[TOPSZ];
+ char stemp2[TOPSZ];
+ byte what = 0;
+ byte restart;
+ String result = "";
+
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Parameter save"));
+
+ if (strlen(webServer->arg("w").c_str())) {
+ what = atoi(webServer->arg("w").c_str());
+ }
+ switch (what) {
+ case 1:
+ strlcpy(sysCfg.hostname, (!strlen(webServer->arg("h").c_str())) ? WIFI_HOSTNAME : webServer->arg("h").c_str(), sizeof(sysCfg.hostname));
+ if (strstr(sysCfg.hostname,"%")) {
+ strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname));
+ }
+ strlcpy(sysCfg.sta_ssid[0], (!strlen(webServer->arg("s1").c_str())) ? STA_SSID1 : webServer->arg("s1").c_str(), sizeof(sysCfg.sta_ssid[0]));
+ strlcpy(sysCfg.sta_pwd[0], (!strlen(webServer->arg("p1").c_str())) ? STA_PASS1 : webServer->arg("p1").c_str(), sizeof(sysCfg.sta_pwd[0]));
+ strlcpy(sysCfg.sta_ssid[1], (!strlen(webServer->arg("s2").c_str())) ? STA_SSID2 : webServer->arg("s2").c_str(), sizeof(sysCfg.sta_ssid[1]));
+ strlcpy(sysCfg.sta_pwd[1], (!strlen(webServer->arg("p2").c_str())) ? STA_PASS2 : webServer->arg("p2").c_str(), sizeof(sysCfg.sta_pwd[1]));
+ snprintf_P(log, sizeof(log), PSTR("HTTP: Wifi Hostname %s, SSID1 %s, Password1 %s, SSID2 %s, Password2 %s"),
+ sysCfg.hostname, sysCfg.sta_ssid[0], sysCfg.sta_pwd[0], sysCfg.sta_ssid[1], sysCfg.sta_pwd[1]);
+ addLog(LOG_LEVEL_INFO, log);
+ result += F("
Trying to connect device to network
If it fails reconnect to try again");
+ break;
+ case 2:
+ strlcpy(stemp, (!strlen(webServer->arg("mt").c_str())) ? MQTT_TOPIC : webServer->arg("mt").c_str(), sizeof(stemp));
+ mqttfy(0, stemp);
+ strlcpy(stemp2, (!strlen(webServer->arg("mf").c_str())) ? MQTT_FULLTOPIC : webServer->arg("mf").c_str(), sizeof(stemp2));
+ mqttfy(1,stemp2);
+ if ((strcmp(stemp, sysCfg.mqtt_topic)) || (strcmp(stemp2, sysCfg.mqtt_fulltopic))) {
+ mqtt_publish_topic_P(2, PSTR("LWT"), (sysCfg.flag.mqtt_offline) ? "Offline" : "", true); // Offline or remove previous retained topic
+ }
+ strlcpy(sysCfg.mqtt_topic, stemp, sizeof(sysCfg.mqtt_topic));
+ strlcpy(sysCfg.mqtt_fulltopic, stemp2, sizeof(sysCfg.mqtt_fulltopic));
+ strlcpy(sysCfg.mqtt_host, (!strlen(webServer->arg("mh").c_str())) ? MQTT_HOST : webServer->arg("mh").c_str(), sizeof(sysCfg.mqtt_host));
+ sysCfg.mqtt_port = (!strlen(webServer->arg("ml").c_str())) ? MQTT_PORT : atoi(webServer->arg("ml").c_str());
+ strlcpy(sysCfg.mqtt_client, (!strlen(webServer->arg("mc").c_str())) ? MQTT_CLIENT_ID : webServer->arg("mc").c_str(), sizeof(sysCfg.mqtt_client));
+ strlcpy(sysCfg.mqtt_user, (!strlen(webServer->arg("mu").c_str())) ? MQTT_USER : (!strcmp(webServer->arg("mu").c_str(),"0")) ? "" : webServer->arg("mu").c_str(), sizeof(sysCfg.mqtt_user));
+ strlcpy(sysCfg.mqtt_pwd, (!strlen(webServer->arg("mp").c_str())) ? MQTT_PASS : (!strcmp(webServer->arg("mp").c_str(),"0")) ? "" : webServer->arg("mp").c_str(), sizeof(sysCfg.mqtt_pwd));
+ snprintf_P(log, sizeof(log), PSTR("HTTP: MQTT Host %s, Port %d, Client %s, User %s, Password %s, Topic %s, FullTopic %s"),
+ sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.mqtt_client, sysCfg.mqtt_user, sysCfg.mqtt_pwd, sysCfg.mqtt_topic, sysCfg.mqtt_fulltopic);
+ addLog(LOG_LEVEL_INFO, log);
+ break;
+ case 3:
+ sysCfg.seriallog_level = (!strlen(webServer->arg("ls").c_str())) ? SERIAL_LOG_LEVEL : atoi(webServer->arg("ls").c_str());
+ sysCfg.weblog_level = (!strlen(webServer->arg("lw").c_str())) ? WEB_LOG_LEVEL : atoi(webServer->arg("lw").c_str());
+ sysCfg.syslog_level = (!strlen(webServer->arg("ll").c_str())) ? SYS_LOG_LEVEL : atoi(webServer->arg("ll").c_str());
+ syslog_level = sysCfg.syslog_level;
+ syslog_timer = 0;
+ strlcpy(sysCfg.syslog_host, (!strlen(webServer->arg("lh").c_str())) ? SYS_LOG_HOST : webServer->arg("lh").c_str(), sizeof(sysCfg.syslog_host));
+ sysCfg.syslog_port = (!strlen(webServer->arg("lp").c_str())) ? SYS_LOG_PORT : atoi(webServer->arg("lp").c_str());
+ sysCfg.tele_period = (!strlen(webServer->arg("lt").c_str())) ? TELE_PERIOD : atoi(webServer->arg("lt").c_str());
+ snprintf_P(log, sizeof(log), PSTR("HTTP: Logging Seriallog %d, Weblog %d, Syslog %d, Host %s, Port %d, TelePeriod %d"),
+ sysCfg.seriallog_level, sysCfg.weblog_level, sysCfg.syslog_level, sysCfg.syslog_host, sysCfg.syslog_port, sysCfg.tele_period);
+ addLog(LOG_LEVEL_INFO, log);
+ break;
+#ifdef USE_DOMOTICZ
+ case 4:
+ domoticz_saveSettings();
+ break;
+#endif // USE_DOMOTICZ
+ case 5:
+ strlcpy(sysCfg.web_password, (!strlen(webServer->arg("p1").c_str())) ? WEB_PASSWORD : (!strcmp(webServer->arg("p1").c_str(),"0")) ? "" : webServer->arg("p1").c_str(), sizeof(sysCfg.web_password));
+ sysCfg.flag.mqtt_enabled = webServer->hasArg("b1");
+#ifdef USE_EMULATION
+ sysCfg.flag.emulation = (!strlen(webServer->arg("b2").c_str())) ? 0 : atoi(webServer->arg("b2").c_str());
+#endif // USE_EMULATION
+ strlcpy(sysCfg.friendlyname[0], (!strlen(webServer->arg("a1").c_str())) ? FRIENDLY_NAME : webServer->arg("a1").c_str(), sizeof(sysCfg.friendlyname[0]));
+ strlcpy(sysCfg.friendlyname[1], (!strlen(webServer->arg("a2").c_str())) ? FRIENDLY_NAME"2" : webServer->arg("a2").c_str(), sizeof(sysCfg.friendlyname[1]));
+ strlcpy(sysCfg.friendlyname[2], (!strlen(webServer->arg("a3").c_str())) ? FRIENDLY_NAME"3" : webServer->arg("a3").c_str(), sizeof(sysCfg.friendlyname[2]));
+ strlcpy(sysCfg.friendlyname[3], (!strlen(webServer->arg("a4").c_str())) ? FRIENDLY_NAME"4" : webServer->arg("a4").c_str(), sizeof(sysCfg.friendlyname[3]));
+ snprintf_P(log, sizeof(log), PSTR("HTTP: Other MQTT Enable %s, Emulation %d, Friendly Names %s, %s, %s and %s"),
+ getStateText(sysCfg.flag.mqtt_enabled), sysCfg.flag.emulation, sysCfg.friendlyname[0], sysCfg.friendlyname[1], sysCfg.friendlyname[2], sysCfg.friendlyname[3]);
+ addLog(LOG_LEVEL_INFO, log);
+ break;
+ case 6:
+ byte new_module = (!strlen(webServer->arg("mt").c_str())) ? MODULE : atoi(webServer->arg("mt").c_str());
+ byte new_modflg = (sysCfg.module != new_module);
+ sysCfg.module = new_module;
+ mytmplt cmodule;
+ memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule));
+ String gpios = "";
+ for (byte i = 0; i < MAX_GPIO_PIN; i++) {
+ if (new_modflg) {
+ sysCfg.my_module.gp.io[i] = 0;
+ }
+ if (GPIO_USER == cmodule.gp.io[i]) {
+ snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i);
+ sysCfg.my_module.gp.io[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str());
+ gpios += F(", GPIO"); gpios += String(i); gpios += F(" "); gpios += String(sysCfg.my_module.gp.io[i]);
+ }
+ }
+ snprintf_P(stemp, sizeof(stemp), modules[sysCfg.module].name);
+ snprintf_P(log, sizeof(log), PSTR("HTTP: %s Module%s"), stemp, gpios.c_str());
+ addLog(LOG_LEVEL_INFO, log);
+ break;
+ }
+
+ restart = (!strlen(webServer->arg("r").c_str())) ? 1 : atoi(webServer->arg("r").c_str());
+ if (restart) {
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Save parameters"));
+ page += F("
Parameters saved
");
+ page += result;
+ page += F("
");
+ page += FPSTR(HTTP_MSG_RSTRT);
+ if (HTTP_MANAGER == _httpflag) {
+ _httpflag = HTTP_ADMIN;
+ } else {
+ page += FPSTR(HTTP_BTN_MAIN);
+ }
+ showPage(page);
+
+ restartflag = 2;
+ } else {
+ handleConfig();
+ }
+}
+
+void handleReset()
+{
+ if (httpUser()) {
+ return;
+ }
+
+ char svalue[16]; // was MESSZ
+
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Reset parameters"));
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Default parameters"));
+ page += F("
Parameters reset to default
");
+ page += FPSTR(HTTP_MSG_RSTRT);
+ page += FPSTR(HTTP_BTN_MAIN);
+ showPage(page);
+
+ snprintf_P(svalue, sizeof(svalue), PSTR("reset 1"));
+ do_cmnd(svalue);
+}
+
+void handleRestore()
+{
+ if (httpUser()) {
+ return;
+ }
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Restore"));
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Restore Configuration"));
+ page += FPSTR(HTTP_FORM_RST);
+ page += FPSTR(HTTP_FORM_RST_UPG);
+ page.replace(F("{r1}"), F("restore"));
+ page += FPSTR(HTTP_BTN_CONF);
+ showPage(page);
+
+ _uploaderror = 0;
+ _uploadfiletype = 1;
+}
+
+void handleUpgrade()
+{
+ if (httpUser()) {
+ return;
+ }
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Upgrade"));
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Firmware upgrade"));
+ page += FPSTR(HTTP_FORM_UPG);
+ page.replace(F("{o1}"), sysCfg.otaUrl);
+ page += FPSTR(HTTP_FORM_RST_UPG);
+ page.replace(F("{r1}"), F("upgrade"));
+ page += FPSTR(HTTP_BTN_MAIN);
+ showPage(page);
+
+ _uploaderror = 0;
+ _uploadfiletype = 0;
+}
+
+void handleUpgradeStart()
+{
+ if (httpUser()) {
+ return;
+ }
+ char svalue[100]; // was MESSZ
+
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Firmware upgrade start"));
+ WIFI_configCounter();
+
+ if (strlen(webServer->arg("o").c_str())) {
+ snprintf_P(svalue, sizeof(svalue), PSTR("otaurl %s"), webServer->arg("o").c_str());
+ do_cmnd(svalue);
+ }
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Info"));
+ page += F("
Upgrade started ...
");
+ page += FPSTR(HTTP_MSG_RSTRT);
+ page += FPSTR(HTTP_BTN_MAIN);
+ showPage(page);
+
+ snprintf_P(svalue, sizeof(svalue), PSTR("upgrade 1"));
+ do_cmnd(svalue);
+}
+
+void handleUploadDone()
+{
+ if (httpUser()) {
+ return;
+ }
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: File upload done"));
+
+ char error[80];
+ char log[LOGSZ];
+
+ WIFI_configCounter();
+ restartflag = 0;
+ mqttcounter = 0;
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Info"));
+ page += F("
Upload ");
+ if (_uploaderror) {
+ page += F("failed
");
+ switch (_uploaderror) {
+ case 1: strcpy_P(error, PSTR("No file selected")); break;
+ case 2: strcpy_P(error, PSTR("Not enough space")); break;
+ case 3: strcpy_P(error, PSTR("Magic byte is not 0xE9")); break;
+ case 4: strcpy_P(error, PSTR("IDE flash size larger than device flash size")); break;
+ case 5: strcpy_P(error, PSTR("Upload buffer miscompare")); break;
+ case 6: strcpy_P(error, PSTR("Upload failed. Enable logging 3")); break;
+ case 7: strcpy_P(error, PSTR("Upload aborted")); break;
+ case 8: strcpy_P(error, PSTR("File invalid")); break;
+ case 9: strcpy_P(error, PSTR("File too large")); break;
+ default:
+ snprintf_P(error, sizeof(error), PSTR("Upload error code %d"), _uploaderror);
+ }
+ page += error;
+ snprintf_P(log, sizeof(log), PSTR("Upload: %s"), error);
+ addLog(LOG_LEVEL_DEBUG, log);
+ stop_flash_rotate = sysCfg.flag.stop_flash_rotate;
+ } else {
+ page += F("successful
Device will restart in a few seconds");
+ restartflag = 2;
+ }
+ page += F("
");
+ page += FPSTR(HTTP_BTN_MAIN);
+ showPage(page);
+}
+
+void handleUploadLoop()
+{
+ // Based on ESP8266HTTPUpdateServer.cpp uses ESP8266WebServer Parsing.cpp and Cores Updater.cpp (Update)
+ char log[LOGSZ];
+ boolean _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level);
+
+ if (HTTP_USER == _httpflag) {
+ return;
+ }
+ if (_uploaderror) {
+ if (!_uploadfiletype) {
+ Update.end();
+ }
+ return;
+ }
+
+ HTTPUpload& upload = webServer->upload();
+
+ if (UPLOAD_FILE_START == upload.status) {
+ restartflag = 60;
+ if (0 == upload.filename.c_str()[0]) {
+ _uploaderror = 1;
+ return;
+ }
+ CFG_Save(1); // Free flash for upload
+ snprintf_P(log, sizeof(log), PSTR("Upload: File %s ..."), upload.filename.c_str());
+ addLog(LOG_LEVEL_INFO, log);
+ if (!_uploadfiletype) {
+ mqttcounter = 60;
+#ifdef USE_EMULATION
+ UDP_Disconnect();
+#endif // USE_EMULATION
+ if (sysCfg.flag.mqtt_enabled) {
+ mqttClient.disconnect();
+ }
+ uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
+ if (!Update.begin(maxSketchSpace)) { //start with max available size
+ _uploaderror = 2;
+ return;
+ }
+ }
+ _colcount = 0;
+ } else if (!_uploaderror && (UPLOAD_FILE_WRITE == upload.status)) {
+ if (0 == upload.totalSize)
+ {
+ if (_uploadfiletype) {
+ if (upload.buf[0] != CONFIG_FILE_SIGN) {
+ _uploaderror = 8;
+ return;
+ }
+ if (upload.currentSize > sizeof(sysCfg)) {
+ _uploaderror = 9;
+ return;
+ }
+ } else {
+ if (upload.buf[0] != 0xE9) {
+ _uploaderror = 3;
+ return;
+ }
+ uint32_t bin_flash_size = ESP.magicFlashChipSize((upload.buf[3] & 0xf0) >> 4);
+ if(bin_flash_size > ESP.getFlashChipRealSize()) {
+ _uploaderror = 4;
+ return;
+ }
+ upload.buf[2] = 3; // Force DOUT - ESP8285
+ }
+ }
+ if (_uploadfiletype) { // config
+ if (!_uploaderror) {
+ if (upload.buf[1]) {
+ for (uint16_t i = 2; i < upload.currentSize; i++) {
+ upload.buf[i] ^= (CONFIG_FILE_XOR +i);
+ }
+ }
+ CFG_DefaultSet2();
+ memcpy((char*)&sysCfg +16, upload.buf +16, upload.currentSize -16);
+ memcpy((char*)&sysCfg +8, upload.buf +8, 4); // Restore version and auto upgrade
+ }
+ } else { // firmware
+ if (!_uploaderror && (Update.write(upload.buf, upload.currentSize) != upload.currentSize)) {
+ _uploaderror = 5;
+ return;
+ }
+ if (_serialoutput) {
+ Serial.printf(".");
+ _colcount++;
+ if (!(_colcount % 80)) {
+ Serial.println();
+ }
+ }
+ }
+ } else if(!_uploaderror && (UPLOAD_FILE_END == upload.status)) {
+ if (_serialoutput && (_colcount % 80)) {
+ Serial.println();
+ }
+ if (!_uploadfiletype) {
+ if (!Update.end(true)) { // true to set the size to the current progress
+ if (_serialoutput) {
+ Update.printError(Serial);
+ }
+ _uploaderror = 6;
+ return;
+ }
+ }
+ if (!_uploaderror) {
+ snprintf_P(log, sizeof(log), PSTR("Upload: Successful %u bytes. Restarting"), upload.totalSize);
+ addLog(LOG_LEVEL_INFO, log);
+ }
+ } else if (UPLOAD_FILE_ABORTED == upload.status) {
+ restartflag = 0;
+ mqttcounter = 0;
+ _uploaderror = 7;
+ if (!_uploadfiletype) {
+ Update.end();
+ }
+ }
+ delay(0);
+}
+
+void handleCmnd()
+{
+ if (httpUser()) {
+ return;
+ }
+ char svalue[INPUT_BUFFER_SIZE]; // big to serve Backlog
+
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Command"));
+
+ uint8_t valid = 1;
+ if (sysCfg.web_password[0] != 0) {
+ if (!(!strcmp(webServer->arg("user").c_str(),WEB_USERNAME) && !strcmp(webServer->arg("password").c_str(),sysCfg.web_password))) {
+ valid = 0;
+ }
+ }
+
+ String message = "";
+ if (valid) {
+ byte curridx = logidx;
+ if (strlen(webServer->arg("cmnd").c_str())) {
+// snprintf_P(svalue, sizeof(svalue), webServer->arg("cmnd").c_str());
+ snprintf_P(svalue, sizeof(svalue), PSTR("%s"), webServer->arg("cmnd").c_str());
+ byte syslog_now = syslog_level;
+ syslog_level = 0; // Disable UDP syslog to not trigger hardware WDT
+ do_cmnd(svalue);
+ syslog_level = syslog_now;
+ }
+
+ if (logidx != curridx) {
+ byte counter = curridx;
+ do {
+ if (Log[counter].length()) {
+ if (message.length()) {
+ message += F("\n");
+ }
+ if (sysCfg.flag.mqtt_enabled) {
+ // [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [RESULT = {"POWER":"OFF"}]
+// message += Log[counter].substring(17 + strlen(PUB_PREFIX) + strlen(sysCfg.mqtt_topic));
+ message += Log[counter].substring(Log[counter].lastIndexOf("/",Log[counter].indexOf("="))+1);
+ } else {
+ // [14:49:36 RSLT: RESULT = {"POWER":"OFF"}] > [RESULT = {"POWER":"OFF"}]
+ message += Log[counter].substring(Log[counter].indexOf(": ")+2);
+ }
+ }
+ counter++;
+ if (counter > MAX_LOG_LINES -1) {
+ counter = 0;
+ }
+ } while (counter != logidx);
+ } else {
+ message = F("Enable weblog 2 if response expected\n");
+ }
+ } else {
+ message = F("Need user=
&password=\n");
+ }
+ webServer->send(200, FPSTR(HDR_CTYPE_PLAIN), message);
+}
+
+void handleConsole()
+{
+ if (httpUser()) {
+ return;
+ }
+
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Console"));
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Console"));
+ page.replace(F(""), FPSTR(HTTP_SCRIPT_CONSOL));
+ page.replace(F(""), F(""));
+ page += FPSTR(HTTP_FORM_CMND);
+ page += FPSTR(HTTP_BTN_MAIN);
+ showPage(page);
+}
+
+void handleAjax()
+{
+ if (httpUser()) {
+ return;
+ }
+ char log[LOGSZ];
+ char svalue[INPUT_BUFFER_SIZE]; // big to serve Backlog
+ byte cflg = 1;
+ byte counter = 99;
+
+ if (strlen(webServer->arg("c1").c_str())) {
+ snprintf_P(svalue, sizeof(svalue), PSTR("%s"), webServer->arg("c1").c_str());
+ snprintf_P(log, sizeof(log), PSTR("CMND: %s"), svalue);
+ addLog(LOG_LEVEL_INFO, log);
+ byte syslog_now = syslog_level;
+ syslog_level = 0; // Disable UDP syslog to not trigger hardware WDT
+ do_cmnd(svalue);
+ syslog_level = syslog_now;
+ }
+
+ if (strlen(webServer->arg("c2").c_str())) {
+ counter = atoi(webServer->arg("c2").c_str());
+ }
+
+ String message = F("");
+ message += String(logidx);
+ message += F("");
+ message += String(logajaxflg);
+ if (!logajaxflg) {
+ counter = 99;
+ logajaxflg = 1;
+ }
+ message += F("");
+ if (counter != logidx) {
+ if (99 == counter) {
+ counter = logidx;
+ cflg = 0;
+ }
+ do {
+ if (Log[counter].length()) {
+ if (cflg) {
+ message += F("\n");
+ } else {
+ cflg = 1;
+ }
+ message += Log[counter];
+ }
+ counter++;
+ if (counter > MAX_LOG_LINES -1) {
+ counter = 0;
+ }
+ } while (counter != logidx);
+ }
+ message += F("");
+ webServer->send(200, FPSTR(HDR_CTYPE_XML), message);
+}
+
+void handleInfo()
+{
+ if (httpUser()) {
+ return;
+ }
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Info"));
+
+ char stopic[TOPSZ];
+
+ int freeMem = ESP.getFreeHeap();
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Information"));
+// page += F("");
+ page += F("");
+ page += F("");
+ page += F("Program version | "); page += Version; page += F(" |
");
+ page += F("Build Date & Time | "); page += getBuildDateTime(); page += F(" |
");
+ page += F("Core/SDK version | "); page += ESP.getCoreVersion(); page += F("/"); page += String(ESP.getSdkVersion()); page += F(" |
");
+// page += F("Boot version | "); page += String(ESP.getBootVersion()); page += F(" |
");
+ page += F("Uptime | "); page += String(uptime); page += F(" Hours |
");
+ snprintf_P(stopic, sizeof(stopic), PSTR(" at %X"), CFG_Address());
+ page += F("Flash write count | "); page += String(sysCfg.saveFlag); page += stopic; page += F(" |
");
+ page += F("Boot count | "); page += String(sysCfg.bootcount); page += F(" |
");
+ page += F("Reset reason | "); page += getResetReason(); page += F(" |
");
+ for (byte i = 0; i < Maxdevice; i++) {
+ page += F("Friendly name ");
+ page += i +1;
+ page += F(" | "); page += sysCfg.friendlyname[i]; page += F(" |
");
+ }
+ page += F(" |
");
+ page += F("AP"); page += String(sysCfg.sta_active +1);
+ page += F(" SSId (RSSI) | "); page += sysCfg.sta_ssid[sysCfg.sta_active]; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%) |
");
+ page += F("Hostname | "); page += Hostname; page += F(" |
");
+ if (static_cast(WiFi.localIP()) != 0) {
+ page += F("IP address | "); page += WiFi.localIP().toString(); page += F(" |
");
+ page += F("Gateway | "); page += IPAddress(sysCfg.ip_address[1]).toString(); page += F(" |
");
+ page += F("Subnet mask | "); page += IPAddress(sysCfg.ip_address[2]).toString(); page += F(" |
");
+ page += F("DNS server | "); page += IPAddress(sysCfg.ip_address[3]).toString(); page += F(" |
");
+ page += F("MAC address | "); page += WiFi.macAddress(); page += F(" |
");
+ }
+ if (static_cast(WiFi.softAPIP()) != 0) {
+ page += F("AP IP address | "); page += WiFi.softAPIP().toString(); page += F(" |
");
+ page += F("AP Gateway | "); page += WiFi.softAPIP().toString(); page += F(" |
");
+ page += F("AP MAC address | "); page += WiFi.softAPmacAddress(); page += F(" |
");
+ }
+ page += F(" |
");
+ if (sysCfg.flag.mqtt_enabled) {
+ page += F("MQTT Host | "); page += sysCfg.mqtt_host; page += F(" |
");
+ page += F("MQTT Port | "); page += String(sysCfg.mqtt_port); page += F(" |
");
+ page += F("MQTT Client & Fallback Topic | "); page += MQTTClient; page += F(" |
");
+ page += F("MQTT User | "); page += sysCfg.mqtt_user; page += F(" |
");
+// page += F("MQTT Password | "); page += sysCfg.mqtt_pwd; page += F(" |
");
+ page += F("MQTT Topic | "); page += sysCfg.mqtt_topic; page += F(" |
");
+ page += F("MQTT Group Topic | "); page += sysCfg.mqtt_grptopic; page += F(" |
");
+
+ getTopic_P(stopic, 0, sysCfg.mqtt_topic, "");
+ page += F("MQTT Full Topic | "); page += stopic; page += F(" |
");
+
+ } else {
+ page += F("MQTT | Disabled |
");
+ }
+ page += F(" |
");
+ page += F("Emulation | ");
+#ifdef USE_EMULATION
+ if (EMUL_WEMO == sysCfg.flag.emulation) {
+ page += F("Belkin WeMo");
+ }
+ else if (EMUL_HUE == sysCfg.flag.emulation) {
+ page += F("Hue Bridge");
+ }
+ else {
+ page += F("None");
+ }
+#else
+ page += F("Disabled");
+#endif // USE_EMULATION
+ page += F(" |
");
+
+ page += F("mDNS Discovery | ");
+#ifdef USE_DISCOVERY
+ page += F("Enabled");
+ page += F(" |
");
+ page += F("mDNS Advertise | ");
+#ifdef WEBSERVER_ADVERTISE
+ page += F("Webserver");
+#else
+ page += F("Disabled");
+#endif // WEBSERVER_ADVERTISE
+#else
+ page += F("Disabled");
+#endif // USE_DISCOVERY
+ page += F(" |
");
+
+ page += F(" |
");
+ page += F("ESP Chip id | "); page += String(ESP.getChipId()); page += F(" |
");
+ page += F("Flash Chip id | "); page += String(ESP.getFlashChipId()); page += F(" |
");
+ page += F("Flash size | "); page += String(ESP.getFlashChipRealSize() / 1024); page += F("kB |
");
+ page += F("Program flash size | "); page += String(ESP.getFlashChipSize() / 1024); page += F("kB |
");
+ page += F("Program size | "); page += String(ESP.getSketchSize() / 1024); page += F("kB |
");
+ page += F("Free program space | "); page += String(ESP.getFreeSketchSpace() / 1024); page += F("kB |
");
+ page += F("Free memory | "); page += String(freeMem / 1024); page += F("kB |
");
+ page += F("
");
+// page += F("");
+ page += FPSTR(HTTP_BTN_MAIN);
+ showPage(page);
+}
+
+void handleRestart()
+{
+ if (httpUser()) {
+ return;
+ }
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Restarting"));
+
+ String page = FPSTR(HTTP_HEAD);
+ page.replace(F("{v}"), F("Info"));
+ page += FPSTR(HTTP_MSG_RSTRT);
+ if (HTTP_MANAGER == _httpflag) {
+ _httpflag = HTTP_ADMIN;
+ } else {
+ page += FPSTR(HTTP_BTN_MAIN);
+ }
+ showPage(page);
+
+ restartflag = 2;
+}
+
+/********************************************************************************************/
+
+void handleNotFound()
+{
+ if (captivePortal()) { // If captive portal redirect instead of displaying the error page.
+ return;
+ }
+
+#ifdef USE_EMULATION
+ String path = webServer->uri();
+ if ((EMUL_HUE == sysCfg.flag.emulation) && (path.startsWith("/api"))) {
+ handle_hue_api(&path);
+ } else
+#endif // USE_EMULATION
+ {
+ String message = F("File Not Found\n\nURI: ");
+ message += webServer->uri();
+ message += F("\nMethod: ");
+ message += (webServer->method() == HTTP_GET) ? F("GET") : F("POST");
+ message += F("\nArguments: ");
+ message += webServer->args();
+ message += F("\n");
+ for ( uint8_t i = 0; i < webServer->args(); i++ ) {
+ message += " " + webServer->argName(i) + ": " + webServer->arg(i) + "\n";
+ }
+ setHeader();
+ webServer->send(404, FPSTR(HDR_CTYPE_PLAIN), message);
+ }
+}
+
+/* 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 == _httpflag) && !isIp(webServer->hostHeader())) {
+ addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Request redirected to captive portal"));
+
+ 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 isIp(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;
+}
+#endif // USE_WEBSERVER