Hello,
I have written a small python script, which publishes the departure times of stops in the area of the Munich public transportation system via MQTT. The script runs via cronjob on the OpenHab server every minute and updates the corresponding widget in OpenHab.
You can find the script here:
The widget looks like this:
and here is the widget code:
uid: OEPNV_Widget
tags: []
props:
parameters:
- context: item
description: Abfahrt 1
label: Abfahrt 1
name: abfahrt1
required: false
type: TEXT
- context: item
description: Abfahrt 2
label: Abfahrt 2
name: abfahrt2
required: false
type: TEXT
- context: item
description: Abfahrt 3
label: Abfahrt 3
name: abfahrt3
required: false
type: TEXT
- context: item
description: Abfahrt 4
label: Abfahrt 4
name: abfahrt4
required: false
type: TEXT
- context: item
description: Abfahrt 5
label: Abfahrt 5
name: abfahrt5
required: false
type: TEXT
- context: item
description: Abfahrt 6
label: Abfahrt 6
name: abfahrt6
required: false
type: TEXT
parameterGroups: []
timestamp: Oct 19, 2023, 1:10:11 PM
component: f7-card
config:
key: =Math.random() + items[props.abfahrt1].state.lenght
slots:
default:
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: oh-icon
config:
color: "=items[props.abfahrt1].state.split(' ')[6] === 'U4' ? 'green' : items[props.abfahrt1].state.split(' ')[6] === 'U5' ? 'orange' : items[props.abfahrt1].state.split(' ')[5] === 'Bus' ? 'blue' : items[props.abfahrt1].state.split(' ')[5] === 'Tram' ? 'red' : 'white'"
height: 20
icon: "=items[props.abfahrt1].state.split(' ')[5] === 'U-Bahn' ? 'material:subway' : items[props.abfahrt1].state.split(' ')[5] === 'Tram' ? 'material:tram' : items[props.abfahrt1].state.split(' ')[5] === 'Bus' ? 'material:directions_bus' : 'material:train'"
style:
margin: 3px
visible: "=props.abfahrt1 ? true : false"
- component: Label
config:
style:
margin: 3px
text: =items[props.abfahrt1].state
visible: "=props.abfahrt1 ? true : false"
- component: oh-icon
config:
color: red
height: 20
icon: "=items[props.abfahrt1].state.split(' ')[items[props.abfahrt1].state.split(' ').length -1] === 'CANCELLED' ? 'material:warning' : ''"
style:
margin: 3px
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: oh-icon
config:
color: "=items[props.abfahrt2].state.split(' ')[6] === 'U4' ? 'green' : items[props.abfahrt2].state.split(' ')[6] === 'U5' ? 'orange' : items[props.abfahrt2].state.split(' ')[5] === 'Bus' ? 'blue' : items[props.abfahrt2].state.split(' ')[5] === 'Tram' ? 'red' : 'white'"
height: 20
icon: "=items[props.abfahrt2].state.split(' ')[5] === 'U-Bahn' ? 'material:subway' : items[props.abfahrt2].state.split(' ')[5] === 'Tram' ? 'material:tram' : items[props.abfahrt2].state.split(' ')[5] === 'Bus' ? 'material:directions_bus' : 'material:train'"
style:
margin: 3px
visible: "=props.abfahrt2 ? true : false"
- component: Label
config:
style:
margin: 3px
text: =items[props.abfahrt2].state
visible: "=props.abfahrt2 ? true : false"
- component: oh-icon
config:
color: red
height: 20
icon: "=items[props.abfahrt2].state.split(' ')[items[props.abfahrt2].state.split(' ').length -1] === 'CANCELLED' ? 'material:warning' : ''"
style:
margin: 3px
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: oh-icon
config:
color: "=items[props.abfahrt3].state.split(' ')[6] === 'U4' ? 'green' : items[props.abfahrt3].state.split(' ')[6] === 'U5' ? 'orange' : items[props.abfahrt3].state.split(' ')[5] === 'Bus' ? 'blue' : items[props.abfahrt3].state.split(' ')[5] === 'Tram' ? 'red' : 'white'"
height: 20
icon: "=items[props.abfahrt3].state.split(' ')[5] === 'U-Bahn' ? 'material:subway' : items[props.abfahrt3].state.split(' ')[5] === 'Tram' ? 'material:tram' : items[props.abfahrt3].state.split(' ')[5] === 'Bus' ? 'material:directions_bus' : 'material:train'"
style:
margin: 3px
visible: "=props.abfahrt3 ? true : false"
- component: Label
config:
style:
margin: 3px
text: =items[props.abfahrt3].state
visible: "=props.abfahrt3 ? true : false"
- component: oh-icon
config:
color: red
icon: "=items[props.abfahrt3].state.split(' ')[items[props.abfahrt3].state.split(' ').length -1] === 'CANCELLED' ? 'material:warning' : ''"
style:
margin: 3px
width: 20
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: oh-icon
config:
color: "=items[props.abfahrt4].state.split(' ')[6] === 'U4' ? 'green' : items[props.abfahrt4].state.split(' ')[6] === 'U5' ? 'orange' : items[props.abfahrt4].state.split(' ')[5] === 'Bus' ? 'blue' : items[props.abfahrt4].state.split(' ')[5] === 'Tram' ? 'red' : 'white'"
height: 20
icon: "=items[props.abfahrt4].state.split(' ')[5] === 'U-Bahn' ? 'material:subway' : items[props.abfahrt4].state.split(' ')[5] === 'Tram' ? 'material:tram' : items[props.abfahrt4].state.split(' ')[5] === 'Bus' ? 'material:directions_bus' : 'material:train'"
style:
margin: 3px
visible: "=props.abfahrt4 ? true : false"
- component: Label
config:
style:
margin: 3px
text: =items[props.abfahrt4].state
visible: "=props.abfahrt4 ? true : false"
- component: oh-icon
config:
color: red
height: 20
icon: "=items[props.abfahrt4].state.split(' ')[items[props.abfahrt4].state.split(' ').length -1] === 'CANCELLED' ? 'material:warning' : ''"
style:
margin: 3px
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: oh-icon
config:
color: "=items[props.abfahrt5].state.split(' ')[6] === 'U4' ? 'green' : items[props.abfahrt5].state.split(' ')[6] === 'U5' ? 'orange' : items[props.abfahrt5].state.split(' ')[5] === 'Bus' ? 'blue' : items[props.abfahrt5].state.split(' ')[5] === 'Tram' ? 'red' : 'white'"
height: 20
icon: "=items[props.abfahrt5].state.split(' ')[5] === 'U-Bahn' ? 'material:subway' : items[props.abfahrt5].state.split(' ')[5] === 'Tram' ? 'material:tram' : items[props.abfahrt5].state.split(' ')[5] === 'Bus' ? 'material:directions_bus' : 'material:train'"
style:
margin: 3px
visible: "=props.abfahrt5 ? true : false"
- component: Label
config:
style:
margin: 3px
text: =items[props.abfahrt5].state
visible: "=props.abfahrt5 ? true : false"
- component: oh-icon
config:
color: red
height: 20
icon: "=items[props.abfahrt5].state.split(' ')[items[props.abfahrt5].state.split(' ').length -1] === 'CANCELLED' ? 'material:warning' : ''"
style:
margin: 3px
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: oh-icon
config:
color: "=items[props.abfahrt6].state.split(' ')[6] === 'U4' ? 'green' : items[props.abfahrt6].state.split(' ')[6] === 'U5' ? 'orange' : items[props.abfahrt6].state.split(' ')[5] === 'Bus' ? 'blue' : items[props.abfahrt6].state.split(' ')[5] === 'Tram' ? 'red' : 'white'"
height: 20
icon: "=items[props.abfahrt6].state.split(' ')[5] === 'U-Bahn' ? 'material:subway' : items[props.abfahrt6].state.split(' ')[5] === 'Tram' ? 'material:tram' : items[props.abfahrt6].state.split(' ')[5] === 'Bus' ? 'material:directions_bus' : 'material:train'"
style:
margin: 3px
visible: "=props.abfahrt6 ? true : false"
- component: Label
config:
style:
margin: 3px
text: =items[props.abfahrt6].state
visible: "=props.abfahrt6 ? true : false"
- component: oh-icon
config:
color: red
height: 20
icon: "=items[props.abfahrt6].state.split(' ')[items[props.abfahrt6].state.split(' ').length -1] === 'CANCELLED' ? 'material:warning' : ''"
style:
margin: 3px
Maybe someone else besides me can use this