|
| 1 | +#include <WiFiNINA.h> |
| 2 | +#include <WebSocketServer.h> |
| 3 | +#include <Arduino_LSM6DS3.h> |
| 4 | +#include <Base64.h> |
| 5 | +#include <RTCZero.h> |
| 6 | +#include "wifi_secrets.h" |
| 7 | + |
| 8 | +#define DEBUG 1 |
| 9 | + |
| 10 | +#ifdef DEBUG |
| 11 | + #define Sprint(a) (Serial.print(a)) |
| 12 | + #define Sprintln(a) (Serial.println(a)) |
| 13 | +#else |
| 14 | + #define Sprint(a) |
| 15 | + #define Sprintln(a) |
| 16 | +#endif |
| 17 | + |
| 18 | +char ssid[] = SECRET_SSID; |
| 19 | +char pass[] = SECRET_PASS; |
| 20 | +IPAddress APIP(192, 168, 2, 1); |
| 21 | +int APStatus = WL_IDLE_STATUS; |
| 22 | +const int APChannel = 14; |
| 23 | +const int webPort = 80; |
| 24 | +const int socketPort = 8080; |
| 25 | +WiFiServer webServer(webPort); |
| 26 | +WiFiServer socketServer(socketPort); |
| 27 | +WebSocketServer webSocketServer; |
| 28 | +WiFiClient socketClient; |
| 29 | +RTCZero rtc; |
| 30 | +const int ledPin = 12; |
| 31 | +boolean on = false; |
| 32 | +float volume = 0; |
| 33 | +int cowbell = 1000; |
| 34 | +float zdata[] = {1,1,1,1,1}; |
| 35 | +int zdatasize = sizeof(zdata) / sizeof(zdata[0]); |
| 36 | +float tdata[] = {20,20,20,20,20,20,20,20,20,20}; |
| 37 | +int tdatasize = sizeof(tdata) / sizeof(tdata[0]); |
| 38 | +int ledState = 0; |
| 39 | +unsigned long epoch; |
| 40 | +unsigned long previousCowbellMillis = 0; |
| 41 | +unsigned long previousGravityMillis = 0; |
| 42 | +unsigned long previousTemperatureMillis = 0; |
| 43 | +char interface_gz_base64[] = "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"; |
| 44 | + |
| 45 | +void setup() { |
| 46 | + #ifdef DEBUG |
| 47 | + Serial.begin(115200); |
| 48 | + while (!Serial); |
| 49 | + #endif |
| 50 | + pinMode(LED_BUILTIN, OUTPUT); |
| 51 | + pinMode(ledPin, OUTPUT); |
| 52 | + rtc.begin(); |
| 53 | + IMU.begin(); |
| 54 | + WiFiConnect(); |
| 55 | +} |
| 56 | + |
| 57 | +void loop() { |
| 58 | + |
| 59 | + if (APStatus != WiFi.status()) { |
| 60 | + APStatus = WiFi.status(); |
| 61 | + if (APStatus == WL_AP_CONNECTED) { |
| 62 | + Sprintln("\n--A device connected to the AP"); |
| 63 | + } else { |
| 64 | + Sprintln("\n--A device disconnected from the AP"); |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + WiFiClient webClient = webServer.available(); |
| 69 | + if (webClient.connected()) { |
| 70 | + Sprint("\n--New client: "); Sprint(webClient.remoteIP()); Sprint(":"); Sprintln(webClient.remotePort()); |
| 71 | + String header = ""; |
| 72 | + while (webClient.available()) { |
| 73 | + char c = webClient.read(); |
| 74 | + if (c != '\r') { |
| 75 | + header += c; |
| 76 | + } |
| 77 | + if (header.indexOf("Upgrade") > -1 && header.indexOf("ebsocket") > -1) { |
| 78 | + Sprintln("--Websocket upgrade requested on webserver port"); |
| 79 | + webClient.println("HTTP/1.1 400 Bad Request\nContent-Type: text/plain; charset=utf-8\n\n400 Bad Request; websocket not available on this port\n"); |
| 80 | + webClient.stop(); |
| 81 | + Sprintln("--Client disconnected"); |
| 82 | + } |
| 83 | + if (header.substring(0,1) != "G" && header.substring(0,2) != "GE" && header.substring(0,3) != "GET") { |
| 84 | + Sprintln("--Wrong method in header"); |
| 85 | + webClient.println("HTTP/1.1 405 Method Not Allowed\nAllow: GET\nContent-Type: text/plain; charset=utf-8\n\n405 Method not allowed; GET only\n"); |
| 86 | + webClient.stop(); |
| 87 | + Sprintln("--Client disconnected"); |
| 88 | + } |
| 89 | + if (header.indexOf("event-stream") > -1) { |
| 90 | + Sprintln("--SSE content type request in header"); |
| 91 | + webClient.println("HTTP/1.1 406 Not Acceptable\nContent-Type: text/plain; charset=utf-8\n\n406 Not Acceptable; SSE not available\n"); |
| 92 | + webClient.stop(); |
| 93 | + Sprintln("--Client disconnected"); |
| 94 | + } |
| 95 | + if (header.length() > 512) { |
| 96 | + Sprintln("--Header too long"); |
| 97 | + webClient.println("HTTP/1.1 431 Request Header Fields Too Large\nContent-Type: text/plain; charset=utf-8\n\n431 Request header fields too large\n"); |
| 98 | + webClient.stop(); |
| 99 | + Sprintln("--Client disconnected"); |
| 100 | + } |
| 101 | + if (header.substring(header.length() - 2) == "\n\n") { |
| 102 | + Sprint(header.substring(0, header.length() - 1)); |
| 103 | + if (header.indexOf("GET / HTTP") > -1) { |
| 104 | + sendBase64Page(interface_gz_base64, webClient, 1024); |
| 105 | + Sprintln("--Interface webpage sent"); |
| 106 | + } else if (header.indexOf("GET /author HTTP") > -1) { |
| 107 | + webClient. println( "HTTP/1.1 200 OK\nContent-Type: text/plain; charset=utf-8\n\nOscar den Uijl, [email protected]\n"); |
| 108 | + Sprintln("--Email address sent"); |
| 109 | + } else if (header.indexOf("GET /coffee HTTP") > -1) { |
| 110 | + webClient.println("HTTP/1.1 418 I'm a teapot\nContent-Type: text/plain; charset=utf-8\n\n418 I'm a teapot\n"); |
| 111 | + Sprintln("--Coffee request denied"); |
| 112 | + } else { |
| 113 | + webClient.println("HTTP/1.1 404 Not Found\nContent-Type: text/plain; charset=utf-8\n\n404 Not Found\n"); |
| 114 | + Sprintln("--Page not found"); |
| 115 | + } |
| 116 | + webClient.stop(); |
| 117 | + Sprintln("--Client disconnected"); |
| 118 | + } |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + if (!socketClient.connected()) { |
| 123 | + socketClient = socketServer.available(); |
| 124 | + if (socketClient.connected() && webSocketServer.handshake(socketClient)) { |
| 125 | + Sprint("\n--Websocket connected to: "); Sprint(socketClient.remoteIP()); Sprint(":"); Sprintln(socketClient.remotePort()); |
| 126 | + if (on) { |
| 127 | + webSocketServer.sendData("sw:true"); |
| 128 | + } else { |
| 129 | + webSocketServer.sendData("sw:false"); |
| 130 | + } |
| 131 | + webSocketServer.sendData("volume:" + (String)round((volume*100)/255)); |
| 132 | + webSocketServer.sendData("cowbell:" + (String)((1000-cowbell)/10)); |
| 133 | + Sprintln("--Settings sent"); |
| 134 | + } else { |
| 135 | + //Sprintln("\n--Couldn't connect websocket"); |
| 136 | + socketClient.stop(); |
| 137 | + delay(100); |
| 138 | + } |
| 139 | + } |
| 140 | + |
| 141 | + if (socketClient.connected()) { |
| 142 | + String data = webSocketServer.getData(); |
| 143 | + if (data.length() > 0) { |
| 144 | + String name = data.substring(0, data.indexOf(":")); |
| 145 | + String value = data.substring(data.indexOf(":") + 1); |
| 146 | + boolean goodSettings = true; |
| 147 | + if (name == "switch") { |
| 148 | + on = (value == "true"); |
| 149 | + } else if (name == "volume") { |
| 150 | + volume = (value.toFloat()*255)/100; |
| 151 | + if (cowbell == 1000) { |
| 152 | + analogWrite(ledPin, (int)round(volume)); |
| 153 | + } |
| 154 | + } else if (name == "cowbell") { |
| 155 | + cowbell = 1000 - (value.toInt()*10); |
| 156 | + } else { |
| 157 | + goodSettings = false; |
| 158 | + webSocketServer.sendData("message:Bad data; ignored"); |
| 159 | + } |
| 160 | + if (goodSettings) { |
| 161 | + webSocketServer.sendData("message:" + name + " set to " + value); |
| 162 | + } |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + unsigned long currentCowbellMillis = millis(); |
| 167 | + if ((currentCowbellMillis - previousCowbellMillis) > cowbell) { |
| 168 | + previousCowbellMillis = currentCowbellMillis; |
| 169 | + if (on) { |
| 170 | + if (cowbell == 1000) { |
| 171 | + analogWrite(ledPin, (int) round(volume)); |
| 172 | + } else { |
| 173 | + if (ledState == 0) { |
| 174 | + ledState = 1; |
| 175 | + analogWrite(ledPin, (int) round(volume)); |
| 176 | + } else { |
| 177 | + ledState = 0; |
| 178 | + analogWrite(ledPin, 0); |
| 179 | + } |
| 180 | + } |
| 181 | + } else { |
| 182 | + analogWrite(ledPin, 0); |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + float t, tsum = 0; |
| 187 | + if (IMU.temperatureAvailable()) { |
| 188 | + IMU.readTemperature(t); |
| 189 | + for (int i = 0; i < tdatasize - 1; i++) { |
| 190 | + tdata[i] = tdata[i+1]; |
| 191 | + } |
| 192 | + tdata[tdatasize-1] = t; |
| 193 | + for (int i = 0; i < tdatasize; i++) { |
| 194 | + tsum += tdata[i]; |
| 195 | + } |
| 196 | + if (socketClient.connected()) { |
| 197 | + unsigned long currentTemperatureMillis = millis(); |
| 198 | + if ((currentTemperatureMillis - previousTemperatureMillis) > 5000) { |
| 199 | + previousTemperatureMillis = currentTemperatureMillis; |
| 200 | + webSocketServer.sendData("temperature:" + String(tsum/tdatasize, 3)); |
| 201 | + } |
| 202 | + } |
| 203 | + } |
| 204 | + |
| 205 | + float x, y, z, zsum = 0; |
| 206 | + if (IMU.accelerationAvailable()) { |
| 207 | + IMU.readAcceleration(x, y, z); |
| 208 | + if (x > 0.2 || x < -0.2 || y > 0.2 || y < -0.2 || z > 1.2 || z < 0.8) { |
| 209 | + analogWrite(ledPin, 0); |
| 210 | + Sprintln("\n--TILT!!"); |
| 211 | + if (on) { |
| 212 | + on = false; |
| 213 | + if (socketClient.connected()) { |
| 214 | + webSocketServer.sendData("sw:false"); |
| 215 | + } |
| 216 | + } |
| 217 | + } |
| 218 | + for (int i = 0; i < zdatasize - 1; i++) { |
| 219 | + zdata[i] = zdata[i+1]; |
| 220 | + } |
| 221 | + zdata[zdatasize-1] = z; |
| 222 | + for (int i = 0; i < zdatasize; i++) { |
| 223 | + zsum += zdata[i]; |
| 224 | + } |
| 225 | + if (socketClient.connected()) { |
| 226 | + unsigned long currentGravityMillis = millis(); |
| 227 | + if ((currentGravityMillis - previousGravityMillis) > 2000) { |
| 228 | + previousGravityMillis = currentGravityMillis; |
| 229 | + webSocketServer.sendData("gravity:" + String(zsum/zdatasize, 3)); |
| 230 | + } |
| 231 | + } |
| 232 | + } |
| 233 | + |
| 234 | +} |
| 235 | + |
| 236 | +void WiFiConnect() { |
| 237 | + Sprintln("--Setting up access point " + (String)ssid + " ..."); |
| 238 | + WiFi.setHostname("nano"); |
| 239 | + WiFi.config(APIP, APIP, APIP, IPAddress(255,255,255,0)); |
| 240 | + APStatus = WiFi.beginAP(ssid, pass, APChannel); |
| 241 | + if (APStatus != WL_AP_LISTENING) { |
| 242 | + Sprintln("--Setting up access point " + (String)ssid + " failed"); |
| 243 | + while (true); |
| 244 | + } |
| 245 | + webServer.begin(); |
| 246 | + socketServer.begin(); |
| 247 | + #ifdef DEBUG |
| 248 | + printWifiStatus(); |
| 249 | + #endif |
| 250 | + WiFi.lowPowerMode(); |
| 251 | + Sprintln("--Access point " + (String)ssid + " set up"); |
| 252 | + digitalWrite(LED_BUILTIN, HIGH); |
| 253 | +} |
| 254 | + |
| 255 | +void sendBase64Page(char base64Page[], WiFiClient client, int packetSize) { |
| 256 | + const int base64Page_length = strlen(base64Page); |
| 257 | + const int page_length = base64_dec_len(base64Page, base64Page_length); |
| 258 | + char page[page_length]; |
| 259 | + int done = 0; |
| 260 | + base64_decode(page, base64Page, base64Page_length); |
| 261 | + client.println("HTTP/1.1 200 OK\nContent-Type: text/html"); |
| 262 | + if (page[0] == 0x1f && page[1] == 0x8b) { |
| 263 | + client.println("Content-Encoding: gzip"); |
| 264 | + } |
| 265 | + client.println(""); |
| 266 | + while (page_length > done) { |
| 267 | + if (page_length - done < packetSize) { |
| 268 | + packetSize = page_length - done; |
| 269 | + } |
| 270 | + client.write(page + done, packetSize * sizeof(char)); |
| 271 | + done = done + packetSize; |
| 272 | + } |
| 273 | +} |
| 274 | + |
| 275 | +#ifdef DEBUG |
| 276 | +void printWifiStatus() { |
| 277 | + Sprint("Access point SSID: "); Sprintln(WiFi.SSID()); |
| 278 | + Sprint("Signal strength (RSSI): "); Sprint(WiFi.RSSI()); Sprintln(" dBm"); |
| 279 | + Sprint("IP address: "); Sprintln(WiFi.localIP()); |
| 280 | + Sprint("Gateway: "); Sprintln(WiFi.gatewayIP()); |
| 281 | + Sprint("Netmask: "); Sprintln(WiFi.subnetMask()); |
| 282 | + Sprint("Webserver is at http://"); Sprint(WiFi.localIP()); Sprintln(":" + (String)webPort + "/"); |
| 283 | + Sprint("Websocket is at http://"); Sprint(WiFi.localIP()); Sprintln(":" + (String)socketPort + "/"); |
| 284 | +} |
| 285 | +#endif |
0 commit comments