httpServer.ino 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. //extern ESP8266WebServer httpServer;
  2. static const char httpRoot[] PROGMEM =
  3. R"(<html><body>
  4. <h1><span id='devname'></span></h1>
  5. <h3>WiFi Thermostat</h3>
  6. <form id='minusBtnFrm'>
  7. <input type='hidden' name='minusBtn' value='1'>
  8. </form>
  9. <form id='plusBtnFrm'>
  10. <input type='hidden' name='plusBtn' value='1'>
  11. </form>
  12. <form id='modeBtnFrm'>
  13. <input type='hidden' name='modeBtn' value='1'>
  14. </form>
  15. <form id='onoffBtnFrm'>
  16. <input type='hidden' name='onoffBtn' value='1'>
  17. </form>
  18. <span style="font-size:xx-large" id='setTemp'></span> &#8451;<br>
  19. <span id='mode'></span><br>
  20. <input type='button' onclick='return sendMinusBtn()' value='-'/>
  21. <input type='button' onclick='return sendPlusBtn()' value='+'/>
  22. <input type='button' onclick='return sendModeBtn()' value='MODE'/>
  23. <br>
  24. <br>
  25. <input id='btn_onoff' type='button' onclick='return sendOnOffBtn()' value=''/><br>
  26. <br>
  27. Current: <span id='temp'></span> &#8451;&nbsp;&nbsp;&nbsp;<span id='hum'></span> %<br>
  28. Heating <span id='heating'></span><br>
  29. <br>
  30. WiFi connected to <i><span id='ssid'></span></i>.<br>
  31. <h6>Last update
  32. <span id='ut'></span> seconds ago.
  33. <span id='status'></span>
  34. </h6>
  35. <br>
  36. <a href='/wifi.htm'>WiFi settings</a><br>
  37. <a href='/conf'>Base configuration</a><br>
  38. <a href='/conf2'>Extended configuration</a><br>
  39. <a href='/update'>Firmware update</a><br>
  40. <a href='/restart'>Restart</a>
  41. <script>
  42. function g(i) { return document.getElementById(i) };
  43. var xhttp, updateTime, reqTime, reqFin;
  44. var textA = 'OFF';
  45. var textE = 'ON';
  46. function sendMinusBtn() {
  47. var form = document.getElementById('minusBtnFrm');
  48. return transmit(form);
  49. }
  50. function sendPlusBtn() {
  51. var form = document.getElementById('plusBtnFrm');
  52. return transmit(form);
  53. }
  54. function sendModeBtn() {
  55. var form = document.getElementById('modeBtnFrm');
  56. return transmit(form);
  57. }
  58. function sendOnOffBtn() {
  59. var form = document.getElementById('onoffBtnFrm');
  60. return transmit(form);
  61. }
  62. function transmit(f) {
  63. if (!xhttp) {
  64. g('status').innerHTML = 'loading...';
  65. reqTime = 0;
  66. reqFin = false;
  67. xhttp = new XMLHttpRequest();
  68. xhttp.timeout = 2000;
  69. xhttp.open('POST', 'api');
  70. xhttp.send(f ? (new FormData(f)) : '');
  71. xhttp.onreadystatechange = function () {
  72. if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
  73. var data = JSON.parse(xhttp.responseText);
  74. if(data.devname != undefined) g('devname').innerHTML = data.devname;
  75. g('temp').innerHTML = data.temp.toFixed(1);
  76. g('hum').innerHTML = data.hum;
  77. g('setTemp').innerHTML = data.setTemp.toFixed(1);
  78. g('ssid').innerHTML = data.ssid;
  79. if(data.mode == '0') {
  80. g('btn_onoff').value = textA;
  81. g('mode').innerHTML = 'Heating OFF';
  82. }
  83. else if(data.mode == '1') {
  84. g('btn_onoff').value = textE;
  85. g('mode').innerHTML = 'Normal';
  86. }
  87. else if(data.mode == '2') {
  88. g('btn_onoff').value = textE;
  89. g('mode').innerHTML = 'Reduction';
  90. }
  91. if(data.heating == '1') g('heating').innerHTML = 'active';
  92. else if(data.heating == '0') g('heating').innerHTML = 'not active';
  93. xhttp = null;
  94. g('status').innerHTML = '';
  95. updateTime = 0;
  96. reqFin = true;
  97. }
  98. else {
  99. if(!reqFin && reqTime > 10) {
  100. xhttp = null;
  101. reqFin = true;
  102. }
  103. }
  104. }
  105. }
  106. return false;
  107. }
  108. transmit();
  109. setInterval(function () { g('ut').innerHTML = ++updateTime; ++reqTime; }, 1000);
  110. setInterval(transmit, 5000);
  111. </script>
  112. </body></html>)";
  113. static const char httpConfPage[] PROGMEM =
  114. R"(<html><head><body>
  115. <h3>Base configuration</h3>
  116. <a href='/'>Home</a><br><br>
  117. <input type='button' value='reload' onclick='return transmit()'/><br><br>
  118. <form id='form1' onsubmit='return transmit(this)'>
  119. Device Name: <input type='text' name='devName' id='devName'/><br><br>
  120. HTTP User *: <input type='text' name='httpUser' id='httpUser'/><br>
  121. HTTP Password *: <input type='text' name='httpPass' id='httpPass'/><br><br>
  122. MQTT Server *: <input type='text' name='mqttHost' id='mqttHost'/><br>
  123. MQTT Port *: <input type='number' name='mqttPort' id='mqttPort'/><br>
  124. MQTT User *: <input type='text' name='mqttUser' id='mqttUser'/><br>
  125. MQTT Password *: <input type='text' name='mqttPass' id='mqttPass'/><br><br>
  126. In Topic *: <input type='text' name='inTop' id='inTop'/><br>
  127. Out Topic: <input type='text' name='outTop' id='outTop'/><br>
  128. Out Retain *: <input type='checkbox' name='outRet' id='outRet'/><br><br>
  129. LastWill Topic *: <input type='text' name='willTop' id='willTop'/><br>
  130. LastWill Qos *: <select name='willQos' id='willQos'><option>0</option><option>1</option><option>2</option></select><br>
  131. LastWill Retain *: <input type='checkbox' name='willRet' id='willRet'/><br>
  132. LastWill Message *: <input type='text' name='willMsg' id='willMsg'/><br><br>
  133. Domoticz Out Topic *: <input type='text' name='domOutTop' id='domOutTop'/><br>
  134. <br>
  135. <input type='submit' value='Save'/>
  136. </form>
  137. <form id='restartForm' onsubmit='return res()'>
  138. <input type='hidden' name='restart' value='1'>
  139. <input type='submit' value='Restart'/>
  140. </form>
  141. <script>
  142. function g(i) { return document.getElementById(i) };
  143. var xhttp, reqTime, reqFin, rxhttp;
  144. function res() {
  145. rxhttp = new XMLHttpRequest();
  146. rxhttp.timeout = 1000;
  147. rxhttp.open('POST', 'restart');
  148. rxhttp.send('');
  149. rxhttp = null;
  150. return false;
  151. }
  152. function setCheckbox(ele, dat) {
  153. if(dat == 1) {
  154. ele.checked = true;
  155. ele.style.visibility = 'visible';
  156. }
  157. else {
  158. ele.checked = false;
  159. ele.style.visibility = 'visible';
  160. }
  161. }
  162. function updateCheckboxValue(ele) {
  163. if (ele.checked) ele.value ='1';
  164. else {
  165. ele.value = '0';
  166. ele.checked = true;
  167. ele.style.visibility = 'hidden';
  168. }
  169. }
  170. function transmit(f) {
  171. if (!xhttp) {
  172. reqTime = 0;
  173. reqFin = false;
  174. updateCheckboxValue(g('outRet'));
  175. updateCheckboxValue(g('willRet'));
  176. xhttp = new XMLHttpRequest();
  177. xhttp.timeout = 2000;
  178. xhttp.open('POST', 'confdata');
  179. xhttp.send(f ? (new FormData(f)) : '');
  180. xhttp.onreadystatechange = function () {
  181. if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
  182. var data = JSON.parse(xhttp.responseText);
  183. g('httpUser').value = data.httpUser;
  184. g('httpPass').value = data.httpPass;
  185. g('devName').value = data.devName
  186. g('mqttHost').value = data.mqttHost;
  187. g('mqttPort').value = data.mqttPort;
  188. g('mqttUser').value = data.mqttUser;
  189. g('mqttPass').value = data.mqttPass;
  190. g('inTop').value = data.inTop;
  191. g('outTop').value = data.outTop;
  192. g('willTop').value = data.willTop;
  193. g('willQos').value = data.willQos;
  194. setCheckbox(g('outRet'), data.outRet);
  195. setCheckbox(g('willRet'), data.willRet);
  196. g('willMsg').value = data.willMsg;
  197. g('domOutTop').value = data.domOutTop;
  198. xhttp = null;
  199. reqFin = true;
  200. }
  201. else {
  202. if(!reqFin && reqTime > 10) {
  203. xhttp = null;
  204. reqFin = true;
  205. }
  206. }
  207. }
  208. }
  209. return false;
  210. }
  211. transmit();
  212. setInterval(function () { ++reqTime; }, 1000);
  213. </script>
  214. </body></html>)";
  215. static const char httpConf2Page[] PROGMEM =
  216. R"(<html><head><body>
  217. <h3>Extended configuration</h3>
  218. <a href='/'>Home</a><br><br>
  219. <input type='button' value='reload' onclick='return transmit()'/><br>
  220. <form id='form1' onsubmit='return transmit(this)'>
  221. <h4>Domoticz</h4>
  222. Idx setTemp: <input type='number' name='domIdxTherm' id='domIdxTherm'/><br>
  223. Idx mode: <input type='number' name='domIdxMode' id='domIdxMode'/><br>
  224. Idx TempHum Sensor: <input type='number' name='domIdxTempHum' id='domIdxTempHum'/><br>
  225. Idx PIR: <input type='number' name='domIdxPIR' id='domIdxPIR'/><br>
  226. <h4>Outside Temp/Hum via MQTT</h4>
  227. Temp In-Topic: <input type='text' name='outTempTop' id='outTempTop'/><br>
  228. Hum In-Topic: <input type='text' name='outHumTop' id='outHumTop'/><br>
  229. <h4>Auto-Save</h4>
  230. setTemp: <input type='checkbox' name='autoSaveTemp' id='autoSaveTemp'/><br>
  231. Mode: <input type='checkbox' name='autoSaveMode' id='autoSaveMode'/><br>
  232. <h4>Thermostat / Heating</h4>
  233. Min. Off-Time: <input type='number' name='minOffTime' id='minOffTime'/><br>
  234. Min. Temp: <input type='text' name='tempMin' id='tempMin'/><br>
  235. Max. Temp: <input type='text' name='tempMax' id='tempMax'/><br>
  236. Reduction Mode Temp: <input type='text' name='tempLow' id='tempLow'/><br>
  237. Hysteresis: <input type='text' name='hyst' id='hyst'/><br>
  238. Temp Correction.: <input type='text' name='tempCorr' id='tempCorr'/><br>
  239. Hum Correction: <input type='number' name='humCorr' id='humCorr'/><br>
  240. <h4>Intervals / Timeouts</h4>
  241. Measure Interval: <input type='number' name='measInt' id='measInt'/><br>
  242. Display Interval: <input type='number' name='dispInt' id='dispInt'/><br>
  243. Display Timeout: <input type='number' name='dispTout' id='dispTout'/><br>
  244. <br>
  245. <input type='submit' value='Save'/>
  246. </form>
  247. <form id='rebootForm' onsubmit='return res()'>
  248. <input type='submit' value='Restart'/>
  249. </form>
  250. <script>
  251. function g(i) { return document.getElementById(i) };
  252. var xhttp, reqTime, reqFin, rxhttp;
  253. function res() {
  254. rxhttp = new XMLHttpRequest();
  255. rxhttp.timeout = 1000;
  256. rxhttp.open('POST', 'restart');
  257. rxhttp.send('');
  258. rxhttp = null;
  259. return false;
  260. }
  261. function setCheckbox(ele, dat) {
  262. if(dat == 1) {
  263. ele.checked = true;
  264. ele.style.visibility = 'visible';
  265. }
  266. else {
  267. ele.checked = false;
  268. ele.style.visibility = 'visible';
  269. }
  270. }
  271. function updateCheckboxValue(ele) {
  272. if (ele.checked) ele.value ='1';
  273. else {
  274. ele.value = '0';
  275. ele.checked = true;
  276. ele.style.visibility = 'hidden';
  277. }
  278. }
  279. function transmit(f) {
  280. if (!xhttp) {
  281. updateCheckboxValue(g('autoSaveTemp'));
  282. updateCheckboxValue(g('autoSaveMode'));
  283. xhttp = new XMLHttpRequest();
  284. xhttp.timeout = 2000;
  285. xhttp.open('POST', 'confdata2');
  286. xhttp.send(f ? (new FormData(f)) : '');
  287. xhttp.onreadystatechange = function () {
  288. if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
  289. var data = JSON.parse(xhttp.responseText);
  290. setCheckbox(g('autoSaveTemp'), data.autoSaveTemp);
  291. setCheckbox(g('autoSaveMode'), data.autoSaveMode);
  292. g('domIdxTherm').value = data.domIdxTherm;
  293. g('domIdxMode').value = data.domIdxMode;
  294. g('domIdxTempHum').value = data.domIdxTempHum;
  295. g('domIdxPIR').value = data.domIdxPIR;
  296. g('outTempTop').value = data.outTempTop;
  297. g('outHumTop').value = data.outHumTop;
  298. g('minOffTime').value = data.minOffTime;
  299. g('tempMin').value = data.tempMin;
  300. g('tempMax').value = data.tempMax;
  301. g('tempLow').value = data.tempLow;
  302. g('hyst').value = data.hyst;
  303. g('tempCorr').value = data.tempCorr;
  304. g('humCorr').value = data.humCorr;
  305. g('measInt').value = data.measInt;
  306. g('dispInt').value = data.dispInt;
  307. g('dispTout').value = data.dispTout;
  308. xhttp = null;
  309. reqFin = false;
  310. }
  311. else {
  312. if(!reqFin && reqTime > 10) {
  313. xhttp = null;
  314. reqFin = true;
  315. }
  316. }
  317. }
  318. }
  319. return false;
  320. }
  321. transmit();
  322. setInterval(function () { ++reqTime; }, 1000);
  323. </script>
  324. </body></html>)";
  325. void httpServerHandleRoot() {
  326. httpServer.send_P(200, "text/html", httpRoot);
  327. }
  328. void httpServerHandleConfPage() {
  329. httpServer.send_P(200, "text/html", httpConfPage);
  330. }
  331. void httpServerHandleConf2Page() {
  332. httpServer.send_P(200, "text/html", httpConf2Page);
  333. }
  334. //void httpServerHandleNotFound() {
  335. // String message = "File Not Found\n\n";
  336. // message += "URI: ";
  337. // message += httpServer.uri();
  338. // message += "\nMethod: ";
  339. // message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
  340. // message += "\nArguments: ";
  341. // message += httpServer.args();
  342. // message += "\n";
  343. // for (uint8_t i = 0; i < httpServer.args(); i++) {
  344. // message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
  345. // }
  346. // httpServer.send(404, "text / plain", message);
  347. //}
  348. void httpServerHandleNotFound() {
  349. // if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
  350. // if (!httpServer.authenticate(http_user, http_pass))
  351. // return httpServer.requestAuthentication();
  352. httpServer.send(404, "text/plain", "");
  353. //}
  354. }
  355. void httpServerInit() {
  356. httpServer.on("/delconf", []() {
  357. Serial.println("httpServer.on /delconf");
  358. if (httpServer.hasArg("token")) {
  359. char buf[20];
  360. httpServer.arg("token").toCharArray(buf, 20);
  361. if (strcmp(buf, CLEARCONF_TOKEN) == 0) {
  362. // httpServer.send(200, "text / plain", "Token OK - deleting config");
  363. deleteConfig();
  364. }
  365. } //if
  366. // else {
  367. // httpServer.send(200, "text / plain", "not allowed");
  368. // }
  369. });
  370. httpServer.on("/api", []() {
  371. DEBUG_PRINT("httpServer.on /api");
  372. if (httpServer.hasArg("plusBtn")) {
  373. plusButtonAction();
  374. DEBUG_PRINT(P("web plusBtn"));
  375. } //if
  376. if (httpServer.hasArg("minusBtn")) {
  377. minusButtonAction();
  378. DEBUG_PRINT(P("web minusBtn"));
  379. } //if
  380. if (httpServer.hasArg("modeBtn")) {
  381. modeButtonAction();
  382. DEBUG_PRINT(P("web modeBtn"));
  383. } //if
  384. if (httpServer.hasArg("onoffBtn")) {
  385. modeButtonHoldAction();
  386. DEBUG_PRINT(P("web onoffBtn"));
  387. } //if
  388. //build json object of program data
  389. StaticJsonBuffer<200> jsonBuffer;
  390. JsonObject &json = jsonBuffer.createObject();
  391. json["devname"] = deviceName;
  392. json["ssid"] = WiFi.SSID();
  393. json["setTemp"] = setTemp;
  394. json["temp"] = currTemp;
  395. json["hum"] = int(currHum);
  396. json["mode"] = heatingMode;
  397. json["heating"] = turnHeatingOn;
  398. char jsonchar[200];
  399. json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
  400. httpServer.send(200, "application/json", jsonchar);
  401. }); //httpServer.on /api
  402. httpServer.on("/restart", []() {
  403. Serial.println("web triggered restart");
  404. ESP.restart();
  405. });
  406. httpServer.on("/confdata", []() {
  407. boolean sendData = false;
  408. if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
  409. if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
  410. sendData = true;
  411. }
  412. else sendData = true;
  413. if (sendData) {
  414. Serial.println("httpServer.on /confdata");
  415. for (int i = 0; i < httpServer.args(); i++) {
  416. char bufName[20];
  417. char bufValue[101];
  418. httpServer.argName(i).toCharArray(bufName, 20);
  419. httpServer.arg(i).toCharArray(bufValue, 101);
  420. if (strlen(bufName) > 0) {
  421. Serial.print("web update ");
  422. Serial.print(bufName);
  423. Serial.print(" = ");
  424. Serial.println(bufValue);
  425. setConfig(bufName, bufValue);
  426. }
  427. saveConfigToFlash = true; // will be saved in next loop()
  428. Serial.println("web triggered saveConfigToFlash");
  429. }
  430. yield();
  431. //build json object of program data
  432. StaticJsonBuffer<1000> jsonBuffer;
  433. JsonObject &json = jsonBuffer.createObject();
  434. json["devName"] = deviceName;
  435. json["httpUser"] = http_user;
  436. json["httpPass"] = http_pass;
  437. json["mqttHost"] = mqtt_server;
  438. json["mqttPort"] = mqtt_port;
  439. json["mqttUser"] = mqtt_user;
  440. json["mqttPass"] = mqtt_pass;
  441. json["inTop"] = mqtt_topic_in;
  442. json["outTop"] = mqtt_topic_out;
  443. json["outRet"] = mqtt_outRetain;
  444. json["willTop"] = mqtt_willTopic;
  445. json["willQos"] = mqtt_willQos;
  446. json["willRet"] = mqtt_willRetain;
  447. json["willMsg"] = mqtt_willMsg;
  448. json["domOutTop"] = domoticz_out_topic;
  449. yield();
  450. char jsonchar[1000];
  451. json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
  452. httpServer.send(200, "application/json", jsonchar);
  453. }
  454. }); //httpServer.on /confdata
  455. httpServer.on("/confdata2", []() {
  456. boolean sendData = false;
  457. if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
  458. if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
  459. sendData = true;
  460. }
  461. else sendData = true;
  462. if (sendData) {
  463. Serial.println("httpServer.on /confdata2");
  464. for (int i = 0; i < httpServer.args(); i++) {
  465. char bufName[20];
  466. char bufValue[101];
  467. httpServer.argName(i).toCharArray(bufName, 20);
  468. httpServer.arg(i).toCharArray(bufValue, 101);
  469. if (strlen(bufName) > 0) {
  470. Serial.print("web update ");
  471. Serial.print(bufName);
  472. Serial.print(" = ");
  473. Serial.println(bufValue);
  474. setConfig(bufName, bufValue);
  475. }
  476. saveConfig2ToFlash = true;
  477. Serial.println("web triggered saveConfig2ToFlash");
  478. }
  479. yield();
  480. //build json object of program data
  481. StaticJsonBuffer<1000> jsonBuffer;
  482. JsonObject &json = jsonBuffer.createObject();
  483. json["domIdxTherm"] = domoticzIdx_Thermostat;
  484. json["domIdxMode"] = domoticzIdx_ThermostatMode;
  485. json["domIdxTempHum"] = domoticzIdx_TempHumSensor;
  486. json["domIdxPIR"] = domoticzIdx_PIR;
  487. json["outTempTop"] = outTemp_topic_in;
  488. json["outHumTop"] = outHum_topic_in;
  489. json["autoSaveTemp"] = autoSaveSetTemp;
  490. json["autoSaveMode"] = autoSaveHeatingMode;
  491. json["minOffTime"] = heatingMinOffTime;
  492. json["tempMin"] = setTempMin;
  493. json["tempMax"] = setTempMax;
  494. json["tempLow"] = setTempLow;
  495. json["hyst"] = hysteresis;
  496. json["tempCorr"] = tempCorrVal;
  497. json["humCorr"] = humCorrVal;
  498. json["measInt"] = measureInterval;
  499. json["dispInt"] = displayInterval;
  500. json["dispTout"] = displayTimeout;
  501. yield();
  502. char jsonchar[1000];
  503. json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
  504. httpServer.send(200, "application/json", jsonchar);
  505. }
  506. }); //httpServer.on /confdata2
  507. //get heap status, analog input value and all GPIO statuses in one json call
  508. httpServer.on("/info", HTTP_GET, []() {
  509. boolean sendData = false;
  510. if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
  511. if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
  512. sendData = true;
  513. }
  514. else sendData = true;
  515. if (sendData) {
  516. String json = " {";
  517. json += "\"wifissid\":\"" + WiFi.SSID() + "\"";
  518. json += "\"heap\":" + String(ESP.getFreeHeap());
  519. json += "}";
  520. httpServer.send(200, "text/json", json);
  521. json = String();
  522. }
  523. }); //httpServer.on /info
  524. httpServer.on("/", []() {
  525. httpServerHandleRoot();
  526. });
  527. httpServer.on("/conf", []() {
  528. httpServerHandleConfPage();
  529. });
  530. httpServer.on("/conf2", []() {
  531. httpServerHandleConf2Page();
  532. });
  533. httpServer.onNotFound([]() {
  534. httpServerHandleNotFound();
  535. }); //httpServer.onNotFound
  536. // HTTP Updater at /update
  537. httpUpdater.setup(&httpServer);
  538. httpServer.begin();
  539. }