Imported from cjb230/i-ink (
AGENTS.md). Install upstream withnpx skills add cjb230/i-ink. Copyright stays with the author.
AGENTS.md
What this project is
A Raspberry Pi e-ink dashboard. It runs a loop every 4 minutes: scrape WKD train times, fetch weather from a local proxy, render a composite Pillow image, and push it to a Waveshare 7.5" e-ink display. See README.md for full details.
Running
python run.py # development (uses mock display, saves out.png)
./start.sh # production Pi deploy (pulls git, activates venv, sets GPIO)
Testing
pytest # runs all tests (requires network)
pytest -m "not integration" # offline-safe subset
tests/test_trains.py::test_scraper_runsis marked@pytest.mark.integration— it makes a live HTTP request to wkd.com.pl and will fail offline. Skip it with-m "not integration".tests/test_weather.py— uses local fixture data but requires thetesseractbinary (brew install tesseracton Mac,apt-get install tesseract-ocron Linux)
Architecture notes
display/__init__.pyauto-detects Raspberry Pi viaplatform.uname()and selectsRealDisplayorMockDisplay. No env var or flag needed.- Weather data comes from a local proxy at
192.168.1.129:8080, not directly from OpenWeatherMap. The.envvariables (OWM_API_KEYetc.) are consumed by that proxy, not by this app. I_INK_FAILURE_ALERT_THRESHOLDis consumed by this app. It defaults to3; source errors appear on the panel after more than that many consecutive failures.- Weather and train fetches are isolated. If one source fails, the last good data for that source is reused while the other source can still update normally.
- Times are hardcoded to
Europe/Warsawtimezone intransform.py(unix_ts_to_str,transform_trains,transform_weather). - The display only refreshes when the image body (top 750px) has changed —
conditional_update_screeninmain.pycompares raw pixel bytes. render_weather_daysrenders four daily forecast panels with icon and min/max temperature.
Key files
| File | Role |
|---|---|
i_ink/main.py |
Entry point, main loop, signal handling |
i_ink/trains.py |
WKD scraper — XPath-based, fragile to site changes |
i_ink/weather.py |
Thin HTTP client for the local weather proxy |
i_ink/transform.py |
Converts raw API dicts to display-ready structures |
i_ink/render.py |
All Pillow drawing; font loading; SVG weather icons via cairosvg |
Known issues / rough edges
filter_trains_for_displayintrains.pyis unused — filtering is done intransform_trains.pyproject.tomlis missing several dependencies used by the app/tests (cairosvg,python-dotenv,pytesseract,freezegun).- Weather icon SVGs must be present in
svg/at the repo root (not tracked in git — source them from OpenWeatherMap). A missing SVG raisesFileNotFoundErrorand terminates the process, which is intentional.