diff --git a/webserver.ino b/webserver.ino deleted file mode 100644 index dce438ca6..000000000 --- a/webserver.ino +++ /dev/null @@ -1,1618 +0,0 @@ -/* - webserver.ino - webserver for Sonoff-Tasmota - - Copyright (C) 2017 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_WEBSERVER -/*********************************************************************************************\ - * Web server and WiFi Manager - * - * Enables configuration and reconfiguration of WiFi credentials using a Captive Portal - * Based on source by AlexT (https://github.com/tzapu) -\*********************************************************************************************/ - -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) - -const char HTTP_HEAD[] PROGMEM = - "" - "" - "" - "" - "{v}" - - "" - - "" - - "" - "" - "
" - "

{ha} Module

{h}

"; -const char HTTP_SCRIPT_CONSOL[] PROGMEM = - "var sn=0;" // Scroll position - "var id=99;" // Get most of weblog initially - "function l(p){" // Console log and command service - "var c,o,t;" - "clearTimeout(lt);" - "o='';" - "t=document.getElementById('t1');" - "if(p==1){" - "c=document.getElementById('c1');" - "o='&c1='+encodeURI(c.value);" - "c.value='';" - "t.scrollTop=sn;" - "}" - "if(t.scrollTop>=sn){" // User scrolled back so no updates - "if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1) - "x=new XMLHttpRequest();" - "x.onreadystatechange=function(){" - "if(x.readyState==4&&x.status==200){" - "var z,d;" - "d=x.responseXML;" - "id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue;" - "if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){t.value='';}" - "z=d.getElementsByTagName('l')[0].childNodes;" - "if(z.length>0){t.value+=z[0].nodeValue;}" - "t.scrollTop=99999;" - "sn=t.scrollTop;" - "}" - "};" - "x.open('GET','ax?c2='+id+o,true);" - "x.send();" - "}" - "lt=setTimeout(l,2345);" - "return false;" - "}" - ""; -const char HTTP_SCRIPT_MODULE[] PROGMEM = - "var os;" - "function sk(s,g){" - "var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");" - "document.getElementById('g'+g).innerHTML=o;" - "}" - "function sl(){" - "var o0=\""; -const char HTTP_MSG_RSTRT[] PROGMEM = - "
Device will restart in a few seconds

"; -const char HTTP_BTN_MENU1[] PROGMEM = - "
" - "
" - "
" - "
"; -const char HTTP_BTN_RSTRT[] PROGMEM = - "
"; -const char HTTP_BTN_MENU2[] PROGMEM = - "
" - "
"; -const char HTTP_BTN_MENU3[] PROGMEM = - "
" -#ifdef USE_DOMOTICZ - "
" -#endif // USE_DOMOTICZ - ""; -const char HTTP_BTN_MENU4[] PROGMEM = - "
" - "
" - "
" - "
" - "
"; -const char HTTP_BTN_MAIN[] PROGMEM = - "

"; -const char HTTP_BTN_CONF[] PROGMEM = - "

"; -const char HTTP_FORM_MODULE[] PROGMEM = - "
 Module parameters 
" - "" - "
Module type ({mt})
" - "
AP1 SSId (" STA_SSID1 ")

" - "
AP1 Password

" - "
AP2 SSId (" STA_SSID2 ")

" - "
AP2 Password

" - "
Hostname (" WIFI_HOSTNAME ")

"; -const char HTTP_FORM_MQTT[] PROGMEM = - "
 MQTT parameters " - "" - "
Host (" MQTT_HOST ")

" - "
Port (" STR(MQTT_PORT) ")

" - "
Client Id ({m0})

" - "
User (" MQTT_USER ")

" - "
Password

" - "
Topic = %topic% (" MQTT_TOPIC ")

" - "
Full Topic (" MQTT_FULLTOPIC ")

"; -const char HTTP_FORM_LOG1[] PROGMEM = - "
 Logging parameters " - ""; -const char HTTP_FORM_LOG2[] PROGMEM = - "
{b0}log level ({b1})

"; -const char HTTP_FORM_LOG3[] PROGMEM = - "
Syslog host (" SYS_LOG_HOST ")

" - "
Syslog port (" STR(SYS_LOG_PORT) ")

" - "
Telemetric period (" STR(TELE_PERIOD) ")

"; -const char HTTP_FORM_OTHER[] PROGMEM = - "
 Other parameters " - "" - "
Web Admin Password

" - "
MQTT enable
"; -const char HTTP_FORM_OTHER2[] PROGMEM = - "
Friendly Name {1 ({2)

"; -#ifdef USE_EMULATION -const char HTTP_FORM_OTHER3a[] PROGMEM = - "
 Emulation "; -const char HTTP_FORM_OTHER3b[] PROGMEM = - "
{3{4"; -#endif // USE_EMULATION -const char HTTP_FORM_END[] PROGMEM = - "
"; -const char HTTP_FORM_RST[] PROGMEM = - "
" - "
 Restore configuration "; -const char HTTP_FORM_UPG[] PROGMEM = - "
" - "
 Upgrade by web server " - "
" - "
OTA Url

" - "
" - "


" - "
 Upgrade by file upload "; -const char HTTP_FORM_RST_UPG[] PROGMEM = - "
" - "

" - "
" - "
" - "
" - ""; -const char HTTP_FORM_CMND[] PROGMEM = - "


" - "
" - "
" -// "
" - "
"; -const char HTTP_TABLE100[] PROGMEM = - ""; -const char HTTP_COUNTER[] PROGMEM = - "
"; -const char HTTP_SNS_TEMP[] PROGMEM = - ""; -const char HTTP_SNS_HUM[] PROGMEM = - ""; -const char HTTP_SNS_PRESSURE[] PROGMEM = - ""; -const char HTTP_SNS_LIGHT[] PROGMEM = - ""; -const char HTTP_SNS_NOISE[] PROGMEM = - ""; -const char HTTP_SNS_DUST[] PROGMEM = - ""; -const char HTTP_END[] PROGMEM = - "" - "" - ""; - -const char HDR_CTYPE_PLAIN[] PROGMEM = "text/plain"; -const char HDR_CTYPE_HTML[] PROGMEM = "text/html"; -const char HDR_CTYPE_XML[] PROGMEM = "text/xml"; -const char HDR_CTYPE_JSON[] PROGMEM = "application/json"; -const char HDR_CTYPE_STREAM[] PROGMEM = "application/octet-stream"; - -#define DNS_PORT 53 -enum http_t {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER}; - -DNSServer *dnsServer; -ESP8266WebServer *webServer; - -boolean _removeDuplicateAPs = true; -int _minimumQuality = -1; -uint8_t _httpflag = HTTP_OFF; -uint8_t _uploaderror = 0; -uint8_t _uploadfiletype; -uint8_t _colcount; - -void startWebserver(int type, IPAddress ipweb) -{ - char log[LOGSZ]; - - if (!_httpflag) { - if (!webServer) { - webServer = new ESP8266WebServer((HTTP_MANAGER==type)?80:WEB_PORT); - webServer->on("/", handleRoot); - webServer->on("/cn", handleConfig); - webServer->on("/md", handleModule); - webServer->on("/w1", handleWifi1); - webServer->on("/w0", handleWifi0); - if (sysCfg.flag.mqtt_enabled) { - webServer->on("/mq", handleMqtt); -#ifdef USE_DOMOTICZ - webServer->on("/dm", handleDomoticz); -#endif // USE_DOMOTICZ - } - webServer->on("/lg", handleLog); - webServer->on("/co", handleOther); - webServer->on("/dl", handleDownload); - webServer->on("/sv", handleSave); - webServer->on("/rs", handleRestore); - webServer->on("/rt", handleReset); - webServer->on("/up", handleUpgrade); - webServer->on("/u1", handleUpgradeStart); // OTA - webServer->on("/u2", HTTP_POST, handleUploadDone, handleUploadLoop); - webServer->on("/cm", handleCmnd); - webServer->on("/cs", handleConsole); - webServer->on("/ax", handleAjax); - webServer->on("/ay", handleAjax2); - webServer->on("/in", handleInfo); - webServer->on("/rb", handleRestart); - webServer->on("/fwlink", handleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler. -#ifdef USE_EMULATION - if (EMUL_WEMO == sysCfg.flag.emulation) { - webServer->on("/upnp/control/basicevent1", HTTP_POST, handleUPnPevent); - webServer->on("/eventservice.xml", handleUPnPservice); - webServer->on("/setup.xml", handleUPnPsetupWemo); - } - if (EMUL_HUE == sysCfg.flag.emulation) { - webServer->on("/description.xml", handleUPnPsetupHue); - } -#endif // USE_EMULATION - webServer->onNotFound(handleNotFound); - } - logajaxflg = 0; - webServer->begin(); // Web server start - } - if (_httpflag != type) { - snprintf_P(log, sizeof(log), PSTR("HTTP: Webserver active on %s%s with IP address %s"), - Hostname, (mDNSbegun)?".local":"", ipweb.toString().c_str()); - addLog(LOG_LEVEL_INFO, log); - } - if (type) _httpflag = type; -} - -void stopWebserver() -{ - if (_httpflag) { - webServer->close(); - _httpflag = HTTP_OFF; - addLog_P(LOG_LEVEL_INFO, PSTR("HTTP: Webserver stopped")); - } -} - -void beginWifiManager() -{ - // setup AP - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { - WiFi.mode(WIFI_AP_STA); - addLog_P(LOG_LEVEL_DEBUG, PSTR("Wifimanager: Set AccessPoint and keep Station")); - } else { - WiFi.mode(WIFI_AP); - addLog_P(LOG_LEVEL_DEBUG, PSTR("Wifimanager: Set AccessPoint")); - } - - stopWebserver(); - - dnsServer = new DNSServer(); - WiFi.softAP(Hostname); - delay(500); // Without delay I've seen the IP address blank - /* Setup the DNS server redirecting all the domains to the apIP */ - dnsServer->setErrorReplyCode(DNSReplyCode::NoError); - dnsServer->start(DNS_PORT, "*", WiFi.softAPIP()); - - startWebserver(HTTP_MANAGER, WiFi.softAPIP()); -} - -void pollDnsWeb() -{ - if (dnsServer) { - dnsServer->processNextRequest(); - } - if (webServer) { - webServer->handleClient(); - } -} - -void setHeader() -{ - webServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); - webServer->sendHeader(F("Pragma"), F("no-cache")); - webServer->sendHeader(F("Expires"), F("-1")); -} - -void showPage(String &page) -{ - if((HTTP_ADMIN == _httpflag) && (sysCfg.web_password[0] != 0) && !webServer->authenticate(WEB_USERNAME, sysCfg.web_password)) { - return webServer->requestAuthentication(); - } - page.replace(F("{ha}"), my_module.name); - page.replace(F("{h}"), sysCfg.friendlyname[0]); - if (HTTP_MANAGER == _httpflag) { - if (WIFI_configCounter()) { - page.replace(F(""), F("")); - page += FPSTR(HTTP_COUNTER); - } - } - page += FPSTR(HTTP_END); - setHeader(); - webServer->send(200, FPSTR(HDR_CTYPE_HTML), page); -} - -void handleRoot() -{ - addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Root")); - - if (captivePortal()) { // If captive portal redirect instead of displaying the page. - return; - } - - if (HTTP_MANAGER == _httpflag) { - handleWifi0(); - } else { - char stemp[10], line[100]; - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), F("Main menu")); - page.replace(F(""), F("")); - - page += F("
"); - if (Maxdevice) { - if (sfl_flg) { - snprintf_P(line, sizeof(line), PSTR(""), - sysCfg.led_dimmer[0]); - page += line; - } - page += FPSTR(HTTP_TABLE100); - page += F("
"); - for (byte idx = 1; idx <= Maxdevice; idx++) { - snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - snprintf_P(line, sizeof(line), PSTR(""), - 100 / Maxdevice, idx, (Maxdevice > 1) ? stemp : ""); - page += line; - } - page += F("
%s Temperature%s°%c
%s Humidity%s%
%s Pressure%s hPa
%s Light%d%
%s Noise%d%
%s Air quality%d%
"); - } - if (SONOFF_BRIDGE == sysCfg.module) { - page += FPSTR(HTTP_TABLE100); - page += F(""); - byte idx = 0; - for (byte i = 0; i < 4; i++) { - if (idx > 0) { - page += F(""); - } - for (byte j = 0; j < 4; j++) { - idx++; - snprintf_P(line, sizeof(line), PSTR(""), - idx, idx); - page += line; - } - } - page += F(""); - } - - if (HTTP_ADMIN == _httpflag) { - page += FPSTR(HTTP_BTN_MENU1); - page += FPSTR(HTTP_BTN_RSTRT); - } - showPage(page); - } -} - -void handleAjax2() -{ - char svalue[16]; - - if (strlen(webServer->arg("o").c_str())) { - do_cmnd_power(atoi(webServer->arg("o").c_str()), 2); - } - if (strlen(webServer->arg("d").c_str())) { - snprintf_P(svalue, sizeof(svalue), PSTR("dimmer %s"), webServer->arg("d").c_str()); - do_cmnd(svalue); - } - if (strlen(webServer->arg("k").c_str())) { - snprintf_P(svalue, sizeof(svalue), PSTR("rfkey%s"), webServer->arg("k").c_str()); - do_cmnd(svalue); - } - - String tpage = ""; - tpage += counter_webPresent(); - if (hlw_flg) { - tpage += hlw_webPresent(); - } - if (SONOFF_SC == sysCfg.module) { - tpage += sc_webPresent(); - } -#ifdef USE_DS18B20 - if (pin[GPIO_DSB] < 99) { - tpage += dsb_webPresent(); - } -#endif // USE_DS18B20 -#ifdef USE_DS18x20 - if (pin[GPIO_DSB] < 99) { - tpage += ds18x20_webPresent(); - } -#endif // USE_DS18x20 -#ifdef USE_DHT - if (dht_flg) { - tpage += dht_webPresent(); - } -#endif // USE_DHT -#ifdef USE_I2C - if (i2c_flg) { -#ifdef USE_SHT - tpage += sht_webPresent(); -#endif -#ifdef USE_HTU - tpage += htu_webPresent(); -#endif -#ifdef USE_BMP - tpage += bmp_webPresent(); -#endif -#ifdef USE_BH1750 - tpage += bh1750_webPresent(); -#endif - } -#endif // USE_I2C - String page = ""; - if (tpage.length() > 0) { - page += FPSTR(HTTP_TABLE100); - page += tpage; - page += F(""); - } - char line[120]; - if (Maxdevice) { - page += FPSTR(HTTP_TABLE100); - page += F(""); - for (byte idx = 1; idx <= Maxdevice; idx++) { - snprintf_P(line, sizeof(line), PSTR("
%s
"), - 100 / Maxdevice, 70 - (Maxdevice * 8), getStateText(bitRead(power, idx -1))); - page += line; - } - page += F(""); - } -/* - * Will interrupt user action when selected - if (sfl_flg) { - snprintf_P(line, sizeof(line), PSTR(""), - sysCfg.led_dimmer[0]); - page += line; - } -*/ - webServer->send(200, FPSTR(HDR_CTYPE_HTML), page); -} - -boolean httpUser() -{ - boolean status = (HTTP_USER == _httpflag); - if (status) { - handleRoot(); - } - return status; -} - -void handleConfig() -{ - if (httpUser()) { - return; - } - addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Config")); - - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), F("Configuration")); - page += FPSTR(HTTP_BTN_MENU2); - if (sysCfg.flag.mqtt_enabled) { - page += FPSTR(HTTP_BTN_MENU3); - } - page += FPSTR(HTTP_BTN_MENU4); - page += FPSTR(HTTP_BTN_MAIN); - showPage(page); -} - -boolean inModule(byte val, uint8_t *arr) -{ - int offset = 0; - - if (!val) { - return false; // None - } -#ifndef USE_I2C - if (GPIO_I2C_SCL == val) { - return true; - } - if (GPIO_I2C_SDA == val) { - return true; - } -#endif -#ifndef USE_WS2812 - if (GPIO_WS2812 == val) { - return true; - } -#endif -#ifndef USE_IR_REMOTE - if (GPIO_IRSEND == val) { - return true; - } -#endif - if (((val >= GPIO_REL1) && (val <= GPIO_REL4)) || ((val >= GPIO_LED1) && (val <= GPIO_LED4))) { - offset = 4; - } - if (((val >= GPIO_REL1_INV) && (val <= GPIO_REL4_INV)) || ((val >= GPIO_LED1_INV) && (val <= GPIO_LED4_INV))) { - offset = -4; - } - for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { - return true; - } - if (arr[i] == val + offset) { - return true; - } - } - return false; -} - -void handleModule() -{ - if (httpUser()) { - return; - } - char stemp[20], line[128]; - - addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Module config")); - - String page = FPSTR(HTTP_HEAD); - page.replace(F("{v}"), F("Config module")); - page += FPSTR(HTTP_FORM_MODULE); - - snprintf_P(stemp, sizeof(stemp), modules[MODULE].name); - page.replace(F("{mt}"), stemp); - - for (byte i = 0; i < MAXMODULE; i++) { - snprintf_P(stemp, sizeof(stemp), modules[i].name); - snprintf_P(line, sizeof(line), PSTR("%02d %s"), - (i == sysCfg.module) ? " selected" : "", i, i +1, stemp); - page += line; - } - page += F("
"); - - mytmplt cmodule; - memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule)); - - String func = FPSTR(HTTP_SCRIPT_MODULE); - for (byte j = 0; j < GPIO_SENSOR_END; j++) { - if (!inModule(j, cmodule.gp.io)) { - snprintf_P(stemp, sizeof(stemp), sensors[j]); - snprintf_P(line, sizeof(line), PSTR("-1'%d'>%02d %s-2"), j, j, stemp); - func += line; - } - } - func += F("\";os=o0.replace(/-1/g,\"
"); -#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("
 Information "); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); -// page += F(""); - page += F(""); - snprintf_P(stopic, sizeof(stopic), PSTR(" at %X"), CFG_Address()); - page += F(""); - page += F(""); - page += F(""); - for (byte i = 0; i < Maxdevice; i++) { - page += F(""); - } - page += F(""); - page += F(""); - page += F(""); - if (static_cast(WiFi.localIP()) != 0) { - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - } - if (static_cast(WiFi.softAPIP()) != 0) { - page += F(""); - page += F(""); - page += F(""); - } - page += F(""); - if (sysCfg.flag.mqtt_enabled) { - page += F(""); - page += F(""); - page += F(""); - page += F(""); -// page += F(""); - page += F(""); - page += F(""); - - getTopic_P(stopic, 0, sysCfg.mqtt_topic, ""); - page += F(""); - - } else { - page += F(""); - } - page += F(""); - page += F(""); - - page += F(""); - page += F(""); - - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F(""); - page += F("
Program version"); page += Version; page += F("
Build Date & Time"); page += getBuildDateTime(); page += F("
Core/SDK version"); page += ESP.getCoreVersion(); page += F("/"); page += String(ESP.getSdkVersion()); page += F("
Boot version"); page += String(ESP.getBootVersion()); page += F("
Uptime"); page += String(uptime); page += F(" Hours
Flash write count"); page += String(sysCfg.saveFlag); page += stopic; page += F("
Boot count"); page += String(sysCfg.bootcount); page += F("
Reset reason"); page += getResetReason(); page += F("
Friendly name "); - page += i +1; - page += F(""); page += sysCfg.friendlyname[i]; 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("%)
Hostname"); page += Hostname; page += F("
IP address"); page += WiFi.localIP().toString(); page += F("
Gateway"); page += IPAddress(sysCfg.ip_address[1]).toString(); page += F("
Subnet mask"); page += IPAddress(sysCfg.ip_address[2]).toString(); page += F("
DNS server"); page += IPAddress(sysCfg.ip_address[3]).toString(); page += F("
MAC address"); page += WiFi.macAddress(); page += F("
AP IP address"); page += WiFi.softAPIP().toString(); page += F("
AP Gateway"); page += WiFi.softAPIP().toString(); page += F("
AP MAC address"); page += WiFi.softAPmacAddress(); page += F("
 
MQTT Host"); page += sysCfg.mqtt_host; page += F("
MQTT Port"); page += String(sysCfg.mqtt_port); page += F("
MQTT Client &
 Fallback Topic
"); page += MQTTClient; page += F("
MQTT User"); page += sysCfg.mqtt_user; page += F("
MQTT Password"); page += sysCfg.mqtt_pwd; page += F("
MQTT Topic"); page += sysCfg.mqtt_topic; page += F("
MQTT Group Topic"); page += sysCfg.mqtt_grptopic; page += F("
MQTT Full Topic"); page += stopic; page += F("
MQTTDisabled
 
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("
mDNS Discovery"); -#ifdef USE_DISCOVERY - page += F("Enabled"); - 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("
 
ESP Chip id"); page += String(ESP.getChipId()); page += F("
Flash Chip id"); page += String(ESP.getFlashChipId()); page += F("
Flash size"); page += String(ESP.getFlashChipRealSize() / 1024); page += F("kB
Program flash size"); page += String(ESP.getFlashChipSize() / 1024); page += F("kB
Program size"); page += String(ESP.getSketchSize() / 1024); page += F("kB
Free program space"); page += String(ESP.getFreeSketchSpace() / 1024); page += F("kB
Free memory"); page += String(freeMem / 1024); page += F("kB
"); -// 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