All posts by fash

Pushover notifier for dates

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

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.

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

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

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!

Ben Eater Clock Module on steroids

My previous build of the clock module is as Ben designed. Wellll . Not really, I added some components to change the clock range.

Okay, Ben’s design is awesome. Not because of its technical design. No, you will learn to use the NE555 chip in three ways!
Variable freq, debounce with delay and a flip-flop like switch
I added another function to it. While making my version.
I added a 555 power-on reset pulse part.

I used a perm board (which is shorter than a regular breadboard)
And I moved some components over and added some LEDs/pin headers.
While doing so, I only used 3/4 of the board.

So I added a power-on reset part with a manual push-button. (Partly like the C64 power-on)
I also added the 1Mhz crystal.

Rest of the boards will use JST connectors for the bus-connections.

I am working on big motor controllers and 3D print modelling for clients.

Busy .. work and play

While working on my clients projects, I’ve been busy with other Fun stuff.

All will be posted more about soon

  • Designing 3D models for printing
  • Testing Arduino Code for RS485!
  • Creating T-shirt prints using 3D printing and bleach/paint with Vincent !
  • Transforming my Lab
  • Testing UM25C logging possibilities
  • Testing queries on overpass-turbo.eu (So much fun)
  • Playing chiptune music using Synthcart + Midi
  • Made V2 displayer on my 64×64 HUB75 led display
  • Bought a directional Wi-Fi antenna, tweaking wireshark to pinpoint rogue access points and clients.

Animatronics Tentacle Test

Using 3x SG90s (metal gears).
These performed far better using my Servo tester than the cheap plastic ones.

First version using Openscad, with variables to control how it looks.

This is printed using TPU.

RepeatingBit = 4;
nr = 20;
difference(){
union(){
for (a =[0:nr]) {
    translate([0,0,(a * (RepeatingBit))]) {
        translate([0,0,a*a*1.3])
        
        cylinder ( h=1+(a*1.1), r1=1,r2=7.5+(a*(a/10)), $fn=30 );
        translate([0,0,a*a*1.3+1+(a*1.1)])
        cylinder ( h=3+(a*1.5), r1=7.5+(a*(a/10)),r2=7.5+(a*(a/10)), $fn=30 );
        
        }
}
translate([0,0,0])
cylinder( h=650, r1=2,r2=4 , $fn=30 );
}

translate([5,0,-10])
rotate([0,2.5,0])
cylinder( h=1000, r1=1,r2=1 , $fn=30 );
translate([-3,4,-10])
rotate([-4/2,-3/2,0])
cylinder( h=1000, r1=1,r2=1 , $fn=30 );
translate([-3,-4,-10])
rotate([4/2,-3/2,0])
cylinder( h=1000, r1=1,r2=1 , $fn=30 );

translate([2,3,-10])
rotate([-1.4,0.6,0])
cylinder( h=1000, r1=2,r2=nr*1.3 , $fn=30 );

translate([2,-3,-10])
rotate([1.6,0.7,0])
cylinder( h=1000, r1=2,r2=nr*1.3 , $fn=30 );

translate([-3.5,0,-10])
rotate([0,-1.8,0])
cylinder( h=1000, r1=2,r2=nr*1.3 , $fn=30 );

}

Video with some organic movement

Using a Raspberry Pi, Python3 and a Servo HAT.

Bottom part

New C64 Cartridges

New cartridges stuff.
I’ve bought some in the past, and was gifted some.

Made a case for an own made 8085 cartridge.
In this case, I used a gifted PCB from Bigred (thanks).
This was designed by Venneker.

With a gap for a 40 pins socket to piggyback signals.

https://media.henriaanstoot.nl/c64-cartridge-gap.tgz

Then a new Nordic Replay, this is a new version of the Retro Replay.

Today the TeensyRom, this came without case, so I printed one in fancy dual silk color.

Demos and hacks soon