httpServer.ino 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. //extern ESP8266WebServer httpServer;
  2. static const char httpRoot[] PROGMEM =
  3. R"(<html><body>
  4. <h1><span id='devname'></span></h1>
  5. <h3>WiFi Switch</h3>
  6. <form id='BtnFrm1'><input type='hidden' name='Btn1' value='1'></form>
  7. <form id='BtnFrm2'><input type='hidden' name='Btn2' value='1'></form>
  8. <form id='BtnFrm3'><input type='hidden' name='Btn3' value='1'></form>
  9. <div style='font-size:xx-large'>
  10. <div id='sw1div'>1: <input type='button' id='tbtn1' onclick='return sendBtn(1)'/><br></div>
  11. <div id='sw2div' style='display:none;'>2: <input type='button' id='tbtn2' onclick='return sendBtn(2)'/><br></div>
  12. <div id='sw3div' style='display:none'>3: <input type='button' id='tbtn3' onclick='return sendBtn(3)'/><br></div>
  13. </div>
  14. <br>
  15. <br>
  16. WiFi verbunden mit <i><span id='ssid'></span></i>.<br>
  17. <h6>Letztes Update vor
  18. <span id='ut'></span> Sekunden.
  19. <span id='status'></span>
  20. </h6>
  21. <br>
  22. <a href='/wifi.htm'>WiFi-Einstellungen</a><br>
  23. <a href='/config'>Einstellungen</a><br>
  24. <a href='/update'>Firmware Update</a>
  25. <script>
  26. function g(i) { return document.getElementById(i) };
  27. var xhttp, updateTime, reqTime, reqFin;
  28. var textA = 'AUS';
  29. var textE = 'EIN';
  30. function sendBtn(btn) {
  31. var frmn='BtnFrm'+btn;
  32. var form = g(frmn);
  33. return transmit(form);
  34. }
  35. function transmit(f) {
  36. if (!xhttp) {
  37. g('status').innerHTML = 'l&auml;dt...';
  38. reqTime = 0;
  39. reqFin = false;
  40. xhttp = new XMLHttpRequest();
  41. xhttp.timeout = 2000;
  42. xhttp.open('POST', 'api');
  43. xhttp.send(f ? (new FormData(f)) : '');
  44. xhttp.onreadystatechange = function () {
  45. if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
  46. var data = JSON.parse(xhttp.responseText);
  47. g('ssid').innerHTML = data.ssid;
  48. if(data.devname != undefined) g('devname').innerHTML = data.devname;
  49. if(data.swState2 != undefined) g('sw2div').style.display='inline';
  50. else g('sw2div').style.display='none';
  51. if(data.swState3 != undefined) g('sw3div').style.display='inline';
  52. else g('sw3div').style.display='none';
  53. if(data.swState1 == '1') g('tbtn1').value = textE;
  54. else g('tbtn1').value = textA;
  55. if(data.swState2 == '1') g('tbtn2').value = textE;
  56. else g('tbtn2').value = textA;
  57. if(data.swState3 == '1') g('tbtn3').value = textE;
  58. else g('tbtn3').value = textA;
  59. xhttp = null;
  60. updateTime = 0;
  61. reqFin = true;
  62. }
  63. else{
  64. if(!reqFin && reqTime > 10) {
  65. xhttp = null;
  66. reqFin = true;
  67. }
  68. }
  69. }
  70. }
  71. return false;
  72. }
  73. transmit();
  74. setInterval(function () { g('ut').innerHTML = ++updateTime; ++reqTime; }, 1000);
  75. setInterval(transmit, 5000);
  76. </script>
  77. </body></html>)";
  78. static const char httpConfPage[] PROGMEM =
  79. R"(<html><head><body>
  80. <h3>Configuration</h3>
  81. <input type='button' value='reload' onclick='return transmit()'/><br><br>
  82. <form id='form1' onsubmit='return transmit(this)'>
  83. Device Name: <input type='text' name='devName' id='devName'/><br>
  84. HTTP User *: <input type='text' name='httpUser' id='httpUser'/><br>
  85. HTTP Password *: <input type='password' name='httpPass' id='httpPass'/><br>
  86. MQTT Server *: <input type='text' name='mqttHost' id='mqttHost'/><br>
  87. MQTT Port *: <input type='number' name='mqttPort' id='mqttPort'/><br>
  88. MQTT User *: <input type='text' name='mqttUser' id='mqttUser'/><br>
  89. MQTT Password *: <input type='password' name='mqttPass' id='mqttPass'/><br>
  90. In Topic *: <input type='text' name='inTop' id='inTop'/><br>
  91. Out Topic: <input type='text' name='outTop' id='outTop'/><br>
  92. LastWill Topic *: <input type='text' name='willTop' id='willTop'/><br>
  93. LastWill Qos *: <input type='number' name='willQos' id='willQos'/><br>
  94. LastWill Retain *: <input type='checkbox' name='willRet' id='willRet'/><br>
  95. LastWill Message *: <input type='text' name='willMsg' id='willMsg'/><br>
  96. Domoticz Out Topic *: <input type='text' name='domoOutTop' id='domoOutTop'/><br>
  97. <br>
  98. <input type='submit' value='Save'/>
  99. </form>
  100. <form id='restartForm' onsubmit='return res()'>
  101. <input type='hidden' name='restart' value='1'>
  102. <input type='submit' value='Restart'/>
  103. </form>
  104. <script>
  105. function g(i) { return document.getElementById(i) };
  106. var xhttp, reqTime, reqFin, rxhttp;
  107. function res() {
  108. rxhttp = new XMLHttpRequest();
  109. rxhttp.timeout = 1000;
  110. rxhttp.open('POST', 'restart');
  111. rxhttp.send('');
  112. rxhttp = null;
  113. return false;
  114. }
  115. function transmit(f) {
  116. if (!xhttp) {
  117. reqTime = 0;
  118. reqFin = false;
  119. var wRet = g('willRet');
  120. if (wRet.checked) wRet.value ='1';
  121. else {
  122. wRet.value = '0';
  123. wRet.checked = true;
  124. wRet.style.visibility = 'hidden';
  125. }
  126. xhttp = new XMLHttpRequest();
  127. xhttp.timeout = 2000;
  128. xhttp.open('POST', 'confdata');
  129. xhttp.send(f ? (new FormData(f)) : '');
  130. xhttp.onreadystatechange = function () {
  131. if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
  132. var data = JSON.parse(xhttp.responseText);
  133. g('httpUser').value = data.httpUser;
  134. g('httpPass').value = data.httpPass;
  135. g('devName').value = data.devName
  136. g('mqttHost').value = data.mqttHost;
  137. g('mqttPort').value = data.mqttPort;
  138. g('mqttUser').value = data.mqttUser;
  139. g('mqttPass').value = data.mqttPass;
  140. g('inTop').value = data.inTop;
  141. g('outTop').value = data.outTop;
  142. g('willTop').value = data.willTop;
  143. g('willQos').value = data.willQos;
  144. if(data.willRet == 1) {
  145. wRet.checked = true;
  146. wRet.style.visibility = 'visible';
  147. }
  148. else {
  149. wRet.checked = false;
  150. wRet.style.visibility = 'visible';
  151. }
  152. g('willMsg').value = data.willMsg;
  153. g('domoOutTop').value = data.domoOutTop;
  154. xhttp = null;
  155. reqFin = true;
  156. }
  157. else{
  158. if(!reqFin && reqTime > 10) {
  159. xhttp = null;
  160. reqFin = true;
  161. }
  162. }
  163. }
  164. }
  165. return false;
  166. }
  167. transmit();
  168. setInterval(function () { ++reqTime; }, 1000);
  169. </script>
  170. </body></html>)";
  171. static const char httpConf2Page[] PROGMEM =
  172. R"(<html><head><body>
  173. <h3>Configuration 2</h3>
  174. <input type='button' value='reload' onclick='return transmit()'/><br><br>
  175. <form id='form1' onsubmit='return transmit(this)'>
  176. used Relais: <input type='number' name='usedRelais' id='usedRelais'/><br>
  177. used Buttons: <input type='number' name='usedButtons' id='usedButtons'/><br>
  178. Out Topic Hold 1: <input type='text' name='outTop_hold1' id='outTop_hold1'/><br>
  179. Out Topic Hold 2: <input type='text' name='outTop_hold2' id='outTop_hold2'/><br>
  180. Out Topic Hold 3: <input type='text' name='outTop_hold3' id='outTop_hold3'/><br>
  181. Out Payload Hold 1: <input type='text' name='outPld_hold1' id='outPld_hold1'/><br>
  182. Out Payload Hold 2: <input type='text' name='outPld_hold2' id='outPld_hold2'/><br>
  183. Out Payload Hold 3: <input type='text' name='outPld_hold3' id='outPld_hold3'/><br>
  184. Domoticz Idx 1: <input type='number' name='domoIdx1' id='domoIdx1'/><br>
  185. Domoticz Idx 2: <input type='number' name='domoIdx2' id='domoIdx2'/><br>
  186. Domoticz Idx 3: <input type='number' name='domoIdx3' id='domoIdx3'/><br>
  187. Relais Impulse 1: <input type='number' name='impuls1' id='impuls1'/><br>
  188. Relais Impulse 2: <input type='number' name='impuls2' id='impuls2'/><br>
  189. Relais Impulse 3: <input type='number' name='impuls3' id='impuls3'/><br>
  190. <br>
  191. <input type='submit' value='Save'/>
  192. </form>
  193. <form id='rebootForm' onsubmit='return res()'>
  194. <input type='submit' value='Restart'/>
  195. </form>
  196. <script>
  197. function g(i) { return document.getElementById(i) };
  198. var xhttp, reqTime, reqFin, rxhttp;
  199. function res() {
  200. rxhttp = new XMLHttpRequest();
  201. rxhttp.timeout = 1000;
  202. rxhttp.open('POST', 'restart');
  203. rxhttp.send('');
  204. rxhttp = null;
  205. return false;
  206. }
  207. function transmit(f) {
  208. if (!xhttp) {
  209. xhttp = new XMLHttpRequest();
  210. xhttp.timeout = 2000;
  211. xhttp.open('POST', 'confdata2');
  212. xhttp.send(f ? (new FormData(f)) : '');
  213. xhttp.onreadystatechange = function () {
  214. if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
  215. var data = JSON.parse(xhttp.responseText);
  216. g('usedRelais').value = data.usedRelais;
  217. g('usedButtons').value = data.usedButtons;
  218. g('outTop_hold1').value = data.outTop_hold1;
  219. g('outTop_hold2').value = data.outTop_hold2;
  220. g('outTop_hold3').value = data.outTop_hold3;
  221. g('outPld_hold1').value = data.outPld_hold1;
  222. g('outPld_hold2').value = data.outPld_hold2;
  223. g('outPld_hold3').value = data.outPld_hold3;
  224. g('domoIdx1').value = data.domoIdx1;
  225. g('domoIdx2').value = data.domoIdx2;
  226. g('domoIdx3').value = data.domoIdx3;
  227. g('impuls1').value = data.impuls1;
  228. g('impuls2').value = data.impuls2;
  229. g('impuls3').value = data.impuls3;
  230. xhttp = null;
  231. reqFin = false;
  232. }
  233. else {
  234. if(!reqFin && reqTime > 10) {
  235. xhttp = null;
  236. reqFin = true;
  237. }
  238. }
  239. }
  240. }
  241. return false;
  242. }
  243. transmit();
  244. setInterval(function () { ++reqTime; }, 1000);
  245. </script>
  246. </body></html>)";
  247. void httpServerHandleRoot() {
  248. httpServer.send_P(200, "text/html", httpRoot);
  249. }
  250. void httpServerHandleConfPage() {
  251. httpServer.send_P(200, "text/html", httpConfPage);
  252. }
  253. void httpServerHandleConf2Page() {
  254. httpServer.send_P(200, "text/html", httpConf2Page);
  255. }
  256. void httpServerHandleNotFound() {
  257. String message = "File Not Found\n\n";
  258. message += "URI: ";
  259. message += httpServer.uri();
  260. message += "\nMethod: ";
  261. message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
  262. message += "\nArguments: ";
  263. message += httpServer.args();
  264. message += "\n";
  265. for (uint8_t i = 0; i < httpServer.args(); i++) {
  266. message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
  267. }
  268. httpServer.send(404, "text/plain", message);
  269. }
  270. void httpServerInit() {
  271. //handles commands from webpage, sends live data in JSON format
  272. httpServer.on("/api", []() {
  273. //Serial.println("httpServer.on /api");
  274. if (httpServer.hasArg("Btn1")) {
  275. lastSwitchSource[0] = 2;
  276. relaisToggle(0);
  277. Serial.println("web Btn1");
  278. } //if
  279. if (httpServer.hasArg("Btn2")) {
  280. lastSwitchSource[1] = 2;
  281. relaisToggle(1);
  282. Serial.println("web Btn2");
  283. } //if
  284. if (httpServer.hasArg("Btn3")) {
  285. lastSwitchSource[2] = 2;
  286. relaisToggle(2);
  287. Serial.println("web Btn3");
  288. } //if
  289. //build json object of program data
  290. StaticJsonBuffer<200> jsonBuffer;
  291. JsonObject &json = jsonBuffer.createObject();
  292. json["ssid"] = WiFi.SSID();
  293. json["swState1"] = relais_state[0];
  294. if (RELAIS_COUNT > 1) json["swState2"] = relais_state[1];
  295. if (RELAIS_COUNT > 2) json["swState3"] = relais_state[2];
  296. json["devname"] = deviceName;
  297. char jsonchar[200];
  298. json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
  299. httpServer.send(200, "application/json", jsonchar);
  300. }); //httpServer.on /api
  301. httpServer.on("/restart", []() {
  302. Serial.println("web triggered restart");
  303. ESP.restart();
  304. });
  305. httpServer.on("/confdata", []() {
  306. Serial.println("httpServer.on /confdata");
  307. // if (httpServer.hasArg("saveToFlash")) {
  308. // if (httpServer.arg("saveToFlash").toInt() == 1) {
  309. // Serial.println("web saveToFlash triggered");
  310. // //saveConfig();
  311. // saveConfigToFlash = true;
  312. // }
  313. // }
  314. // else if (httpServer.hasArg("restart")) {
  315. // if (httpServer.arg("restart").toInt() == 1) {
  316. // Serial.println("web restart triggered");
  317. // ESP.restart();
  318. // }
  319. // }
  320. // else {
  321. for (int i = 0; i < httpServer.args(); i++) {
  322. char bufName[20];
  323. char bufValue[101];
  324. httpServer.argName(i).toCharArray(bufName, 20);
  325. httpServer.arg(i).toCharArray(bufValue, 101);
  326. //if(strcmp(bufName, "willRet") == 0) {
  327. // willRetSet = true;
  328. // }
  329. //if (strlen(bufName) > 0 && strlen(bufValue) > 0) {
  330. if (strlen(bufName) > 0) {
  331. Serial.print("web update ");
  332. Serial.print(bufName);
  333. Serial.print(" = ");
  334. Serial.println(bufValue);
  335. setConfig(bufName, bufValue);
  336. }
  337. saveConfigToFlash = true; // will be saved in next loop()
  338. Serial.println("web triggered saveConfigToFlash");
  339. }
  340. // }
  341. //build json object of program data
  342. StaticJsonBuffer<1000> jsonBuffer;
  343. JsonObject &json = jsonBuffer.createObject();
  344. json["devName"] = deviceName;
  345. json["httpUser"] = http_user;
  346. json["httpPass"] = http_pass;
  347. json["mqttHost"] = mqtt_server;
  348. json["mqttPort"] = mqtt_port;
  349. json["mqttUser"] = mqtt_user;
  350. json["mqttPass"] = mqtt_pass;
  351. json["inTop"] = mqtt_topic_in;
  352. json["outTop"] = mqtt_topic_out;
  353. json["willTop"] = mqtt_willTopic;
  354. json["willQos"] = mqtt_willQos;
  355. json["willRet"] = mqtt_willRetain;
  356. json["willMsg"] = mqtt_willMsg;
  357. json["domoOutTop"] = domoticz_out_topic;
  358. char jsonchar[1000];
  359. json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
  360. httpServer.send(200, "application/json", jsonchar);
  361. }); //httpServer.on /confdata
  362. httpServer.on("/confdata2", []() {
  363. Serial.println("httpServer.on /confdata2");
  364. // if (httpServer.hasArg("saveToFlash")) {
  365. // if (httpServer.arg("saveToFlash").toInt() == 1) {
  366. // Serial.println("web saveToFlash triggered");
  367. // //saveConfig();
  368. // saveConfigToFlash = true;
  369. // }
  370. // }
  371. // else if (httpServer.hasArg("restart")) {
  372. // if (httpServer.arg("restart").toInt() == 1) {
  373. // Serial.println("web restart triggered");
  374. // ESP.restart();
  375. // }
  376. // }
  377. // else {
  378. for (int i = 0; i < httpServer.args(); i++) {
  379. char bufName[20];
  380. char bufValue[101];
  381. httpServer.argName(i).toCharArray(bufName, 20);
  382. httpServer.arg(i).toCharArray(bufValue, 101);
  383. //if(strcmp(bufName, "willRet") == 0) {
  384. // willRetSet = true;
  385. // }
  386. //if (strlen(bufName) > 0 && strlen(bufValue) > 0) {
  387. if (strlen(bufName) > 0) {
  388. Serial.print("web update ");
  389. Serial.print(bufName);
  390. Serial.print(" = ");
  391. Serial.println(bufValue);
  392. setConfig(bufName, bufValue);
  393. }
  394. saveConfig2ToFlash = true;
  395. Serial.println("web triggered saveConfig2ToFlash");
  396. }
  397. // }
  398. //build json object of program data
  399. StaticJsonBuffer<1000> jsonBuffer;
  400. JsonObject &json = jsonBuffer.createObject();
  401. json["usedRelais"] = usedRelaisCount;
  402. json["usedButtons"] = usedButtonsCount;
  403. json["outTop_hold1"] = mqtt_topic_out_hold_1;
  404. json["outTop_hold2"] = mqtt_topic_out_hold_2;
  405. json["outTop_hold3"] = mqtt_topic_out_hold_3;
  406. json["outPld_hold1"] = mqtt_payload_out_hold_1;
  407. json["outPld_hold2"] = mqtt_payload_out_hold_2;
  408. json["outPld_hold3"] = mqtt_payload_out_hold_3;
  409. json["domoIdx1"] = domoticzIdx[0];
  410. json["domoIdx2"] = domoticzIdx[1];
  411. json["domoIdx3"] = domoticzIdx[2];
  412. json["impuls1"] = relais_impulse[0];
  413. json["impuls2"] = relais_impulse[1];
  414. json["impuls3"] = relais_impulse[2];
  415. char jsonchar[1000];
  416. json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
  417. httpServer.send(200, "application/json", jsonchar);
  418. }); //httpServer.on /confdata2
  419. //get heap status, analog input value and all GPIO statuses in one json call
  420. httpServer.on("/info", HTTP_GET, []() {
  421. String json = "{";
  422. json += "\"wifissid\":\"" + WiFi.SSID() + "\"";
  423. json += "\"heap\":" + String(ESP.getFreeHeap());
  424. //json += ", \"analog\":" + String(analogRead(A0));
  425. //json += ", \"gpio\":" + String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
  426. json += "}";
  427. httpServer.send(200, "text/json", json);
  428. json = String();
  429. }); //httpServer.on /info
  430. httpServer.on("/", []() {
  431. httpServerHandleRoot();
  432. });
  433. httpServer.on("/conf", []() {
  434. httpServerHandleConfPage();
  435. });
  436. httpServer.on("/conf2", []() {
  437. httpServerHandleConf2Page();
  438. });
  439. httpServer.onNotFound([]() {
  440. httpServerHandleNotFound();
  441. }); //httpServer.onNotFound
  442. // HTTP Updater at /update
  443. httpUpdater.setup(&httpServer);
  444. httpServer.begin();
  445. }