pythonraspberry-piprotoapple-maps

NYC MTA Subway API How to Get Next Trains At a Specific Station going a Specific Direction


I'm working on a raspberry pi LED Matrix to display when two specific trains are scheduled to arrive at the station near my apartment. I created a MTA developer account (https://api.mta.info/#/landing) and am accessing the APIs, but I'm not sure how to use the API data to figure out when the trains for a certain line going a certain direction are scheduled to arrive (eg. in Apple Maps or NYC Subway or NYC Transit apps you can click on a station and it'll tell you when the next few trains for that line on that direction will arrive eg. Penn Station 2 Train Downtown to Flatbush Ave: 2, 12, 29 min) I'm using this API endpoint: https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs to get the data for the 1 through 7 trains and am able to extract it into an object via the proto file (https://developers.google.com/transit/gtfs-realtime/gtfs-realtime-proto) but I'm not sure what I'm looking at when I do. Here's an example of an entry from it:

vehicle {
  trip {
    trip_id: "096900_1..S03R"
    start_date: "20220815"
    route_id: "1"
  }
  current_stop_sequence: 37
  current_status: STOPPED_AT
  timestamp: 1660597518
  stop_id: "139S"
}
, id: "000005"
trip_update {
  trip {
    trip_id: "097200_1..N03R"
    start_date: "20220815"
    route_id: "1"
  }
  stop_time_update {
    arrival {
      time: 1660597411
    }
    departure {
      time: 1660597471
    }
    stop_id: "103N"
  }
  stop_time_update {
    arrival {
      time: 1660597531
    }
    stop_id: "101N"
  }
}

I figure I want the stop_time_updates (and the vehicle to check if it is stopped at the station I'm interested in) and I can figure out which stop is which via the ID & which train is which via route_id, but the optional direction_id isn't listed and when I try to take the expected arrival time and take the difference between that and the current time listed in the header my results don't line up with what my live apps are telling me in either direction (Apple Maps, NYC Transit, NYC Subway). My two main questions are how do I tell which way the train is going and how do I get the time at which it'll arrive at a specific station. Am I going about this the right way or is there a better solution? Thanks in advance for any help!

My current python code for reference if it helps (I changed route_id and station in the if statements for anonymity):

subwaydata = gtfs_realtime_pb2.FeedMessage()
subwaydata.ParseFromString(response.content)

currentTime = subwaydata.header.timestamp

for entity in subwaydata.entity:
    if (entity.trip_update != None and entity.trip_update.trip.route_id == "ROUTE"):
        for stop_time_update in entity.trip_update.stop_time_update:
            if (stop_time_update.stop_id == "STATION"):
                print("Trip ID: " + entity.trip_update.trip.trip_id)
                print("Train: " + str(round((stop_time_update.arrival.time - currentTime) / 60)))
    # elif (entity.vehicle != None and entity.vehicle.trip.route_id == "ROUTE" and entity.vehicle.stop_id == "STATION"):
    #     print(entity.vehicle)
    elif (entity.trip_update != None and entity.trip_update.trip.route_id == "ROUTE"):
        for stop_time_update in entity.trip_update.stop_time_update:
            if (stop_time_update.stop_id == "STATION"):
                print("Trip ID: " + entity.trip_update.trip.trip_id)
                print("Train: " + str(round((stop_time_update.arrival.time - currentTime) / 60)))
    # elif (entity.vehicle != None and entity.vehicle.trip.route_id == "ROUTE" and entity.vehicle.stop_id == "STATION"):
    #     print(entity.vehicle)

print(subwaydata.header)

Solution

  • I was able to figure it out!

    This repo (https://github.com/zacs/ha-gtfs-rt) helped me refine my code to isolate stop times for specific lines at specific stations (specifically the _update_route_statuses function). Also figured out that the stop_id is different depending on which direction the train is heading for the same station depending (ie. 212N and 212S are the same station with two different stop_ids for two different directions)