SvitloPulse

Home power sensor

Any mains-powered device with internet access can “ping” SvitloPulse once a minute. When the pings stop, power is most likely out.

What it is

It is the strongest independent signal we use: the device itself reports that mains power is present. The request is so simple that it can come from a router, a single-board computer, a $3 board or Home Assistant.

It improves accuracy only when many neighbours do it. One sensor changes nothing publicly: signals appear only when at least five independent sources of the same queue send them, and with a delay.

Privacy

  • Individual sensors are never shown: not on the map, not in the API. Only aggregates of five or more sensors of the same queue are public, with a delay of at least 30 minutes.
  • A sensor is tied to a queue, not to an address. We do not ask for an address, name, phone or location.
  • The ping URL contains a secret token: it is the sensor’s password. Do not publish it in repositories or screenshots. If it leaked, delete the sensor below and create a new one.
  • Sensor readings are deleted automatically after 48 hours. More: privacy.

Create a sensor

The interval sets how quickly we notice that the pings stopped.

Set up a device

Pick a method. Each one uses the ping URL: before you create a sensor it contains YOUR_TOKEN and after creation it becomes your token.

  1. Connect to the router over SSH and install curl with HTTPS support (on OpenWrt these are the packages curl, ca-bundle).
  2. Add a cron job and start cron.
OpenWrt · SSH
opkg update && opkg install curl ca-bundle
echo '__CRON__ curl -fsS -m 10 "https://svitlopulse.andrewboyko.name/api/v1/sensor/YOUR_TOKEN/ping" >/dev/null 2>&1' >> /etc/crontabs/root
/etc/init.d/cron enable
/etc/init.d/cron restart

The router must have no backup power, otherwise it “sees” power that is already gone. If curl does not fit in flash, uclient-fetch (with libustream-mbedtls) works instead.

Works on a Raspberry Pi, mini PC, NAS and any Linux. Run crontab -e and add the line:

crontab
__CRON__ curl -fsS -m 10 "https://svitlopulse.andrewboyko.name/api/v1/sensor/YOUR_TOKEN/ping" >/dev/null 2>&1

If the device is on a UPS or a battery-backed supply it keeps pinging during an outage. A plain mains socket is what a sensor needs.

A sketch for Arduino IDE or PlatformIO. Works on ESP32 and ESP8266, keeps the Wi-Fi connection and sends a request once per interval.

Arduino · ESP32 / ESP8266
#if defined(ESP8266)
  #include <ESP8266WiFi.h>
  #include <ESP8266HTTPClient.h>
  #include <WiFiClientSecureBearSSL.h>
#else
  #include <WiFi.h>
  #include <HTTPClient.h>
  #include <WiFiClientSecure.h>
#endif

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_PASSWORD";
const char* PING_URL  = "https://svitlopulse.andrewboyko.name/api/v1/sensor/YOUR_TOKEN/ping";
const unsigned long EVERY_MS = __MS__UL;

void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
#if defined(ESP8266)
    BearSSL::WiFiClientSecure client;
#else
    WiFiClientSecure client;
#endif
    client.setInsecure();  // simplest; for production pin the root CA with setCACert()
    HTTPClient http;
    if (http.begin(client, PING_URL)) {
      http.setTimeout(8000);
      http.GET();          // 204 = accepted
      http.end();
    }
  }
  delay(EVERY_MS);
}

Power the board from an ordinary USB adapter in a mains socket, not from a power bank. setInsecure() does not verify the server certificate; pin the root certificate for robustness.

Add a command and an automation (Home Assistant 2024.10 and newer syntax):

configuration.yaml
rest_command:
  svitlopulse_ping:
    url: "https://svitlopulse.andrewboyko.name/api/v1/sensor/YOUR_TOKEN/ping"
    method: get
    timeout: 10

automation:
  - alias: "SvitloPulse: датчик світла"
    triggers:
      - trigger: time_pattern
        minutes: "__HAMIN__"
    actions:
      - action: rest_command.svitlopulse_ping

A Home Assistant on a NAS or mini PC behind a UPS “sees” power even during an outage. That is not a sensor but a false “power on” signal.

You can check that the sensor works with one command. The server answers 204 with no body. Both GET and POST are accepted.

curl
curl -fsS -m 10 -o /dev/null -w "%{http_code}\n" "https://svitlopulse.andrewboyko.name/api/v1/sensor/YOUR_TOKEN/ping"
# 204 = accepted

# the same with POST
curl -fsS -m 10 -X POST -o /dev/null -w "%{http_code}\n" "https://svitlopulse.andrewboyko.name/api/v1/sensor/YOUR_TOKEN/ping"

Delete a sensor

Deleting stops accepting pings with this token immediately.

Honest about accuracy

  • Missing pings do not always mean no power: the network, Wi-Fi, the ISP or the device itself may have failed. That is why one sensor decides nothing, and several neighbouring sensors agreeing does.
  • Backup power (UPS, inverter, power bank, generator) gives a false “power on”. Plug the sensor into a socket without backup.
  • The signal only adjusts the estimate based on the operator’s schedule, and its influence is capped. See “How it works”.
  • Do not connect other people’s devices or create several sensors for one home: it adds no accuracy and only distorts the picture.