Suggestions for returning external API train disruption details in HA notification

I recently found the Public Transport Victoria (PTV) custom integration which returns upcoming departures for our local station. I plan do use this to send a ping when we are getting ready / leaving work (if at work, not on holiday etc.) of the upcoming next trains [good wife points :smiley:]. This integration has an entity for each of the next 5 trains on the route requested (e.g. sensor.city_to_home_station_0, _1 etc.)

In the attributes for each next train there is also a list of disruptions IDs, these can be used with the PTV API to return details about current disruptions for that service, my next plan was to have these disruptions sent via a phone notification.
I have written a template which takes these disruption IDs removes ones that are in an input_text ignore list (as some are constant e.g. car park closed for work).
I have also written cobbled together a python script (borrowing some of bremorā€™s code) to take an input list of disruptions and return a string of the titles.
I was all good and ready to use the python_script integration to send data: and then update an input_text with hass.services.call("input_text", "set", service_data) with the disruptions but then i found that import isnā€™t allowed :cry: - i probably should have read the wiki properly.

Does anyone have any thoughts on how to best approach this next? Is there a way to send some data to an external python script and get a response back to then spit out a notification?

My other thought was to update the custom integration - i think it might be beyond me with my coding but i also really donā€™t see how the disruptions would fit into standard Home Assistant structure either, especially with an ignore list etc. Has anyone seen something like i have described before in another integration.

I might just be asking too much here and perhaps i need to use a shell script and another method of sending a message to my phone, and just calling a shell_command

Why not use pyscript integration. This will allow imports.

1 Like

Thank you.

I missed that bit in the wiki, read about appDaemon and that was too complex for me but missed PyScript.

After a lot of trial and error and more Python that i have ever used before i have about 10 lines of code to send a notification to a phone with the API response based on some input Disruption IDs.

If anyone comes across this thread and wants more details let me know.

Hi, Sorry for opening a few months old post, but I am looking at how to implement disruptions in my automations as well.

Currently there is bus replacement on my section of the Frankston line, however it is still showing the usual times, so if you could maybe share how, you implement the disruptions, that would be goodā€¦

Hi,

This is very crude but the python is here:

import aiohttp
import hmac
import logging
from hashlib import sha1


BASE_URL = "https://timetableapi.ptv.vic.gov.au"
DISRUPTIONS_PATH = "/v3/disruptions/{}"

def build_URL(id, api_key, request):
    request = request + ('&' if ('?' in request) else '?')
    raw = request + 'devid={}'.format(id)
    hashed = hmac.new(api_key.encode('utf-8'), raw.encode('utf-8'), sha1)
    signature = hashed.hexdigest()
    url = BASE_URL + raw + '&signature={}'.format(signature)
    return url


@service
async def send_disruption_details(disruptions=None,sendToPerson1=False, sendToPerson2=False):

    disruption = str(disruptions)
    id = '###'
    api_key = '####-####'
    output = ""
    disruptionArray = disruption.split(",")
    for d in disruptionArray :
        disruptions_path = DISRUPTIONS_PATH.format(d)
        url = build_URL(id, api_key, disruptions_path)
        async with aiohttp.ClientSession() as session:
            response = await session.get(url)
        
        if response is not None and response.status == 200:
            response = response.json()
            output = output + response["disruption"]["title"] + "\n" 

    dataInput = {"channel":"Transport"}
    if sendToPerson1 == True:
        notify.mobile_app_person1_phone(message=output,title="PTV Travel Disruption Reported",data=dataInput)
        
    if sendToPerson2 == True:
        notify.mobile_app_person2_phone(message=output,title="PTV Travel Disruption Reported",data=dataInput)
    

This takes a comma separated array of disruptions and gets the titles for them, it puts them back together in a single string separated by new lines and then depending on the function inputs will sent to person1 and/or person2 via the mobile app.

The in a scheduled Automation the Action that calls this is the following:

service: pyscript.send_disruption_details
data:
  disruptions: >-
    {% set disruptions = state_attr('sensor.X_line_to_Y_from_parliament_station_0','disruption_ids') | string | trim('[]')  %}
    {% set disruptions = disruptions.split(', ')  %}
    {% set ignored_disruptions = states('input_text.ptv_ignored_disruptions') | string | trim('[]') %}  
    {% set ignored_disruptions = ignored_disruptions.split(', ')  %}
    {% set ns = namespace(output = [] ) %} 
    {%- for a in disruptions -%}
      {%- if a not in ignored_disruptions -%}  
        {%- set ns.output = ns.output + [a] -%}
      {%- endif -%}
    {%- endfor -%} 
    {{ ns.output | join(',') }}
  sendToPerson1: true
  sendToPerson2: false

This takes the disruptions_ids attribute details for the relevant route sensor. It converts to an array, removes any disruption ids that exist in the input_text.ptv_ignored_disruptions comma separated text field then sends that as a comma separated list to the python function along with who to send to.

The input_text.ptv_ignored_disruptions is used to avoid getting persistent disruptions like ā€œcar park closed until xyzā€ as i donā€™t want to get a ping from these every time.

All in all is incredibly janky and custom for exactly what i needed but it did the job for me.

Feel free to take it and convert to your needs.

Thank for that, I have implemented itā€¦ Since I have no python skills, i will leave it as it does what I require.

Thanks

1 Like

Is there a trick to get PTV to respond with a Developer ID and Key? Iā€™ve sent 3 emails about a week apart, and I canā€™t seem to get a response.

HI. I emailed [email protected] back in 2018 when I just requested it. Looking at my emails, it seems it was about 3 weeks after I sent it for them to reply.

Who knows how login it will take now.

I was lucky and got a response in 5 days in 2023.

If they donā€™t respond in a few more days perhaps you should try their general support contact details to get them to check if the inbox is still monitored.