|
@@ -29,6 +29,7 @@ UPDATE_WEB_SERVER server(80);
|
29
|
29
|
WebSocketsServer socket = WebSocketsServer(81);
|
30
|
30
|
SimpleUpdater updater;
|
31
|
31
|
unsigned long last_server_handle_time = 0;
|
|
32
|
+unsigned long last_websocket_update_time = 0;
|
32
|
33
|
|
33
|
34
|
String message_buffer_a;
|
34
|
35
|
String message_buffer_b;
|
|
@@ -40,6 +41,17 @@ void wifi_set_message_buffer(String a, String b, String c, String d) {
|
40
|
41
|
message_buffer_b = b;
|
41
|
42
|
message_buffer_c = c;
|
42
|
43
|
message_buffer_d = d;
|
|
44
|
+}
|
|
45
|
+
|
|
46
|
+void wifi_schedule_websocket(void) {
|
|
47
|
+ last_websocket_update_time = 0;
|
|
48
|
+}
|
|
49
|
+
|
|
50
|
+void wifi_send_websocket(void) {
|
|
51
|
+ String a = message_buffer_a ;
|
|
52
|
+ String b = message_buffer_b;
|
|
53
|
+ String c = message_buffer_c;
|
|
54
|
+ String d = message_buffer_d;
|
43
|
55
|
|
44
|
56
|
a.replace("\"", "'");
|
45
|
57
|
b.replace("\"", "'");
|
|
@@ -47,12 +59,64 @@ void wifi_set_message_buffer(String a, String b, String c, String d) {
|
47
|
59
|
d.replace("\"", "'");
|
48
|
60
|
|
49
|
61
|
String ws = "{\n";
|
|
62
|
+
|
50
|
63
|
ws += "\"a\": \"" + a + "\",\n";
|
51
|
64
|
ws += "\"b\": \"" + b + "\",\n";
|
52
|
65
|
ws += "\"c\": \"" + c + "\",\n";
|
53
|
66
|
ws += "\"d\": \"" + d + "\",\n";
|
54
|
|
- ws += "\"state\": \"" + String(control_state_name()) + "\"\n";
|
|
67
|
+
|
|
68
|
+ ws += "\"state\": \"" + String(control_state_name()) + "\",\n";
|
|
69
|
+
|
|
70
|
+ ws += F("\"valves\": [ ");
|
|
71
|
+ for (int i = 0; i < VALVE_COUNT; i++) {
|
|
72
|
+ ws += "\"";
|
|
73
|
+ ws += get_plants()->getValves()->getPin(i) ? "1" : "0";
|
|
74
|
+ ws += "\"";
|
|
75
|
+
|
|
76
|
+ if (i < (VALVE_COUNT - 1)) {
|
|
77
|
+ ws += ", ";
|
|
78
|
+ }
|
|
79
|
+ }
|
|
80
|
+ ws += " ],\n";
|
|
81
|
+
|
|
82
|
+ ws += F("\"pumps\": [ ");
|
|
83
|
+ for (int i = 0; i < PUMP_COUNT; i++) {
|
|
84
|
+ ws += "\"";
|
|
85
|
+ ws += get_plants()->getPumps()->getPin(i) ? "1" : "0";
|
|
86
|
+ ws += "\"";
|
|
87
|
+
|
|
88
|
+ if (i < (PUMP_COUNT - 1)) {
|
|
89
|
+ ws += ", ";
|
|
90
|
+ }
|
|
91
|
+ }
|
|
92
|
+ ws += " ],\n";
|
|
93
|
+
|
|
94
|
+ ws += F("\"switches\": [ ");
|
|
95
|
+ for (int i = 0; i < SWITCH_COUNT; i++) {
|
|
96
|
+ ws += "\"";
|
|
97
|
+ ws += get_plants()->getSwitches()->getPin(i) ? "1" : "0";
|
|
98
|
+ ws += "\"";
|
|
99
|
+
|
|
100
|
+ if (i < (SWITCH_COUNT - 1)) {
|
|
101
|
+ ws += ", ";
|
|
102
|
+ }
|
|
103
|
+ }
|
|
104
|
+ ws += " ],\n";
|
|
105
|
+
|
|
106
|
+ ws += "\"switchstate\": \"";
|
|
107
|
+ Plants::Waterlevel wl = get_plants()->getWaterlevel();
|
|
108
|
+ if (wl == Plants::empty) {
|
|
109
|
+ ws += F("tank empty");
|
|
110
|
+ } else if (wl == Plants::inbetween) {
|
|
111
|
+ ws += F("tank half-filled");
|
|
112
|
+ } else if (wl == Plants::full) {
|
|
113
|
+ ws += F("tank full");
|
|
114
|
+ } else {
|
|
115
|
+ ws += F("invalid sensor state");
|
|
116
|
+ }
|
|
117
|
+ ws += "\"\n";
|
55
|
118
|
ws += "}";
|
|
119
|
+
|
56
|
120
|
socket.broadcastTXT(ws);
|
57
|
121
|
}
|
58
|
122
|
|
|
@@ -70,18 +134,57 @@ void handleRoot() {
|
70
|
134
|
|
71
|
135
|
message += F(".ui {\n");
|
72
|
136
|
message += F("width: max-content;\n");
|
|
137
|
+ message += F("height: max-content;\n");
|
73
|
138
|
message += F("margin-right: 1em;\n");
|
74
|
139
|
message += F("padding: 0 1.0em;\n");
|
75
|
140
|
message += F("border: 1px dashed black;\n");
|
76
|
141
|
message += F("}\n");
|
77
|
142
|
|
|
143
|
+ message += F(".io {\n");
|
|
144
|
+ message += F("width: max-content;\n");
|
|
145
|
+ message += F("height: max-content;\n");
|
|
146
|
+ message += F("margin-right: 1em;\n");
|
|
147
|
+ message += F("padding: 0.8em 1.0em;\n");
|
|
148
|
+ message += F("border: 1px dashed black;\n");
|
|
149
|
+ message += F("font-family: monospace;\n");
|
|
150
|
+ message += F("}\n");
|
|
151
|
+
|
|
152
|
+ message += F(".switch {\n");
|
|
153
|
+ message += F("width: max-content;\n");
|
|
154
|
+ message += F("border: 1px solid black;\n");
|
|
155
|
+ message += F("border-radius: 50%;\n");
|
|
156
|
+ message += F("padding: 2em;\n");
|
|
157
|
+ message += F("margin: 1em;\n");
|
|
158
|
+ message += F("}\n");
|
|
159
|
+
|
|
160
|
+ message += F(".valve {\n");
|
|
161
|
+ message += F("width: max-content;\n");
|
|
162
|
+ message += F("border: 1px solid black;\n");
|
|
163
|
+ message += F("border-radius: 50%;\n");
|
|
164
|
+ message += F("padding: 2em;\n");
|
|
165
|
+ message += F("margin: 1em;\n");
|
|
166
|
+ message += F("}\n");
|
|
167
|
+
|
|
168
|
+ message += F(".pump {\n");
|
|
169
|
+ message += F("width: max-content;\n");
|
|
170
|
+ message += F("border: 1px solid black;\n");
|
|
171
|
+ message += F("border-radius: 50%;\n");
|
|
172
|
+ message += F("padding: 2em;\n");
|
|
173
|
+ message += F("margin: 1em;\n");
|
|
174
|
+ message += F("}\n");
|
|
175
|
+
|
78
|
176
|
message += F(".info {\n");
|
79
|
|
- message += F("flex-grow: 1;\n");
|
|
177
|
+ message += F("width: max-content;\n");
|
|
178
|
+ message += F("height: max-content;\n");
|
|
179
|
+ message += F("padding: 0 1.0em;\n");
|
|
180
|
+ message += F("border: 1px dashed black;\n");
|
|
181
|
+ message += F("font-family: monospace;\n");
|
80
|
182
|
message += F("}\n");
|
81
|
183
|
|
82
|
184
|
message += F(".pad {\n");
|
83
|
185
|
message += F("background: black;\n");
|
84
|
186
|
message += F("border: 3px solid black;\n");
|
|
187
|
+ message += F("border-radius: 20px;\n");
|
85
|
188
|
message += F("width: max-content;\n");
|
86
|
189
|
message += F("padding: 1.5em;\n");
|
87
|
190
|
message += F("margin-left: auto;\n");
|
|
@@ -90,8 +193,10 @@ void handleRoot() {
|
90
|
193
|
|
91
|
194
|
message += F(".pad input {\n");
|
92
|
195
|
message += F("background: #fff0cf;\n");
|
|
196
|
+ message += F("border-radius: 6px;\n");
|
93
|
197
|
message += F("font-weight: bold;\n");
|
94
|
198
|
message += F("font-family: monospace;\n");
|
|
199
|
+ message += F("font-size: 1.2em;\n");
|
95
|
200
|
message += F("padding: 0.5em 1em;\n");
|
96
|
201
|
message += F("margin: 0.5em;\n");
|
97
|
202
|
message += F("}\n");
|
|
@@ -100,7 +205,8 @@ void handleRoot() {
|
100
|
205
|
message += F(".lcd {\n");
|
101
|
206
|
//message += F("background: #9ea18c;\n");
|
102
|
207
|
message += F("background: #9ed18c;\n");
|
103
|
|
- message += F("border: 3px solid black;\n");
|
|
208
|
+ message += F("border: 5px solid black;\n");
|
|
209
|
+ message += F("border-radius: 10px;\n");
|
104
|
210
|
message += F("width: max-content;\n");
|
105
|
211
|
message += F("padding: 0.65em 1em;\n");
|
106
|
212
|
message += F("box-shadow: inset 0 0 5px 5px rgba(0,0,0,.1);\n");
|
|
@@ -111,6 +217,12 @@ void handleRoot() {
|
111
|
217
|
message += F("line-height: 160%;\n");
|
112
|
218
|
message += F("color: #21230e;\n");
|
113
|
219
|
message += F("text-shadow: -1px 2px 1px rgba(0,0,0,.1);\n");
|
|
220
|
+ message += F("margin-left: auto;\n");
|
|
221
|
+ message += F("margin-right: auto;\n");
|
|
222
|
+ message += F("}\n");
|
|
223
|
+
|
|
224
|
+ message += F("#state {\n");
|
|
225
|
+ message += F("text-align: center;\n");
|
114
|
226
|
message += F("}\n");
|
115
|
227
|
message += F("</style>\n");
|
116
|
228
|
|
|
@@ -149,6 +261,68 @@ void handleRoot() {
|
149
|
261
|
message += control_state_name();
|
150
|
262
|
message += F("</p></div>\n");
|
151
|
263
|
|
|
264
|
+ message += F("<div class='io'>\n");
|
|
265
|
+ message += F("Switches: <span id='switchstate'>");
|
|
266
|
+
|
|
267
|
+ Plants::Waterlevel wl = get_plants()->getWaterlevel();
|
|
268
|
+ if (wl == Plants::empty) {
|
|
269
|
+ message += F("tank empty");
|
|
270
|
+ } else if (wl == Plants::inbetween) {
|
|
271
|
+ message += F("tank half-filled");
|
|
272
|
+ } else if (wl == Plants::full) {
|
|
273
|
+ message += F("tank full");
|
|
274
|
+ } else {
|
|
275
|
+ message += F("invalid sensor state");
|
|
276
|
+ }
|
|
277
|
+ message += F("</span>");
|
|
278
|
+
|
|
279
|
+ message += F("<div class='container'>\n");
|
|
280
|
+ for (int i = 0; i < SWITCH_COUNT; i++) {
|
|
281
|
+ message += F("<div class='switch' style='background-color: ");
|
|
282
|
+ if (get_plants()->getSwitches()->getPin(i)) {
|
|
283
|
+ message += F("red");
|
|
284
|
+ } else {
|
|
285
|
+ message += F("green");
|
|
286
|
+ }
|
|
287
|
+ message += F(";'>S");
|
|
288
|
+ message += String(i + 1);
|
|
289
|
+ message += F("</div>");
|
|
290
|
+ }
|
|
291
|
+ message += F("</div><hr>\n");
|
|
292
|
+
|
|
293
|
+ message += F("Valves:\n");
|
|
294
|
+ message += F("<div class='container'>\n");
|
|
295
|
+ for (int i = 0; i < VALVE_COUNT; i++) {
|
|
296
|
+ message += F("<div class='valve' style='background-color: ");
|
|
297
|
+ if (get_plants()->getValves()->getPin(i)) {
|
|
298
|
+ message += F("red");
|
|
299
|
+ } else {
|
|
300
|
+ message += F("green");
|
|
301
|
+ }
|
|
302
|
+ message += F(";'>V");
|
|
303
|
+ message += String(i + 1);
|
|
304
|
+ message += F("</div>");
|
|
305
|
+ }
|
|
306
|
+ message += F("</div><hr>\n");
|
|
307
|
+
|
|
308
|
+ message += F("Pumps:\n");
|
|
309
|
+ message += F("<div class='container'>\n");
|
|
310
|
+ for (int i = 0; i < PUMP_COUNT; i++) {
|
|
311
|
+ message += F("<div class='pump' style='background-color: ");
|
|
312
|
+ if (get_plants()->getPumps()->getPin(i)) {
|
|
313
|
+ message += F("red");
|
|
314
|
+ } else {
|
|
315
|
+ message += F("green");
|
|
316
|
+ }
|
|
317
|
+ message += F(";'>P");
|
|
318
|
+ message += String(i + 1);
|
|
319
|
+ message += F("</div>");
|
|
320
|
+ }
|
|
321
|
+ message += F("</div><hr>\n");
|
|
322
|
+ message += F("Green means valve is closed / pump is off / switch is not submersed.\n");
|
|
323
|
+ message += F("<br>\n");
|
|
324
|
+ message += F("Red means valve is open / pump is running / switch is submersed.</div>\n");
|
|
325
|
+
|
152
|
326
|
message += F("<div class='info'><p>\n");
|
153
|
327
|
message += F("Version: ");
|
154
|
328
|
message += FIRMWARE_VERSION;
|
|
@@ -214,6 +388,42 @@ void handleRoot() {
|
214
|
388
|
message += F( "lcd[0].innerHTML = str;\n");
|
215
|
389
|
message += F( "var state = document.getElementById('state');\n");
|
216
|
390
|
message += F( "state.innerHTML = \"State: \" + msg.state;\n");
|
|
391
|
+
|
|
392
|
+ message += F( "for (let i = 0; i < ");
|
|
393
|
+ message += String(VALVE_COUNT);
|
|
394
|
+ message += F("; i++) {\n");
|
|
395
|
+ message += F( "var valves = document.getElementsByClassName('valve');\n");
|
|
396
|
+ message += F( "if (msg.valves[i] == '0') {\n");
|
|
397
|
+ message += F( "valves[i].style = 'background-color: green;';\n");
|
|
398
|
+ message += F( "} else {\n");
|
|
399
|
+ message += F( "valves[i].style = 'background-color: red;';\n");
|
|
400
|
+ message += F( "}\n");
|
|
401
|
+ message += F( "}\n");
|
|
402
|
+
|
|
403
|
+ message += F( "for (let i = 0; i < ");
|
|
404
|
+ message += String(PUMP_COUNT);
|
|
405
|
+ message += F("; i++) {\n");
|
|
406
|
+ message += F( "var pumps = document.getElementsByClassName('pump');\n");
|
|
407
|
+ message += F( "if (msg.pumps[i] == '0') {\n");
|
|
408
|
+ message += F( "pumps[i].style = 'background-color: green;';\n");
|
|
409
|
+ message += F( "} else {\n");
|
|
410
|
+ message += F( "pumps[i].style = 'background-color: red;';\n");
|
|
411
|
+ message += F( "}\n");
|
|
412
|
+ message += F( "}\n");
|
|
413
|
+
|
|
414
|
+ message += F( "for (let i = 0; i < ");
|
|
415
|
+ message += String(SWITCH_COUNT);
|
|
416
|
+ message += F("; i++) {\n");
|
|
417
|
+ message += F( "var switches = document.getElementsByClassName('switch');\n");
|
|
418
|
+ message += F( "if (msg.switches[i] == '0') {\n");
|
|
419
|
+ message += F( "switches[i].style = 'background-color: green;';\n");
|
|
420
|
+ message += F( "} else {\n");
|
|
421
|
+ message += F( "switches[i].style = 'background-color: red;';\n");
|
|
422
|
+ message += F( "}\n");
|
|
423
|
+ message += F( "}\n");
|
|
424
|
+
|
|
425
|
+ message += F( "var switchstate = document.getElementById('switchstate');\n");
|
|
426
|
+ message += F( "switchstate.innerHTML = msg.switchstate;\n");
|
217
|
427
|
message += F("};\n");
|
218
|
428
|
|
219
|
429
|
message += F("var buttons = document.getElementsByTagName('input');\n");
|
|
@@ -325,6 +535,11 @@ void wifi_run() {
|
325
|
535
|
#endif // ARDUINO_ARCH_ESP8266
|
326
|
536
|
}
|
327
|
537
|
|
|
538
|
+ if ((millis() - last_websocket_update_time) >= WEBSOCKET_UPDATE_INTERVAL) {
|
|
539
|
+ last_websocket_update_time = millis();
|
|
540
|
+ wifi_send_websocket();
|
|
541
|
+ }
|
|
542
|
+
|
328
|
543
|
// reset ESP every 6h to be safe
|
329
|
544
|
if (millis() >= (6 * 60 * 60 * 1000)) {
|
330
|
545
|
ESP.restart();
|