Pushover notifier for dates

Last Updated or created 2025-05-16

Below is my python script to push messages via pushover to my phone.

It’s being run from a cron during the day.

CODE

import csv
import datetime
import requests

# configure own creds
PUSHOVER_USER_KEY = 'keykeykeykeykeykeykeykey'
PUSHOVER_API_TOKEN = 'tokentokentokentokentokentokentoken'
CSV_FILE = '/data/notifications.csv'

def send_pushover_notification(message):
    url = "https://api.pushover.net/1/messages.json"
    payload = {
        "token": PUSHOVER_API_TOKEN,
        "user": PUSHOVER_USER_KEY,
        "message": message
    }
    response = requests.post(url, data=payload)
    if response.status_code != 200:
        print("Failed to send notification:", response.text)

def check_and_notify():
    today = datetime.date.today()
    with open(CSV_FILE, newline='') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            try:
                day = int(row['day'])
                month = int(row['month'])
                if today.day == day and today.month == month:
                    send_pushover_notification(row['message'])
            except ValueError:
                continue

if __name__ == "__main__":
    check_and_notify()

notifications.csv file

day,month,message
1,1,Birthday of a new year
16,05,Project Deadline
16,05,Test2 (blah) 2
7,3,Glorious bastard Rik Mayall birthday
27,3,International whisky day

Nice to haves (didn’t implement because i’m a lazy bastard)

  • 3rd Saturday every may
  • Getting dates or updates from another app
  • Selecting Pushover device, level of alertness .. etc

Wireless ping tester with beeps using Wemos

Last Updated or created 2025-05-19

While I’ve used a Laptop with a ping script I made in the past, I needed something more portable.

So I build:

  • Scan for wifi networks
  • Connect
  • Enter IP to ping
  • Buzzer beeps when ICMP packet received
  • Gateway not reachable ? Sound alarm note

This way I can use both hands, hanging upside-down in a hard-to-reach place, without turning my head to a screen or my phone.

CODE (Below code is for D6)

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <ESP8266Ping.h>

ESP8266WebServer server(80);
String pingHost = "";
bool startPinging = false;
unsigned long lastPingTime = 0;
bool gpioState = false;

void setup() {
  Serial.begin(115200);
  pinMode(D6, OUTPUT);  

  // WiFiManager captive portal
  WiFiManager wm;
  if (!wm.autoConnect("ESP_SetupAP")) {
    Serial.println("Failed to connect, restarting...");
    ESP.restart();
  }

  Serial.println("WiFi connected. IP:");
  Serial.println(WiFi.localIP());

  // Web UI
  server.on("/", HTTP_GET, []() {
    String html = "<html><body><h2>ESP Continuous Ping</h2>"
                  "<form action='/start'>"
                  "Host/IP to ping: <input name='host' type='text'>"
                  "<input type='submit' value='Start Pinging'>"
                  "</form></body></html>";
    server.send(200, "text/html", html);
  });

  server.on("/start", HTTP_GET, []() {
    if (!server.hasArg("host")) {
      server.send(400, "text/plain", "Missing 'host' parameter.");
      return;
    }
    pingHost = server.arg("host");
    startPinging = true;
    server.send(200, "text/plain", "Started pinging " + pingHost);
  });

  server.begin();
}

void loop() {
  server.handleClient();

  if (startPinging && millis() - lastPingTime > 2000) {
    lastPingTime = millis();
    bool success = Ping.ping(pingHost.c_str(), 1);

    if (success) {
      gpioState = !gpioState;
      digitalWrite(D6, HIGH);
      delay(500);
      digitalWrite(D6, LOW);
      delay(500);
      Serial.println("Ping success, toggled D6.");
    } else {
      Serial.println("Ping failed.");
      digitalWrite(D6, LOW);
    }
  }
}

Further ideas

D2 pin because easier soldering

New project : Find nearest booze shop.

Last Updated or created 2025-05-16

Or anything else. ( idea from a reddit post )

Combining a GPS module, compass, a LED ring and some code, I want to make a little device which shows you the way to the nearest … something.

To make it completely standalone, I have to use a SIM module. (Same as I have used before) This POC will use my phone as hotspot.

The LED ring will show the direction to go.

Edit: Maybe not a LED ring but a little display.

As previously posted, I was playing with Overpass turbo.
Using an API, I can use code to query this.

  • Arduino sends latitude, longitude to my webserver
  • Webserver queries API for neastest POIs and calculates distance.
  • Send data from webserver to arduino
  • Arduino uses heading data to light up direction LED
    (also on secondary display with distance info?)
    edit: and shop info

Test code for my web server to query the data

import overpy
import math

api = overpy.Overpass()

# This location will be filled with data from GPS module on Arduino.
latitude = 52.2270745        # Center latitude (e.g. Berlin)
longitude = 5.177519      # Center longitude
box_size = 0.05         # Box size in degrees (about ~5 km)

south = latitude - box_size
north = latitude + box_size
west = longitude - box_size
east = longitude + box_size

def haversine(lat1, lon1, lat2, lon2):
    R = 6371  # Earth radius in km
    phi1 = math.radians(lat1)
    phi2 = math.radians(lat2)
    d_phi = math.radians(lat2 - lat1)
    d_lambda = math.radians(lon2 - lon1)

    a = math.sin(d_phi / 2)**2 + math.cos(phi1) * math.cos(phi2) * math.sin(d_lambda / 2)**2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))

    return R * c  # Distance in kilometers

# Calculate bearing in degrees (0-360)
def bearing(lat1, lon1, lat2, lon2):
    phi1 = math.radians(lat1)
    phi2 = math.radians(lat2)
    delta_lon = math.radians(lon2 - lon1)

    x = math.sin(delta_lon) * math.cos(phi2)
    y = math.cos(phi1) * math.sin(phi2) - math.sin(phi1) * math.cos(phi2) * math.cos(delta_lon)

    initial_bearing = math.atan2(x, y)
    compass_bearing = (math.degrees(initial_bearing) + 360) % 360  # Normalize to 0–360

    return compass_bearing

# Overpass QL query
query = f"""
[out:json];
node
  ["shop"="alcohol"]
  ({south}, {west}, {north}, {east});
out body;
>;
out skel qt;
"""

try:
    result = api.query(query)

    # Collect and sort places by distance
    places = []
    for node in result.nodes:
        node_lat = float(node.lat)
        node_lon = float(node.lon)
        distance = haversine(latitude, longitude, node_lat, node_lon)
        direction = bearing(latitude, longitude, node_lat, node_lon)
        name = node.tags.get("name", "Unnamed")
        places.append((distance, direction, name, node_lat, node_lon))

    places.sort()

    print(f"Found {len(places)} alcohol-related places sorted by distance:")
    for dist, dir_deg, name, lat, lon in places:
        print(f"- {name} at ({lat:.5f}, {lon:.5f}) — {dist:.2f} km, {dir_deg:.0f}°")

except Exception as e:
    print(f"Error: {e}")

Output:

Found 10 alcohol-related places sorted by distance:
- The Skiff at (52.22583, 5.17860) — 0.16 km, 152°
- Onzewijnen at (52.22612, 5.17045) — 0.49 km, 258°
- Gall & Gall at (52.23244, 5.19204) — 1.15 km, 59°
- Gall & Gall at (52.21536, 5.16735) — 1.48 km, 208°
- Eric's Beer Craft at (52.21549, 5.16632) — 1.50 km, 211°
- Slijterij at (52.21082, 5.15692) — 2.29 km, 218°
- Gall & Gall at (52.21590, 5.14074) — 2.80 km, 244°
- Gall & Gall at (52.25422, 5.22705) — 4.53 km, 48°
- Gall & Gall at (52.26808, 5.18348) — 4.58 km, 5°
- Il DiVino at (52.27507, 5.16414) — 5.41 km, 350°

Example using Overpass Turbo to find breweries

Other ideas

  • Geocaching (Thanks Vincent)
  • Find each other at festivals?

UPS Load in Home Assistant using Curl

Last Updated or created 2025-05-07

Example is for a UPS, but other generic uses can be setup in same manner.

Create helper (1-100 unit %)

input_number.uspload

Create curl command in configuration.yaml

(Fix grep/cut accordantly )

shell_command:
    getups: curl -s  "http://x.x.x.x/cgi-bin/apcupsd/upsstats.cgi?host=127.0.0.1&img1=5&img2=6&img3=5&temp=C&refresh=30" | grep "UPS Load" | grep img  | cut -f4 -d= | cut -f1 -d. | head -1

    

Automation

alias: UPStest
description: ""
triggers:
  - trigger: time_pattern
    minutes: /5
conditions: []
actions:
  - action: shell_command.getups
    metadata: {}
    data: {}
    response_variable: upsload
  - action: input_number.set_value
    metadata: {}
    data:
      value: " {{ upsload['stdout'] }} "
    target:
      entity_id: input_number.uspload
mode: single

Found a rogue AP in my house

Last Updated or created 2025-05-07

Where is it, what device could it be?

Its SSID started with ESP. So I probably am the one responsible for its existence.
I’ve got a sh*tload of ESPs/NodeMCUs/8266 turned on 24-7.

Using a Wifi analizer I could narrow it down to my livingroom.
Checked all devices, and they are all connected to my AccessPoint.
(So no fallback AP mode)

The problem with this method is that you can’t figure out a direction.

So I used this on my Laptop.

See graphs on the left

This is a directional antenna.

Using Wireshark and wavemon, I could find the direction.

There were only two devices in the direction with the strongest signal.
My photo viewer remote, and my mini turntable controller with RFID.

But these devices are working just fine! .. So lets disconnect the power.
So it IS the mini recordplayer!

Lets look at the code. (part of)

WiFi.mode(WIFI_AP_STA); 

I should have used

WiFi.mode(WIFI_STA); 

Now it was a client AND an Access Point!

Mystery solved!