Skip to content

Instantly share code, notes, and snippets.

@spacegauch0
Last active February 18, 2026 14:52
Show Gist options
  • Select an option

  • Save spacegauch0/2effda8be6131af9a59cccc78a84c3ad to your computer and use it in GitHub Desktop.

Select an option

Save spacegauch0/2effda8be6131af9a59cccc78a84c3ad to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
BVG Departures Display for Waveshare 2.13" e-Paper HAT
Shows U6 departures from Kaiserin-Augusta-Str station
"""
import sys
import os
import json
from datetime import datetime, timezone, timedelta
try:
from waveshare_epd import epd2in13_V2
from PIL import Image, ImageDraw, ImageFont
HAS_EPAPER = True
except Exception as e:
HAS_EPAPER = False
print(f"e-Paper not available: {e}")
sys.exit(1)
# Display dimensions
EPD_WIDTH = 250
EPD_HEIGHT = 122
# Fonts
try:
FONT_UI = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf", 10)
except:
FONT_UI = ImageFont.load_default()
def display_bvg():
"""Fetch and display BVG departures."""
import urllib.request
# Station ID for U6 Kaiserin-Augusta-Str
STATION_ID = "900068302"
try:
url = f"https://v6.bvg.transport.rest/stops/{STATION_ID}/departures?limit=5"
req = urllib.request.Request(url, headers={'User-Agent': 'OpenClawGotchi'})
with urllib.request.urlopen(req, timeout=15) as response:
data = json.loads(response.read())
except Exception as e:
print(f"BVG API error: {e}")
# Try to show error on display
try:
epd = epd2in13_V2.EPD()
epd.init(epd.FULL_UPDATE)
image = Image.new('1', (EPD_WIDTH, EPD_HEIGHT), 255)
draw = ImageDraw.Draw(image)
draw.text((10, 50), "BVG Error", font=FONT_UI, fill=0)
draw.text((10, 70), str(e)[:30], font=FONT_UI, fill=0)
epd.display(epd.getbuffer(image))
epd.sleep()
except:
pass
return
try:
epd = epd2in13_V2.EPD()
epd.init(epd.FULL_UPDATE)
image = Image.new('1', (EPD_WIDTH, EPD_HEIGHT), 255)
draw = ImageDraw.Draw(image)
# Header
now = datetime.now()
draw.text((2, 1), "U6 Kaiserin-Augusta-Str.", font=FONT_UI, fill=0)
time_str = now.strftime('%H:%M')
time_w = draw.textbbox((0, 0), time_str, font=FONT_UI)[2]
draw.text((EPD_WIDTH - time_w - 2, 1), time_str, font=FONT_UI, fill=0)
draw.line((0, 14, EPD_WIDTH, 14), fill=0)
# Departures
y = 20
for dep in data.get('departures', [])[:4]:
line = dep.get('line', {}).get('name', 'U?')
direction = dep.get('direction', '')
when = dep.get('when') or dep.get('plannedWhen', '')
if when:
try:
when = when.replace('+01:00', '+0100').replace('Z', '+0000')
dt = datetime.fromisoformat(when)
now_tz = now.replace(tzinfo=timezone(timedelta(hours=1)))
diff = dt - now_tz
mins = int(diff.total_seconds() / 60)
if mins < 0:
mins = 0
if mins == 0:
time_display = "now"
elif mins == 1:
time_display = "1 min"
else:
time_display = f"{mins} mins"
except:
time_display = "--"
else:
time_display = "--"
direction = direction[:16]
draw.text((5, y), line, font=FONT_UI, fill=0)
draw.text((28, y), direction[:14], font=FONT_UI, fill=0)
time_w = draw.textbbox((0, 0), time_display, font=FONT_UI)[2]
draw.text((EPD_WIDTH - time_w - 5, y), time_display, font=FONT_UI, fill=0)
y += 22
draw.line((0, EPD_HEIGHT - 10, EPD_WIDTH, EPD_HEIGHT - 10), fill=0)
epd.display(epd.getbuffer(image))
epd.sleep()
print("BVG departures shown")
except Exception as e:
print(f"Display error: {e}")
if __name__ == "__main__":
display_bvg()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment