No commit activity in last 3 years
No release in over 3 years
San Francisco Bay Area 511 Real-time Transit Data Services API
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.0
~> 2.10
~> 3.1

Runtime

 Project Readme

SFBATransitAPI

Information

SFBATransitAPI provides a simple wrapper around Real-time Transit Data Services Application Programming Interface (API) sponsored by 511 in the San Francisco Bay Area. More detail can be found http://www.511.org/developer-resources_transit-api.asp.

How to use

Install the gem

> gem install sfba_transit_api

Register and get your secure token

Go to this website http://511.org/developer-resources_api-security-token_rtt.asp and get your token.

Create a new new client and query away

Assuming you put the token in an environment variable

require 'sfba_transit_api'

client = SFBATransitAPI.client ENV['SFBA_TRANSIT_API_TOKEN']

# When will the next MUNI bus 19 leave from the Polk and Sutter Station to go to
# Potrero Hill?

agencies = client.get_stops_for_route(agency_name: "SF-MUNI", route_code: "19", route_direction_code: "Outbound")

stops = agencies[0]["routes"][0]["route_directions"][0]["stops"]

my_stop = stops.find { |stop| stop["name"] =~ /Polk.+Sutter/ }

puts my_stop.stop_code
# => "16002"

puts client.get_next_departures_by_stop_code("16002")[0]["routes"][0]["route_directions"][0]["stops"][0]["departure_times"]
# => [5, 12]

Result format

Since this is a very thin wrapper around the API, minimal effort is applied in "reinterpreting" the result. Generally a response should look like the following, with agencies that have directions:

<RTT>
  <AgencyList>
    <Agency Name="SF-MUNI" HasDirection="True" Mode="Bus">
      <RouteList>
        <Route Name="19-Polk" Code="19">
          <RouteDirectionList>
            <RouteDirection Code="Outbound" Name="Outbound to Hunters Point">
              <StopList>
                <Stop name="Polk St and Sutter St" StopCode="16002">
                  <DepartureTimeList>
                    <DepartureTime>21</DepartureTime>
                    <DepartureTime>36</DepartureTime>
                    <DepartureTime>55</DepartureTime>
                  </DepartureTimeList>
                </Stop>
              </StopList>
            </RouteDirection>
          </RouteDirectionList>
        </Route>
      </RouteList>
    </Agency>
  </AgencyList>
</RTT>
[
  {
    "type" => "agency",
    "name" => "SF-MUNI",
    "has_direction" => true,
    "mode" => "Bus",
    "routes" => [
      {
        "type" => "route",
        "name" => "19-Polk",
        "code" => "19",
        "route_directions" => [
          {
            "type" => "route_direction",
            "name" => "Outbound to Hunters Point",
            "code" => "Outbound",
            "stops" => [
              {
                "type" => "stop",
                "name" => "Polk St and Sutter St",
                "stop_code" => "16002",
                "departure_times" => [21, 36, 55]
              }
            ]
          }
        ]
      }
    ]
  }
]

or with agencies without directions:

<RTT>
  <AgencyList>
    <Agency Name="BART" HasDirection="False" Mode="Rail">
      <RouteList>
        <Route Name="24th St. Mission" Code="587">
          <StopList>
            <Stop name="16th St. Mission (SF)" StopCode="10">
              <DepartureTimeList/>
            </Stop>
          </StopList>
        </Route>
        <Route Name="Daly City" Code="747">
          <StopList>
            <Stop name="16th St. Mission (SF)" StopCode="10">
              <DepartureTimeList>
                <DepartureTime>15</DepartureTime>
                <DepartureTime>29</DepartureTime>
                <DepartureTime>42</DepartureTime>
              </DepartureTimeList>
            </Stop>
          </StopList>
        </Route>
      </RouteList>
    </Agency>
  </AgencyList>
</RTT>
[
  {
    "type" => "agency",
    "name" => "BART",
    "has_direction" => false,
    "mode" => "Rail",
    "routes" => [
      {
        "type" => "route",
        "name" => "24th St. Mission",
        "code" => "587",
        "stops" => [
          {
            "type" => "stop",
            "name" => "16th St. Mission (SF)",
            "stop_code" => "10",
            "departure_times" => []
          }
        ]
      },
      {
        "type" => "route",
        "name" => "Daly City",
        "code" => "747",
        "stops" => [
          {
            "type" => "stop",
            "name" => "16th St. Mission (SF)",
            "stop_code" => "10",
            "departure_times" => [ 15, 29, 42 ]
          }
        ]
      }
    ]
  }
]

API

TODO (Read the test or code for now)

module SFBATransitAPI

  # creates the client
  #
  # @param token [String]
  # @param opts [Hash]
  # @option opts [String] :api_endpoint default to "http://services.my511.org"
  # @option opts [String] :path_prefix default to "/Transit2.0"
  # @return [SFBATransitAPI::Client]
  def client(token, opts={}); end

  class Client

    # get a list of transit agencies
    #
    # @return [Array<Hash>]
    def get_agencies; end

    # get a list of routes for a given agency
    #
    # @param agency_name [String]
    # @return [Array<Hash>]
    def get_routes_for_agency(agency_name); end

    # get a list of routes for multiple agencies
    #
    # @param agency_names [Array<String>]
    # @return [Array<Hash>]
    def get_routes_for_agencies(agency_names); end

    # get a list of stops for a given route
    #
    # @param route_info [Hash]
    # @option route_info [String] :agency_name required
    # @option route_info [String] :route_code required
    # @option route_info [String] :route_direction_code optional if agency is direction-less
    # @return [Array<Hash>]
    def get_stops_for_route(route_info); end

    # get a list of stops for multiple routes
    #
    # @param route_infos [Array<Hash>] see `#get_stops_for_route` for param info
    # @return [Array<Hash>]
    def get_stops_for_route(route_info); end

    # get a stop with departure times
    #
    # @param stopcode [String]
    # @return [Array<Hash>]
    def get_next_departures_by_stop_code(stopcode); end
  end

end

Note on tesing

There are a few tests that require hitting the real endpoint, which is currently tagged as external. To run the tests without these tests

> rspec --tag ~@external

or run it with your token

> SFBA_TRANSIT_API_TOKEN=[your token here] rspec

or simply add it to your .env file