#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(); }