ESP32 / ESP8266 & BME280 / SHT2x sensor with InfluxDB support
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

html.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * html.cpp
  3. *
  4. * ESP8266 / ESP32 Environmental Sensor
  5. *
  6. * ----------------------------------------------------------------------------
  7. * "THE BEER-WARE LICENSE" (Revision 42):
  8. * <xythobuz@xythobuz.de> wrote this file. As long as you retain this notice
  9. * you can do whatever you want with this stuff. If we meet some day, and you
  10. * think this stuff is worth it, you can buy me a beer in return. Thomas Buck
  11. * ----------------------------------------------------------------------------
  12. */
  13. #include <Arduino.h>
  14. #if defined(ARDUINO_ARCH_ESP8266)
  15. #include <ESP8266WiFi.h>
  16. #include <ESP8266WebServer.h>
  17. #include <ESP8266mDNS.h>
  18. #define ESP_PLATFORM_NAME "ESP8266"
  19. #elif defined(ARDUINO_ARCH_ESP32)
  20. #include <WiFi.h>
  21. #include <WebServer.h>
  22. #include <ESPmDNS.h>
  23. #define ESP_PLATFORM_NAME "ESP32"
  24. #elif defined(ARDUINO_ARCH_AVR)
  25. #include <UnoWiFiDevEdSerial1.h>
  26. #include <WiFiLink.h>
  27. #define ESP_PLATFORM_NAME "Uno WiFi"
  28. #endif
  29. #include "config.h"
  30. #include "DebugLog.h"
  31. #include "sensors.h"
  32. #include "servers.h"
  33. #include "memory.h"
  34. #include "relais.h"
  35. #include "moisture.h"
  36. #include "html.h"
  37. #if defined(ARDUINO_ARCH_AVR)
  38. #define ARDUINO_SEND_PARTIAL_PAGE() do { \
  39. size_t len = message.length(), off = 0; \
  40. while (off < len) { \
  41. if ((len - off) >= 50) { \
  42. client.write(message.c_str() + off, 50); \
  43. off += 50; \
  44. } else { \
  45. client.write(message.c_str() + off, len - off); \
  46. off = len; \
  47. } \
  48. } \
  49. message = ""; \
  50. } while (false);
  51. #else
  52. #define ARDUINO_SEND_PARTIAL_PAGE() while (false) { }
  53. #endif
  54. #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
  55. void handlePage(int mode, int id) {
  56. #else
  57. void handlePage(WiFiClient &client, int mode, int id) {
  58. #endif
  59. String message;
  60. message += F("<!DOCTYPE html>");
  61. message += F("<html><head>");
  62. message += F("<meta charset='utf-8'/>");
  63. message += F("<meta name='viewport' content='width=device-width, initial-scale=1'/>");
  64. message += F("<title>" ESP_PLATFORM_NAME " Environment Sensor</title>");
  65. message += F("<style>");
  66. message += F(".log {\n");
  67. message += F( "max-height: 300px;\n");
  68. message += F( "padding: 0 1.0em;\n");
  69. message += F( "max-width: 1200px;\n");
  70. message += F( "margin: auto;\n");
  71. message += F( "margin-top: 1.5em;\n");
  72. message += F( "border: 1px dashed black;\n");
  73. message += F( "font-family: monospace;\n");
  74. message += F( "overflow-y: scroll;\n");
  75. message += F( "word-break: break-all;\n");
  76. message += F("}\n");
  77. message += F("#logbuf {\n");
  78. message += F( "white-space: break-spaces;\n");
  79. message += F("}\n");
  80. message += F("@media (prefers-color-scheme: dark) {");
  81. message += F( "body {");
  82. message += F( "background-color: black;");
  83. message += F( "color: white;");
  84. message += F( "}");
  85. message += F( ".log {\n");
  86. message += F( "border-color: white;");
  87. message += F( "}");
  88. message += F("}");
  89. message += F("</style>");
  90. message += F("</head><body>");
  91. message += F("<h1>" ESP_PLATFORM_NAME " Environment Sensor</h1>");
  92. message += F("\n<p>\n");
  93. message += F("Version: ");
  94. message += ESP_ENV_VERSION;
  95. message += F("\n<br>\n");
  96. message += F("Location: ");
  97. message += SENSOR_LOCATION;
  98. message += F("\n<br>\n");
  99. message += F("ID: ");
  100. message += SENSOR_ID;
  101. #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
  102. message += F("\n<br>\n");
  103. message += F("MAC: ");
  104. message += WiFi.macAddress();
  105. #endif
  106. message += F("\n</p>\n");
  107. ARDUINO_SEND_PARTIAL_PAGE();
  108. #if defined(ARDUINO_ARCH_ESP8266)
  109. message += F("<p>");
  110. message += F("Reset reason: ");
  111. message += ESP.getResetReason();
  112. message += F("<br>");
  113. message += F("Free heap: ");
  114. message += String(ESP.getFreeHeap());
  115. message += F(" (");
  116. message += String(ESP.getHeapFragmentation());
  117. message += F("% fragmentation)");
  118. message += F("<br>");
  119. message += F("Free sketch space: ");
  120. message += String(ESP.getFreeSketchSpace());
  121. message += F("<br>");
  122. message += F("Flash chip real size: ");
  123. message += String(ESP.getFlashChipRealSize());
  124. if (ESP.getFlashChipSize() != ESP.getFlashChipRealSize()) {
  125. message += F("<br>");
  126. message += F("WARNING: sdk chip size (");
  127. message += (ESP.getFlashChipSize());
  128. message += F(") does not match!");
  129. }
  130. message += F("</p>");
  131. #elif defined(ARDUINO_ARCH_ESP32)
  132. message += F("<p>");
  133. message += F("Free heap: ");
  134. message += String(ESP.getFreeHeap() / 1024.0);
  135. message += F("k<br>");
  136. message += F("Free sketch space: ");
  137. message += String(ESP.getFreeSketchSpace() / 1024.0);
  138. message += F("k<br>");
  139. message += F("Flash chip size: ");
  140. message += String(ESP.getFlashChipSize() / 1024.0);
  141. message += F("k</p><hr>");
  142. #endif
  143. message += F("\n<p>\n");
  144. if (found_bme1) {
  145. message += F("BME280 Low:");
  146. message += F("\n<br>\n");
  147. message += F("Temperature: ");
  148. message += String(bme1_temp());
  149. message += F("\n<br>\n");
  150. message += F("Humidity: ");
  151. message += String(bme1_humid());
  152. message += F("\n<br>\n");
  153. message += F("Pressure: ");
  154. message += String(bme1_pressure());
  155. message += F("\n<br>\n");
  156. message += F("Offset: ");
  157. message += String(config.bme1_temp_off);
  158. message += F("\n<br>\n");
  159. message += F("<form method=\"GET\" action=\"/calibrate\">");
  160. message += F("<input type=\"text\" name=\"bme1\" placeholder=\"Real Temp.\">");
  161. message += F("<input type=\"submit\" value=\"Calibrate\">");
  162. message += F("</form>");
  163. } else {
  164. message += F("BME280 (low) not connected!");
  165. }
  166. message += F("\n</p><hr>\n");
  167. message += F("\n<p>\n");
  168. if (found_bme2) {
  169. message += F("BME280 High:");
  170. message += F("\n<br>\n");
  171. message += F("Temperature: ");
  172. message += String(bme2_temp());
  173. message += F("\n<br>\n");
  174. message += F("Humidity: ");
  175. message += String(bme2_humid());
  176. message += F("\n<br>\n");
  177. message += F("Pressure: ");
  178. message += String(bme2_pressure());
  179. message += F("\n<br>\n");
  180. message += F("Offset: ");
  181. message += String(config.bme2_temp_off);
  182. message += F("\n<br>\n");
  183. message += F("<form method=\"GET\" action=\"/calibrate\">");
  184. message += F("<input type=\"text\" name=\"bme2\" placeholder=\"Real Temp.\">");
  185. message += F("<input type=\"submit\" value=\"Calibrate\">");
  186. message += F("</form>");
  187. } else {
  188. message += F("BME280 (high) not connected!");
  189. }
  190. message += F("\n</p><hr>\n");
  191. ARDUINO_SEND_PARTIAL_PAGE();
  192. message += F("\n<p>\n");
  193. if (found_sht) {
  194. message += F("SHT21:");
  195. message += F("\n<br>\n");
  196. message += F("Temperature: ");
  197. message += String(sht_temp());
  198. message += F("\n<br>\n");
  199. message += F("Humidity: ");
  200. message += String(sht_humid());
  201. message += F("\n<br>\n");
  202. message += F("Offset: ");
  203. message += String(config.sht_temp_off);
  204. message += F("\n<br>\n");
  205. message += F("<form method=\"GET\" action=\"/calibrate\">");
  206. message += F("<input type=\"text\" name=\"sht\" placeholder=\"Real Temp.\">");
  207. message += F("<input type=\"submit\" value=\"Calibrate\">");
  208. message += F("</form>");
  209. } else {
  210. message += F("SHT21 not connected!");
  211. }
  212. message += F("\n</p><hr>\n");
  213. #ifdef ENABLE_CCS811
  214. message += F("\n<p>\n");
  215. if (found_ccs1) {
  216. message += F("CCS811 Low:");
  217. message += F("\n<br>\n");
  218. message += F("eCO2: ");
  219. message += String(ccs1_eco2());
  220. message += F("ppm");
  221. message += F("\n<br>\n");
  222. message += F("TVOC: ");
  223. message += String(ccs1_tvoc());
  224. message += F("ppb");
  225. if (!ccs1_data_valid) {
  226. message += F("\n<br>\n");
  227. message += F("Data invalid (");
  228. message += String(ccs1_error_code);
  229. message += F(")!");
  230. }
  231. } else {
  232. message += F("CCS811 (Low) not connected!");
  233. }
  234. message += F("\n</p><hr>\n");
  235. message += F("\n<p>\n");
  236. if (found_ccs2) {
  237. message += F("CCS811 High:");
  238. message += F("\n<br>\n");
  239. message += F("eCO2: ");
  240. message += String(ccs2_eco2());
  241. message += F("ppm");
  242. message += F("\n<br>\n");
  243. message += F("TVOC: ");
  244. message += String(ccs2_tvoc());
  245. message += F("ppb");
  246. if (!ccs2_data_valid) {
  247. message += F("\n<br>\n");
  248. message += F("Data invalid (");
  249. message += String(ccs2_error_code);
  250. message += F(")!");
  251. }
  252. } else {
  253. message += F("CCS811 (High) not connected!");
  254. }
  255. message += F("\n</p><hr>\n");
  256. #endif // ENABLE_CCS811
  257. ARDUINO_SEND_PARTIAL_PAGE();
  258. #ifdef FEATURE_MOISTURE
  259. for (int i = 0; i < moisture_count(); i++) {
  260. int moisture = moisture_read(i);
  261. if (moisture < moisture_max()) {
  262. message += F("\n<p>\n");
  263. message += F("Sensor ");
  264. message += String(i + 1);
  265. message += F(":\n<br>\n");
  266. message += F("Moisture: ");
  267. message += String(moisture);
  268. message += F(" / ");
  269. message += String(moisture_max());
  270. message += F("\n</p>\n");
  271. }
  272. }
  273. if (moisture_count() <= 0) {
  274. message += F("\n<p>\n");
  275. message += F("No moisture sensors configured!");
  276. message += F("\n</p>\n");
  277. }
  278. ARDUINO_SEND_PARTIAL_PAGE();
  279. #endif // FEATURE_MOISTURE
  280. #ifdef FEATURE_RELAIS
  281. message += F("\n<p>\n");
  282. for (int i = 0; i < relais_count(); i++) {
  283. message += String(F("<a href=\"/on?id=")) + String(i) + String(F("\">Relais ")) + String(i) + String(F(" On (")) + relais_name(i) + String(F(")</a><br>\n"));
  284. message += String(F("<a href=\"/off?id=")) + String(i) + String(F("\">Relais ")) + String(i) + String(F(" Off (")) + relais_name(i) + String(F(")</a><br>\n"));
  285. }
  286. message += String(F("<a href=\"/on?id=")) + String(relais_count()) + String(F("\">All Relais On</a><br>\n"));
  287. message += String(F("<a href=\"/off?id=")) + String(relais_count()) + String(F("\">All Relais Off</a><br>\n"));
  288. message += F("</p>\n");
  289. if ((mode >= 0) && (mode <= 1)) {
  290. message += F("<p>");
  291. message += F("Turned Relais ");
  292. message += (id < relais_count()) ? String(id) : String(F("1-4"));
  293. message += (mode ? String(F(" On")) : String(F(" Off")));
  294. message += F("</p>\n");
  295. }
  296. message += F("\n<p>\n");
  297. for (int i = 0; i < relais_count(); i++) {
  298. message += String(F("Relais ")) + String(i) + String(F(" (")) + relais_name(i) + String(F(") = ")) + (relais_get(i) ? String(F("On")) : String(F("Off"))) + String(F("<br>\n"));
  299. }
  300. message += F("</p>\n");
  301. ARDUINO_SEND_PARTIAL_PAGE();
  302. #endif // FEATURE_RELAIS
  303. if (mode == 42) {
  304. message += F("<p>New calibration value saved!</p>\n");
  305. }
  306. #if ! defined(ARDUINO_ARCH_AVR)
  307. message += F("<p>");
  308. message += F("Try <a href=\"/update\">/update</a> for OTA firmware updates!");
  309. message += F("</p><p>");
  310. message += F("Try <a href=\"/reset\">/reset</a> to reset ESP!");
  311. message += F("</p>");
  312. #endif
  313. message += F("<p>");
  314. #ifdef ENABLE_INFLUXDB_LOGGING
  315. message += F("InfluxDB: ");
  316. message += INFLUXDB_DATABASE;
  317. message += F(" @ ");
  318. message += INFLUXDB_HOST;
  319. message += F(":");
  320. message += String(INFLUXDB_PORT);
  321. #else
  322. message += F("InfluxDB logging not enabled!");
  323. #endif
  324. message += F("</p>");
  325. message += F("<p>Uptime: ");
  326. message += String(millis() / 1000);
  327. message += F(" sec.</p>");
  328. #if ! defined(ARDUINO_ARCH_AVR)
  329. message += F("<hr><p>Debug Log:</p>");
  330. message += F("<div class='log'><pre id='logbuf'>");
  331. message += debug.getBuffer();
  332. message += F("</pre></div>");
  333. #endif
  334. message += F("</body>");
  335. #if ! defined(ARDUINO_ARCH_AVR)
  336. message += F("<script type='text/javascript'>\n");
  337. message += F("var socket = new WebSocket('ws://' + window.location.hostname + ':81');\n");
  338. message += F("socket.onmessage = function(e) {");
  339. message += F( "var log = document.getElementById('logbuf');");
  340. message += F( "var div = document.getElementsByClassName('log')[0];");
  341. message += F( "log.innerHTML += e.data.substring(4);");
  342. message += F( "if (log.innerHTML.length > (1024 * 1024)) {");
  343. message += F( "log.innerHTML = log.innerHTML.substring(1024 * 1024);");
  344. message += F( "}");
  345. message += F( "div.scrollTop = div.scrollHeight;");
  346. message += F("};\n");
  347. message += F("var hist = document.getElementsByClassName('log')[0];\n");
  348. message += F("hist.scrollTop = hist.scrollHeight;\n");
  349. message += F("</script>\n");
  350. #endif
  351. message += F("</html>");
  352. #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
  353. server.send(200, "text/html", message);
  354. #else
  355. ARDUINO_SEND_PARTIAL_PAGE();
  356. #endif
  357. }
  358. #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
  359. void handleReset() {
  360. String message;
  361. message += F("<!DOCTYPE html>");
  362. message += F("<html><head>");
  363. message += F("<meta charset='utf-8'/>");
  364. message += F("<meta name='viewport' content='width=device-width, initial-scale=1'/>");
  365. message += F("<meta http-equiv='refresh' content='10; URL=/'/>");
  366. message += F("<title>" ESP_PLATFORM_NAME " Environment Sensor</title>");
  367. message += F("<style>");
  368. message += F("@media (prefers-color-scheme: dark) {");
  369. message += F( "body {");
  370. message += F( "background-color: black;");
  371. message += F( "color: white;");
  372. message += F( "}");
  373. message += F("}");
  374. message += F("</style>");
  375. message += F("</head><body>");
  376. message += F("<p>Resetting in 2s...</p>");
  377. message += F("<p>Auto redirect in 10s. Please retry manually on error.</p>");
  378. message += F("<p>Go <a href=\"/\">back</a> to start.</p>");
  379. message += F("</body></html>");
  380. server.send(200, "text/html", message);
  381. delay(2000);
  382. ESP.restart();
  383. }
  384. #endif