ESP32 • Swiss public transport API • ST7789

Swiss Transit Tracker

A configurable departure board for Swiss public transport. Pick a station or stop, choose API modes like train, tram, bus, ship, or cableway, then prioritize the lines and destinations you actually care about.

4
rows shown
60s
refresh cycle
120s
watchdog
ESP32 board Wi‑Fi connected microcontroller
USB-C power 5V input for simple mounting
ST7789 display Color rows for any selected mode
Departure UI Four sorted public-transport departures
Watchdog 120s hang protection
JSON pipeline Filtered fields and user rules

Drag to rotate • Scroll to zoom

What it does

A compact board built for reliable glanceable departures.

Real-time departures

Select a Swiss stop and request trains, trams, buses, ships, cableways, or any combination supported by the API.

Delay state at a glance

Green blocks mark departures that are on time. Red blocks show delays above one minute, capped at two digits.

Custom route filters

Prioritize destination text and exact line labels, or hide non-matching departures for a focused board.

Night brightness

Uses the HTTP date header to dim the ST7789 backlight late at night and restore normal brightness during the day.

Data pipeline

Modes and filters are chosen before the display logic runs.

The sketch asks the transport API for up to eight departures using your selected transport modes. ArduinoJson keeps only the fields the UI and custom filters need, reducing parse pressure on the ESP32.

01 Wi‑Fi Reconnect tries before failing cleanly
02 Selected modes transportations[]=bus
03 User filters Destination and line rules
04 Sorted display Best four matches shown
const char* TRANSPORTATION_TYPES[] = {"train", "bus"};
const char* DESTINATION_FILTERS[] = {"basel", "laufen"};
const char* LINE_FILTERS[] = {"S3", "B50"};
const bool ONLY_SHOW_FILTER_MATCHES = false;

filter["stationboard"][0]["to"] = true;
filter["stationboard"][0]["category"] = true;
filter["stationboard"][0]["number"] = true;
filter["stationboard"][0]["stop"]["departure"] = true;
filter["stationboard"][0]["stop"]["delay"] = true;

RAM discipline

Static buffers, bounded rows, predictable work.

9216

JSON document bytes

StaticJsonDocument<9216> holds the filtered stationboard data after parsing.

512

Filter bytes

StaticJsonDocument<512> stores the ArduinoJson filter schema.

12288

Payload reserve

The response string reserves room up front to reduce repeated heap growth.

8→4

Bounded display work

Temporary arrays inspect up to eight API rows, then render the best four matching rows.

Reliability

The watchdog turns bad network states into visible recovery.

The board resets the task watchdog around long network and parse steps. If Wi‑Fi, HTTP, or JSON handling fails, the display shows the reason briefly before the ESP32 restarts into a clean state.

1 Feed WDT esp_task_wdt_reset() before and after blocking work.
2 Classify failure wifi, http, json_nomemory, or body validation errors.
3 Show reset reason The ST7789 prints RESET: with the failure message.
4 Restart cleanly ESP.restart() recovers from a stuck or corrupted runtime state.

Build details

Hardware, libraries, and setup steps.

Display pinout

ST7789 pin ESP32 pin
MOSIGPIO 6
SCLKGPIO 7
CSGPIO 14
DCGPIO 15
RSTGPIO 21
BLGPIO 22

Quick setup

  1. Install ESP32 board support in Arduino IDE.
  2. Add ArduinoJson, Adafruit GFX, and Adafruit ST7789.
  3. Set STATION, ssid, and password.
  4. Choose TRANSPORTATION_TYPES for train, tram, ship, bus, or cableway.
  5. Adjust destination and line filters for the departures you want.
  6. Flash the sketch and power the board through USB-C.
ESP32 ST7789 ArduinoJson Adafruit GFX Transport API Task WDT