2017-01-28 13:41:01 +00:00
/*
Copyright ( c ) 2017 Theo Arends . All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
- Redistributions of source code must retain the above copyright notice ,
this list of conditions and the following disclaimer .
- Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE .
*/
# ifdef USE_WEBSERVER
/*********************************************************************************************\
* Web server and WiFi Manager
*
* Enables configuration and reconfiguration of WiFi credentials using a Captive Portal
* Source by AlexT ( https : //github.com/tzapu)
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define STR_HELPER(x) #x
# define STR(x) STR_HELPER(x)
const char HTTP_HEAD [ ] PROGMEM =
" <!DOCTYPE html><html lang= \" en \" class= \" \" > "
" <head> "
" <meta charset='utf-8'> "
" <meta name= \" viewport \" content= \" width=device-width,initial-scale=1,user-scalable=no \" /> "
" <title>{v}</title> "
2017-03-08 15:20:45 +00:00
2017-01-28 13:41:01 +00:00
" <script> "
2017-03-08 15:20:45 +00:00
" var cn,x,lt; "
" cn=120; "
" x=null; " // Allow for abortion
2017-01-28 13:41:01 +00:00
" function u(){ "
" if(cn>=0){ "
" document.getElementById('t').innerHTML='Restart in '+cn+' seconds'; "
" cn--; "
" setTimeout(u,1000); "
" } "
" } "
" function c(l){ "
" document.getElementById('s1').value=l.innerText||l.textContent; "
" document.getElementById('p1').focus(); "
" } "
2017-02-24 17:17:48 +00:00
" function la(p){ "
" var a=''; "
" if(la.arguments.length==1){ "
2017-03-08 15:20:45 +00:00
" a=p; "
2017-02-24 17:17:48 +00:00
" clearTimeout(lt); "
" } "
" 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){ "
" document.getElementById('l1').innerHTML=x.responseText; "
" } "
" }; "
" x.open('GET','ay'+a,true); "
" x.send(); "
2017-02-28 15:01:48 +00:00
" lt=setTimeout(la,2345); "
2017-02-24 17:17:48 +00:00
" } "
2017-03-08 15:20:45 +00:00
" function lb(p){ "
" la('?d='+p); "
" } "
" </script> "
" <style> "
" div,fieldset,input,select{padding:5px;font-size:1em;} "
" input{width:95%;} "
" select{width:100%;} "
" textarea{resize:none;width:98%;height:318px;padding:5px;overflow:auto;} "
" body{text-align:center;font-family:verdana;} "
" td{padding:0px;} "
" button{border:0;border-radius:0.3rem;background-color:#1fa3ec;color:#fff;line-height:2.4rem;font-size:1.2rem;width:100%;-webkit-transition-duration:0.4s;transition-duration:0.4s;} "
" button:hover{background-color:#006cba;} "
" </style> "
" </head> "
" <body> "
" <div style='text-align:left;display:inline-block;min-width:320px;'> "
" <div style='text-align:center;'><h3>{ha} Module</h3><h2>{h}</h2></div> " ;
const char HTTP_SCRIPT_CONSOL [ ] PROGMEM =
2017-02-24 17:17:48 +00:00
" var sn=0; " // Scroll position
" var id=99; " // Get most of weblog initially
2017-02-28 15:01:48 +00:00
" 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='+c.value; "
" c.value=''; "
" t.scrollTop=sn; "
" } "
" if(t.scrollTop>=sn){ " // User scrolled back so no updates
2017-02-24 17:17:48 +00:00
" if(x!=null){x.abort();} " // Abort if no response within 2 seconds (happens on restart 1)
" x=new XMLHttpRequest(); "
2017-01-28 13:41:01 +00:00
" x.onreadystatechange=function(){ "
" if(x.readyState==4&&x.status==200){ "
2017-02-24 17:17:48 +00:00
" var z,d; "
" d=x.responseXML; "
" id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue; "
2017-02-28 15:01:48 +00:00
" if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){t.value='';} "
2017-02-24 17:17:48 +00:00
" z=d.getElementsByTagName('l')[0].childNodes; "
2017-02-28 15:01:48 +00:00
" if(z.length>0){t.value+=z[0].nodeValue;} "
" t.scrollTop=99999; "
" sn=t.scrollTop; "
2017-01-28 13:41:01 +00:00
" } "
" }; "
2017-02-28 15:01:48 +00:00
" x.open('GET','ax?c2='+id+o,true); "
2017-01-28 13:41:01 +00:00
" x.send(); "
" } "
2017-02-28 15:01:48 +00:00
" lt=setTimeout(l,2345); "
2017-02-24 17:17:48 +00:00
" return false; "
" } "
2017-03-08 15:20:45 +00:00
" </script> " ;
const char HTTP_LNK_STYLE [ ] PROGMEM =
2017-01-28 13:41:01 +00:00
" .q{float:right;width:64px;text-align:right;} "
" .l{background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAALVBMVEX///8EBwfBwsLw8PAzNjaCg4NTVVUjJiZDRUUUFxdiZGSho6O "
" Sk5Pg4eFydHTCjaf3AAAAZElEQVQ4je2NSw7AIAhEBamKn97/uMXEGBvozkWb9C2Zx4xzWykBhFAeYp9gkLyZE0zIMno9n4g19hmdY39scwqVkOXaxph0ZCXQcqxSpgQpONa59wkRDOL93eA "
" XvimwlbPbwwVAegLS1HGfZAAAAABJRU5ErkJggg==') no-repeat left center;background-size:1em;} "
2017-03-08 15:20:45 +00:00
" </style> " ;
2017-01-28 13:41:01 +00:00
const char HTTP_MSG_RSTRT [ ] PROGMEM =
" <br/><div style='text-align:center;'>Device will restart in a few seconds</div><br/> " ;
const char HTTP_BTN_MENU1 [ ] PROGMEM =
" <br/><form action='/cn' method='post'><button>Configuration</button></form> "
" <br/><form action='/in' method='post'><button>Information</button></form> "
" <br/><form action='/up' method='post'><button>Firmware upgrade</button></form> "
" <br/><form action='/cs' method='post'><button>Console</button></form> " ;
const char HTTP_BTN_RSTRT [ ] PROGMEM =
" <br/><form action='/rb' method='post' onsubmit='return confirm( \" Confirm Restart \" );'><button>Restart</button></form> " ;
const char HTTP_BTN_MENU2 [ ] PROGMEM =
" <br/><form action='/md' method='post'><button>Configure Module</button></form> "
" <br/><form action='/w0' method='post'><button>Configure WiFi</button></form> " ;
const char HTTP_BTN_MENU3 [ ] PROGMEM =
" <br/><form action='/mq' method='post'><button>Configure MQTT</button></form> "
# ifdef USE_DOMOTICZ
" <br/><form action='/dm' method='post'><button>Configure Domoticz</button></form> "
# endif // USE_DOMOTICZ
" " ;
const char HTTP_BTN_MENU4 [ ] PROGMEM =
" <br/><form action='/lg' method='post'><button>Configure Logging</button></form> "
" <br/><form action='/co' method='post'><button>Configure Other</button></form> "
2017-02-10 16:03:34 +00:00
" <br/><form action='/rt' method='post' onsubmit='return confirm( \" Confirm Reset Configuration \" );'><button>Reset Configuration</button></form> "
" <br/><form action='/dl' method='post'><button>Backup Configuration</button></form> "
" <br/><form action='/rs' method='post'><button>Restore Configuration</button></form> " ;
2017-01-28 13:41:01 +00:00
const char HTTP_BTN_MAIN [ ] PROGMEM =
" <br/><br/><form action='/' method='post'><button>Main menu</button></form> " ;
const char HTTP_BTN_CONF [ ] PROGMEM =
" <br/><br/><form action='/cn' method='post'><button>Configuration menu</button></form> " ;
const char HTTP_FORM_MODULE [ ] PROGMEM =
" <fieldset><legend><b> Module parameters </b></legend><form method='post' action='sv'> "
" <input id='w' name='w' value='6' hidden><input id='r' name='r' value='1' hidden> "
" <br/><b>Module type</b> ({mt})<br/><select id='mt' name='mt'> " ;
const char HTTP_LNK_ITEM [ ] PROGMEM =
" <div><a href='#p' onclick='c(this)'>{v}</a> <span class='q {i}'>{r}%</span></div> " ;
const char HTTP_LNK_SCAN [ ] PROGMEM =
" <div><a href='/w1'>Scan for wifi networks</a></div><br/> " ;
const char HTTP_FORM_WIFI [ ] PROGMEM =
" <fieldset><legend><b> Wifi parameters </b></legend><form method='post' action='sv'> "
" <input id='w' name='w' value='1' hidden><input id='r' name='r' value='1' hidden> "
" <br/><b>AP1 SSId</b> ( " STA_SSID1 " )<br/><input id='s1' name='s1' length=32 placeholder=' " STA_SSID1 " ' value='{s1}'><br/> "
" <br/><b>AP1 Password</b></br><input id='p1' name='p1' length=64 type='password' placeholder=' " STA_PASS1 " ' value='{p1}'><br/> "
" <br/><b>AP2 SSId</b> ( " STA_SSID2 " )<br/><input id='s2' name='s2' length=32 placeholder=' " STA_SSID2 " ' value='{s2}'><br/> "
" <br/><b>AP2 Password</b></br><input id='p2' name='p2' length=64 type='password' placeholder=' " STA_PASS2 " ' value='{p2}'><br/> "
2017-02-08 11:56:51 +00:00
" <br/><b>Hostname</b> ( " WIFI_HOSTNAME " )<br/><input id='h' name='h' length=32 placeholder=' " WIFI_HOSTNAME " ' value='{h1}'><br/> " ;
2017-01-28 13:41:01 +00:00
const char HTTP_FORM_MQTT [ ] PROGMEM =
" <fieldset><legend><b> MQTT parameters </b></legend><form method='post' action='sv'> "
" <input id='w' name='w' value='2' hidden><input id='r' name='r' value='1' hidden> "
" <br/><b>Host</b> ( " MQTT_HOST " )<br/><input id='mh' name='mh' length=32 placeholder=' " MQTT_HOST " ' value='{m1}'><br/> "
" <br/><b>Port</b> ( " STR ( MQTT_PORT ) " )<br/><input id='ml' name='ml' length=5 placeholder=' " STR ( MQTT_PORT ) " ' value='{m2}'><br/> "
" <br/><b>Client Id</b> ({m0})<br/><input id='mc' name='mc' length=32 placeholder=' " MQTT_CLIENT_ID " ' value='{m3}'><br/> "
" <br/><b>User</b> ( " MQTT_USER " )<br/><input id='mu' name='mu' length=32 placeholder=' " MQTT_USER " ' value='{m4}'><br/> "
" <br/><b>Password</b><br/><input id='mp' name='mp' length=32 type='password' placeholder=' " MQTT_PASS " ' value='{m5}'><br/> "
" <br/><b>Topic</b> ( " MQTT_TOPIC " )<br/><input id='mt' name='mt' length=32 placeholder=' " MQTT_TOPIC " ' value='{m6}'><br/> " ;
const char HTTP_FORM_LOG1 [ ] PROGMEM =
" <fieldset><legend><b> Logging parameters </b></legend><form method='post' action='sv'> "
" <input id='w' name='w' value='3' hidden><input id='r' name='r' value='0' hidden> " ;
const char HTTP_FORM_LOG2 [ ] PROGMEM =
2017-03-03 11:35:23 +00:00
" <br/><b>{b0}log level</b> ({b1})<br/><select id='{b2}' name='{b2}'> "
2017-01-28 13:41:01 +00:00
" <option{a0value='0'>0 None</option> "
" <option{a1value='1'>1 Error</option> "
" <option{a2value='2'>2 Info</option> "
" <option{a3value='3'>3 Debug</option> "
" <option{a4value='4'>4 More debug</option> "
" </select></br> " ;
const char HTTP_FORM_LOG3 [ ] PROGMEM =
" <br/><b>Syslog host</b> ( " SYS_LOG_HOST " )<br/><input id='lh' name='lh' length=32 placeholder=' " SYS_LOG_HOST " ' value='{l2}'><br/> "
" <br/><b>Syslog port</b> ( " STR ( SYS_LOG_PORT ) " )<br/><input id='lp' name='lp' length=5 placeholder=' " STR ( SYS_LOG_PORT ) " ' value='{l3}'><br/> "
" <br/><b>Telemetric period</b> ( " STR ( TELE_PERIOD ) " )<br/><input id='lt' name='lt' length=4 placeholder=' " STR ( TELE_PERIOD ) " ' value='{l4}'><br/> " ;
const char HTTP_FORM_OTHER [ ] PROGMEM =
" <fieldset><legend><b> Other parameters </b></legend><form method='post' action='sv'> "
" <input id='w' name='w' value='5' hidden><input id='r' name='r' value='1' hidden> "
2017-02-21 17:14:33 +00:00
" <br/><b>Web Admin Password</b><br/><input id='p1' name='p1' length=32 type='password' placeholder=' " WEB_PASSWORD " ' value='{p1}'><br/> "
2017-01-29 20:36:12 +00:00
" <br/><input style='width:10%;float:left' id='b1' name='b1' type='checkbox'{r1}><b>MQTT enable</b><br/> " ;
const char HTTP_FORM_OTHER2 [ ] PROGMEM =
" <br/><b>Friendly Name {1</b> ({2)<br/><input id='a{1' name='a{1' length=32 placeholder='{2' value='{3'><br/> " ;
# ifdef USE_EMULATION
const char HTTP_FORM_OTHER3 [ ] PROGMEM =
" <br/><fieldset><legend><b> Emulation </b></legend> "
2017-02-04 16:09:54 +00:00
" <br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='0'{r2}><b>None</b> "
" <br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='1'{r3}><b>Belkin WeMo</b> "
2017-01-29 20:36:12 +00:00
" <br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='2'{r4}><b>Hue Bridge</b><br/> " ;
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
const char HTTP_FORM_END [ ] PROGMEM =
" <br/><button type='submit'>Save</button></form></fieldset> " ;
2017-02-10 16:03:34 +00:00
const char HTTP_FORM_RST [ ] PROGMEM =
" <div id='f1' name='f1' style='display:block;'> "
" <fieldset><legend><b> Restore configuration </b></legend> "
" <form method='post' action='u2' enctype='multipart/form-data'> "
" <br/><input type='file' name='u2'><br/> "
" <br/><button type='submit' onclick='document.getElementById( \" f1 \" ).style.display= \" none \" ;document.getElementById( \" f2 \" ).style.display= \" block \" ;this.form.submit();'>Start restore</button></form> "
" </fieldset> "
" </div> "
" <div id='f2' name='f2' style='display:none;text-align:center;'><b>Restore started ...</b></div> " ;
2017-01-28 13:41:01 +00:00
const char HTTP_FORM_UPG [ ] PROGMEM =
" <div id='f1' name='f1' style='display:block;'> "
" <fieldset><legend><b> Upgrade by web server </b></legend> "
" <form method='post' action='u1'> "
" <br/>OTA Url<br/><input id='o' name='o' length=80 placeholder='OTA_URL' value='{o1}'><br/> "
" <br/><button type='submit'>Start upgrade</button></form> "
" </fieldset><br/><br/> "
" <fieldset><legend><b> Upgrade by file upload </b></legend> "
" <form method='post' action='u2' enctype='multipart/form-data'> "
" <br/><input type='file' name='u2'><br/> "
// "<br/><button type='submit' onclick='this.disabled=true;this.form.submit();'>Start upgrade</button></form></fieldset>"
" <br/><button type='submit' onclick='document.getElementById( \" f1 \" ).style.display= \" none \" ;document.getElementById( \" f2 \" ).style.display= \" block \" ;this.form.submit();'>Start upgrade</button></form> "
" </fieldset> "
" </div> "
" <div id='f2' name='f2' style='display:none;text-align:center;'><b>Upload started ...</b></div> " ;
const char HTTP_FORM_CMND [ ] PROGMEM =
2017-02-17 16:18:41 +00:00
" <br/><textarea readonly id='t1' name='t1' cols='99' wrap='off'></textarea><br/><br/> "
2017-02-28 15:01:48 +00:00
" <form method='get' onsubmit='return l(1);'> "
2017-02-17 16:18:41 +00:00
" <input style='width:98%' id='c1' name='c1' length='99' placeholder='Enter command' autofocus><br/> "
2017-01-28 13:41:01 +00:00
// "<br/><button type='submit'>Send command</button>"
" </form> " ;
const char HTTP_COUNTER [ ] PROGMEM =
" <br/><div id='t' name='t' style='text-align:center;'></div> " ;
2017-02-28 15:01:48 +00:00
const char HTTP_SNS_TEMP [ ] PROGMEM =
" <tr><th>%s Temperature</th><td>%s°%c</td></tr> " ;
const char HTTP_SNS_HUM [ ] PROGMEM =
" <tr><th>%s Humidity</th><td>%s%</td></tr> " ;
const char HTTP_SNS_PRESSURE [ ] PROGMEM =
" <tr><th>%s Pressure</th><td>%s hPa</td></tr> " ;
2017-01-28 13:41:01 +00:00
const char HTTP_END [ ] PROGMEM =
" </div> "
" </body> "
" </html> " ;
# define DNS_PORT 53
enum http_t { HTTP_OFF , HTTP_USER , HTTP_ADMIN , HTTP_MANAGER } ;
DNSServer * dnsServer ;
ESP8266WebServer * webServer ;
boolean _removeDuplicateAPs = true ;
2017-02-10 16:03:34 +00:00
int _minimumQuality = - 1 ;
uint8_t _httpflag = HTTP_OFF , _uploaderror = 0 , _uploadfiletype , _colcount ;
2017-01-28 13:41:01 +00:00
void startWebserver ( int type , IPAddress ipweb )
{
char log [ LOGSZ ] ;
if ( ! _httpflag ) {
if ( ! webServer ) {
webServer = new ESP8266WebServer ( 80 ) ;
webServer - > on ( " / " , handleRoot ) ;
webServer - > on ( " /cn " , handleConfig ) ;
webServer - > on ( " /md " , handleModule ) ;
webServer - > on ( " /w1 " , handleWifi1 ) ;
webServer - > on ( " /w0 " , handleWifi0 ) ;
if ( sysCfg . mqtt_enabled ) {
webServer - > on ( " /mq " , handleMqtt ) ;
# ifdef USE_DOMOTICZ
webServer - > on ( " /dm " , handleDomoticz ) ;
# endif // USE_DOMOTICZ
}
webServer - > on ( " /lg " , handleLog ) ;
webServer - > on ( " /co " , handleOther ) ;
2017-02-10 16:03:34 +00:00
webServer - > on ( " /dl " , handleDownload ) ;
2017-01-28 13:41:01 +00:00
webServer - > on ( " /sv " , handleSave ) ;
2017-02-10 16:03:34 +00:00
webServer - > on ( " /rs " , handleRestore ) ;
2017-01-28 13:41:01 +00:00
webServer - > on ( " /rt " , handleReset ) ;
webServer - > on ( " /up " , handleUpgrade ) ;
2017-02-10 16:03:34 +00:00
webServer - > on ( " /u1 " , handleUpgradeStart ) ; // OTA
2017-01-28 13:41:01 +00:00
webServer - > on ( " /u2 " , HTTP_POST , handleUploadDone , handleUploadLoop ) ;
webServer - > on ( " /cm " , handleCmnd ) ;
webServer - > on ( " /cs " , handleConsole ) ;
webServer - > on ( " /ax " , handleAjax ) ;
2017-02-24 17:17:48 +00:00
webServer - > on ( " /ay " , handleAjax2 ) ;
2017-01-28 13:41:01 +00:00
webServer - > on ( " /in " , handleInfo ) ;
webServer - > on ( " /rb " , handleRestart ) ;
webServer - > on ( " /fwlink " , handleRoot ) ; // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
if ( sysCfg . emulation = = EMUL_WEMO ) {
webServer - > on ( " /upnp/control/basicevent1 " , HTTP_POST , handleUPnPevent ) ;
webServer - > on ( " /eventservice.xml " , handleUPnPservice ) ;
webServer - > on ( " /setup.xml " , handleUPnPsetupWemo ) ;
}
2017-02-21 17:14:33 +00:00
if ( sysCfg . emulation = = EMUL_HUE ) {
webServer - > on ( " /description.xml " , handleUPnPsetupHue ) ;
}
2017-01-29 20:36:12 +00:00
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
webServer - > onNotFound ( handleNotFound ) ;
}
2017-02-24 17:17:48 +00:00
logajaxflg = 0 ;
2017-01-28 13:41:01 +00:00
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 ( ( WiFi . status ( ) = = WL_CONNECTED ) & & ( static_cast < uint32_t > ( 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 showPage ( String & page )
{
2017-02-21 17:14:33 +00:00
if ( ( _httpflag = = HTTP_ADMIN ) & & ( sysCfg . web_password [ 0 ] ! = 0 ) & & ! webServer - > authenticate ( WEB_USERNAME , sysCfg . web_password ) ) {
return webServer - > requestAuthentication ( ) ;
}
2017-01-28 13:41:01 +00:00
page . replace ( " {ha} " , my_module . name ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {h} " , sysCfg . friendlyname [ 0 ] ) ;
2017-01-28 13:41:01 +00:00
if ( _httpflag = = HTTP_MANAGER ) {
if ( WIFI_configCounter ( ) ) {
page . replace ( " <body> " , " <body onload='u()'> " ) ;
page + = FPSTR ( HTTP_COUNTER ) ;
}
}
page + = FPSTR ( HTTP_END ) ;
webServer - > sendHeader ( " Cache-Control " , " no-cache, no-store, must-revalidate " ) ;
webServer - > sendHeader ( " Pragma " , " no-cache " ) ;
webServer - > sendHeader ( " Expires " , " -1 " ) ;
webServer - > send ( 200 , " text/html " , page ) ;
}
void handleRoot ( )
{
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle root " ) ) ;
if ( captivePortal ( ) ) { // If captive portal redirect instead of displaying the page.
return ;
}
if ( _httpflag = = HTTP_MANAGER ) {
handleWifi0 ( ) ;
} else {
2017-03-03 11:35:23 +00:00
char stemp [ 10 ] , line [ 100 ] ;
2017-01-28 13:41:01 +00:00
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Main menu " ) ;
2017-02-24 17:17:48 +00:00
page . replace ( " <body> " , " <body onload='la()'> " ) ;
2017-01-28 13:41:01 +00:00
2017-02-24 17:17:48 +00:00
page + = F ( " <div id='l1' name='l1'></div> " ) ;
2017-01-28 13:41:01 +00:00
if ( Maxdevice ) {
2017-03-08 15:20:45 +00:00
if ( sysCfg . module = = SONOFF_LED ) {
snprintf_P ( line , sizeof ( line ) , PSTR ( " <input type='range' min='1' max='100' value='%d' onchange='lb(value)'> " ) ,
sysCfg . led_dimmer [ 0 ] ) ;
page + = line ;
}
2017-01-28 13:41:01 +00:00
page + = F ( " <table style='width:100%'><tr> " ) ;
for ( byte idx = 1 ; idx < = Maxdevice ; idx + + ) {
2017-03-03 11:35:23 +00:00
snprintf_P ( stemp , sizeof ( stemp ) , PSTR ( " %d " ) , idx ) ;
2017-03-08 15:20:45 +00:00
snprintf_P ( line , sizeof ( line ) , PSTR ( " <td style='width:%d%'><button onclick='la( \" ?o=%d \" );'>Toggle%s</button></td> " ) ,
2017-03-03 11:35:23 +00:00
100 / Maxdevice , idx , ( Maxdevice > 1 ) ? stemp : " " ) ;
page + = line ;
2017-01-28 13:41:01 +00:00
}
2017-02-24 17:17:48 +00:00
page + = F ( " </tr></table> " ) ;
2017-01-28 13:41:01 +00:00
}
2017-02-24 17:17:48 +00:00
2017-01-28 13:41:01 +00:00
if ( _httpflag = = HTTP_ADMIN ) {
page + = FPSTR ( HTTP_BTN_MENU1 ) ;
page + = FPSTR ( HTTP_BTN_RSTRT ) ;
}
showPage ( page ) ;
2017-02-24 17:17:48 +00:00
}
}
2017-01-28 13:41:01 +00:00
2017-02-24 17:17:48 +00:00
void handleAjax2 ( )
{
2017-03-08 15:20:45 +00:00
char svalue [ 16 ] ;
2017-02-24 17:17:48 +00:00
if ( strlen ( webServer - > arg ( " o " ) . c_str ( ) ) ) do_cmnd_power ( atoi ( webServer - > arg ( " o " ) . c_str ( ) ) , 2 ) ;
2017-03-08 15:20:45 +00:00
if ( strlen ( webServer - > arg ( " d " ) . c_str ( ) ) ) {
snprintf_P ( svalue , sizeof ( svalue ) , PSTR ( " dimmer %s " ) , webServer - > arg ( " d " ) . c_str ( ) ) ;
do_cmnd ( svalue ) ;
}
2017-02-24 17:17:48 +00:00
String tpage = " " ;
if ( hlw_flg ) tpage + = hlw_webPresent ( ) ;
# ifdef USE_DS18B20
if ( pin [ GPIO_DSB ] < 99 ) tpage + = dsb_webPresent ( ) ;
# endif // USE_DS18B20
2017-01-28 13:41:01 +00:00
# ifdef USE_DS18x20
2017-03-05 14:07:30 +00:00
if ( pin [ GPIO_DSB ] < 99 ) tpage + = ds18x20_webPresent ( ) ;
2017-01-28 13:41:01 +00:00
# endif // USE_DS18x20
2017-02-24 17:17:48 +00:00
# ifdef USE_DHT
if ( dht_type ) tpage + = dht_webPresent ( ) ;
# endif // USE_DHT
# ifdef USE_I2C
if ( i2c_flg ) {
tpage + = htu_webPresent ( ) ;
tpage + = bmp_webPresent ( ) ;
tpage + = bh1750_webPresent ( ) ;
}
# endif // USE_I2C
String page = " " ;
if ( tpage . length ( ) > 0 ) {
page + = F ( " <table style='width:100%'> " ) ;
page + = tpage ;
page + = F ( " </table> " ) ;
}
2017-03-03 11:35:23 +00:00
char line [ 120 ] ;
2017-02-24 17:17:48 +00:00
if ( Maxdevice ) {
page + = F ( " <table style='width:100%'><tr> " ) ;
for ( byte idx = 1 ; idx < = Maxdevice ; idx + + ) {
2017-03-03 11:35:23 +00:00
snprintf_P ( line , sizeof ( line ) , PSTR ( " <td style='width:%d%'><div style='text-align:center;font-weight:bold;font-size:%dpx'>%s</div></td> " ) ,
100 / Maxdevice , 70 - ( Maxdevice * 8 ) , ( power & ( 0x01 < < ( idx - 1 ) ) ) ? " ON " : " OFF " ) ;
page + = line ;
2017-02-24 17:17:48 +00:00
}
page + = F ( " </tr></table> " ) ;
2017-01-28 13:41:01 +00:00
}
2017-03-08 15:20:45 +00:00
/*
* Will interrupt user action when selected
if ( sysCfg . module = = SONOFF_LED ) {
snprintf_P ( line , sizeof ( line ) , PSTR ( " <input type='range' min='1' max='100' value='%d' onchange='lb(value)'> " ) ,
sysCfg . led_dimmer [ 0 ] ) ;
page + = line ;
}
*/
2017-02-24 17:17:48 +00:00
webServer - > sendHeader ( " Cache-Control " , " no-cache, no-store, must-revalidate " ) ;
webServer - > sendHeader ( " Pragma " , " no-cache " ) ;
webServer - > sendHeader ( " Expires " , " -1 " ) ;
webServer - > send ( 200 , " text/plain " , page ) ;
2017-01-28 13:41:01 +00:00
}
2017-02-10 16:03:34 +00:00
boolean httpUser ( )
{
boolean status = ( _httpflag = = HTTP_USER ) ;
if ( status ) handleRoot ( ) ;
return status ;
}
2017-01-28 13:41:01 +00:00
void handleConfig ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle config " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Configuration " ) ;
page + = FPSTR ( HTTP_BTN_MENU2 ) ;
2017-03-08 15:20:45 +00:00
if ( sysCfg . mqtt_enabled ) page + = FPSTR ( HTTP_BTN_MENU3 ) ;
2017-01-28 13:41:01 +00:00
page + = FPSTR ( HTTP_BTN_MENU4 ) ;
page + = FPSTR ( HTTP_BTN_MAIN ) ;
showPage ( page ) ;
}
void handleModule ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-03-03 11:35:23 +00:00
char stemp [ 20 ] , line [ 128 ] ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle Module config " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Config module " ) ;
page + = FPSTR ( HTTP_FORM_MODULE ) ;
snprintf_P ( stemp , sizeof ( stemp ) , modules [ MODULE ] . name ) ;
page . replace ( " {mt} " , stemp ) ;
2017-03-03 11:35:23 +00:00
for ( byte i = 0 ; i < MAXMODULE ; i + + ) {
2017-01-28 13:41:01 +00:00
snprintf_P ( stemp , sizeof ( stemp ) , modules [ i ] . name ) ;
2017-03-03 11:35:23 +00:00
snprintf_P ( line , sizeof ( line ) , PSTR ( " <option%s value='%d'>%d %s</option> " ) ,
( i = = sysCfg . module ) ? " selected " : " " , i , i + 1 , stemp ) ;
page + = line ;
2017-01-28 13:41:01 +00:00
}
page + = F ( " </select></br> " ) ;
mytmplt cmodule ;
memcpy_P ( & cmodule , & modules [ sysCfg . module ] , sizeof ( cmodule ) ) ;
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
if ( cmodule . gp . io [ i ] = = GPIO_USER ) {
2017-03-03 11:35:23 +00:00
snprintf_P ( line , sizeof ( line ) , PSTR ( " <br/><b>GPIO%d</b><select id='g%d' name='g%d'> " ) , i , i , i ) ;
page + = line ;
2017-02-11 14:06:23 +00:00
for ( byte j = 0 ; j < GPIO_SENSOR_END ; j + + ) {
2017-01-28 13:41:01 +00:00
snprintf_P ( stemp , sizeof ( stemp ) , sensors [ j ] ) ;
2017-03-03 11:35:23 +00:00
snprintf_P ( line , sizeof ( line ) , PSTR ( " <option%s value='%d'>%d %s</option> " ) ,
( j = = my_module . gp . io [ i ] ) ? " selected " : " " , j , j , stemp ) ;
page + = line ;
2017-01-28 13:41:01 +00:00
}
page + = F ( " </select></br> " ) ;
}
}
page + = FPSTR ( HTTP_FORM_END ) ;
page + = FPSTR ( HTTP_BTN_CONF ) ;
showPage ( page ) ;
}
void handleWifi1 ( )
{
handleWifi ( true ) ;
}
void handleWifi0 ( )
{
handleWifi ( false ) ;
}
void handleWifi ( boolean scan )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
char log [ LOGSZ ] ;
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle Wifi config " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Configure Wifi " ) ;
2017-03-08 15:20:45 +00:00
page . replace ( " </style> " , FPSTR ( HTTP_LNK_STYLE ) ) ;
2017-01-28 13:41:01 +00:00
if ( scan ) {
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
2017-01-28 13:41:01 +00:00
UDP_Disconnect ( ) ;
2017-01-29 20:36:12 +00:00
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
int n = WiFi . scanNetworks ( ) ;
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " Wifi: Scan done " ) ) ;
if ( n = = 0 ) {
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " Wifi: No networks found " ) ) ;
page + = F ( " No networks found. Refresh to scan again. " ) ;
} else {
//sort networks
int indices [ n ] ;
for ( int i = 0 ; i < n ; i + + ) {
indices [ i ] = i ;
}
// RSSI SORT
for ( int i = 0 ; i < n ; i + + ) {
for ( int j = i + 1 ; j < n ; j + + ) {
if ( WiFi . RSSI ( indices [ j ] ) > WiFi . RSSI ( indices [ i ] ) ) {
std : : swap ( indices [ i ] , indices [ j ] ) ;
}
}
}
// remove duplicates ( must be RSSI sorted )
if ( _removeDuplicateAPs ) {
String cssid ;
for ( int i = 0 ; i < n ; i + + ) {
if ( indices [ i ] = = - 1 ) continue ;
cssid = WiFi . SSID ( indices [ i ] ) ;
for ( int j = i + 1 ; j < n ; j + + ) {
if ( cssid = = WiFi . SSID ( indices [ j ] ) ) {
snprintf_P ( log , sizeof ( log ) , PSTR ( " Wifi: Duplicate AccessPoint %s " ) , WiFi . SSID ( indices [ j ] ) . c_str ( ) ) ;
addLog ( LOG_LEVEL_DEBUG , log ) ;
indices [ j ] = - 1 ; // set dup aps to index -1
}
}
}
}
//display networks in page
for ( int i = 0 ; i < n ; i + + ) {
if ( indices [ i ] = = - 1 ) continue ; // skip dups
snprintf_P ( log , sizeof ( log ) , PSTR ( " Wifi: SSID %s, RSSI %d " ) , WiFi . SSID ( indices [ i ] ) . c_str ( ) , WiFi . RSSI ( indices [ i ] ) ) ;
addLog ( LOG_LEVEL_DEBUG , log ) ;
int quality = WIFI_getRSSIasQuality ( WiFi . RSSI ( indices [ i ] ) ) ;
if ( _minimumQuality = = - 1 | | _minimumQuality < quality ) {
String item = FPSTR ( HTTP_LNK_ITEM ) ;
String rssiQ ;
rssiQ + = quality ;
item . replace ( " {v} " , WiFi . SSID ( indices [ i ] ) ) ;
item . replace ( " {r} " , rssiQ ) ;
if ( WiFi . encryptionType ( indices [ i ] ) ! = ENC_TYPE_NONE ) {
item . replace ( " {i} " , " l " ) ;
} else {
item . replace ( " {i} " , " " ) ;
}
page + = item ;
delay ( 0 ) ;
} else {
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " Wifi: Skipping due to low quality " ) ) ;
}
}
page + = " <br/> " ;
}
} else {
page + = FPSTR ( HTTP_LNK_SCAN ) ;
}
page + = FPSTR ( HTTP_FORM_WIFI ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {h1} " , sysCfg . hostname ) ;
page . replace ( " {s1} " , sysCfg . sta_ssid [ 0 ] ) ;
page . replace ( " {p1} " , sysCfg . sta_pwd [ 0 ] ) ;
page . replace ( " {s2} " , sysCfg . sta_ssid [ 1 ] ) ;
page . replace ( " {p2} " , sysCfg . sta_pwd [ 1 ] ) ;
2017-01-28 13:41:01 +00:00
page + = FPSTR ( HTTP_FORM_END ) ;
if ( _httpflag = = HTTP_MANAGER ) {
page + = FPSTR ( HTTP_BTN_RSTRT ) ;
} else {
page + = FPSTR ( HTTP_BTN_CONF ) ;
}
showPage ( page ) ;
}
void handleMqtt ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle MQTT config " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Configure MQTT " ) ;
page + = FPSTR ( HTTP_FORM_MQTT ) ;
char str [ sizeof ( sysCfg . mqtt_client ) ] ;
getClient ( str , MQTT_CLIENT_ID , sizeof ( sysCfg . mqtt_client ) ) ;
page . replace ( " {m0} " , str ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {m1} " , sysCfg . mqtt_host ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {m2} " , String ( sysCfg . mqtt_port ) ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {m3} " , sysCfg . mqtt_client ) ;
page . replace ( " {m4} " , sysCfg . mqtt_user ) ;
page . replace ( " {m5} " , sysCfg . mqtt_pwd ) ;
page . replace ( " {m6} " , sysCfg . mqtt_topic ) ;
2017-01-28 13:41:01 +00:00
page + = FPSTR ( HTTP_FORM_END ) ;
page + = FPSTR ( HTTP_BTN_CONF ) ;
showPage ( page ) ;
}
void handleLog ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle Log config " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Config logging " ) ;
page + = FPSTR ( HTTP_FORM_LOG1 ) ;
for ( byte idx = 0 ; idx < 3 ; idx + + ) {
page + = FPSTR ( HTTP_FORM_LOG2 ) ;
switch ( idx ) {
case 0 :
2017-03-03 11:35:23 +00:00
page . replace ( " {b0} " , F ( " Serial " ) ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {b1} " , STR ( SERIAL_LOG_LEVEL ) ) ;
page . replace ( " {b2} " , " ls " ) ;
for ( byte i = LOG_LEVEL_NONE ; i < LOG_LEVEL_ALL ; i + + ) {
page . replace ( " {a " + String ( i ) , ( i = = sysCfg . seriallog_level ) ? " selected " : " " ) ;
}
break ;
case 1 :
2017-03-03 11:35:23 +00:00
page . replace ( " {b0} " , F ( " Web " ) ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {b1} " , STR ( WEB_LOG_LEVEL ) ) ;
page . replace ( " {b2} " , " lw " ) ;
for ( byte i = LOG_LEVEL_NONE ; i < LOG_LEVEL_ALL ; i + + ) {
page . replace ( " {a " + String ( i ) , ( i = = sysCfg . weblog_level ) ? " selected " : " " ) ;
}
break ;
case 2 :
2017-03-03 11:35:23 +00:00
page . replace ( " {b0} " , F ( " Sys " ) ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {b1} " , STR ( SYS_LOG_LEVEL ) ) ;
page . replace ( " {b2} " , " ll " ) ;
for ( byte i = LOG_LEVEL_NONE ; i < LOG_LEVEL_ALL ; i + + ) {
page . replace ( " {a " + String ( i ) , ( i = = sysCfg . syslog_level ) ? " selected " : " " ) ;
}
break ;
}
}
page + = FPSTR ( HTTP_FORM_LOG3 ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {l2} " , sysCfg . syslog_host ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {l3} " , String ( sysCfg . syslog_port ) ) ;
page . replace ( " {l4} " , String ( sysCfg . tele_period ) ) ;
page + = FPSTR ( HTTP_FORM_END ) ;
page + = FPSTR ( HTTP_BTN_CONF ) ;
showPage ( page ) ;
}
void handleOther ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle other config " ) ) ;
2017-01-29 20:36:12 +00:00
char stemp [ 40 ] ;
2017-01-28 13:41:01 +00:00
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Configure Other " ) ;
page + = FPSTR ( HTTP_FORM_OTHER ) ;
2017-02-21 17:14:33 +00:00
page . replace ( " {p1} " , sysCfg . web_password ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {r1} " , ( sysCfg . mqtt_enabled ) ? " checked " : " " ) ;
2017-01-29 20:36:12 +00:00
page + = FPSTR ( HTTP_FORM_OTHER2 ) ;
page . replace ( " {1 " , " 1 " ) ;
page . replace ( " {2 " , FRIENDLY_NAME ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {3 " , sysCfg . friendlyname [ 0 ] ) ;
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
page + = FPSTR ( HTTP_FORM_OTHER3 ) ;
page . replace ( " {r2} " , ( sysCfg . emulation = = EMUL_NONE ) ? " checked " : " " ) ;
page . replace ( " {r3} " , ( sysCfg . emulation = = EMUL_WEMO ) ? " checked " : " " ) ;
page . replace ( " {r4} " , ( sysCfg . emulation = = EMUL_HUE ) ? " checked " : " " ) ;
for ( int i = 1 ; i < Maxdevice ; i + + ) {
page + = FPSTR ( HTTP_FORM_OTHER2 ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " {1 " , String ( i + 1 ) ) ;
2017-01-29 20:36:12 +00:00
snprintf_P ( stemp , sizeof ( stemp ) , PSTR ( FRIENDLY_NAME " %d " ) , i + 1 ) ;
page . replace ( " {2 " , stemp ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {3 " , sysCfg . friendlyname [ i ] ) ;
2017-01-28 13:41:01 +00:00
}
2017-01-29 20:36:12 +00:00
page + = F ( " <br/></fieldset> " ) ;
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
page + = FPSTR ( HTTP_FORM_END ) ;
page + = FPSTR ( HTTP_BTN_CONF ) ;
showPage ( page ) ;
}
2017-02-10 16:03:34 +00:00
void handleDownload ( )
{
if ( httpUser ( ) ) return ;
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle download config " ) ) ;
uint8_t buffer [ sizeof ( sysCfg ) ] ;
WiFiClient myClient = webServer - > client ( ) ;
webServer - > setContentLength ( 4096 ) ;
2017-03-03 11:35:23 +00:00
char attachment [ 100 ] ;
snprintf_P ( attachment , sizeof ( attachment ) , PSTR ( " attachment; filename=Config_%s_%s.dmp " ) ,
sysCfg . friendlyname [ 0 ] , Version ) ;
2017-02-10 16:03:34 +00:00
webServer - > sendHeader ( " Content-Disposition " , attachment ) ;
webServer - > send ( 200 , " application/octet-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 ) ) ;
}
2017-01-28 13:41:01 +00:00
void handleSave ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
char log [ LOGSZ ] , stemp [ 20 ] ;
byte what = 0 , 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 ) ) ;
2017-02-08 11:56:51 +00:00
if ( strstr ( sysCfg . hostname , " % " ) ) strlcpy ( sysCfg . hostname , WIFI_HOSTNAME , sizeof ( sysCfg . hostname ) ) ;
2017-01-28 13:41:01 +00:00
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 ( " <br/>Trying to connect device to network<br/>If it fails reconnect to try again " ) ;
break ;
case 2 :
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 : webServer - > arg ( " mu " ) . c_str ( ) , sizeof ( sysCfg . mqtt_user ) ) ;
strlcpy ( sysCfg . mqtt_pwd , ( ! strlen ( webServer - > arg ( " mp " ) . c_str ( ) ) ) ? MQTT_PASS : webServer - > arg ( " mp " ) . c_str ( ) , sizeof ( sysCfg . mqtt_pwd ) ) ;
strlcpy ( sysCfg . mqtt_topic , ( ! strlen ( webServer - > arg ( " mt " ) . c_str ( ) ) ) ? MQTT_TOPIC : webServer - > arg ( " mt " ) . c_str ( ) , sizeof ( sysCfg . mqtt_topic ) ) ;
snprintf_P ( log , sizeof ( log ) , PSTR ( " HTTP: MQTT Host %s, Port %d, Client %s, User %s, Password %s, Topic %s " ) ,
sysCfg . mqtt_host , sysCfg . mqtt_port , sysCfg . mqtt_client , sysCfg . mqtt_user , sysCfg . mqtt_pwd , sysCfg . mqtt_topic ) ;
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 :
2017-02-21 17:14:33 +00:00
strlcpy ( sysCfg . web_password , ( ! strlen ( webServer - > arg ( " p1 " ) . c_str ( ) ) ) ? WEB_PASSWORD : webServer - > arg ( " p1 " ) . c_str ( ) , sizeof ( sysCfg . web_password ) ) ;
if ( sysCfg . web_password [ 0 ] = = ' 0 ' ) sysCfg . web_password [ 0 ] = ' \0 ' ;
2017-01-29 20:36:12 +00:00
sysCfg . mqtt_enabled = webServer - > hasArg ( " b1 " ) ;
# ifdef USE_EMULATION
sysCfg . 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 " ) ,
( sysCfg . mqtt_enabled ) ? MQTT_STATUS_ON : MQTT_STATUS_OFF , sysCfg . emulation , sysCfg . friendlyname [ 0 ] , sysCfg . friendlyname [ 1 ] , sysCfg . friendlyname [ 2 ] , sysCfg . friendlyname [ 3 ] ) ;
2017-01-28 13:41:01 +00:00
addLog ( LOG_LEVEL_INFO , log ) ;
break ;
case 6 :
sysCfg . module = ( ! strlen ( webServer - > arg ( " mt " ) . c_str ( ) ) ) ? MODULE : atoi ( webServer - > arg ( " mt " ) . c_str ( ) ) ;
mytmplt cmodule ;
memcpy_P ( & cmodule , & modules [ sysCfg . module ] , sizeof ( cmodule ) ) ;
String gpios = " " ;
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
if ( cmodule . gp . io [ i ] = = GPIO_USER ) {
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 ( " {v} " , " Save parameters " ) ;
page + = F ( " <div style='text-align:center;'><b>Parameters saved</b><br/> " ) ;
page + = result ;
page + = F ( " </div> " ) ;
page + = FPSTR ( HTTP_MSG_RSTRT ) ;
if ( _httpflag = = HTTP_MANAGER ) {
_httpflag = HTTP_ADMIN ;
} else {
page + = FPSTR ( HTTP_BTN_MAIN ) ;
}
showPage ( page ) ;
restartflag = 2 ;
} else {
handleConfig ( ) ;
}
}
void handleReset ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-03-05 14:07:30 +00:00
char svalue [ 16 ] ; // was MESSZ
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Reset parameters " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Default parameters " ) ;
page + = F ( " <div style='text-align:center;'>Parameters reset to default</div> " ) ;
page + = FPSTR ( HTTP_MSG_RSTRT ) ;
page + = FPSTR ( HTTP_BTN_MAIN ) ;
showPage ( page ) ;
snprintf_P ( svalue , sizeof ( svalue ) , PSTR ( " reset 1 " ) ) ;
do_cmnd ( svalue ) ;
}
2017-02-10 16:03:34 +00:00
void handleRestore ( )
{
if ( httpUser ( ) ) return ;
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle restore " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Restore Configuration " ) ;
page + = FPSTR ( HTTP_FORM_RST ) ;
page + = FPSTR ( HTTP_BTN_CONF ) ;
showPage ( page ) ;
_uploaderror = 0 ;
_uploadfiletype = 1 ;
}
2017-01-28 13:41:01 +00:00
void handleUpgrade ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle upgrade " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Firmware upgrade " ) ;
page + = FPSTR ( HTTP_FORM_UPG ) ;
2017-02-17 16:18:41 +00:00
page . replace ( " {o1} " , sysCfg . otaUrl ) ;
2017-01-28 13:41:01 +00:00
page + = FPSTR ( HTTP_BTN_MAIN ) ;
showPage ( page ) ;
_uploaderror = 0 ;
2017-02-10 16:03:34 +00:00
_uploadfiletype = 0 ;
2017-01-28 13:41:01 +00:00
}
void handleUpgradeStart ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-03-05 14:07:30 +00:00
char svalue [ 16 ] ; // was MESSZ
2017-01-28 13:41:01 +00:00
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 ( " {v} " , " Info " ) ;
page + = F ( " <div style='text-align:center;'><b>Upgrade started ...</b></div> " ) ;
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 ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: File upload done " ) ) ;
2017-01-28 13:41:01 +00:00
2017-03-03 11:35:23 +00:00
char error [ 80 ] , log [ LOGSZ ] ;
2017-01-28 13:41:01 +00:00
WIFI_configCounter ( ) ;
restartflag = 0 ;
mqttcounter = 0 ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Info " ) ;
page + = F ( " <div style='text-align:center;'><b>Upload " ) ;
if ( _uploaderror ) {
2017-02-04 16:09:54 +00:00
page + = F ( " <font color='red'>failed</font></b><br/><br/> " ) ;
2017-03-03 11:35:23 +00:00
switch ( _uploaderror ) {
case 1 : strcpy_P ( error , PSTR ( " No file selected " ) ) ; break ;
case 2 : strcpy_P ( error , PSTR ( " File size is larger than available free space " ) ) ; break ;
case 3 : strcpy_P ( error , PSTR ( " File magic header does not start with 0xE9 " ) ) ; break ;
case 4 : strcpy_P ( error , PSTR ( " File flash size is larger than device flash size " ) ) ; break ;
case 5 : strcpy_P ( error , PSTR ( " File upload buffer miscompare " ) ) ; break ;
case 6 : strcpy_P ( error , PSTR ( " Upload failed. Enable logging option 3 for more information " ) ) ; break ;
case 7 : strcpy_P ( error , PSTR ( " Upload aborted " ) ) ; break ;
case 8 : strcpy_P ( error , PSTR ( " Invalid configuration file " ) ) ; break ;
case 9 : strcpy_P ( error , PSTR ( " Configuration file too large " ) ) ; break ;
default :
snprintf_P ( error , sizeof ( error ) , PSTR ( " Upload error code %d " ) , _uploaderror ) ;
2017-01-28 13:41:01 +00:00
}
2017-02-10 16:03:34 +00:00
page + = error ;
if ( ! _uploadfiletype & & Update . hasError ( ) ) {
2017-01-28 13:41:01 +00:00
page + = F ( " <br/><br/>Update error code (see Updater.cpp) " ) ;
page + = String ( Update . getError ( ) ) ;
}
2017-03-03 11:35:23 +00:00
snprintf_P ( log , sizeof ( log ) , PSTR ( " Upload: Error - %s " ) , error ) ;
2017-02-10 16:03:34 +00:00
addLog ( LOG_LEVEL_DEBUG , log ) ;
2017-02-19 16:49:17 +00:00
sl_blank ( 0 ) ;
2017-01-28 13:41:01 +00:00
} else {
page + = F ( " <font color='green'>successful</font></b><br/><br/>Device will restart in a few seconds " ) ;
restartflag = 2 ;
}
page + = F ( " </div><br/> " ) ;
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 ( _httpflag = = HTTP_USER ) return ;
if ( _uploaderror ) {
2017-02-10 16:03:34 +00:00
if ( ! _uploadfiletype ) Update . end ( ) ;
2017-01-28 13:41:01 +00:00
return ;
}
HTTPUpload & upload = webServer - > upload ( ) ;
if ( upload . status = = UPLOAD_FILE_START ) {
restartflag = 60 ;
2017-02-10 16:03:34 +00:00
if ( upload . filename . c_str ( ) [ 0 ] = = 0 ) {
2017-01-28 13:41:01 +00:00
_uploaderror = 1 ;
return ;
}
snprintf_P ( log , sizeof ( log ) , PSTR ( " Upload: File %s ... " ) , upload . filename . c_str ( ) ) ;
addLog ( LOG_LEVEL_INFO , log ) ;
2017-02-10 16:03:34 +00:00
if ( ! _uploadfiletype ) {
mqttcounter = 60 ;
# ifdef USE_EMULATION
UDP_Disconnect ( ) ;
# endif // USE_EMULATION
if ( sysCfg . mqtt_enabled ) mqttClient . disconnect ( ) ;
uint32_t maxSketchSpace = ( ESP . getFreeSketchSpace ( ) - 0x1000 ) & 0xFFFFF000 ;
if ( ! Update . begin ( maxSketchSpace ) ) { //start with max available size
if ( _serialoutput ) Update . printError ( Serial ) ;
_uploaderror = 2 ;
return ;
}
2017-01-28 13:41:01 +00:00
}
2017-02-19 16:49:17 +00:00
sl_blank ( 1 ) ;
2017-01-28 13:41:01 +00:00
_colcount = 0 ;
} else if ( ! _uploaderror & & ( upload . status = = UPLOAD_FILE_WRITE ) ) {
if ( upload . totalSize = = 0 )
{
2017-02-10 16:03:34 +00:00
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 ;
}
if ( ( sysCfg . module = = SONOFF_TOUCH ) | | ( sysCfg . module = = SONOFF_4CH ) ) {
upload . buf [ 2 ] = 3 ; // DOUT - ESP8285
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " FLSH: Updated Flash Chip Mode to 3 " ) ) ;
}
2017-01-28 13:41:01 +00:00
}
2017-02-10 16:03:34 +00:00
}
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 ) ;
}
} else { // firmware
if ( ! _uploaderror & & ( Update . write ( upload . buf , upload . currentSize ) ! = upload . currentSize ) ) {
if ( _serialoutput ) Update . printError ( Serial ) ;
_uploaderror = 5 ;
2017-01-28 13:41:01 +00:00
return ;
}
2017-02-10 16:03:34 +00:00
if ( _serialoutput ) {
Serial . printf ( " . " ) ;
_colcount + + ;
if ( ! ( _colcount % 80 ) ) Serial . println ( ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-02-10 16:03:34 +00:00
} else if ( ! _uploaderror & & ( upload . status = = UPLOAD_FILE_END ) ) {
2017-01-28 13:41:01 +00:00
if ( _serialoutput & & ( _colcount % 80 ) ) Serial . println ( ) ;
2017-02-10 16:03:34 +00:00
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 ) {
2017-01-28 13:41:01 +00:00
snprintf_P ( log , sizeof ( log ) , PSTR ( " Upload: Successful %u bytes. Restarting " ) , upload . totalSize ) ;
addLog ( LOG_LEVEL_INFO , log ) ;
}
} else if ( upload . status = = UPLOAD_FILE_ABORTED ) {
restartflag = 0 ;
mqttcounter = 0 ;
_uploaderror = 7 ;
2017-02-10 16:03:34 +00:00
if ( ! _uploadfiletype ) Update . end ( ) ;
2017-01-28 13:41:01 +00:00
}
delay ( 0 ) ;
}
void handleCmnd ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-03-05 14:07:30 +00:00
char svalue [ 128 ] ; // was MESSZ
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle cmnd " ) ) ;
2017-02-21 17:14:33 +00:00
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 ;
}
2017-01-28 13:41:01 +00:00
}
String message = " " ;
2017-02-21 17:14:33 +00:00
if ( valid ) {
byte curridx = logidx ;
if ( strlen ( webServer - > arg ( " cmnd " ) . c_str ( ) ) ) {
snprintf_P ( svalue , sizeof ( svalue ) , webServer - > arg ( " cmnd " ) . c_str ( ) ) ;
2017-03-03 11:35:23 +00:00
byte syslog_now = syslog_level ;
syslog_level = 0 ; // Disable UDP syslog to not trigger hardware WDT
2017-02-21 17:14:33 +00:00
do_cmnd ( svalue ) ;
2017-03-03 11:35:23 +00:00
syslog_level = syslog_now ;
2017-02-21 17:14:33 +00:00
}
if ( logidx ! = curridx ) {
byte counter = curridx ;
do {
if ( Log [ counter ] . length ( ) ) {
if ( message . length ( ) ) message + = F ( " \n " ) ;
if ( sysCfg . 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 ) ;
}
2017-01-28 13:41:01 +00:00
}
2017-02-21 17:14:33 +00:00
counter + + ;
if ( counter > MAX_LOG_LINES - 1 ) counter = 0 ;
} while ( counter ! = logidx ) ;
} else {
message = F ( " Enable weblog 2 if response expected \n " ) ;
}
2017-01-28 13:41:01 +00:00
} else {
2017-02-21 17:14:33 +00:00
message = F ( " Need user=<username>&password=<password> \n " ) ;
2017-01-28 13:41:01 +00:00
}
webServer - > sendHeader ( " Cache-Control " , " no-cache, no-store, must-revalidate " ) ;
webServer - > sendHeader ( " Pragma " , " no-cache " ) ;
webServer - > sendHeader ( " Expires " , " -1 " ) ;
webServer - > send ( 200 , " text/plain " , message ) ;
}
void handleConsole ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle console " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Console " ) ;
2017-03-08 15:20:45 +00:00
page . replace ( " </script> " , FPSTR ( HTTP_SCRIPT_CONSOL ) ) ;
2017-01-28 13:41:01 +00:00
page . replace ( " <body> " , " <body onload='l()'> " ) ;
page + = FPSTR ( HTTP_FORM_CMND ) ;
page + = FPSTR ( HTTP_BTN_MAIN ) ;
showPage ( page ) ;
}
void handleAjax ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-03-05 14:07:30 +00:00
char log [ LOGSZ ] , svalue [ 128 ] ; // was MESSZ
2017-02-28 15:01:48 +00:00
byte cflg = 1 , counter = 99 ;
2017-02-24 17:17:48 +00:00
if ( strlen ( webServer - > arg ( " c1 " ) . c_str ( ) ) ) {
snprintf_P ( svalue , sizeof ( svalue ) , webServer - > arg ( " c1 " ) . c_str ( ) ) ;
snprintf_P ( log , sizeof ( log ) , PSTR ( " CMND: %s " ) , svalue ) ;
addLog ( LOG_LEVEL_INFO , log ) ;
2017-03-03 11:35:23 +00:00
byte syslog_now = syslog_level ;
syslog_level = 0 ; // Disable UDP syslog to not trigger hardware WDT
2017-02-24 17:17:48 +00:00
do_cmnd ( svalue ) ;
2017-03-03 11:35:23 +00:00
syslog_level = syslog_now ;
2017-02-24 17:17:48 +00:00
}
if ( strlen ( webServer - > arg ( " c2 " ) . c_str ( ) ) ) counter = atoi ( webServer - > arg ( " c2 " ) . c_str ( ) ) ;
String message = F ( " <r><i> " ) ;
message + = String ( logidx ) ;
message + = F ( " </i><j> " ) ;
message + = String ( logajaxflg ) ;
if ( ! logajaxflg ) {
counter = 99 ;
logajaxflg = 1 ;
}
message + = F ( " </j><l> " ) ;
if ( counter ! = logidx ) {
2017-02-28 15:01:48 +00:00
if ( counter = = 99 ) {
counter = logidx ;
cflg = 0 ;
}
2017-02-24 17:17:48 +00:00
do {
if ( Log [ counter ] . length ( ) ) {
2017-02-28 15:01:48 +00:00
if ( cflg ) message + = F ( " \n " ) ; else cflg = 1 ;
2017-02-24 17:17:48 +00:00
message + = Log [ counter ] ;
}
counter + + ;
if ( counter > MAX_LOG_LINES - 1 ) counter = 0 ;
} while ( counter ! = logidx ) ;
}
message + = F ( " </l></r> " ) ;
2017-01-28 13:41:01 +00:00
webServer - > sendHeader ( " Cache-Control " , " no-cache, no-store, must-revalidate " ) ;
webServer - > sendHeader ( " Pragma " , " no-cache " ) ;
webServer - > sendHeader ( " Expires " , " -1 " ) ;
2017-02-24 17:17:48 +00:00
webServer - > send ( 200 , " text/xml " , message ) ;
2017-01-28 13:41:01 +00:00
}
void handleInfo ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Handle info " ) ) ;
int freeMem = ESP . getFreeHeap ( ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Information " ) ;
// page += F("<fieldset><legend><b> Information </b></legend>");
page + = F ( " <style>td{padding:0px 5px;}</style> " ) ;
page + = F ( " <table style'width:100%;'> " ) ;
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>Program version</th><td> " ) ; page + = Version ; page + = F ( " </td></tr> " ) ;
2017-03-08 15:20:45 +00:00
page + = F ( " <tr><th>Build Date & Time</th><td> " ) ; page + = getBuildDateTime ( ) ; page + = F ( " </td></tr> " ) ;
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>Core/SDK version</th><td> " ) ; page + = ESP . getCoreVersion ( ) ; page + = F ( " / " ) ; page + = String ( ESP . getSdkVersion ( ) ) ; page + = F ( " </td></tr> " ) ;
// page += F("<tr><th>Boot version</th><td>"); page += String(ESP.getBootVersion()); page += F("</td></tr>");
page + = F ( " <tr><th>Uptime</th><td> " ) ; page + = String ( uptime ) ; page + = F ( " Hours</td></tr> " ) ;
page + = F ( " <tr><th>Flash write count</th><td> " ) ; page + = String ( sysCfg . saveFlag ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>Boot count</th><td> " ) ; page + = String ( sysCfg . bootcount ) ; page + = F ( " </td></tr> " ) ;
2017-02-28 15:01:48 +00:00
page + = F ( " <tr><th>Reset reason</th><td> " ) ; page + = getResetReason ( ) ; page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
for ( byte i = 0 ; i < Maxdevice ; i + + ) {
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>Friendly name " ) ;
2017-01-28 13:41:01 +00:00
page + = i + 1 ;
2017-02-17 16:18:41 +00:00
page + = F ( " </th><td> " ) ; page + = sysCfg . friendlyname [ i ] ; page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
}
page + = F ( " <tr><td> </td></tr> " ) ;
2017-02-04 16:09:54 +00:00
// page += F("<tr><th>SSId (RSSI)</th><td>"); page += (sysCfg.sta_active)? sysCfg.sta_ssid2 : sysCfg.sta_ssid1; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%)</td></tr>");
page + = F ( " <tr><th>AP " ) ; page + = String ( sysCfg . sta_active + 1 ) ; page + = F ( " SSId (RSSI)</th><td> " ) ; page + = sysCfg . sta_ssid [ sysCfg . sta_active ] ; page + = F ( " ( " ) ; page + = WIFI_getRSSIasQuality ( WiFi . RSSI ( ) ) ; page + = F ( " %)</td></tr> " ) ;
page + = F ( " <tr><th>Hostname</th><td> " ) ; page + = Hostname ; page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
if ( static_cast < uint32_t > ( WiFi . localIP ( ) ) ! = 0 ) {
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>IP address</th><td> " ) ; page + = WiFi . localIP ( ) . toString ( ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>Gateway</th><td> " ) ; page + = WiFi . gatewayIP ( ) . toString ( ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>MAC address</th><td> " ) ; page + = WiFi . macAddress ( ) ; page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
}
if ( static_cast < uint32_t > ( WiFi . softAPIP ( ) ) ! = 0 ) {
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>AP IP address</th><td> " ) ; page + = WiFi . softAPIP ( ) . toString ( ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>AP Gateway</th><td> " ) ; page + = WiFi . softAPIP ( ) . toString ( ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>AP MAC address</th><td> " ) ; page + = WiFi . softAPmacAddress ( ) ; page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
}
page + = F ( " <tr><td> </td></tr> " ) ;
if ( sysCfg . mqtt_enabled ) {
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>MQTT Host</th><td> " ) ; page + = sysCfg . mqtt_host ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>MQTT Port</th><td> " ) ; page + = String ( sysCfg . mqtt_port ) ; page + = F ( " </td></tr> " ) ;
2017-03-08 15:20:45 +00:00
page + = F ( " <tr><th>MQTT Client &<br/> Fallback Topic</th><td> " ) ; page + = MQTTClient ; page + = F ( " </td></tr> " ) ;
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>MQTT User</th><td> " ) ; page + = sysCfg . mqtt_user ; page + = F ( " </td></tr> " ) ;
// page += F("<tr><th>MQTT Password</th><td>"); page += sysCfg.mqtt_pwd; page += F("</td></tr>");
page + = F ( " <tr><th>MQTT Topic</th><td> " ) ; page + = sysCfg . mqtt_topic ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>MQTT Group Topic</th><td> " ) ; page + = sysCfg . mqtt_grptopic ; page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
} else {
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>MQTT</th><td>Disabled</td></tr> " ) ;
}
page + = F ( " <tr><th>Emulation</th><td> " ) ;
# ifdef USE_EMULATION
2017-02-21 17:14:33 +00:00
if ( sysCfg . emulation = = EMUL_WEMO ) page + = F ( " Belkin WeMo " ) ;
else if ( sysCfg . emulation = = EMUL_HUE ) page + = F ( " Hue Bridge " ) ;
else page + = F ( " None " ) ;
2017-02-04 16:09:54 +00:00
# else
2017-02-21 17:14:33 +00:00
page + = F ( " Disabled " ) ;
2017-02-04 16:09:54 +00:00
# endif // USE_EMULATION
page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>mDNS Discovery</th><td> " ) ;
# ifdef USE_DISCOVERY
page + = F ( " Enabled " ) ;
page + = F ( " </td></tr> " ) ;
2017-03-08 15:20:45 +00:00
page + = F ( " <tr><th>mDNS Advertise</th><td> " ) ;
2017-02-04 16:09:54 +00:00
# ifdef WEBSERVER_ADVERTISE
2017-03-08 15:20:45 +00:00
page + = F ( " Webserver " ) ;
2017-02-04 16:09:54 +00:00
# else
page + = F ( " Disabled " ) ;
# endif // WEBSERVER_ADVERTISE
# else
page + = F ( " Disabled " ) ;
# endif // USE_DISCOVERY
page + = F ( " </td></tr> " ) ;
2017-01-28 13:41:01 +00:00
page + = F ( " <tr><td> </td></tr> " ) ;
2017-02-04 16:09:54 +00:00
page + = F ( " <tr><th>ESP Chip id</th><td> " ) ; page + = String ( ESP . getChipId ( ) ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>Flash Chip id</th><td> " ) ; page + = String ( ESP . getFlashChipId ( ) ) ; page + = F ( " </td></tr> " ) ;
page + = F ( " <tr><th>Flash size</th><td> " ) ; page + = String ( ESP . getFlashChipRealSize ( ) / 1024 ) ; page + = F ( " kB</td></tr> " ) ;
page + = F ( " <tr><th>Program flash size</th><td> " ) ; page + = String ( ESP . getFlashChipSize ( ) / 1024 ) ; page + = F ( " kB</td></tr> " ) ;
page + = F ( " <tr><th>Program size</th><td> " ) ; page + = String ( ESP . getSketchSize ( ) / 1024 ) ; page + = F ( " kB</td></tr> " ) ;
page + = F ( " <tr><th>Free program space</th><td> " ) ; page + = String ( ESP . getFreeSketchSpace ( ) / 1024 ) ; page + = F ( " kB</td></tr> " ) ;
page + = F ( " <tr><th>Free memory</th><td> " ) ; page + = String ( freeMem / 1024 ) ; page + = F ( " kB</td></tr> " ) ;
2017-01-28 13:41:01 +00:00
page + = F ( " </table> " ) ;
// page += F("</fieldset>");
page + = FPSTR ( HTTP_BTN_MAIN ) ;
showPage ( page ) ;
}
void handleRestart ( )
{
2017-02-10 16:03:34 +00:00
if ( httpUser ( ) ) return ;
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Restarting " ) ) ;
String page = FPSTR ( HTTP_HEAD ) ;
page . replace ( " {v} " , " Info " ) ;
page + = FPSTR ( HTTP_MSG_RSTRT ) ;
if ( _httpflag = = HTTP_MANAGER ) {
_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 ;
}
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
2017-01-28 13:41:01 +00:00
String path = webServer - > uri ( ) ;
2017-01-29 20:36:12 +00:00
if ( ( sysCfg . emulation = = EMUL_HUE ) & & ( path . startsWith ( " /api " ) ) ) {
2017-01-28 13:41:01 +00:00
handle_hue_api ( & path ) ;
2017-01-29 20:36:12 +00:00
} else
# endif // USE_EMULATION
{
String message = " File Not Found \n \n " ;
message + = " URI: " ;
message + = webServer - > uri ( ) ;
message + = " \n Method: " ;
message + = ( webServer - > method ( ) = = HTTP_GET ) ? " GET " : " POST " ;
message + = " \n Arguments: " ;
message + = webServer - > args ( ) ;
message + = " \n " ;
for ( uint8_t i = 0 ; i < webServer - > args ( ) ; i + + ) {
message + = " " + webServer - > argName ( i ) + " : " + webServer - > arg ( i ) + " \n " ;
}
2017-01-28 13:41:01 +00:00
2017-01-29 20:36:12 +00:00
webServer - > sendHeader ( " Cache-Control " , " no-cache, no-store, must-revalidate " ) ;
webServer - > sendHeader ( " Pragma " , " no-cache " ) ;
webServer - > sendHeader ( " Expires " , " -1 " ) ;
webServer - > send ( 404 , " text/plain " , message ) ;
2017-01-28 13:41:01 +00:00
}
}
/* 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 ( )
{
2017-03-08 15:20:45 +00:00
if ( ( _httpflag = = HTTP_MANAGER ) & & ! isIp ( webServer - > hostHeader ( ) ) ) {
2017-01-28 13:41:01 +00:00
addLog_P ( LOG_LEVEL_DEBUG , PSTR ( " HTTP: Request redirected to captive portal " ) ) ;
webServer - > sendHeader ( " Location " , String ( " http:// " ) + webServer - > client ( ) . localIP ( ) . toString ( ) , true ) ;
webServer - > send ( 302 , " text/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