Hey guys,
i tried my best, but unfortunateley i am unable to scrape a simple table on that website of my local transportation service.
sensor:
- platform: scrape
name: "Abfahrt Nußbaumerstraße Linie"
resource: "https://www.kvb.koeln/qr/246/"
select: "table#qr_ergebnis tbody tr td"
index: 0
headers:
User-Agent: Mozilla/5.0
My goal is to get the information on the next train departing from this station. After some research i think i am stuck because this is a dynamic webpage and the big table is loading afterwards. Is there any way to handle this kind of pages?
Hopefully someone can help. I tried it with https://try.jsoup.org/ and it seems to be right!?
Dunno whats wrong
1 Like
lolouk44
(lolouk44)
March 4, 2020, 9:50pm
3
Not sure what you mean by dynamic, but it’s definitely not a page that pulls the data via javascript: just display the page source and you’ll find the table there.
From what I guess you want to retrieve the line #. This can be achieved with this:
- platform: scrape
name: "Abfahrt Nußbaumerstraße Linie"
resource: "https://www.kvb.koeln/qr/246/"
select: "td"
index: 4
headers:
User-Agent: Mozilla/5.0
Wow, thank you!
My Error did come from that “tbody” element in the select-statement. That page does not have a named tbody-html-element. Now, this works like a charm:
sensor:
- platform: scrape
name: "Abfahrt Nußbaumerstraße Info"
resource: "https://www.kvb.koeln/qr/246/"
select: ".qr_td"
index: 0
headers:
User-Agent: Mozilla/5.0
- platform: scrape
name: "Abfahrt Nußbaumerstraße 1 Linie"
resource: "https://www.kvb.koeln/qr/246/"
select: "table#qr_ergebnis tr td"
index: 0
headers:
User-Agent: Mozilla/5.0
- platform: scrape
name: "Abfahrt Nußbaumerstraße 1 Ziel"
resource: "https://www.kvb.koeln/qr/246/"
select: "table#qr_ergebnis tr td"
index: 1
headers:
User-Agent: Mozilla/5.0
- platform: scrape
name: "Abfahrt Nußbaumerstraße 1 Abfahrt"
resource: "https://www.kvb.koeln/qr/246/"
select: "table#qr_ergebnis tr td"
index: 2
headers:
User-Agent: Mozilla/5.0
This is, what my lovelace-card looks like:
Here is the lovelace-code:
card:
entities:
- entity: sensor.abfahrt_nussbaumerstrasse_1_abfahrt
name: '${vars[0] + "\xa0".repeat(5) + vars[1]}'
type: 'custom:multiple-entity-row'
- entity: sensor.abfahrt_nussbaumerstrasse_2_abfahrt
name: '${vars[2] + "\xa0".repeat(5) + vars[3]}'
type: 'custom:multiple-entity-row'
- entity: sensor.abfahrt_nussbaumerstrasse_3_abfahrt
name: '${vars[4] + "\xa0".repeat(5) + vars[5]}'
type: 'custom:multiple-entity-row'
show_header_toggle: false
title: Abfahrt Nußbaumerstraße
type: entities
entities:
- sensor.abfahrt_nussbaumerstrasse_1_abfahrt
- sensor.abfahrt_nussbaumerstrasse_2_abfahrt
- sensor.abfahrt_nussbaumerstrasse_3_abfahrt
type: 'custom:config-template-card'
variables:
- 'states[''sensor.abfahrt_nussbaumerstrasse_1_linie''].state'
- 'states[''sensor.abfahrt_nussbaumerstrasse_1_ziel''].state'
- 'states[''sensor.abfahrt_nussbaumerstrasse_2_linie''].state'
- 'states[''sensor.abfahrt_nussbaumerstrasse_2_ziel''].state'
- 'states[''sensor.abfahrt_nussbaumerstrasse_3_linie''].state'
- 'states[''sensor.abfahrt_nussbaumerstrasse_3_ziel''].state'
Perhaps I should spend my time in developing a integration for the transportation service of cologne, the ‘KVB’ …
4 Likes
LagaV
(LagaV)
January 27, 2023, 3:59pm
5
Quick question: Is this solution still valid or has the underlying source system changed and this approach is no longer operational?
Hello LagaV,
This version is actually outdated, as the KVB website is now dynamic and very difficult to scrape, I have not been able to do it yet.
But: I got behind it in the last days and found out that the Verkehrsverbund Rhein-Sieg (VRS) provides the data via HTML
transport.yaml
rest:
- resource: https://www.vrs.de/index.php?eID=tx_vrsinfo_departuremonitor&i=ccf18ded5585169c2bc1ac8d07693055
scan_interval: 120
timeout: 20
headers:
User-Agent: Mozilla/5.0
sensor:
- name: "KVB Abfahrt 1 Line"
value_template: '{{ value_json.events[0].line.number }}'
json_attributes_path: $.events[0].line
json_attributes:
- direction
- product
- name: "KVB Abfahrt 1 Departure"
value_template: '{{ iif(value_json.events[0].departure.estimate is defined, value_json.events[0].departure.estimate, value_json.events[0].departure.timetable) }}'
json_attributes_path: $.events[0].departure
json_attributes:
- timetable
- timestamp
- estimate
- delayed
- day
- name: "KVB Abfahrt 2 Line"
value_template: '{{ value_json.events[1].line.number }}'
json_attributes_path: $.events[1].line
json_attributes:
- direction
- product
- name: "KVB Abfahrt 2 Departure"
value_template: '{{ iif(value_json.events[1].departure.estimate is defined, value_json.events[1].departure.estimate, value_json.events[1].departure.timetable) }}'
json_attributes_path: $.events[1].departure
json_attributes:
- timetable
- timestamp
- estimate
- delayed
- day
- name: "KVB Abfahrt 3 Line"
value_template: '{{ value_json.events[2].line.number }}'
json_attributes_path: $.events[2].line
json_attributes:
- direction
- product
- name: "KVB Abfahrt 3 Departure"
value_template: '{{ iif(value_json.events[2].departure.estimate is defined, value_json.events[2].departure.estimate, value_json.events[2].departure.timetable) }}'
json_attributes_path: $.events[2].departure
json_attributes:
- timetable
- timestamp
- estimate
- delayed
- day
homeassistant:
customize_glob:
"sensor.kvb_abfahrt_*_line":
icon: mdi:train
"sensor.kvb_abfahrt_*_departure":
icon: mdi:clock-outline
The first thing you need to do is to create a personal request here:
The generated ID (https://www.vrs.de/am/s/<ID>
) you put into the URL (https://www.vrs.de/index.php?eID=tx_vrsinfo_ass2_departuremonitor&i=<ID>
). In my example, the query is for the stop Chlodwigplatz in Südstadt.
Lovelace:
cards:
- type: custom:config-template-card
variables:
- states['sensor.kvb_abfahrt_1_line'].state
- states['sensor.kvb_abfahrt_1_line'].attributes.direction
- states['sensor.kvb_abfahrt_2_line'].state
- states['sensor.kvb_abfahrt_2_line'].attributes.direction
- states['sensor.kvb_abfahrt_3_line'].state
- states['sensor.kvb_abfahrt_3_line'].attributes.direction
entities:
- ${vars[0]}
- ${vars[2]}
- ${vars[4]}
card:
type: entities
entities:
- entity: sensor.kvb_abfahrt_1_departure
icon: mdi:train
name: ${vars[0] + "\xa0".repeat(5) + vars[1]}
type: custom:multiple-entity-row
- entity: sensor.kvb_abfahrt_2_departure
icon: mdi:train
name: ${vars[2] + "\xa0".repeat(5) + vars[3]}
type: custom:multiple-entity-row
- entity: sensor.kvb_abfahrt_3_departure
icon: mdi:train
name: ${vars[4] + "\xa0".repeat(5) + vars[5]}
type: custom:multiple-entity-row
gridcol: 1
gridrow: 1
type: vertical-stack
title: Abfahrt Chlodwigplatz
Please let me know if the instructions were comprehensible and work!
Many greetings from the Südstadt!
1 Like
LagaV
(LagaV)
January 30, 2023, 2:05pm
7
blackmesa:
transport.yaml
rest:
- resource: https://www.vrs.de/index.php?eID=tx_vrsinfo_ass2_departuremonitor&i=ccf18ded5585169c2bc1ac8d07693055
[...]
Lovelace:
cards:
- type: custom:config-template-card
[...]
entities:
- entity: sensor.kvb_abfahrt_1_departure
icon: mdi:train
name: ${vars[0] + "\xa0".repeat(5) + vars[1]}
type: custom:multiple-entity-row
[...]
Please let me know if the instructions were comprehensible and work!
Hi blackmesa,
thanks for providing this solution. Works as expected!
I struggled a little bit with transport.yaml and finally put all configuration stuff in configuration.yaml as my attempts to !include the additional yaml failed.
Additionally I got errors for missing cards, so in my case needed to add multiple-entity-row .
Greetings back to Südstadt from a borough nearby.
Thanks,
LagaV
LagaV
(LagaV)
February 7, 2023, 8:51pm
8
@blackmesa : Did the VRS site change some days back and the results are no longer available or is there a problem with my system?
Fugazzy
(Lutz Fricke)
February 9, 2023, 8:01am
9
It is also not working for me anymore . . .
LagaV
(LagaV)
February 9, 2023, 9:38am
10
Looks like the source system is broken:
When trying to generate a new ID I see, that plenty of stations (Cologne (KVB), but might be complete VRS) aren’t available to select / not offered to select.
The URL changed from
https://www.vrs.de/index.php?eID=tx_vrsinfo_ass2_departuremonitor&i=ccf18ded5585169c2bc1ac8d07693055
to
https://www.vrs.de/index.php?eID=tx_vrsinfo_departuremonitor&i=ccf18ded5585169c2bc1ac8d07693055
I edited the post above
1 Like
LagaV
(LagaV)
February 14, 2023, 9:20am
12
Thanks! Works as expected again.
klspn
March 4, 2023, 4:22pm
13
Hey
same here! Did you ever figure out how to !include the transport.yaml?
I got it working the way you did, but it is a bit too messy for my taste.
Greetings from Poll
It’s easy
I separated my yaml-config in shorter yaml-files in a “packages” folder in the config-folder. Then just add this to your configuration.yaml.
homeassistant:
packages: !include_dir_named packages
https://www.home-assistant.io/docs/configuration/packages/
Otherwise just include all the code from the transport.yaml to your configuration.yaml
1 Like
** EDIT: It’s working now! Somehow it didn’t work when using the transport.yaml, but with the code within configuration.yaml it’s all good.
Hey there,
I just found your Thread here
first of all thx for sharing the script.
I tried to implement it as you described…
So I installed the two front-end integrations (multiple-entity-row & config-template-card) and afterwards set the corresponding ressources.
Then I created the ‘packages’ folder and the ‘transport.yaml’ within. In the configuration.yaml I refered to the ‘packages’ folder.
Then I copied&pasted your transport.yaml code, but now when I create the a new lovelace-card with your code, the card is actually empty and I just can see the title of the card (see screenshot).
There are no errors, only the message that the keys ‘gridcol’ and ‘gridrow’ are not supported in the visual-editor, which shouldnt be unusual?
Most likely I’ve done something wrong or this approach is not working anymore?
Thanks in advance and greetings from Cologne Buchheim
hsch0
March 11, 2024, 10:18pm
17
@blackmesa many thanks for this, I actually tried it myself with the kvb website, but the VRS json data is much more convenient. I did a few “improvements” I would like to share:
Different icons for bus/train/tram
Depature time in minutes
Platform information
No need for custom components, as I use a markdown card
configuration.yaml:
rest:
- resource: https://www.vrs.de/index.php?eID=tx_vrsinfo_departuremonitor&i=75dd1734756e97c5a49516e8930d018a
scan_interval: 30
timeout: 20
headers:
User-Agent: Mozilla/5.0
sensor:
- name: "KVB Abfahrt 1 Line"
value_template: '{{ value_json.events[0].line.number }}'
- name: "KVB Abfahrt 1 Direction"
value_template: '{{ value_json.events[0].line.direction }}'
- name: "KVB Abfahrt 1 Departure time"
value_template: '{{ iif(value_json.events[0].departure.estimate is defined, value_json.events[0].departure.estimate, value_json.events[0].departure.timetable) }}'
- name: "KVB Abfahrt 1 Departure minutes"
value_template: '{{ ( (value_json.events[0].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 1 Platform"
value_template: '{{ value_json.events[0].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 1 Product"
value_template: '{% if value_json.events[0].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[0].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[0].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[0].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 2 Line"
value_template: '{{ value_json.events[1].line.number }}'
- name: "KVB Abfahrt 2 Direction"
value_template: '{{ value_json.events[1].line.direction }}'
- name: "KVB Abfahrt 2 Departure time"
value_template: '{{ iif(value_json.events[1].departure.estimate is defined, value_json.events[1].departure.estimate, value_json.events[1].departure.timetable) }}'
- name: "KVB Abfahrt 2 Departure minutes"
value_template: '{{ ( (value_json.events[1].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 2 Platform"
value_template: '{{ value_json.events[1].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 2 Product"
value_template: '{% if value_json.events[1].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[1].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[1].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[1].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 3 Line"
value_template: '{{ value_json.events[2].line.number }}'
- name: "KVB Abfahrt 3 Direction"
value_template: '{{ value_json.events[2].line.direction }}'
- name: "KVB Abfahrt 3 Departure time"
value_template: '{{ iif(value_json.events[2].departure.estimate is defined, value_json.events[2].departure.estimate, value_json.events[2].departure.timetable) }}'
- name: "KVB Abfahrt 3 Departure minutes"
value_template: '{{ ( (value_json.events[2].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 3 Platform"
value_template: '{{ value_json.events[2].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 3 Product"
value_template: '{% if value_json.events[2].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[2].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[2].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[2].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 4 Line"
value_template: '{{ value_json.events[3].line.number }}'
- name: "KVB Abfahrt 4 Direction"
value_template: '{{ value_json.events[3].line.direction }}'
- name: "KVB Abfahrt 4 Departure time"
value_template: '{{ iif(value_json.events[3].departure.estimate is defined, value_json.events[3].departure.estimate, value_json.events[3].departure.timetable) }}'
- name: "KVB Abfahrt 4 Departure minutes"
value_template: '{{ ( (value_json.events[3].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 4 Platform"
value_template: '{{ value_json.events[3].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 4 Product"
value_template: '{% if value_json.events[3].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[3].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[3].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[3].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 5 Line"
value_template: '{{ value_json.events[4].line.number }}'
- name: "KVB Abfahrt 5 Direction"
value_template: '{{ value_json.events[4].line.direction }}'
- name: "KVB Abfahrt 5 Departure time"
value_template: '{{ iif(value_json.events[4].departure.estimate is defined, value_json.events[4].departure.estimate, value_json.events[4].departure.timetable) }}'
- name: "KVB Abfahrt 5 Departure minutes"
value_template: '{{ ( (value_json.events[4].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 5 Platform"
value_template: '{{ value_json.events[4].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 5 Product"
value_template: '{% if value_json.events[4].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[4].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[4].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[4].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 6 Line"
value_template: '{{ value_json.events[5].line.number }}'
- name: "KVB Abfahrt 6 Direction"
value_template: '{{ value_json.events[5].line.direction }}'
- name: "KVB Abfahrt 6 Departure time"
value_template: '{{ iif(value_json.events[5].departure.estimate is defined, value_json.events[5].departure.estimate, value_json.events[5].departure.timetable) }}'
- name: "KVB Abfahrt 6 Departure minutes"
value_template: '{{ ( (value_json.events[5].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 6 Platform"
value_template: '{{ value_json.events[5].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 6 Product"
value_template: '{% if value_json.events[5].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[5].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[5].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[5].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 7 Line"
value_template: '{{ value_json.events[6].line.number }}'
- name: "KVB Abfahrt 7 Direction"
value_template: '{{ value_json.events[6].line.direction }}'
- name: "KVB Abfahrt 7 Departure time"
value_template: '{{ iif(value_json.events[6].departure.estimate is defined, value_json.events[6].departure.estimate, value_json.events[6].departure.timetable) }}'
- name: "KVB Abfahrt 7 Departure minutes"
value_template: '{{ ( (value_json.events[6].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 7 Platform"
value_template: '{{ value_json.events[6].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 7 Product"
value_template: '{% if value_json.events[6].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[6].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[6].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[6].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 8 Line"
value_template: '{{ value_json.events[7].line.number }}'
- name: "KVB Abfahrt 8 Direction"
value_template: '{{ value_json.events[7].line.direction }}'
- name: "KVB Abfahrt 8 Departure time"
value_template: '{{ iif(value_json.events[7].departure.estimate is defined, value_json.events[7].departure.estimate, value_json.events[7].departure.timetable) }}'
- name: "KVB Abfahrt 8 Departure minutes"
value_template: '{{ ( (value_json.events[7].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 8 Platform"
value_template: '{{ value_json.events[7].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 8 Product"
value_template: '{% if value_json.events[7].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[7].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[7].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[7].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 9 Line"
value_template: '{{ value_json.events[8].line.number }}'
- name: "KVB Abfahrt 9 Direction"
value_template: '{{ value_json.events[8].line.direction }}'
- name: "KVB Abfahrt 9 Departure time"
value_template: '{{ iif(value_json.events[8].departure.estimate is defined, value_json.events[8].departure.estimate, value_json.events[8].departure.timetable) }}'
- name: "KVB Abfahrt 9 Departure minutes"
value_template: '{{ ( (value_json.events[8].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 9 Platform"
value_template: '{{ value_json.events[8].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 9 Product"
value_template: '{% if value_json.events[8].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[8].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[8].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[8].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
- name: "KVB Abfahrt 10 Line"
value_template: '{{ value_json.events[9].line.number }}'
- name: "KVB Abfahrt 10 Direction"
value_template: '{{ value_json.events[9].line.direction }}'
- name: "KVB Abfahrt 10 Departure time"
value_template: '{{ iif(value_json.events[9].departure.estimate is defined, value_json.events[9].departure.estimate, value_json.events[9].departure.timetable) }}'
- name: "KVB Abfahrt 10 Departure minutes"
value_template: '{{ ( (value_json.events[9].departure.timestamp - as_timestamp(utcnow()) ) / 60 ) | round(0) }}'
- name: "KVB Abfahrt 10 Platform"
value_template: '{{ value_json.events[9].stopPoint.name | regex_findall_index("(?:^|[^A-Za-z0-9])([A-TV-Z0-9])(?![A-Za-z0-9])") }}'
- name: "KVB Abfahrt 10 Product"
value_template: '{% if value_json.events[9].line.product == "LightRail" %} {{"tram"}} {% elif value_json.events[9].line.product == "RegionalTrains" %} {{"train"}} {% elif value_json.events[9].line.product == "SuburbanTrains" %} {{"train"}} {% elif value_json.events[9].line.product == "Bus" %} {{"bus"}} {% else %} {{"help-box-outline"}} {% endif %}'
Markdown card:
| | Linie| Richtung| Gleis| Abfahrt|
|:----:|:----:|:----|:----:|:----:|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_1_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_1_line') }}| {{ states('sensor.kvb_abfahrt_1_direction') }}| {{ states('sensor.kvb_abfahrt_1_platform') }}| {{ states('sensor.kvb_abfahrt_1_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_2_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_2_line') }}| {{ states('sensor.kvb_abfahrt_2_direction') }}| {{ states('sensor.kvb_abfahrt_2_platform') }}| {{ states('sensor.kvb_abfahrt_2_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_3_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_3_line') }}| {{ states('sensor.kvb_abfahrt_3_direction') }}| {{ states('sensor.kvb_abfahrt_3_platform') }}| {{ states('sensor.kvb_abfahrt_3_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_4_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_4_line') }}| {{ states('sensor.kvb_abfahrt_4_direction') }}| {{ states('sensor.kvb_abfahrt_4_platform') }}| {{ states('sensor.kvb_abfahrt_4_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_5_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_5_line') }}| {{ states('sensor.kvb_abfahrt_5_direction') }}| {{ states('sensor.kvb_abfahrt_5_platform') }}| {{ states('sensor.kvb_abfahrt_5_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_6_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_6_line') }}| {{ states('sensor.kvb_abfahrt_6_direction') }}| {{ states('sensor.kvb_abfahrt_6_platform') }}| {{ states('sensor.kvb_abfahrt_6_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_7_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_7_line') }}| {{ states('sensor.kvb_abfahrt_7_direction') }}| {{ states('sensor.kvb_abfahrt_7_platform') }}| {{ states('sensor.kvb_abfahrt_7_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_8_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_8_line') }}| {{ states('sensor.kvb_abfahrt_8_direction') }}| {{ states('sensor.kvb_abfahrt_8_platform') }}| {{ states('sensor.kvb_abfahrt_8_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_8_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_8_line') }}| {{ states('sensor.kvb_abfahrt_8_direction') }}| {{ states('sensor.kvb_abfahrt_8_platform') }}| {{ states('sensor.kvb_abfahrt_8_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_9_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_9_line') }}| {{ states('sensor.kvb_abfahrt_9_direction') }}| {{ states('sensor.kvb_abfahrt_9_platform') }}| {{ states('sensor.kvb_abfahrt_9_departure_minutes') }} min|
|<ha-icon icon="mdi:{{ states('sensor.kvb_abfahrt_10_product') }}"></ha-icon>| {{ states('sensor.kvb_abfahrt_10_line') }}| {{ states('sensor.kvb_abfahrt_10_direction') }}| {{ states('sensor.kvb_abfahrt_10_platform') }}| {{ states('sensor.kvb_abfahrt_10_departure_minutes') }} min|
1 Like