Custom component Stib - Brussels public transportation


I wrote a custom_component sensor for the Brussels public transportation :

It adds a new sensor for each line that passes a given stop or station and returns the waiting time for the 2 next passing vehicles.

(I added a customize for the friendly name).


very nice, could you do the same thing for DE LIJN in flanders :wink:

1 Like

Really nice, thank you!

1 Like

Hi Daniel,

I’m using HA v100.1 and unable to run it :frowning:
I first tried as indicated by copying into the custom_components/sensor folder. The component is not found. I then (just to try it out without actually believing it would ever work) renamed the into, created a manifest.json and an empty file to mimic the structure of other components to get this:

Error doing job: Task exception was never retrieved Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/", line 408, in _async_add_entity await entity.async_update_ha_state() File "/usr/src/homeassistant/homeassistant/helpers/", line 273, in async_update_ha_state self._async_write_ha_state() File "/usr/src/homeassistant/homeassistant/helpers/", line 327, in _async_write_ha_state icon = self.icon File "/config/custom_components/stib/", line 113, in icon if self.mode == 'M': AttributeError: 'StibSensor' object has no attribute 'mode'

What would I need to adapt code wise to make it work? This is really a useful component for anybody using the Brussels public transportation and I am sure I am not the only one appreciating the work done so far :slight_smile:

Many thanks

As I didn’t update to the new way working with the custom components, I’m afraid it’s not working anymore. I started to work on a new version and wanted to submit a PR to integrate Stib in core HA, but still laking time.
I’m now using a script that takes the xml files from, converts the necessary data to a MQTT message and uses mqtt sensors in HA. I’ll check if I can clean it up and publish it on my Github in the next hours.
Or you wait a bit more, your message made me put this project on top of the pile :wink:

Hi Daniel,

Happy to waken it up again, as I am still playing around with both HA and Nodered, both would be great :slight_smile: I appreciate this takes time, no worries.
Do not hesitate to let me know if I can help testing, I’ll be glad to do so.

Bad news: the simpler, old api has been disabled and doesn’t works any more since yesterday.
I’ll have to start over withe the new api. Luckely someone made a wrapper for the new version :
Now if you want to use this, you need to get an api key from
Will check how this is working with HA.

Many thanks, I am looking forward to hearing your test results :slight_smile:
I would not know where to start with the wrapper… I guess the motivation to dig into it will come when, after finishing my dashboards I feel the need to improve it by making a component/card myself :wink:
Tx again for looking into this

I adapted the code to work with the new STIB API, and further rewrote it somewhat. Every sensor entity now for example shares one single StibData object, so that the amount of requests is limited.

The kind of sensors created and their state is like before: one sensor is created for every line passing at a given stop, containing the times in minutes before the next two arrivals. I just could not obtain the line ‘mode’ with the API, which was maybe possible before.

But this means that when Home Assistant is started, a sensor will only be created for the lines for which there currently are upcoming arrivals, and thus if Home Assistant is started during the night the sensors could not be created. The other option is to create one sensor per stop to prevent this problem, but the entities would then not be as clear and easy to use in the user interface. For that a custom lovelace card could be created based on the custom cards for other public transport components such as the one for De Lijn. What do you think?

1 Like

That’s so cool. Thank you.
I was trying to get the pyODStibMivb async working, but I couldn’t find out how to make this work, so I stopped working on this.
For the sensors and stops and cards, yes, I’ve thought about this, it’s a headache. It would be nice to have a custom card by stop and display passing vehicles. But at the same time, if you want to use automation for an approaching vehicle, having a sensor for this is also useful.
Perhaps we can add a list of lines for each stop, so that when no data is available at any time, the sensor can be created in any case? And then try to extract the first passage from the time table? This would also help for some lines which only drive after a certain hour like the T32.

For the line “mode”, this is now in a static routes.txt (csv) file which is present in the gtfs package. We can add this file and extract the data from there (see how he did this for the pyODStibMivb package). Problem is that, this has to be updated each time there are new lines.

1 Like

Hi, I created the pyodstibmivb package with the intention of creating an official integration, but I never got to actually make the sensor in Home Assistant (and also didn’t see this one existed). What problems did you have with the async?

For creating the sensor I would say giving a stop and a list of lines makes the most sense.

The routes seems to change a lot more than I expected, so I will update pyodstibmivb so that it downloads the file and only use the static one as a backup.

I couldn’t figure out how to use async loops with HA. Did you create a custom component with pyODstibmivb and HA? Can you share it?


This is what I have now. Feel free to add or suggest any improvements

1 Like

Great job. Hope your PR gets quickly merged into production.
I tried to use the custom card with it, which is very nice, but it seems to block when there are no more vehicles passing at the stop (I had some errors in the js console, but it was late so I didn’t check this further).
Another thing, the sensor name is stop name + line ids. So if you take the same lines for both stops you get the same name + _2. Maybe you can add the suburb/city direction indication of the first line_id in the name (from get_stops_by_line()).
If I select multiple lines, it’s impossible to get a single sensor waiting_times for a particular line. I need to ad another stop_id with one single line. Maybe it’s worth to think about making two type of sensors, one for all lines at a stop and one for each single line with both waiting times in minutes.
You might also have a look at the nmbs sensor they use a HA time util so probably no need to import pytz).

What exactly is your problem when there are no more vehicles passing at the stop? I get the “EINDE-DIENST” message as expected. Are there stops that do return an empty list? I haven’t coded for that since the stops I checked always either returned a passing time or a message.

That is a good idea about the suburb/city direction, I hadn’t thought of that problem yet. I’ll look into the HA time util too.

I think the missing messages are a server error on their side. Some stops have them, and others I know for sure that did don’t anymore.

When I installed the the card.js with stop_id 5719 and lines 54 82 50 it was after 1:0 am so no buses were riding and the js on the page stopped working and there where some errors in the js console.
I’ll check with line 82 this night to see if I can reproduce this.
My setup:

entity: sensor.saint_denis_line_54_82_50
title: Saint Denis
type: 'custom:stib-mivb-card'


- platform: stib-mivb                                                                                                                                                                                                                                                           
  api_key: !secret stib_api                                                                                                                                                                                                                                                     
  lang: "fr"                                                                                                                                                                                                                                                                    
  message_lang: "fr"                                                                                                                                                                                                                                                            
      - stop_id: 5719                                                                                                                                                                                                                                                           
           - 54                                                                                                                                                                                                                                                                 
           - 82                                                                                                                                                                                                                                                                 
           - 50                                                                                                                                                                                                                                                                 
      - stop_id: 5152                                                                                                                                                                                                                                                           
           - 54                                                                                                                                                                                                                                                                 
           - 82                                                                                                                                                                                                                                                                 
           - 50                                                                                                                                                                                                                                                                 
      - stop_id: 5719                                                                                                                                                                                                                                                           
           - 54                                                                                                                                                                                                                                                                 
      - stop_id: 5152                                                                                                                                                                                                                                                           
           - 54                                                                                                                                                                                                                                                                 
- platform: template                                                                                                                                                                                                                                                            
        friendly_name: "B54 dir Trone"                                                                                                                                                                                                                                          
        unit_of_measurement: "min"                                                                                                                                                                                                                                              
        value_template: "{{ states.sensor.saint_denis_line_54.attributes.next_passages[0]['waiting_time'] }}"

I don’t think that is supposed to happen, but I’ll try to make it work even if that happens.

Now it’s back to normal and it shows the message “FIN DE SERVICE”. I updated the sensor and the card so that it won’t crash when this happens again.


I’m also working on a custom STIB integration.

So far i created a python lib:
And a custom sensor (which doesn’t work at the moment because it creates duplicate sensors…) /helldog136/stib-mvib-sensor

My idea was to be the more user-friendly i could be. I saw all these intgrations asking for a stop_id which is a number that doesn’t really make sense…
My solution was to parse the shapefiles given by the STIB in the python lib to translate “human-readable” stop names and destinations into tachnical IDs. This works like a charm. Maybe we could work together on making this work?

I created this branch:
I’m struggling with the new configuration flow of HA unfortunately…

I also created a custom card that reads info from the sensor: