Custom component Stib - Brussels public transportation

I like the idea that you don’t need to look up the stop_ids any more and you’re looking it up by stop name, better not have a typo or put accents in the name then, I guess.
What about user errors, for example stop_name : “De Brouckere” with line_id : 18, just log an error or return a warning in the sensor that this line isn’t passing at this stop?

With config flow I think we can check this during setup, maybe even show a list of all the possible lines per stop. Once I figure out how to get config flow working that is.

While having a card with all details of the stop (like the display at the stop) is very nice, it’s also very useful to have the waiting times for a particular line, as I trigger some automations when it’s time to leave the house to catch the next bus. I’m using for now a quick and dirty script that takes the passing times and pushes the remaining minutes with mqtt as@Emilv2 's sensor is returning this info only in an attribute. Maybe a sensor for the the stop and a sensor for every single line passing would be more useful, but in this case I thing you need to parse stops.txt to fin out what line passes at which stop…

You can use attributes in automations or make template sensors, wouldn’t that solve your problem? There are arguments for and against putting things in attributes or in separate sensors, I think keeping it the same as most other transport sensors, one sensor per stop, is the way to go.

Fin de service: would there be a way to check the timetable to have the first foreseen passing time in the next morning, that would avoid an empty state?

I think that should be possible, but the information seems to be quite scattered around in the gtfs file.

May I suggest to prefix the sensor name for easier filtering in the developer tools?

Sounds good to me, I’ll see if they accept it. Most components don’t do that but I don’t know if that is a requirement or just up to the developer.

BTW, pyStibMivb should be available on pypi, if no one else grabbed it after I deleted my project.

For the moment, my lib is called pystibmVIb thus it is already available on pypi. Tell me when you delete yours so i can prepare to post it with the right name just after that (and let’s hope that no one is using your lib :D)

better not have a typo or put accents in the name then,

Yeah that’s the drawback but i think that’s the user that must check his input. Wrong input means wrong answers from service.

I guess.What about user errors, for example stop_name : “De Brouckere” with line_id : 18, just log an error or return a warning in the sensor that this line isn’t passing at this stop?

I could detect this type of wrong configuration and throw an error like “InvalidLines” for example but only if no line matches. (a more advanced check isn’t relevant for me there… i could do it if you really want but i would consider this a bonus feature)

While having a card with all details of the stop (like the display at the stop) is very nice, it’s also very useful to have the waiting times for a particular line, as I trigger some automations when it’s time to leave the house to catch the next bus.

For this you could just define another stop entry with only one line and direction. the associated sensor would only have waiting time for the line you’re interested in.

Fin de service: would there be a way to check the timetable to have the first foreseen passing time in the next morning, that would avoid an empty state?

This can be done if we decide that the user never wants to know if it’s the end of the service.
I can replace the “end of service” by a fake waiting time based on the timetables.
I think it’s better to let “end of service” for now and in a v2.0 add that crawling of GTFS to add this info.

Guys, I found a solution for our text-color problem without looking at STIB files:

A simple calculation can determine if it’s better to have a white text or a black text :smiley:

pystibmvib released in v1.1.5 (we’ll sort out the name issue later… It’s not really important after all…)

I’ve added the text_color, the direction accepted in place of the terminus and an exception that raises if the specified lines creates a stop without monitored lines (eg: de brouckere with only line 18) BUT won’t raise if the specified lines contains at least one true line (e.g. de brouckere with lines 5 and 18 won’t raise error because metro 5 passes by at de brouckere)

1 Like

For the moment, my lib is called pystibmVIb thus it is already available on pypi. Tell me when you delete yours so i can prepare to post it with the right name just after that (and let’s hope that no one is using your lib :D)

The lib has been long deleted and should still be available

1 Like

I would rather use the official colors, even if this method would technically be better

1 Like

Hi,

I deleted pyStibMivb from pypi a couple of month ago, so if you like, go and reserve the name already, even if you don’t switch yet.
I’m totally fine with attributes, and looking again at it, I did configure several sensors with a single line for a stop so that I can use the attribute next_passages[0][‘waiting_time’] for this. Only thing by now is when configuring a line that is not in service at the time, the sensor is not showing up and you wonder why. Line 32 for stop “Saint Denis” for example, or when you do a reconfiguration of your ha installation at 2 in the morning. :wink:
Other idea for a v.2.x configuration: take the home zone’s localisation and add automatically all nearby stops and lines (and add them to the map).

I think that should not happen, there should be a message saying"einde dienst" or something similar but it does indeed frequently happen. We probably best get the lines per stop from the gtfs file. That’s a lot more complicated though.

I would rather use the official colors, even if this method would technically be better

I tested it and it gives the right colors for the STIB lines.

I don’t think it does for line 5. The color is #E6B012 (230,176,18) but (0.299*230+0.587*176+ 0.114*18)/255 = 0.68288 which should give a black text color but the official color is white. Or am I missing something?

At any rate I don’t see why we should try to reverse engineer the algorithm they use to determine the colors when the data is readily available.

I’m kind of sad because this is way less efficient but hey… dark STIB logic applies here

Renamed repo and pypi lib:

Can you open issues on the new repo if you need some additional functionalities.
I like the idea of maybe adding the gps coordinates of the stop you’re monitoring to add on a map. might be quite easy to do… We could consider this in a future version of the sensor

1 Like

Hi,
I’ve checked again, for lines that are not in service, there’s no message.
Thats what I get for pointDetail 5719:

[{'points': [{'gpsCoordinates': {'latitude': 50.809901, 'longitude': 4.317548}, 'id': '5719', 'name': {'fr': 'SAINT-DENIS', 'nl': 'SINT-DENIJS'}}]}]
[{'points': [{'passingTimes': [{'destination': {'fr': 'SPORTCENTRUM R.',
                                                'nl': 'SPORTCENTRUM R.'},
                                'expectedArrivalTime': '2020-05-29T17:36:00+02:00',
                                'lineId': '50'},
                               {'destination': {'fr': 'TRONE', 'nl': 'TROON'},
                                'expectedArrivalTime': '2020-05-29T17:28:00+02:00',
                                'lineId': '54'},
                               {'destination': {'fr': 'DROGENBOS CHATEAU',
                                                'nl': 'DROGENBOS KASTEEL'},
                                'expectedArrivalTime': '2020-05-29T17:30:00+02:00',
                                'lineId': '82'},
                               {'destination': {'fr': 'DIEWEG', 'nl': 'DIEWEG'},
                                'expectedArrivalTime': '2020-05-29T17:28:00+02:00',
                                'lineId': '97'},
                               {'destination': {'fr': 'SPORTCENTRUM R.',
                                                'nl': 'SPORTCENTRUM R.'},
                                'expectedArrivalTime': '2020-05-29T17:45:00+02:00',
                                'lineId': '50'},
                               {'destination': {'fr': 'TRONE', 'nl': 'TROON'},
                                'expectedArrivalTime': '2020-05-29T17:39:00+02:00',
                                'lineId': '54'},
                               {'destination': {'fr': 'DROGENBOS CHATEAU',
                                                'nl': 'DROGENBOS KASTEEL'},
                                'expectedArrivalTime': '2020-05-29T17:33:00+02:00',
                                'lineId': '82'},
                               {'destination': {'fr': 'DIEWEG', 'nl': 'DIEWEG'},
                                'expectedArrivalTime': '2020-05-29T17:47:00+02:00',
                                'lineId': '97'}],
              'pointId': '5719'}]}]

T32 and N12 are missing from this list and the sensor returns an error.

So one cannot know all lines that are passing by a certain stop. I’m afraid one must cycle through all PointByLine and check if the line does pass at the given stop.

Then that either has changed or they have a lot of problems with their api at the moment. See the last card example on my github, that’s how it used/is supposed to be when a line temporarely does not serve a stop. I’ve asked on the forum but haven’t got a reply yet.

Hi, at the moment i don’t know how my lib will react to the end of service. I’ll try it ASAP and i think that the best solution is to raise an exception “end of service” that will contain information about the next passage in the next morning. I’ll try to implement that ASAP. ( https://github.com/helldog136/pystibmivb/issues/2 )

Added methods to get GPS location of Stops
Improved stop_name matching
Added crawling of schedule in GTFS files
When API returns no waiting times or is End_of_service, an Exception is now raised containing information about the next scheduled passage (from GTFS)

Hello Emil, are you ok with the config-flow? Can I help? Where is your latest work so I can look at it and help you a little when I have time.

Kind Regards,

EDIT: 17/06 No news, i guess Emil doesn’t have time at the moment to develop.
I plan on making my own PR with my library then.

See https://github.com/helldog136/ha-stib-mivb

(Still a WIP)

1 Like

@Helldog136 @Emilv2 has any one already looked into API v2?
Seems that we don’t need an api-key anymore and can directly get json from an url like
https://data.stib-mivb.be/api/records/1.0/search/?dataset=waiting-time-rt-production&q=5152&timezone=Europe%2Fbrussels
Time to rewrite pyStibMivb :wink:

Hi, I have seen the mail about API V2, Once I get a bit of time I will rethink pystibmivb… I’m not satified with the current version anyway…

1 Like

I have now played with it a bit. You still need an API key (bot no token anymore).

I created a quick & dirty python script that gets json date from the API and sends it to mqtt

def getJson(q, ds, api):
    #print("getJson")
    url = "https://data.stib-mivb.be/api/records/1.0/search/"
    params = dict(
    dataset= ds,
    q=q,
    start=0,
    rows=99,
    apikey = api
    )

    resp = requests.get(url=url, params=params)
    data = resp.json()
    records = data['records']
    return records

...
    {
    "LT8257191": {
        "arrival": -1,
        "destination": "DROGENBOS",
        "gpscoordinates": "50.809901; 4.317548",
        "message": "Ligne déviée",
        "status": "not available",
        "stopName": "SAINT-DENIS",
        "timestamp": "2022-10-28T18:11:00+02:00"
    },
    "LT8257192": {
        "arrival": -1,
        "destination": "DROGENBOS",
        "gpscoordinates": "50.809901; 4.317548",
        "message": "Ligne déviée",
        "status": "not available",
        "stopName": "SAINT-DENIS",
        "timestamp": "2022-10-28T18:11:00+02:00"
    }
}

In HA I have some mqtt sensors (one for each estimated arrival time):

sensors:
 - platform: mqtt
   name: "50 dir Gare du Midi 1er passage Bervoets"
   state_topic: stib
   value_template: "{{ value_json.L5010851.arrival }}"
   unit_of_measurement: "min"
   state_class: "measurement"
   json_attributes_topic: "stib"
   json_attributes_template: "{{ value_json.L5010851 | default('') | tojson}}"    
 - platform: mqtt
   name: "50 dir Gare du Midi 2e passage Bervoets"
   state_topic: stib
   value_template: "{{ value_json.L5010852.arrival }}"
   unit_of_measurement: "min"
   state_class: "measurement"
   json_attributes_topic: "stib"
   json_attributes_template: "{{ value_json.L5010852 | default('') | tojson}}" 

You can even get the GTFS files via a json request.
But still some data are hard to get (like if a bus is at a certain stop).