diff --git a/v2.ino b/v2.ino new file mode 100644 index 0000000..756f2b2 --- /dev/null +++ b/v2.ino @@ -0,0 +1,124 @@ +#include +#include +#include // <-- Use BearSSL client + +// ---------- Wi-Fi ---------- +const char* ssid = "SSIDHERE"; +const char* password = "PASSWORDHERE"; + +// ---------- ntfy ---------- +const String ntfyServerUrl = "https://ntfy.sh/TOPIC"; + +// ---------- Healthchecks.io ---------- +const char* HC_URL = "https://hc-ping.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; +const unsigned long PING_INTERVAL = 5UL * 60UL * 1000UL; // 5 minutes + +// ---------- Hardware ---------- +const int powerStatusPin = 5; // D1 – optocoupler +const int ledPin = 2; // Built-in blue LED (active-low) + +// ---------- State ---------- +bool previousPowerStatus = false; +unsigned long lastPing = 0; + +BearSSL::WiFiClientSecure wifiClient; // Secure client for both ntfy & HC + +void setup() { + Serial.begin(115200); + pinMode(powerStatusPin, INPUT_PULLUP); + pinMode(ledPin, OUTPUT); + + // ---- Wi-Fi ---- + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.print(F("Connecting to Wi-Fi")); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print('.'); + } + Serial.println(); + Serial.println(F("Connected! IP: ")); + Serial.println(WiFi.localIP()); + + // Allow insecure TLS (self-signed ntfy or HC certs) – remove in prod if you have proper certs + wifiClient.setInsecure(); + + // Optional: tell HC the check just started + pingHealthchecks(String(HC_URL) + "/start"); +} + +void loop() { + // ----- LED blink ----- + digitalWrite(ledPin, LOW); delay(500); + digitalWrite(ledPin, HIGH); delay(500); + + // ----- Power monitoring ----- + bool current = digitalRead(powerStatusPin); + if (current != previousPowerStatus) { + if (current == LOW) { // LOW = power ON + Serial.println(F("Power Restored.")); + sendNotification("Power is on! Control MDF is back on mains power."); + } else { + Serial.println(F("Power Outage Detected!")); + sendNotification("Power is off! Control MDF is on battery power."); + } + previousPowerStatus = current; + } + + // ----- Healthchecks heartbeat ----- + unsigned long now = millis(); + if (now - lastPing >= PING_INTERVAL) { + lastPing = now; + pingHealthchecks(HC_URL); + } + + delay(1000); // debounce / loop pacing +} + +// --------------------------------------------------------------- +// Send ntfy notification (unchanged, just uses the shared client) +// --------------------------------------------------------------- +void sendNotification(const String& message) { + if (WiFi.status() != WL_CONNECTED) { + Serial.println(F("Wi-Fi lost – cannot send ntfy")); + return; + } + + HTTPClient http; + http.begin(wifiClient, ntfyServerUrl); + http.addHeader("Content-Type", "text/plain"); + + Serial.print(F("ntfy → ")); + Serial.println(message); + + int code = http.POST(message); + Serial.print(F("ntfy response: ")); + Serial.println(code); + + http.end(); +} + +// --------------------------------------------------------------- +// Ping healthchecks.io – tiny HTTPS GET +// --------------------------------------------------------------- +void pingHealthchecks(const String& url) { + if (WiFi.status() != WL_CONNECTED) { + Serial.println(F("No Wi-Fi for HC ping")); + return; + } + + HTTPClient http; + http.setTimeout(10000); // 10 s timeout + http.begin(wifiClient, url); // HTTPS + + Serial.print(F("HC ping → ")); + Serial.println(url); + + int code = http.GET(); + if (code > 0) { + Serial.printf("HC OK (code %d)\n", code); + } else { + Serial.printf("HC failed: %s\n", http.errorToString(code).c_str()); + } + http.end(); +} \ No newline at end of file