Public Transport MVG (Munich/Germany)

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:
Screenshot 2023-12-03 114906

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 :wink:

2 Likes