Skip to content

Latest commit

 

History

History
158 lines (119 loc) · 5.07 KB

File metadata and controls

158 lines (119 loc) · 5.07 KB

GTFS-Realtime Stream

Real-time public transit data (vehicle positions, trip updates, service alerts) via GTFS-Realtime protobuf feeds.

No setup required — defaults to the MBTA (Boston) open feed.

Quick Start

uv run python examples/gtfs_example.py

Expected output:

Polling GTFS feed: https://cdn.mbta.com/realtime/VehiclePositions.pb
Press Ctrl+C to stop.

09:20:31 | Vehicle y3285        | route 66     | STOPPED_AT    | (42.3292, -71.0839)
09:20:31 | Vehicle y1863        | route 28     | STOPPED_AT    | (42.3291, -71.0839)
09:20:31 | Vehicle y2008        | route 111    | STOPPED_AT    | (42.4093, -71.0301)
09:20:31 | Vehicle y3347        | route 116    | IN_TRANSIT_TO | (42.4460, -70.9844)
09:20:31 | Vehicle y1992        | route 8993   | STOPPED_AT    | (42.3973, -71.1040)

Environment Variables

# .env

# Feed URL — defaults to MBTA (Boston), no auth required
GTFS_FEED_URL=https://cdn.mbta.com/realtime/VehiclePositions.pb

# Short label for this feed, used as event.source
GTFS_FEED_ID=mbta

# API key — leave blank for open feeds, required for MTA / Bay Area 511
GTFS_API_KEY=

All three variables are optional when using an open feed.

Tested Open Feeds

Both of these were verified working with no API key:

MBTA — Boston, MA (default)

GTFS_FEED_URL=https://cdn.mbta.com/realtime/VehiclePositions.pb
GTFS_FEED_ID=mbta
Feed type URL
Vehicle Positions https://cdn.mbta.com/realtime/VehiclePositions.pb
Trip Updates https://cdn.mbta.com/realtime/TripUpdates.pb
Alerts https://cdn.mbta.com/realtime/Alerts.pb

Translink — Brisbane, AU

GTFS_FEED_URL=https://gtfsrt.api.translink.com.au/api/realtime/SEQ/VehiclePositions
GTFS_FEED_ID=translink
Feed type URL
Vehicle Positions https://gtfsrt.api.translink.com.au/api/realtime/SEQ/VehiclePositions
Trip Updates https://gtfsrt.api.translink.com.au/api/realtime/SEQ/TripUpdates

Feeds Requiring a Key

Agency Auth Setup instructions
NYC MTA Free key See SETUP.md
Bay Area 511 Free key See SETUP.md
LA Metro Swiftly API key See developer.metro.net/api

Usage

from streams.gtfs import GTFSStream, VehiclePosition, TripUpdate, ServiceAlert

stream = GTFSStream()
await stream.start()

async for event in stream:
    entity = event.payload
    if isinstance(entity, VehiclePosition):
        print(f"Vehicle {entity.vehicle_id} on route {entity.route_id}")
        if entity.position:
            print(f"  at ({entity.position.latitude:.4f}, {entity.position.longitude:.4f})")
    elif isinstance(entity, TripUpdate):
        print(f"Trip {entity.trip_id}: {len(entity.stop_time_updates)} stop updates")
    elif isinstance(entity, ServiceAlert):
        print(f"Alert [{entity.effect}]: {entity.header}")

To use a non-default feed without changing .env, pass config directly:

from streams.config import GTFSConfig
from streams.gtfs import GTFSStream

stream = GTFSStream(config=GTFSConfig(
    feed_url="https://gtfsrt.api.translink.com.au/api/realtime/SEQ/VehiclePositions",
    feed_id="translink",
))

Entity Types

VehiclePosition

Field Type Description
feed_id str Feed identifier (from GTFS_FEED_ID)
vehicle_id str Vehicle identifier
trip_id str | None Current trip
route_id str | None Route
position Position | None Lat/lon/bearing/speed
current_status str | None INCOMING_AT, STOPPED_AT, IN_TRANSIT_TO
timestamp datetime | None Position timestamp
occupancy_status str | None EMPTY, MANY_SEATS_AVAILABLE, FULL, etc.

TripUpdate

Field Type Description
feed_id str Feed identifier
trip_id str Trip identifier
route_id str | None Route
vehicle_id str | None Vehicle
stop_time_updates tuple[StopTimeUpdate] Per-stop arrival/departure delays
timestamp datetime | None Feed timestamp

ServiceAlert

Field Type Description
feed_id str Feed identifier
alert_id str Alert identifier
cause str | None STRIKE, WEATHER, MAINTENANCE, etc.
effect str | None NO_SERVICE, DETOUR, SIGNIFICANT_DELAYS, etc.
header str Short alert text
description str Full alert text
active_period tuple (start, end) unix timestamp pairs
route_ids tuple[str] Affected routes
stop_ids tuple[str] Affected stops

Notes

  • Default poll interval is 30 seconds
  • Entities are deduplicated across polls by vehicle/trip ID + timestamp
  • The GTFSStream polls a single feed URL; run multiple instances for multiple feed types
  • Use isinstance() checks to handle the three entity types