
Mit diesem Projekt habe ich mein erstes größeres Experiment gestartet, bei dem Docker-Deployment, API-Datenverarbeitung und KI-gestützte Entwicklung in Visual Studio Code und openai/codex zusammengekommen sind. Ziel war ein universell einsetzbares Abfahrts-Widget für Bus- und Bahnverbindungen, das sich in beliebige Dashboards und Smart-Home-Oberflächen integrieren lässt.
Die Anwendung läuft vollständig containerisiert und stellt sowohl eine HTML-Darstellung als Widget als auch einen JSON-Endpoint bereit. Dadurch kann sie gleichzeitig direkt im Browser angezeigt oder von anderen Systemen weiterverarbeitet werden.
Vorab: Der komplette Quellcode für den Docker-Container ist hier veröffentlicht: https://github.com/ifs-net/timetable-widget/tree/main
Was das Widget kann
Das Timetable-Widget ist ein konfigurierbarer Micro-Service zur Anzeige von ÖPNV-Abfahrten. Die Daten werden live aus offiziellen Quellen geladen und aufbereitet.
- Anzeige von Bus- und Bahnabfahrten in Echtzeit
- Unterstützung mehrerer Haltestellen gleichzeitig
- Filter nach Richtung oder Linien
- Anzeige von Verspätungen
- Feed-Alter / Aktualität der Daten sichtbar
- JSON-API zur Weiterverarbeitung
- Mehrere Widgets parallel konfigurierbar
Technisch werden dabei zwei Datenquellen unterstützt:
- GTFS-Realtime (typisch Verkehrsverbünde)
- Deutsche Bahn Timetables / IRIS API
Die Anwendung normalisiert beide Formate und stellt sie einheitlich dar. Das Widget selbst ist somit unabhängig vom Verkehrsverbund verwendbar.
Technische Umsetzung
Die Logik in eine openHAB-Rule direkt zu implementieren wäre sehr aufwändig gewesen und kaum wartbar. Daher fiel die Entscheidung, einen containerisierten Service zu entwickeln und die Logik darin zu kapseln. Die komplette Anwendung ist als Docker-Container aufgebaut. Nach dem Start stellt sie eine kleine Web-API bereit:
- /widget → Übersicht aller konfigurierten Widgets
- /widget/<id> → HTML-Widget
- /json/<id> → strukturierte Daten
- /health → Statuscheck
Intern passiert dabei mehr, als man auf den ersten Blick sieht:
- Abruf von Protobuf- und XML-Feeds
- Parsing und Normalisierung der Daten
- Zwischencaching
- Mapping von Linien- und Richtungsinformationen
- Berechnung der nächsten Abfahrten
- HTML-Rendering für Dashboards
Mögliche Einsatzszenarien
- Smart-Home-Dashboards
- Wall-Displays (Tablet / E-Ink)
- Infodisplays im Büro
- Home-Assistant / openHAB
- eigene Web-Frontends
Durch die JSON-Schnittstelle lässt sich das Widget auch komplett ohne HTML-Darstellung verwenden. Damit wird es praktisch zu einem kleinen Verkehrs-Backend-Service.
Einbindung in openHAB
Einerseits könnte man nun einfach die Webansicht in openHAB integrieren – oder eben die JSON-Daten in ein Widget packen. Das war mir lieber, das Widget übernimmt dann auch die optische Darstellung in openHAB.
Hierzu wurde eine Rule erstellt, die generisch zu allen Widgets alle Daten abholt:
Inhalt der Rule-Datei
var boolean timetableGenericLog = false
val String timetableGenericBaseUrl = "http://localhost:8000/json/"
val String timetableGenericWidgetIndexUrl = "http://localhost:8000/widget"
var java.util.Set<String> timetableKnownIds = newHashSet
rule "Timetable Generic JSON Refresh"
when
System started
or Time cron "20 * * * * ?"
then
val java.util.Set<String> idsToFetch = newHashSet
try {
val String widgetIndexResponse = sendHttpGetRequest(timetableGenericWidgetIndexUrl, 15000)
if (widgetIndexResponse !== null && widgetIndexResponse != "") {
val matcher = java.util.regex.Pattern::compile("/widget/([A-Za-z0-9_-]+)").matcher(widgetIndexResponse)
while (matcher.find) {
idsToFetch.add(matcher.group(1))
}
if (idsToFetch.size > 0) {
timetableKnownIds.clear
timetableKnownIds.addAll(idsToFetch)
}
} else {
logWarn("timetableGeneric", "Leere oder ungueltige Antwort von " + timetableGenericWidgetIndexUrl)
}
} catch (Throwable t) {
logWarn("timetableGeneric", "Widget-Index-Refresh fehlgeschlagen: " + t.getMessage)
}
if (idsToFetch.size == 0 && timetableKnownIds.size > 0) {
idsToFetch.addAll(timetableKnownIds)
}
if (idsToFetch.size == 0) {
logWarn("timetableGeneric", "Keine Widget-IDs verfuegbar fuer Refresh")
return
}
var String mergedEntries = ""
var boolean first = true
var int okCount = 0
idsToFetch.forEach([id |
try {
val String response = sendHttpGetRequest(timetableGenericBaseUrl + id, 15000)
if (response !== null && response != "" && response.startsWith("{")) {
if (first) {
mergedEntries = "\"" + id + "\":" + response
first = false
} else {
mergedEntries = mergedEntries + ",\"" + id + "\":" + response
}
okCount = okCount + 1
} else {
logWarn("timetableGeneric", "Leere oder ungueltige Antwort von " + timetableGenericBaseUrl + id)
}
} catch (Throwable t) {
logWarn("timetableGeneric", "JSON refresh fehlgeschlagen fuer ID " + id + ": " + t.getMessage)
}
])
if (okCount > 0) {
TIMETABLE_JSON_ALL.postUpdate("{" + mergedEntries + "}")
if (timetableGenericLog) {
logInfo("timetableGeneric", "Refresh abgeschlossen. ids=" + idsToFetch.size.toString + ", ok=" + okCount.toString)
}
} else {
logWarn("timetableGeneric", "Keine gueltigen JSON-Antworten erhalten")
}
end
Für die generische Fahrplan-Anzeige werden folgende Bausteine benötigt:
- openHAB 5.x (getestet mit 5.1.2), MainUI und Rules DSL aktiv.
- Ein laufender Timetable-Dienst, aus Sicht von openHAB erreichbar unter:
http://localhost:8000/widget(liefert verfügbare IDs)http://localhost:8000/json/<id>(liefert Daten je Widget-ID)
- Ein String-Item
TIMETABLE_JSON_ALLals zentrale Datenablage. - Die Rule
conf/rules/Timetable_Generic.rules, die alle 60 Sekunden:- IDs dynamisch ermittelt,
- JSON-Daten je ID lädt,
- alles als Sammel-JSON in
TIMETABLE_JSON_ALLspeichert.
- Das MainUI-Widget
widget_timetable_genericmit den Parametern:propTitle(optional),jsonId(Pflicht für die konkrete Datenquelle),maxRows(optional).
Hinweis: Das Widget kann beliebig oft auf einer Seite eingebunden werden. Pro Instanz wird nur jsonId unterschiedlich gesetzt (z. B. 1, 2, 3).
Dann werden die Timetables auch in der UI passend angezeigt. Und damit wissen wir künftig am zentralen Smarthome-Display wann die Busse und Züge vor unserer Haustüre starten 😉

Hier noch der Widget-Code:
uid: widget_timetable_generic
tags:
- card
- cell
props:
parameters:
- label: Titel
name: propTitle
required: false
type: TEXT
- label: JSON ID
name: jsonId
required: false
type: TEXT
- label: Zeilen
name: maxRows
required: false
type: INTEGER
parameterGroups: []
timestamp: Feb 21, 2026, 10:38:47 AM
component: f7-card
config:
style:
color: var(--f7-text-color)
border-radius: 18px
background: var(--f7-card-bg-color)
box-shadow: 0 12px 30px rgba(0,0,0,0.25)
title: "=props.propTitle ? props.propTitle : (items.TIMETABLE_JSON_ALL &&
items.TIMETABLE_JSON_ALL.state && items.TIMETABLE_JSON_ALL.state != 'NULL'
&& items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].widget_title ?
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].widget_title : ('Timetable ID ' + (props.jsonId ?
props.jsonId : '1'))) : ('Timetable ID ' + (props.jsonId ? props.jsonId :
'1')))"
slots:
default:
- component: oh-list
config:
noHairlinesBetween: true
style:
--f7-list-item-padding-horizontal: 4px
--f7-list-item-padding-left: 2px
--f7-list-item-media-margin: 8px
slots:
default:
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 0 && (!props.maxRows ||
Number(props.maxRows) > 0)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 0 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[0].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[0].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 0 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[0].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 0 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[0].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[0].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 0 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[0].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[0].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[0].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[0].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 1 && (!props.maxRows ||
Number(props.maxRows) > 1)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 1 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[1].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[1].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 1 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[1].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 1 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[1].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[1].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 1 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[1].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[1].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[1].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[1].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 2 && (!props.maxRows ||
Number(props.maxRows) > 2)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 2 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[2].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[2].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 2 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[2].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 2 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[2].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[2].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 2 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[2].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[2].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[2].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[2].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 3 && (!props.maxRows ||
Number(props.maxRows) > 3)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 3 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[3].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[3].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 3 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[3].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 3 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[3].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[3].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 3 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[3].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[3].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[3].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[3].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 4 && (!props.maxRows ||
Number(props.maxRows) > 4)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 4 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[4].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[4].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 4 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[4].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 4 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[4].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[4].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 4 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[4].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[4].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[4].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[4].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 5 && (!props.maxRows ||
Number(props.maxRows) > 5)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 5 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[5].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[5].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 5 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[5].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 5 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[5].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[5].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 5 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[5].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[5].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[5].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[5].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 6 && (!props.maxRows ||
Number(props.maxRows) > 6)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 6 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[6].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[6].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 6 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[6].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 6 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[6].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[6].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 6 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[6].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[6].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[6].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[6].platform + ')') : ''))
: '-'"
- component: oh-list-item
config:
visible: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 7 && (!props.maxRows ||
Number(props.maxRows) > 7)"
icon: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 7 ?
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[7].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[7].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/))) ? 'material:train' : 'material:directions_bus') : ''"
badgeColor: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 7 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].delay_s === null ? 'gray' :
(Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.js\
onId ? ('' + props.jsonId) : '1'].departures[7].delay_s / 60) >
0 ? 'red' : 'green')) : 'gray'"
badge: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 7 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].delay_s === null ? '-' :
((Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.j\
sonId ? ('' + props.jsonId) : '1'].departures[7].delay_s / 60) >
0 ? '+' : '') +
Math.round(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jso\
nId ? ('' + props.jsonId) : '1'].departures[7].delay_s / 60) + '
min')) : '-'"
style:
--f7-list-item-title-font-size: 13px
--f7-list-item-padding-left: 2px
padding-left: 0px
title: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures.length > 7 ?
(JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].time_local + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].route + ' | ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].direction +
((JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? (''
+ props.jsonId) : '1'].departures[7].route && (('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) :
'1'].departures[7].route).match(/^(ICE|IC|EC|RE|RB|S|RJ|IR|NJ|A\
LEX)/)) &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].platform !== null && ('' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].departures[7].platform) != '') ? (' (Gleis:
' + JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ?
('' + props.jsonId) : '1'].departures[7].platform + ')') : ''))
: '-'"
- component: f7-block
config:
style:
border-top: 1px solid var(--f7-list-item-border-color)
margin: "0"
padding: 6px 12px 10px 12px
slots:
default:
- component: Label
config:
text: "=items.TIMETABLE_JSON_ALL && items.TIMETABLE_JSON_ALL.state &&
items.TIMETABLE_JSON_ALL.state != 'NULL' &&
items.TIMETABLE_JSON_ALL.state != 'UNDEF' &&
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'] ? ('Letztes Update vor ' +
JSON.parse(items.TIMETABLE_JSON_ALL.state)[props.jsonId ? ('' +
props.jsonId) : '1'].age_s + ' s') : 'Warte auf Daten'"
style:
font-size: 12px
color: var(--f7-text-color)
text-align: left
opacity: "0.72"
display: block
