#include #ifdef PLATFORM_ESP #if defined(ARDUINO_ARCH_ESP8266) #include #include #include #elif defined(ARDUINO_ARCH_ESP32) #include #include #include #endif #include #include "wifi.h" #include "config.h" #include "config_pins.h" #include "Functionality.h" #include "SimpleUpdater.h" #include "DebugLog.h" #include "WifiStuff.h" UPDATE_WEB_SERVER server(80); WebSocketsServer socket = WebSocketsServer(81); SimpleUpdater updater; unsigned long last_server_handle_time = 0; unsigned long last_websocket_update_time = 0; String message_buffer_a; String message_buffer_b; String message_buffer_c; String message_buffer_d; void wifi_set_message_buffer(String a, String b, String c, String d) { message_buffer_a = a; message_buffer_b = b; message_buffer_c = c; message_buffer_d = d; } void wifi_schedule_websocket(void) { last_websocket_update_time = 0; } void wifi_send_status_broadcast(void) { if (socket.connectedClients() <= 0) { return; } String a = message_buffer_a ; String b = message_buffer_b; String c = message_buffer_c; String d = message_buffer_d; a.replace("\"", "'"); b.replace("\"", "'"); c.replace("\"", "'"); d.replace("\"", "'"); String ws = "{\n"; ws += "\"a\": \"" + a + "\",\n"; ws += "\"b\": \"" + b + "\",\n"; ws += "\"c\": \"" + c + "\",\n"; ws += "\"d\": \"" + d + "\",\n"; ws += "\"state\": \"" + String(control_state_name()) + "\",\n"; ws += F("\"valves\": [ "); for (int i = 0; i < VALVE_COUNT; i++) { ws += "\""; ws += get_plants()->getValves()->getPin(i) ? "1" : "0"; ws += "\""; if (i < (VALVE_COUNT - 1)) { ws += ", "; } } ws += " ],\n"; ws += F("\"pumps\": [ "); for (int i = 0; i < PUMP_COUNT; i++) { ws += "\""; ws += get_plants()->getPumps()->getPin(i) ? "1" : "0"; ws += "\""; if (i < (PUMP_COUNT - 1)) { ws += ", "; } } ws += " ],\n"; ws += F("\"switches\": [ "); for (int i = 0; i < SWITCH_COUNT; i++) { bool v = get_plants()->getSwitches()->getPin(i); #ifdef INVERT_SENSOR_BOTTOM if (i == 0) { v = !v; } #endif // INVERT_SENSOR_BOTTOM #ifdef INVERT_SENSOR_TOP if (i == 1) { v = !v; } #endif // INVERT_SENSOR_TOP ws += "\""; ws += v ? "1" : "0"; ws += "\""; if (i < (SWITCH_COUNT - 1)) { ws += ", "; } } ws += " ],\n"; ws += "\"switchstate\": \""; Plants::Waterlevel wl = get_plants()->getWaterlevel(); if (wl == Plants::empty) { ws += F("tank empty"); } else if (wl == Plants::inbetween) { ws += F("tank half-filled"); } else if (wl == Plants::full) { ws += F("tank full"); } else { ws += F("invalid sensor state"); } ws += "\"\n"; ws += "}"; wifi_send_websocket(ws); } void wifi_send_websocket(String s) { socket.broadcastTXT(s); } void handleRoot() { String message = F("\n"); message += F("\n"); message += F("\n"); message += F("\n"); message += F("Gieß-o-mat\n"); message += F("\n"); message += F("\n"); message += F("

Gieß-o-mat

\n"); message += F("
\n"); message += F("
\n"); message += F("
\n");
    message += message_buffer_a + '\n';
    message += message_buffer_b + '\n';
    message += message_buffer_c + '\n';
    message += message_buffer_d + '\n';
    message += F("
\n"); message += F("
\n"); message += F(""); message += F(""); message += F(""); message += F("
\n"); message += F(""); message += F(""); message += F(""); message += F("
\n"); message += F(""); message += F(""); message += F(""); message += F("
\n"); message += F(""); message += F(""); message += F(""); message += F("
\n"); message += F("

\n"); message += F("State: "); message += control_state_name(); message += F("

\n"); message += F("
\n"); message += F("Switches: "); Plants::Waterlevel wl = get_plants()->getWaterlevel(); if (wl == Plants::empty) { message += F("tank empty"); } else if (wl == Plants::inbetween) { message += F("tank half-filled"); } else if (wl == Plants::full) { message += F("tank full"); } else { message += F("invalid sensor state"); } message += F(""); message += F("
\n"); for (int i = 0; i < SWITCH_COUNT; i++) { message += F("
S"); message += String(i + 1); message += F("
"); } message += F("

\n"); message += F("Valves:\n"); message += F("
\n"); for (int i = 0; i < VALVE_COUNT; i++) { message += F("
V"); message += String(i + 1); message += F("
"); } message += F("

\n"); message += F("Pumps:\n"); message += F("
\n"); for (int i = 0; i < PUMP_COUNT; i++) { message += F("
P"); message += String(i + 1); message += F("
"); } message += F("

\n"); message += F("Green means valve is closed / pump is off / switch is not submersed.\n"); message += F("
\n"); message += F("Red means valve is open / pump is running / switch is submersed.
\n"); message += F("

\n"); message += F("Version: "); message += FIRMWARE_VERSION; message += F("\n
\n"); message += F("Build Date: "); message += __DATE__; message += F("\n
\n"); message += F("Build Time: "); message += __TIME__; message += F("\n

\n"); message += F("MAC: "); message += WiFi.macAddress(); message += F("\n

\n"); #if defined(ARDUINO_ARCH_ESP8266) message += F("\n

\n"); message += F("Reset reason: "); message += ESP.getResetReason(); message += F("\n
\n"); message += F("Free heap: "); message += String(ESP.getFreeHeap()); message += F(" ("); message += String(ESP.getHeapFragmentation()); message += F("% fragmentation)"); message += F("\n
\n"); message += F("Free sketch space: "); message += String(ESP.getFreeSketchSpace()); message += F("\n
\n"); message += F("Flash chip real size: "); message += String(ESP.getFlashChipRealSize()); if (ESP.getFlashChipSize() != ESP.getFlashChipRealSize()) { message += F("\n
\n"); message += F("WARNING: sdk chip size ("); message += (ESP.getFlashChipSize()); message += F(") does not match!"); } message += F("\n

\n"); #elif defined(ARDUINO_ARCH_ESP32) message += F("\n

\n"); message += F("Free heap: "); message += String(ESP.getFreeHeap() / 1024.0); message += F("k\n
\n"); message += F("Free sketch space: "); message += String(ESP.getFreeSketchSpace() / 1024.0); message += F("k\n
\n"); message += F("Flash chip size: "); message += String(ESP.getFlashChipSize() / 1024.0); message += F("k\n

\n"); #endif message += F("

Try /update for OTA firmware updates!

\n"); message += F("

Made by xythobuz

\n"); message += F("

Project Repository

\n"); message += F("
\n"); message += F("
\n");
    message += debug.getBuffer();
    message += F("
\n"); message += F("\n"); message += F("\n"); message += F("\n"); server.send(200, "text/html", message); } void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) { if ((type != WStype_TEXT) || (length != 1)) { return; } char c = payload[0]; if ((c >= '0') && (c <= '9')) { control_act_input(c - '0'); } else if (c == '*') { control_act_input(-1); } else if (c == '#') { control_act_input(-2); } } void wifi_setup() { // Build hostname string String hostname = "giess-o-mat"; #if defined(ARDUINO_ARCH_ESP8266) // Connect to WiFi AP debug.println("WiFi: initializing"); WiFi.hostname(hostname); WiFi.mode(WIFI_STA); debug.print("WiFi: connecting"); WiFi.begin(WIFI_SSID, WIFI_PW); while (WiFi.status() != WL_CONNECTED) { debug.print("."); delay(LED_CONNECT_BLINK_INTERVAL); digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN)); } debug.println(); #elif defined(ARDUINO_ARCH_ESP32) // Set hostname workaround debug.println("WiFi: set hostname"); WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); WiFi.setHostname(hostname.c_str()); // Workaround for WiFi connecting only every 2nd reset // https://github.com/espressif/arduino-esp32/issues/2501#issuecomment-513602522 debug.println("WiFi: connection work-around"); WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) { if (info.disconnected.reason == 202) { esp_sleep_enable_timer_wakeup(10); esp_deep_sleep_start(); delay(100); } }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); // Connect to WiFi AP debug.println("WiFi: SSID=" WIFI_SSID); debug.print("WiFi: connecting"); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PW); while (WiFi.status() != WL_CONNECTED) { debug.print("."); delay(LED_CONNECT_BLINK_INTERVAL); digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN)); } debug.println(); // Set hostname workaround debug.println("WiFi: set hostname work-around"); WiFi.setHostname(hostname.c_str()); #endif // Setup HTTP Server debug.println("WiFi: initializing HTTP server"); MDNS.begin(hostname.c_str()); updater.setup(&server); server.on("/", handleRoot); server.begin(); MDNS.addService("http", "tcp", 80); socket.begin(); socket.onEvent(webSocketEvent); debug.println("WiFi: setup done"); } void wifi_run() { if ((millis() - last_server_handle_time) >= SERVER_HANDLE_INTERVAL) { last_server_handle_time = millis(); server.handleClient(); socket.loop(); #ifdef ARDUINO_ARCH_ESP8266 MDNS.update(); #endif // ARDUINO_ARCH_ESP8266 } if ((millis() - last_websocket_update_time) >= WEBSOCKET_UPDATE_INTERVAL) { last_websocket_update_time = millis(); wifi_send_status_broadcast(); } // reset ESP every 6h to be safe if (millis() >= (6 * 60 * 60 * 1000)) { ESP.restart(); } } #endif // PLATFORM_ESP