OC Transpo (Ottawa, Canada) bus arrival time sensor

With the recent launch of Ottawa’s long-awaited light rail transit, I thought it would be useful to have a sensor to tell me when the next bus is arriving. Fortunately, I was able to implement this without a PR using the RESTful and Template sensors. I also put together a TTS script, which I plan to use to automate announcements.

If you’d like to do the same, just register for access to the API here, and plug your application ID, API key, stop number, and route number into the resource URL in the snippet below.

If you have any trouble, let me know.

  - platform: rest
    name: oc_transpo
    resource: >
    method: POST
    value_template: 'OK'
      - GetNextTripsForStopResult

  - platform: template
        friendly_name: "Next Bus"
        unit_of_measurement: "min"
        value_template: >
          '{{ states.sensor.oc_transpo.attributes["GetNextTripsForStopResult"]
          ["Route"]["RouteDirection"]["Trips"]["Trip"][0]["AdjustedScheduleTime"] }}'

    alias: Next Bus TTS
      - service: tts.amazon_polly_say
          message: 'The next bus will arrive in {{ states("sensor.next_bus") }} minutes.'


Hi I had problem with my google saying “…unknown minutes”, but I solved the issue by making both resource & value_template as one single line solved the problem!

thanks for this post!

Just wanted to say thanks, I’ve been using this for several months now. However, I received an email from the City today regarding API changes coming this month. I’m not technical enough to know if the above is impacted by it.

Here is the link to the new API documentation.

I tested the new version, and it seems to still work if you switch 1.3 to 2.0 and the JSON to json. I’ve updated the post above to reflect this. Please test this out and let me know how it goes.

Thanks! That was fast. I didn’t think their API changes were going to be in effect for a couple more weeks. I’ll update it next week. Very appreciated.

1 Like

@michaeldavie Does this still work ??? I keep getting error to retrieve routes? eg: route 72 and stop id 7754. then it will say error :confused:

I haven’t used this in years, so it’s entirely possible that it doesn’t work any more.

The current documentation is below.


I’m new to HA but here’s my attempt at the current API of OC transpo. This will give a state of “OK” (as otherwise the JSON is too large) and then saves off the attributes for the next bus (if any), the last time the schedule was updated, whether it’s the last of the day, how many minutes from “now” the bus is due (don’t laugh, Ottawans) and the destination.

There’s other options for actual location and speed but my bus route doesn’t have any of those (although apparently this fiscal they’re getting kitted out).

I’m going to try some of the other options on here for varying the update interval with a script so this can be polled a bit more often during the day and stop overnight, but that’s a slower job.

  - platform: rest                                                                       
    resource: "https://api.octranspo1.com/v2.0/GetNextTripsForStop"                      
    scan_interval: 900                                                                   
      format: JSON                                                                       
      appID: !secret octranspo_appid                                                     
      apiKey: !secret octranspo_apikey                                                   
      stopNo: xxx                                                                       
      routeNo: yyy                                                                        
    name: octranspo_bus_info                                                             
    icon: directions_bus                                                                 
    value_template: OK                                                                   
    json_attributes_path: '$.GetNextTripsForStopResult.Route.RouteDirection.Trips.Trip[0]'
      - TripStartTime                                                                    
      - AdjustmentAge                                                                    
      - LastTripOfSchedule                                                               
      - AdjustedScheduleTime                                                             
      - TripDestination

The time from that API is the scheduled time, OCtranspo is a bit infamous for not actually keeping to that schedule, but they appear to be improving in reporting it. I’m using a helper to apply the AdjustedScheduleTime (which is helpfully in minutes from this API call) if the AdjustmentAge is set (it’s in decimal fractions of minutes, obviously).

{% if state_attr("sensor.octranspo_bus_info", 
                 "AdjustmentAge") != -1 -%}
{{ states.sensor.octranspo_bus_info.last_updated + timedelta(minutes=int(state_attr("sensor.octranspo_bus_info", "AdjustedScheduleTime"))) }}
{% elif state_attr("sensor.octranspo_bus_info", 
                   "TripStartTime") %}
{{ today_at(state_attr("sensor.octranspo_bus_info", 
                       "TripStartTime")).isoformat() }}
{%- else -%}
{%- endif %}

I’ve had some ideas of when to refresh more often but I’ve settled on just giving my wife a button on the dash that does it so she can press it when she’s actually waiting for a bus.