[Custom Component] OEBB Austria next journeys

Hello,

Sharing custom integration to retreive next departures from a certain stop in Austria.
I am using it with local public transport, but in principle it should work also with trains/buses.

oebb-fahrplan

It is my first custom integration for home assistant, so any feedback is highly appreciated. :slight_smile:
Each journey is implemented as a dedicated timestamp sensor.
What I did not manage to do for the moment:

  • Grouping / relating entities
  • Show on a card as a list both the departure time as a “static” info (I have saved in attributes) and the state Solved via templating and glance card

home-assistant-oebb

1 Like

Hey, nice :ok_hand: this looks super convenient.
How’s your experience with train delay information from the API?

It would be super helpful to get a quick setup tutorial on the repository. Mainly:

  • where to install the repository into
  • how to get oebb stop ID
  • maybe add it to hacs if that’s possible. I have never done this so nevermind if a bunch of work ^^

Hey,

the integration looks nice, but I am unable to install it.
Could you please share some instructions?

Thank you

I managed to install it now via HACS and it works really nice. As the API even provides the delay info, I slightly modified the code to add this info too. Only issue I have, is that only journeys within the next hour are shown and I can’t find a way to extend the timewindow.

Thats how it looks in my dashboard now.

Many thanks for this integration! :+1:

2 Likes

Hey airman,
great work! Can you share your change to the code? And how do I get the attributes information into the tiles?

Hey,

you just need to add the last line to the sensor.py
This adds the field “rt” to the sensor attributes. In case of a canceled or delayed train, info will be there.

Cheers

        else:
            self.attributes = {
                "startTime": data["journey"][self.idx]["ti"],
                "startDate": data["journey"][self.idx]["da"],
                "lastStop": data["journey"][self.idx]["lastStop"],
                "line": data["journey"][self.idx]["pr"],
                "rt": data["journey"][self.idx]["rt"],
1 Like

Hi guys! Thank you very much for the integration! Does it work with OeBB only? Is there a way to integrate Westbahn schedule as well?

Hi,

for my understanding, this should work even with the default config.

Hey guys

I am having trouble with that integration. It seems like it has problems with some of the stations. I am trying to integrate it with “Krems an der Donau Bahnhof” which has the evaID 1230101, and I keep getting “Unavailable”. I have the suspicion that this happens due to the fact that this evaID is one char longer than your default, because that works. Not sure though.

It works with the examples. But as soon as I enter my own evaID it does not.

S.

Hi,

the evaID shouldn’t be the problem, I am using 1231205 and I am getting results. From what I have observed, only departures within the next hour are shown, maybe in combination with dirInput there is no matching departure…

Hey Oliver,

Sonofabitch! That is correct, it DOES only show connections for the next hour. I am actually looking for trains from Krems to Heiligenstadt, and there is only one per hour… And the sensor.xxx always created themselves new when I used the original ones it seems…

Damn. That pretty much cost me a day. Thanks Oliver, very much appreciated!!!

S.

P.S. Now it would be interesting to see why with this API we only get one hour in advance… I scoured the sensor.py, I also added the platform, but I did not find anything which limits to an hour.

Hi, could you possibly share how you have these cards configured, I would love to have similar

Yes, that would be interesting to know. But as this project seems to be not further maintained, I guess it will be difficult…

Hi,

I don’t have the exact same setup anymore, but here is what I have now:
image

In configuration.yaml I am creating new sensors with reference to the original sensor, to be able to sort the cards according departure time (including delay). Here example of sensor oebb0, I created another with oebb1 too, as I want to display just the next 2 connections.

  - sensor:
      - name: "oebb0"
        state: >
          {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'startTime'), '%d.%m.%Y %H:%M') }}
        attributes:
          actualDeparture: > 
            {% if state_attr('sensor.oebb_journey_0', 'rt') == false %}
            {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'startTime'), '%d.%m.%Y %H:%M') }}
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] == 'Ausfall' %}
            {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'startTime'), '%d.%m.%Y %H:%M') }}
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] is none %}
            {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'rt')['dlt'], '%d.%m.%Y %H:%M') }}
            {% endif %}
          scheduledTime: >
            {{ state_attr('sensor.oebb_journey_0', 'startTime') }}
          actualTime: >
            {% if state_attr('sensor.oebb_journey_0', 'rt') == false %}
            {{ state_attr('sensor.oebb_journey_0', 'startTime') }}
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] is none %}
            {{ state_attr('sensor.oebb_journey_0', 'rt')['dlt'] }}
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] == 'Ausfall' %}
            {{ state_attr('sensor.oebb_journey_0', 'startTime') }}
            {% endif %}
          lastStop: >
            {{ ((state_attr('sensor.oebb_journey_0', 'lastStop'))) | replace('Bahnhof', '') | replace('Hbf', '') | replace('.', '. ') | replace('ö', 'ö') }}
          line: >
            {{ ((state_attr('sensor.oebb_journey_0', 'line'))) | replace(' ', '') }}
          status: >
            {% if state_attr('sensor.oebb_journey_0', 'rt') == false %}
            PĂĽnktlich
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] is none %}
            Verspätet
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] == 'Ausfall' %}
            Ausfall
            {% endif %}

And then I made the cards with the mushroom template card and auto-entities to sort it:

- type: custom:auto-entities
    card:
      type: grid
      columns: 2
      square: false
    card_param: cards
    filter:
      include:
        - entity_id: sensor.oebb0
          options:
            type: custom:mushroom-template-card
            tap_action:
              action: none
            hold_action:
              action: none
            double_tap_action:
              action: none
            icon: mdi:tram
            icon_color: >
              {% if state_attr('sensor.oebb0', 'status') == 'PĂĽnktlich' %} green
              {% elif state_attr('sensor.oebb0', 'status') == 'Verspätet' %}
              orange {% elif state_attr('sensor.oebb0', 'status') == 'Ausfall'
              %} red {% endif %}
            primary: |
              {{ state_attr('sensor.oebb0', 'actualTime') }}
            secondary: |
              {{ state_attr('sensor.oebb0', 'line') }}  
            layout: vertical
        - entity_id: sensor.oebb1
          options:
            type: custom:mushroom-template-card
            tap_action:
              action: none
            hold_action:
              action: none
            double_tap_action:
              action: none
            icon: mdi:tram
            icon_color: >
              {% if state_attr('sensor.oebb1', 'status') == 'PĂĽnktlich' %} green
              {% elif state_attr('sensor.oebb1', 'status') == 'Verspätet' %}
              orange {% elif state_attr('sensor.oebb1', 'status') == 'Ausfall'
              %} red {% endif %}
            primary: |
              {{ state_attr('sensor.oebb1', 'actualTime') }}
            secondary: |
              {{ state_attr('sensor.oebb1', 'line') }}  
            layout: vertical
    sort:
      method: attribute
      attribute: actualDeparture

Don’t know enough about this yet, but maybe we can force to check for trains in an hour from now, using the parameter “time” which the API seems to provide. Like “start to poll connections at TIME (which is NOW + 1hr)” as an additional line. Have not found yet where the polling is done, but maybe that’s an option. Or test first whether TIME will give back anything at all…

Brilliant, thanks. I had been tooling around with a template sensor to extract attributes etc. but I wasn’t getting very far.

Hello Oliver, now that I know that the sensor only shows the trains for the next hour, I tried to use your template. Since I am a total noob, I am not getting it to run.

I used your code from above to create a template sensor in the configuration.yaml. HA also finds that sensor, but it has the term “Unavailable”. Which I am pretty sure is also the reason the mushroom card is also not working. Also, the sensor.oebb0 that I created does not have any attributes to choose from.

Any idea what I am doing wrong here?

Here is the configuration.yaml (with the original oebb-entry):

sensor:
  platform: oebb
  evaId: 1230101
  dirInput: 1291903

template:              
  - sensor:            
      - name: "oebb_0" 
        state: >                                                                                                                                     
          {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'startTime'), '%d.%m.%Y %H:%M') }}   
        attributes:                                                                                                                                  
          actualDeparture: >                                                                                                                         
            {% if state_attr('sensor.oebb_journey_0', 'rt') == false %}                                                                                
            {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'startTime'), '%d.%m.%Y %H:%M') }}   
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] == 'Ausfall' %}                                                                
            {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'startTime'), '%d.%m.%Y %H:%M') }}   
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] is none %}                                                                     
            {{ strptime(state_attr('sensor.oebb_journey_0', 'startDate') + " " + state_attr('sensor.oebb_journey_0', 'rt')['dlt'], '%d.%m.%Y %H:%M') }}   
            {% endif %}                                                                                                                                
          scheduledTime: >                                                                                                                             
            {{ state_attr('sensor.oebb_journey_0', 'startTime') }}                                                                                     
          actualTime: >                                                                                                                                
            {% if state_attr('sensor.oebb_journey_0', 'rt') == false %}   
            {{ state_attr('sensor.oebb_journey_0', 'startTime') }}                
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] is none %}   
            {{ state_attr('sensor.oebb_journey_0', 'rt')['dlt'] }}                     
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] == 'Ausfall' %}   
            {{ state_attr('sensor.oebb_journey_0', 'startTime') }}                     
            {% endif %}                                                                
          lastStop: >                                                                                                                                             
            {{ ((state_attr('sensor.oebb_journey_0', 'lastStop'))) | replace('Bahnhof', '') | replace('Hbf', '') | replace('.', '. ') | replace('ö', '..') }}   
          line: >                                                                                                                                                 
            {{ ((state_attr('sensor.oebb_journey_0', 'line'))) | replace(' ', '') }}                                                                              
          status: >                                                                                                                                               
            {% if state_attr('sensor.oebb_journey_0', 'rt') == false %}                                                                                           
            On_Time                                                                 
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] is none %}   
            Late                                                                       
            {% elif state_attr('sensor.oebb_journey_0', 'rt')['status'] == 'Ausfall' %}   
            Cancelled                                                                  
            {% endif %}

I am now as a first step just trying to use the sensor.oebb_0 (I renamed that) to get ANY information, but that fails…

Any help is appreciated.

Found it. Oliver, you did not mention that the attribute startDate has to be added to sensor.py, since it is not in there as a standard.

Yes, you are right, sorry for that, completely forgot about it!

hey community!

to me it looks like, the issue with only getting data 1h ahead only occurs when dirInput is used.

can anybody confirm this?
btw, is this integration still maintained? I saw that there are couple of forks with also some rather important fixes (e.g. making dirInput actually optional not mandatory as in @lollopod repository, …)

EDIT: I was wrong, even without dirInput the API does not provide information more than one hour ahead.

BR,
Tom