TransPerth API Integration

Hi All,

I just came across an unofficial TransPerth API which gives access to Train, Bus and Ferry times as well as the ability to check your SmartRider balance.

I’m no developer but perhaps someone out there has the ability to integrate this to HA…

https://transperth.maxrumsey.xyz/

You should be able to use rest sensor for what you want.

Yeah, I found another site talking about REST sensors but the links it had to an official API didn’t work. I’ll have to investigate it further.

Hi Dave

Did you have any success with this?

No, unfortunately not.

I’ve been using the following rest command for a while to get train schedules for a given train line and station.

rest_command:
  get_next_train_time:
    url: "https://www.transperth.wa.gov.au/API/TrainLiveTimes/LiveStatus/{{ line_name }}/{{ station_name }}"
    method: GET
    headers:
      ModuleId: 5111
      TabId: 248

I then have a script with a couple fields with the expected station/line names which make it easier to use in automations.

get_next_train_times:
  alias: Get Next Train Times
  sequence:
  - service: rest_command.get_next_train_time
    metadata: {}
    data:
      line_name: '{{ line }}'
      station_name: '{{ station }}'
    response_variable: api_result
  - variables:
      trips: "{% set script_ns = namespace(to_perth=[], from_perth=[]) %}  \n{% if
        api_result.content.result == 'success' %}\n  {% for trip in api_result.content.data.StatusDetailList
        %}\n    {% set departure_hours, departure_mins = trip.Departure.split(':')
        %}\n    {% set departure_time = now().replace(hour=departure_hours|int, minute=departure_mins|int)
        %}\n    {% set diff_seconds = as_timestamp(departure_time) - as_timestamp(now())
        %}\n    {% set diff_minutes = max((diff_seconds / 60) | round(0, 'ceil'),
        0) %}\n    {% set trip = dict(trip, **{'mins_away': diff_minutes}) %}\n    {%
        if trip.Destination == 'Perth' %}\n      {% set script_ns.to_perth = script_ns.to_perth
        + [trip] %}\n    {% elif trip.Destination != 'Perth' %}\n      {% set script_ns.from_perth
        = script_ns.from_perth + [trip] %}\n    {% endif %}\n  {% endfor %}\n{% endif
        %}\n{ \"to_perth\": {{ script_ns.to_perth }}, \"from_perth\": {{ script_ns.from_perth
        }} }\n"
  - stop: ''
    response_variable: trips
  mode: single
  icon: mdi:train
  fields:
    line:
      selector:
        select:
          options:
          - All
          - Airport Line
          - Armadale Line
          - Fremantle Line
          - Yanchep Line
          - Mandurah Line
          - Midland Line
          - Thornlie Line
      name: Line
      description: Which train line?
      required: true
    station:
      selector:
        select:
          options:
          - Airport Central Stn
          - Armadale Stn
          - Ashfield Stn
          - Aubin Grove Stn
          - Bassendean Stn
          - Bayswater Stn
          - Beckenham Stn
          - Bull Creek Stn
          - Burswood Stn
          - Butler Stn
          - Canning Bridge Stn
          - Cannington Stn
          - Carlisle Stn
          - Challis Stn
          - City West Stn
          - Claisebrook Stn
          - Claremont Stn
          - Clarkson Stn
          - Cockburn Central Stn
          - Cottesloe Stn
          - Currambine Stn
          - Daglish Stn
          - East Guildford Stn
          - East Perth Stn
          - Edgewater Stn
          - Elizabeth Quay Stn
          - Fremantle Stn
          - Glendalough Stn
          - Gosnells Stn
          - Grant Street Stn
          - Greenwood Stn
          - Guildford Stn
          - High Wycombe Stn
          - Joondalup Stn
          - Karrakatta Stn
          - Kelmscott Stn
          - Kenwick Stn
          - Kwinana Stn
          - Lakelands Stn
          - Leederville Stn
          - Loch Street Stn
          - Maddington Stn
          - Mandurah Stn
          - Maylands Stn
          - McIver Stn
          - Meltham Stn
          - Midland Stn
          - Mosman Park Stn
          - Mt Lawley Stn
          - Murdoch Stn
          - North Fremantle Stn
          - Oats Street Stn
          - Perth Stadium Stn
          - Perth Stn
          - Perth Underground Stn
          - Queens Park Stn
          - Redcliffe Stn
          - Rockingham Stn
          - Seaforth Stn
          - Shenton Park Stn
          - Sherwood Stn
          - Showgrounds Stn
          - Stirling Stn
          - Subiaco Stn
          - Success Hill Stn
          - Swanbourne Stn
          - Thornlie Stn
          - Victoria Park Stn
          - Victoria Street Stn
          - Warnbro Stn
          - Warwick Stn
          - Wellard Stn
          - Welshpool Stn
          - West Leederville Stn
          - Whitfords Stn
          - Woodbridge Stn
      name: Station
      description: Which station?
      required: true

Hope that helps someone do something cool.

2 Likes

I finally got around to implementing this code and it seems to work, but where does the response end up? The script runs without issue but nothing else happens and I can’t find any entity with the response data.

How are you displaying it?

Thank you so much for this. I have added this rest_command and some custom sentences to my voice assistant pipeline, and now I can ask my assist when the next train to Perth departs my local station. I like that the API tells you if there are delays.

Would you mind sharing the sentences etc so I can try to implement the same thing? Sounds handy

I have an automation that triggers when I arrive at my local station and it runs the script then sends me a notification with how many minutes until the next train so I know if i need to go quickly or if I’ve got some time.

I thought about some interface or dashboard that said I need to leave in the next x minutes to make the train but they come so frequently and I have no real start time for work so there wasn’t any benefit.

alias: Notification - Train Time
description: ""
mode: single
triggers:
  - entity_id: person.chris
    zone: zone.edgewater_train_station
    event: enter
    id: Chris Arrived At Station
    trigger: zone
conditions:
  - condition: time
    after: "06:00:00"
    before: "10:30:00"
    weekday:
      - fri
      - wed
      - mon
      - tue
      - thu
actions:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - Chris Arrived At Station
        sequence:
          - repeat:
              sequence:
                - metadata: {}
                  data:
                    line: Yanchep Line
                    station: Edgewater Stn
                  response_variable: train_times_response
                  action: script.get_next_train_times
                - variables:
                    next_train: "{{ train_times_response.to_perth | first }}"
                    second_train: "{{ train_times_response.to_perth[1] }}"
                - metadata: {}
                  data:
                    title: Next Train To Perth
                    message: |-
                      {% if next_train is defined %}
                        Next train at {{ next_train.Departure }} in {{ next_train.mins_away }} mins ({{ next_train.StatusDetail }})
                        {% if next_train.mins_away | int <= 5 %}
                          The train after that is due at {{ second_train.Departure }} in {{ second_train.mins_away }} mins ({{ second_train.StatusDetail }})
                        {% endif %}
                      {% else %}
                        There are no trains to Perth on the Yanchep Line scheduled.
                      {% endif %}
                  action: notify.mobile_app_chris_mobile
                - if:
                    - condition: template
                      value_template: "{{ train_times_response.to_perth | length == 0 }}"
                  then:
                    - stop: No trains scheduled
                - delay:
                    hours: 0
                    minutes: >-
                      {{ max(train_times_response.to_perth[0].mins_away | int,
                      1.5 ) }}
                    seconds: 0
                    milliseconds: 0
              while:
                - condition: zone
                  entity_id: person.chris
                  zone: zone.edgewater_train_station
                  enabled: true
2 Likes

Awesome work @Chris112 - love it. I’ve been wanting to add this and you’ve made it super easy for me to do it! Working nicely.