#include #include #include Preferences prefs; WebServer server(80); // dedicated reset/setup button: wire gpio27 -> momentary button -> gnd const int RESET_PIN = 27; const unsigned long RESET_HOLD_MS = 1000; // softap fallback const char* AP_SSID = "baby-monitor-setup"; const char* AP_PASSWORD = "setup1234"; // saved / editable config String wifi_ssid = ""; String wifi_password = ""; String dest_ip_str = "192.168.1.190"; uint16_t udp_port = 5004; c:\Users\moses\proj\vtech\mic\mic.ino bool config_mode = false; const unsigned long WIFI_CONNECT_TIMEOUT_MS = 15000; unsigned long reset_press_start = 0; bool reset_armed = false; String html_escape(const String& s) { String out = s; out.replace("&", "&"); out.replace("<", "<"); out.replace(">", ">"); out.replace("\"", """); return out; } void load_config() { prefs.begin("bmcfg", true); wifi_ssid = prefs.getString("ssid", ""); wifi_password = prefs.getString("pwd", ""); dest_ip_str = prefs.getString("destip", "192.168.1.190"); udp_port = prefs.getUShort("port", 5004); prefs.end(); } void save_config(const String& ssid, const String& pwd, const String& dest_ip, uint16_t port) { prefs.begin("bmcfg", false); prefs.putString("ssid", ssid); prefs.putString("pwd", pwd); prefs.putString("destip", dest_ip); prefs.putUShort("port", port); prefs.end(); } void clear_config() { prefs.begin("bmcfg", false); prefs.clear(); prefs.end(); } bool valid_ipv4(const String& s) { IPAddress ip; return ip.fromString(s); } void handle_root() { String page = "" "" "" "baby monitor setup" "" "" "

baby monitor setup

" "

connect to ap " + String(AP_SSID) + " then browse to 192.168.4.1.

" "
" "" "" "" "" "" "" "" "" "" "
" "
" "" "
" "

view status json

" ""; server.send(200, "text/html", page); } void handle_status() { String json = "{"; json += "\"config_mode\":" + String(config_mode ? "true" : "false") + ","; json += "\"ap_ssid\":\"" + String(AP_SSID) + "\","; json += "\"saved_ssid\":\"" + html_escape(wifi_ssid) + "\","; json += "\"dest_ip\":\"" + html_escape(dest_ip_str) + "\","; json += "\"udp_port\":" + String(udp_port); json += "}"; server.send(200, "application/json", json); } void reboot_to_setup_mode() { Serial.println("clearing config and rebooting to setup mode..."); clear_config(); delay(250); ESP.restart(); } void handle_save() { String new_ssid = server.arg("ssid"); String new_pwd = server.arg("pwd"); String new_dest = server.arg("destip"); uint16_t new_port = (uint16_t)server.arg("port").toInt(); if (new_ssid.length() == 0) { server.send(400, "text/plain", "ssid required"); return; } if (!valid_ipv4(new_dest)) { server.send(400, "text/plain", "invalid destination ip"); return; } if (new_port == 0) { server.send(400, "text/plain", "invalid udp port"); return; } save_config(new_ssid, new_pwd, new_dest, new_port); server.send(200, "text/html", "

saved. rebooting...

"); delay(1000); ESP.restart(); } void handle_clear() { clear_config(); server.send(200, "text/html", "

config cleared. rebooting...

"); delay(1000); ESP.restart(); } void start_config_ap() { config_mode = true; WiFi.disconnect(true, true); delay(250); WiFi.mode(WIFI_AP); WiFi.softAP(AP_SSID, AP_PASSWORD); IPAddress ip = WiFi.softAPIP(); Serial.println("config ap active"); Serial.printf(" ssid: %s\n", AP_SSID); Serial.printf(" pass: %s\n", AP_PASSWORD); Serial.printf(" ip: %s\n", ip.toString().c_str()); server.on("/", HTTP_GET, handle_root); server.on("/save", HTTP_POST, handle_save); server.on("/clear", HTTP_POST, handle_clear); server.on("/status", HTTP_GET, handle_status); server.begin(); } bool try_connect_wifi() { if (wifi_ssid.length() == 0) { Serial.println("no saved wifi ssid"); return false; } WiFi.disconnect(true, true); delay(250); WiFi.mode(WIFI_STA); WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str()); Serial.printf("connecting to wifi: %s\n", wifi_ssid.c_str()); unsigned long start = millis(); while (WiFi.status() != WL_CONNECTED && millis() - start < WIFI_CONNECT_TIMEOUT_MS) { delay(500); Serial.print("."); } Serial.println(); if (WiFi.status() == WL_CONNECTED) { Serial.println("connected"); Serial.printf(" ip: %s\n", WiFi.localIP().toString().c_str()); Serial.printf(" dest ip: %s\n", dest_ip_str.c_str()); Serial.printf(" udp port: %u\n", udp_port); return true; } Serial.println("wifi connect failed"); return false; } void check_reset_button() { bool pressed = (digitalRead(RESET_PIN) == LOW); if (pressed) { if (!reset_armed) { reset_armed = true; reset_press_start = millis(); Serial.println("reset button pressed..."); } else if (millis() - reset_press_start >= RESET_HOLD_MS) { Serial.println("reset hold met"); reboot_to_setup_mode(); } } else { if (reset_armed) { Serial.println("reset button released"); } reset_armed = false; reset_press_start = 0; } } void setup() { Serial.begin(115200); delay(200); pinMode(RESET_PIN, INPUT_PULLUP); load_config(); if (!try_connect_wifi()) { start_config_ap(); } } void loop() { check_reset_button(); if (config_mode) { server.handleClient(); delay(2); return; } // placeholder for later normal-mode behavior static unsigned long last_print = 0; if (millis() - last_print > 5000) { Serial.printf("normal mode alive. wifi=%s ip=%s dest=%s:%u\n", wifi_ssid.c_str(), WiFi.localIP().toString().c_str(), dest_ip_str.c_str(), udp_port); last_print = millis(); } delay(10); }