Browse Source

added websocket lib, UI control now possible via webinterface

Thomas Buck 3 years ago
parent
commit
829c587926
7 changed files with 242 additions and 79 deletions
  1. 3
    0
      include/Functionality.h
  2. 5
    1
      include/Statemachine.h
  3. 2
    0
      platformio.ini
  4. 8
    0
      src/Functionality.cpp
  5. 52
    40
      src/SimpleUpdater.cpp
  6. 27
    0
      src/Statemachine.cpp
  7. 145
    38
      src/WifiStuff.cpp

+ 3
- 0
include/Functionality.h View File

16
 void control_begin(void);
16
 void control_begin(void);
17
 void control_run(void);
17
 void control_run(void);
18
 
18
 
19
+const char *control_state_name(void);
20
+void control_act_input(int n);
21
+
19
 #endif // FUNCTION_CONTROL
22
 #endif // FUNCTION_CONTROL
20
 
23
 
21
 // ----------------------------------------------------------------------------
24
 // ----------------------------------------------------------------------------

+ 5
- 1
include/Statemachine.h View File

3
 
3
 
4
 #include <Arduino.h>
4
 #include <Arduino.h>
5
 
5
 
6
+#define stringify( name ) # name
7
+
6
 class Statemachine {
8
 class Statemachine {
7
 public:
9
 public:
8
     enum States {
10
     enum States {
9
-        init,
11
+        init = 0,
10
         menu, // auto, pumps, valves
12
         menu, // auto, pumps, valves
11
         
13
         
12
         menu_auto, // select mode
14
         menu_auto, // select mode
63
     void input(int n);
65
     void input(int n);
64
     void act(void);
66
     void act(void);
65
     
67
     
68
+    const char *getStateName(void);
69
+    
66
 private:
70
 private:
67
     void switch_to(States s);
71
     void switch_to(States s);
68
     uint32_t number_input(void);
72
     uint32_t number_input(void);

+ 2
- 0
platformio.ini View File

18
 build_flags = -D PLATFORM_ESP -D FUNCTION_CONTROL
18
 build_flags = -D PLATFORM_ESP -D FUNCTION_CONTROL
19
 lib_deps =
19
 lib_deps =
20
     Wire
20
     Wire
21
+    https://github.com/Links2004/arduinoWebSockets
21
 
22
 
22
 [env:esp32_main]
23
 [env:esp32_main]
23
 platform = espressif32
24
 platform = espressif32
28
 upload_port = /dev/ttyUSB1
29
 upload_port = /dev/ttyUSB1
29
 lib_deps =
30
 lib_deps =
30
     Wire
31
     Wire
32
+    https://github.com/Links2004/arduinoWebSockets
31
 
33
 
32
 [env:arduino_ui]
34
 [env:arduino_ui]
33
 platform = atmelavr
35
 platform = atmelavr

+ 8
- 0
src/Functionality.cpp View File

413
 
413
 
414
 #ifdef FUNCTION_CONTROL
414
 #ifdef FUNCTION_CONTROL
415
 
415
 
416
+const char *control_state_name(void) {
417
+    return sm.getStateName();
418
+}
419
+
420
+void control_act_input(int n) {
421
+    sm.input(n);
422
+}
423
+
416
 void control_setup(void) {
424
 void control_setup(void) {
417
     plants.setValvePins(valve_pins);
425
     plants.setValvePins(valve_pins);
418
     plants.setPumpPins(pump_pins);
426
     plants.setPumpPins(pump_pins);

+ 52
- 40
src/SimpleUpdater.cpp View File

23
 
23
 
24
 void SimpleUpdater::get(void) {
24
 void SimpleUpdater::get(void) {
25
     String uploadPage = F(
25
     String uploadPage = F(
26
-        "<html><head>"
27
-        "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
28
-        "<title>SimpleUpdater ESP32</title>"
29
-        "</head><body>"
30
-        "<h1>SimpleUpdater</h1>"
31
-        "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
32
-        "<input type='file' name='update'>"
33
-        "<input type='submit' value='Update'>"
34
-        "</form>"
35
-        "<div id='prg'>progress: 0%</div>"
36
-        "<a href=\"/\">Back to Main Page</a>"
37
-        "<script>"
38
-        "$('form').submit(function(e){"
39
-        "e.preventDefault();"
40
-        "var form = $('#upload_form')[0];"
41
-        "var data = new FormData(form);"
42
-        " $.ajax({"
43
-        "url: '/update',"
44
-        "type: 'POST',"
45
-        "data: data,"
46
-        "contentType: false,"
47
-        "processData:false,"
48
-        "xhr: function() {"
49
-        "var xhr = new window.XMLHttpRequest();"
50
-        "xhr.upload.addEventListener('progress', function(evt) {"
51
-        "if (evt.lengthComputable) {"
52
-        "var per = evt.loaded / evt.total;"
53
-        "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
54
-        "}"
55
-        "}, false);"
56
-        "return xhr;"
57
-        "},"
58
-        "success:function(d, s) {"
59
-        "console.log('success!')" 
60
-        "},"
61
-        "error: function (a, b, c) {"
62
-        "}"
63
-        "});"
64
-        "});"
65
-        "</script>"
26
+        "<!DOCTYPE html>\n"
27
+        "<html><head>\n"
28
+        "<meta charset='utf-8'/>\n"
29
+        "<meta name='viewport' content='width=device-width, initial-scale=1'/>\n"
30
+        "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>\n"
31
+        "<title>SimpleUpdater ESP32</title>\n"
32
+        "</head><body>\n"
33
+        
34
+        "<h1>SimpleUpdater</h1>\n"
35
+        "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>\n"
36
+        "<input type='file' name='update' accept='.bin'>\n"
37
+        "<input type='submit' value='Update'>\n"
38
+        "</form>\n"
39
+        "<div id='prg'>progress: 0%</div>\n"
40
+        "<a href=\"/\">Back to Main Page</a>\n"
41
+        
42
+        "<script>\n"
43
+        "$('form').submit(function(e){\n"
44
+            "e.preventDefault();\n"
45
+            "var form = $('#upload_form')[0];\n"
46
+            "var data = new FormData(form);\n"
47
+            " $.ajax({\n"
48
+                "url: '/update',\n"
49
+                "type: 'POST',\n"
50
+                "data: data,\n"
51
+                "contentType: false,\n"
52
+                "processData:false,\n"
53
+                "xhr: function() {\n"
54
+                    "var xhr = new window.XMLHttpRequest();\n"
55
+                    "xhr.upload.addEventListener('progress', function(evt) {\n"
56
+                        "if (evt.lengthComputable) {\n"
57
+                            "var per = evt.loaded / evt.total;\n"
58
+                            "$('#prg').html('progress: ' + Math.round(per*100) + '%');\n"
59
+                        "}\n"
60
+                    "}, false);\n"
61
+                    "return xhr;\n"
62
+                "},\n"
63
+                "success: function(d, s) {\n"
64
+                    "$('#prg').html('progress: success! redirecting...');\n"
65
+                    "setTimeout(function() {\n"
66
+                        "window.location.href = '/';\n"
67
+                    "}, 3000);\n"
68
+                "},\n"
69
+                "error: function(a, b, c) {\n"
70
+                    "$('#prg').html('progress: error! redirecting...');\n"
71
+                    "setTimeout(function() {\n"
72
+                        "window.location.href = '/';\n"
73
+                    "}, 1000);\n"
74
+                "}\n"
75
+            "});\n"
76
+        "});\n"
77
+        "</script>\n"
66
         "</body></html>"
78
         "</body></html>"
67
     );
79
     );
68
     
80
     

+ 27
- 0
src/Statemachine.cpp View File

51
     return sum;
51
     return sum;
52
 }
52
 }
53
 
53
 
54
+static const char *state_names[] = {
55
+    stringify(init),
56
+    stringify(menu),
57
+    stringify(menu_auto),
58
+    stringify(menu_auto_fertilizer),
59
+    stringify(menu_auto_fertilizer_running),
60
+    stringify(menu_auto_reservoir_running),
61
+    stringify(menu_auto_plant),
62
+    stringify(menu_auto_plant_running),
63
+    stringify(menu_auto_done),
64
+    stringify(menu_pumps),
65
+    stringify(menu_pumps_time),
66
+    stringify(menu_pumps_go),
67
+    stringify(menu_pumps_running),
68
+    stringify(menu_pumps_done),
69
+    stringify(menu_valves),
70
+    stringify(menu_valves_time),
71
+    stringify(menu_valves_go),
72
+    stringify(menu_valves_running),
73
+    stringify(menu_valves_done),
74
+    stringify(error)
75
+};
76
+
77
+const char *Statemachine::getStateName(void) {
78
+    return state_names[state];
79
+}
80
+
54
 Statemachine::Statemachine(print_fn _print, backspace_fn _backspace)
81
 Statemachine::Statemachine(print_fn _print, backspace_fn _backspace)
55
         : db(7) {
82
         : db(7) {
56
     state = init;
83
     state = init;

+ 145
- 38
src/WifiStuff.cpp View File

16
 
16
 
17
 #endif
17
 #endif
18
 
18
 
19
+#include <WebSocketsServer.h>
20
+
19
 #include "wifi.h"
21
 #include "wifi.h"
20
 #include "config.h"
22
 #include "config.h"
21
 #include "config_pins.h"
23
 #include "config_pins.h"
24
+#include "Functionality.h"
22
 #include "SimpleUpdater.h"
25
 #include "SimpleUpdater.h"
23
 #include "WifiStuff.h"
26
 #include "WifiStuff.h"
24
 
27
 
25
 UPDATE_WEB_SERVER server(80);
28
 UPDATE_WEB_SERVER server(80);
29
+WebSocketsServer socket = WebSocketsServer(81);
26
 SimpleUpdater updater;
30
 SimpleUpdater updater;
27
 unsigned long last_server_handle_time = 0;
31
 unsigned long last_server_handle_time = 0;
28
 
32
 
36
     message_buffer_b = b;
40
     message_buffer_b = b;
37
     message_buffer_c = c;
41
     message_buffer_c = c;
38
     message_buffer_d = d;
42
     message_buffer_d = d;
43
+    
44
+    a.replace("\"", "'");
45
+    b.replace("\"", "'");
46
+    c.replace("\"", "'");
47
+    d.replace("\"", "'");
48
+    
49
+    String ws = "{\n";
50
+    ws += "\"a\": \"" + a + "\",\n";
51
+    ws += "\"b\": \"" + b + "\",\n";
52
+    ws += "\"c\": \"" + c + "\",\n";
53
+    ws += "\"d\": \"" + d + "\",\n";
54
+    ws += "\"state\": \"" + String(control_state_name()) + "\"\n";
55
+    ws += "}";
56
+    socket.broadcastTXT(ws);
39
 }
57
 }
40
 
58
 
41
 void handleRoot() {
59
 void handleRoot() {
42
-    String message = F("<html><head>\n");
43
-    message += F("<title>Giess-o-mat</title>\n");
44
-    message += F("</head><body>\n");
45
-    message += F("<h1>Giess-o-mat</h1>\n");
60
+    String message = F("<!DOCTYPE html>\n");
61
+    message += F("<html><head>\n");
62
+    message += F("<meta charset='utf-8'/>\n");
63
+    message += F("<meta name='viewport' content='width=device-width, initial-scale=1'/>\n");
64
+    message += F("<title>Gieß-o-mat</title>\n");
46
     
65
     
47
-    message += F("\n<pre>\n");
48
-    message += F(" ----------------------\n");
66
+    message += F("<style type='text/css'>\n");
67
+    message += F(".container {\n");
68
+    message += F("display: flex;\n");
69
+    message += F("}\n");
49
     
70
     
50
-    message += F("| ");
51
-    message += message_buffer_a;
52
-    for (int i = 0; i < (20 - message_buffer_a.length()); i++) {
53
-        message += ' ';
54
-    }
55
-    message += F(" |\n");
71
+    message += F(".ui {\n");
72
+    message += F("width: max-content;\n");
73
+    message += F("margin-right: 1em;\n");
74
+    message += F("padding: 0 1.0em;\n");
75
+    message += F("border: 1px dashed black;\n");
76
+    message += F("}\n");
56
     
77
     
57
-    message += F("| ");
58
-    message += message_buffer_b;
59
-    for (int i = 0; i < (20 - message_buffer_b.length()); i++) {
60
-        message += ' ';
61
-    }
62
-    message += F(" |\n");
78
+    message += F(".info {\n");
79
+    message += F("flex-grow: 1;\n");
80
+    message += F("}\n");
63
     
81
     
64
-    message += F("| ");
65
-    message += message_buffer_c;
66
-    for (int i = 0; i < (20 - message_buffer_c.length()); i++) {
67
-        message += ' ';
68
-    }
69
-    message += F(" |\n");
82
+    message += F(".pad {\n");
83
+    message += F("background: black;\n");
84
+    message += F("border: 3px solid black;\n");
85
+    message += F("width: max-content;\n");
86
+    message += F("padding: 1.5em;\n");
87
+    message += F("margin-left: auto;\n");
88
+    message += F("margin-right: auto;\n");
89
+    message += F("}\n");
70
     
90
     
71
-    message += F("| ");
72
-    message += message_buffer_d;
73
-    for (int i = 0; i < (20 - message_buffer_d.length()); i++) {
74
-        message += ' ';
75
-    }
76
-    message += F(" |\n");
91
+    message += F(".pad input {\n");
92
+    message += F("background: #fff0cf;\n");
93
+    message += F("font-weight: bold;\n");
94
+    message += F("font-family: monospace;\n");
95
+    message += F("padding: 0.5em 1em;\n");
96
+    message += F("margin: 0.5em;\n");
97
+    message += F("}\n");
98
+    
99
+    // https://codepen.io/hawkz/pres/RpPaGK
100
+    message += F(".lcd {\n");
101
+    //message += F("background: #9ea18c;\n");
102
+    message += F("background: #9ed18c;\n");
103
+    message += F("border: 3px solid black;\n");
104
+    message += F("width: max-content;\n");
105
+    message += F("padding: 0.65em 1em;\n");
106
+    message += F("box-shadow: inset 0 0 5px 5px rgba(0,0,0,.1);\n");
107
+    message += F("font-weight: bold;\n");
108
+    message += F("font-family: monospace;\n");
109
+    message += F("letter-spacing: 0.1em;\n");
110
+    message += F("font-size: 1.2em;\n");
111
+    message += F("line-height: 160%;\n");
112
+    message += F("color: #21230e;\n");
113
+    message += F("text-shadow: -1px 2px 1px rgba(0,0,0,.1);\n");
114
+    message += F("}\n");
115
+    message += F("</style>\n");
77
     
116
     
78
-    message += F(" ----------------------\n");
117
+    message += F("</head><body>\n");
118
+    message += F("<h1>Gieß-o-mat</h1>\n");
119
+    
120
+    message += F("<div class='container'>\n");
121
+    message += F("<div class='ui'>\n");
122
+    message += F("<pre class='lcd'>\n");
123
+    message += message_buffer_a + '\n';
124
+    message += message_buffer_b + '\n';
125
+    message += message_buffer_c + '\n';
126
+    message += message_buffer_d + '\n';
79
     message += F("</pre>\n");
127
     message += F("</pre>\n");
80
     
128
     
81
-    message += F("\n<p>\n");
129
+    message += F("<form class='pad'>\n");
130
+    message += F("<input type='button' value='1'>");
131
+    message += F("<input type='button' value='2'>");
132
+    message += F("<input type='button' value='3'>");
133
+    message += F("<br>\n");
134
+    message += F("<input type='button' value='4'>");
135
+    message += F("<input type='button' value='5'>");
136
+    message += F("<input type='button' value='6'>");
137
+    message += F("<br>\n");
138
+    message += F("<input type='button' value='7'>");
139
+    message += F("<input type='button' value='8'>");
140
+    message += F("<input type='button' value='9'>");
141
+    message += F("<br>\n");
142
+    message += F("<input type='button' value='*'>");
143
+    message += F("<input type='button' value='0'>");
144
+    message += F("<input type='button' value='#'>");
145
+    message += F("</form>\n");
146
+    
147
+    message += F("<p id='state'>\n");
82
     message += F("State: ");
148
     message += F("State: ");
83
-    // TODO
84
-    message += F("\n</p>\n");
149
+    message += control_state_name();
150
+    message += F("</p></div>\n");
85
     
151
     
86
-    message += F("\n<p>\n");
152
+    message += F("<div class='info'><p>\n");
87
     message += F("Version: ");
153
     message += F("Version: ");
88
     message += FIRMWARE_VERSION;
154
     message += FIRMWARE_VERSION;
89
     message += F("\n<br>\n");
155
     message += F("\n<br>\n");
134
 #endif
200
 #endif
135
 
201
 
136
     message += F("<p>\n");
202
     message += F("<p>\n");
137
-    message += F("Try <a href=\"/update\">/update</a> for OTA firmware updates!\n");
138
-    message += F("</p>\n");
139
-    message += F("</body></html>\n");
203
+    message += F("Try <a href='/update'>/update</a> for OTA firmware updates!\n");
204
+    message += F("</p></div>\n");
205
+    message += F("</div></body>\n");
206
+    
207
+    message += F("<script type='text/javascript'>\n");
208
+    message += F("var socket = new WebSocket('ws://' + window.location.hostname + ':81');\n");
209
+    message += F("socket.onmessage = function(e) {\n");
210
+    message += F(    "var msg = JSON.parse(e.data);\n");
211
+    message += F(    "var str = msg.a + '\\n' + msg.b + '\\n' + msg.c + '\\n' + msg.d;\n");
212
+    message += F(    "console.log(str);\n");
213
+    message += F(    "var lcd = document.getElementsByClassName('lcd');\n");
214
+    message += F(    "lcd[0].innerHTML = str;\n");
215
+    message += F(    "var state = document.getElementById('state');\n");
216
+    message += F(    "state.innerHTML = \"State: \" + msg.state;\n");
217
+    message += F("};\n");
218
+    
219
+    message += F("var buttons = document.getElementsByTagName('input');\n");
220
+    message += F("for (let i = 0; i < buttons.length; i++) {\n");
221
+    message += F(    "buttons[i].addEventListener('click', updateButton);\n");
222
+    message += F("}\n");
223
+    message += F("function updateButton() {\n");
224
+    message += F(    "socket.send(this.value);\n");
225
+    message += F("}\n");
226
+    message += F("</script>\n");
227
+    message += F("</html>\n");
140
 
228
 
141
     server.send(200, "text/html", message);
229
     server.send(200, "text/html", message);
142
 }
230
 }
143
 
231
 
232
+void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) {
233
+    if ((type != WStype_TEXT) || (length != 1)) {
234
+        return;
235
+    }
236
+    
237
+    char c = payload[0];
238
+    if ((c >= '0') && (c <= '9')) {
239
+        control_act_input(c - '0');
240
+    } else if (c == '*') {
241
+        control_act_input(-1);
242
+    } else if (c == '#') {
243
+        control_act_input(-2);
244
+    }
245
+}
246
+
144
 void wifi_setup() {
247
 void wifi_setup() {
145
     // Build hostname string
248
     // Build hostname string
146
     String hostname = "giess-o-mat";
249
     String hostname = "giess-o-mat";
205
     server.begin();
308
     server.begin();
206
     MDNS.addService("http", "tcp", 80);
309
     MDNS.addService("http", "tcp", 80);
207
     
310
     
311
+    socket.begin();
312
+    socket.onEvent(webSocketEvent);
313
+    
208
     Serial.println("WiFi: setup done");
314
     Serial.println("WiFi: setup done");
209
 }
315
 }
210
 
316
 
212
     if ((millis() - last_server_handle_time) >= SERVER_HANDLE_INTERVAL) {
318
     if ((millis() - last_server_handle_time) >= SERVER_HANDLE_INTERVAL) {
213
         last_server_handle_time = millis();
319
         last_server_handle_time = millis();
214
         server.handleClient();
320
         server.handleClient();
321
+        socket.loop();
215
         
322
         
216
 #ifdef ARDUINO_ARCH_ESP8266
323
 #ifdef ARDUINO_ARCH_ESP8266
217
         MDNS.update();
324
         MDNS.update();

Loading…
Cancel
Save