Nextride: Unterschied zwischen den Versionen

Aus Hackerspace Bielefeld Wiki
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „Der nextride-Teil besteht aus einem Haskell-Programm, welches cronjob-gesteuert die Bahn-Seite für die nächstgelegene Straßenbahnhaltestelle abgreift und di…“)
 
Keine Bearbeitungszusammenfassung
 
(4 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
Der nextride-Teil besteht aus einem Haskell-Programm, welches cronjob-gesteuert die Bahn-Seite für die nächstgelegene Straßenbahnhaltestelle abgreift und die Abfahrtszeiten als JSON in eine Datei schreibt. Diese Datei wird bei Änderung vom Infobeamer ([[Armageddon_Notifier]]) per Lua-Script eingelesen und dargestellt.
== Wann fährt die nächste Bahn? ==
 
* [http://haltestellenmonitor.vrr.de/monitor/5c1a5bf76de06ea27630edc685232626 Mobiel/VRR Abfahrzeiten Ziegelstraße]
 
== Nextride 2.0? ==
 
Im alten Space an der Sudbrackstraße hatten wir ein Display der nächsten Nahverkehr-Abfahrzeiten (s.u.), an der Blomestraße fehlt so etwas leider bisher. Der Link oben wurde mit dem [https://haltestellenmonitor.vrr.de/vu/mobiel#/index VRR-Haltestellenmonitor] erstellt.
 
Der eigentliche API-Endpunkt hinter dem Haltestellenmonitor ist '''"https://haltestellenmonitor.vrr.de/backend/api/stations/table''', darauf aufbauend könnte ein neues '''nextride''' entstehen.
 
Als neue Anzeigemöglichkeit könnte ich mir zB. -- energiesparend :) -- einen Arduino mit eInk-Display vorstellen?
 
=== VRR API ===
 
Dokumentation zu diesem API habe ich beim VRR auf die Schnelle nicht gefunden, es gibt dort zwar einen "Open Data" Bereich, aber dort scheinen nur Download-Datensätze angeboten zu werden, aber keine Live-Daten. Daher ist alles was hier folgt Ergebnis von Reverse Engineering.
 
==== Suche von Stationen ====
[https://haltestellenmonitor.vrr.de/backend/api/stations/search?query=blomestr]
 
==== Request ====
Der Haltestellenmonitor schickt die Haltestellendaten als POST-Request, und die POST-Parameter für eine Haltestelle sind konstant, zB. für die Stadtbahn-Haltestelle Ziegelstraße:
 
<nowiki>
table%5Bdeparture%5D%5BstationId%5D=23005614&table%5Bdeparture%5D%5BstationName%5D=Bielefeld+Ziegelstra%C3%9Fe&table%5Bdeparture%5D%5BplatformVisibility%5D=1&table%5Bdeparture%5D%5Btransport%5D=0%2C1%2C2%2C3%2C4%2C15%2C6&table%5Bdeparture%5D%5BuseAllLines%5D=1&table%5Bdeparture%5D%5BlinesFilter%5D=&table%5Bdeparture%5D%5BoptimizedForStation%5D=0&table%5Bdeparture%5D%5BrowCount%5D=6&table%5Bdeparture%5D%5BrefreshInterval%5D=60&table%5Bdeparture%5D%5Bdistance%5D=0&table%5Bdeparture%5D%5Bmarquee%5D=-1&table%5BsortBy%5D=0
</nowiki>
 
oder netter formatiert:
 
<nowiki>
table[departure][stationId] "23005614"
table[departure][stationName] "Bielefeld+Ziegelstraße"
table[departure][platformVisibility] "1"
table[departure][transport] "0,1,2,3,4,15,6"
table[departure][useAllLines] "1"
table[departure][linesFilter] ""
table[departure][optimizedForStation] "0"
table[departure][rowCount] "6"
table[departure][refreshInterval] "60"
table[departure][distance] "0"
table[departure][marquee] "-1"
table[sortBy] "0"
</nowiki>
 
 
===== Feldwerte =====
* table[departure][transport]
{| class="wikitable"
|+ Werte
|-
| 0 || ICE/IC/EC
|-
| 1 || Zug
|-
| 2 || S-Bahn
|-
| 3 || U-Bahn
|-
| 4 || Straßenbahn
|-
| 5 || Bus
|-
| 6 || Schwebebahn
|}
 
==== Response ====
 
Die Antwort kommt als JSON-Dokument zurück, damit lässt sich gut weiterarbeiten:
 
<nowiki>
{
  "departureData":[
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Altenhagen",
      "directionCode":"H",
      "route":"Bielefeld, Altenhagen",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"03",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"00",
      "countdown":"4",
      "platform":"",
      "delay":"3",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682233380",
      "orgFullTime":"1682233200",
      "supplement":"",
      "key":"231"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Sieker",
      "directionCode":"R",
      "route":"Bielefeld, Sieker",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"04",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"04",
      "countdown":"5",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682233440",
      "orgFullTime":"1682233440",
      "supplement":"",
      "key":"38"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Altenhagen",
      "directionCode":"H",
      "route":"Bielefeld, Altenhagen",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"15",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"15",
      "countdown":"16",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682234100",
      "orgFullTime":"1682234100",
      "supplement":"",
      "key":"234"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Sieker",
      "directionCode":"R",
      "route":"Bielefeld, Sieker",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"19",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"19",
      "countdown":"20",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682234340",
      "orgFullTime":"1682234340",
      "supplement":"",
      "key":"40"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Altenhagen",
      "directionCode":"H",
      "route":"Bielefeld, Altenhagen",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"30",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"30",
      "countdown":"31",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682235000",
      "orgFullTime":"1682235000",
      "supplement":"",
      "key":"236"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Sieker",
      "directionCode":"R",
      "route":"Bielefeld, Sieker",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"34",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"34",
      "countdown":"35",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
           
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682235240",
      "orgFullTime":"1682235240",
      "supplement":"",
      "key":"43"
    }
  ],
  "departureInfo":{
    "stopInfo":{
      "text":""
    },
    "stopBlocking":{
      "text":""
    },
    "areaInfo":{
      "text":""
    },
    "areaBlocking":{
      "text":""
    }
  },
  "globalInfo":"",
  "stationName":"Bielefeld, Ziegelstra\u00dfe",
  "marquee":-1,
  "stationInfo":[
   
  ],
  "currentTime":1682233123,
  "currentTimeReal":1682233123
}
</nowiki>
 
==== Q&D Example ====
"Bielefeld existiert, und PHP ist OK" ;)
 
<nowiki>
<?php
 
$url = "https://haltestellenmonitor.vrr.de/backend/api/stations/table";
 
$data = "table%5Bdeparture%5D%5BstationId%5D=23005614&table%5Bdeparture%5D%5BstationName%5D=Bielefeld+Ziegelstra%C3%9Fe&table%5Bdeparture%5D%5BplatformVisibility%5D=1&table%5Bdeparture%5D%5Btransport%5D=0%2C1%2C2%2C3%2C4%2C15%2C6&table%5Bdeparture%5D%5BuseAllLines%5D=1&table%5Bdeparture%5D%5BlinesFilter%5D=&table%5Bdeparture%5D%5BoptimizedForStation%5D=0&table%5Bdeparture%5D%5BrowCount%5D=6&table%5Bdeparture%5D%5BrefreshInterval%5D=60&table%5Bdeparture%5D%5Bdistance%5D=0&table%5Bdeparture%5D%5Bmarquee%5D=-1&table%5BsortBy%5D=0";
 
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
 
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
 
$resp = curl_exec($curl);
curl_close($curl);
 
$data = json_decode($resp, true);
 
foreach ($data["departureData"] as $dep) {
    $dir  = $dep["direction"];
    $time  = strftime("%R", $dep["orgFullTime"]);
    if ($dep["delay"] > 0) {
        $time .= " +".$dep["delay"];
    }
    $left  = ($dep["fullTime"] - time())/60;
 
    printf("+%-3d %-15s %s\n", $left, $time, $dir);
}
</nowiki>
 
== Nextride in der Sudbrackstraße ==
 
Der nextride-Teil bestand aus einem Haskell-Programm, welches cronjob-gesteuert die Bahn-Seite für die nächstgelegene Straßenbahnhaltestelle abgriff und die Abfahrtszeiten als JSON in eine Datei schrieb. Diese Datei wurde bei Änderung vom Infobeamer ([[Armageddon_Notifier]]) per Lua-Script eingelesen und dargestellt.
 
Diese Lösung funktioniert aus verschiedenen Gründen leider nicht mehr, unter anderem weil das damals genutzte API der Bahn keine Daten anderer Verkehrsbetriebe mehr zur Verfügung stellt.
 
* [https://github.com/HackerspaceBielefeld/Nextride nextride code auf GitHub]
 
[[Kategorie:Projekt]]
[[Kategorie:Sudbrackstraße]]

Aktuelle Version vom 24. April 2023, 06:13 Uhr

Wann fährt die nächste Bahn?

Nextride 2.0?

Im alten Space an der Sudbrackstraße hatten wir ein Display der nächsten Nahverkehr-Abfahrzeiten (s.u.), an der Blomestraße fehlt so etwas leider bisher. Der Link oben wurde mit dem VRR-Haltestellenmonitor erstellt.

Der eigentliche API-Endpunkt hinter dem Haltestellenmonitor ist "https://haltestellenmonitor.vrr.de/backend/api/stations/table, darauf aufbauend könnte ein neues nextride entstehen.

Als neue Anzeigemöglichkeit könnte ich mir zB. -- energiesparend :) -- einen Arduino mit eInk-Display vorstellen?

VRR API

Dokumentation zu diesem API habe ich beim VRR auf die Schnelle nicht gefunden, es gibt dort zwar einen "Open Data" Bereich, aber dort scheinen nur Download-Datensätze angeboten zu werden, aber keine Live-Daten. Daher ist alles was hier folgt Ergebnis von Reverse Engineering.

Suche von Stationen

[1]

Request

Der Haltestellenmonitor schickt die Haltestellendaten als POST-Request, und die POST-Parameter für eine Haltestelle sind konstant, zB. für die Stadtbahn-Haltestelle Ziegelstraße:

table%5Bdeparture%5D%5BstationId%5D=23005614&table%5Bdeparture%5D%5BstationName%5D=Bielefeld+Ziegelstra%C3%9Fe&table%5Bdeparture%5D%5BplatformVisibility%5D=1&table%5Bdeparture%5D%5Btransport%5D=0%2C1%2C2%2C3%2C4%2C15%2C6&table%5Bdeparture%5D%5BuseAllLines%5D=1&table%5Bdeparture%5D%5BlinesFilter%5D=&table%5Bdeparture%5D%5BoptimizedForStation%5D=0&table%5Bdeparture%5D%5BrowCount%5D=6&table%5Bdeparture%5D%5BrefreshInterval%5D=60&table%5Bdeparture%5D%5Bdistance%5D=0&table%5Bdeparture%5D%5Bmarquee%5D=-1&table%5BsortBy%5D=0

oder netter formatiert:

table[departure][stationId]	"23005614"
table[departure][stationName]	"Bielefeld+Ziegelstraße"
table[departure][platformVisibility]	"1"
table[departure][transport]	"0,1,2,3,4,15,6"
table[departure][useAllLines]	"1"
table[departure][linesFilter]	""
table[departure][optimizedForStation]	"0"
table[departure][rowCount]	"6"
table[departure][refreshInterval]	"60"
table[departure][distance]	"0"
table[departure][marquee]	"-1"
table[sortBy]	"0"


Feldwerte
  • table[departure][transport]
Werte
0 ICE/IC/EC
1 Zug
2 S-Bahn
3 U-Bahn
4 Straßenbahn
5 Bus
6 Schwebebahn

Response

Die Antwort kommt als JSON-Dokument zurück, damit lässt sich gut weiterarbeiten:

{
  "departureData":[
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Altenhagen",
      "directionCode":"H",
      "route":"Bielefeld, Altenhagen",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"03",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"00",
      "countdown":"4",
      "platform":"",
      "delay":"3",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682233380",
      "orgFullTime":"1682233200",
      "supplement":"",
      "key":"231"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Sieker",
      "directionCode":"R",
      "route":"Bielefeld, Sieker",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"04",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"04",
      "countdown":"5",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682233440",
      "orgFullTime":"1682233440",
      "supplement":"",
      "key":"38"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Altenhagen",
      "directionCode":"H",
      "route":"Bielefeld, Altenhagen",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"15",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"15",
      "countdown":"16",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682234100",
      "orgFullTime":"1682234100",
      "supplement":"",
      "key":"234"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Sieker",
      "directionCode":"R",
      "route":"Bielefeld, Sieker",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"19",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"19",
      "countdown":"20",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682234340",
      "orgFullTime":"1682234340",
      "supplement":"",
      "key":"40"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Altenhagen",
      "directionCode":"H",
      "route":"Bielefeld, Altenhagen",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"30",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"30",
      "countdown":"31",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682235000",
      "orgFullTime":"1682235000",
      "supplement":"",
      "key":"236"
    },
    {
      "name":"2",
      "lineNumber":"2",
      "lineCode":"31002",
      "subname":"Stadtbahn",
      "direction":"Bielefeld, Sieker",
      "directionCode":"R",
      "route":"Bielefeld, Sieker",
      "type":4,
      "day":"23",
      "month":"4",
      "year":"2023",
      "hour":"9",
      "minute":"34",
      "orgDay":"23",
      "orgHour":"9",
      "orgMinute":"34",
      "countdown":"35",
      "platform":"",
      "delay":"0",
      "isRealTime":true,
      "isDateOverflow":false,
      "lineInfo":{
        "lineInfo":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        },
        "lineBlocking":{
          "messages":[
            
          ],
          "text":"",
          "priority":0
        }
      },
      "fullTime":"1682235240",
      "orgFullTime":"1682235240",
      "supplement":"",
      "key":"43"
    }
  ],
  "departureInfo":{
    "stopInfo":{
      "text":""
    },
    "stopBlocking":{
      "text":""
    },
    "areaInfo":{
      "text":""
    },
    "areaBlocking":{
      "text":""
    }
  },
  "globalInfo":"",
  "stationName":"Bielefeld, Ziegelstra\u00dfe",
  "marquee":-1,
  "stationInfo":[
    
  ],
  "currentTime":1682233123,
  "currentTimeReal":1682233123
}

Q&D Example

"Bielefeld existiert, und PHP ist OK" ;)

<?php

$url = "https://haltestellenmonitor.vrr.de/backend/api/stations/table";

$data = "table%5Bdeparture%5D%5BstationId%5D=23005614&table%5Bdeparture%5D%5BstationName%5D=Bielefeld+Ziegelstra%C3%9Fe&table%5Bdeparture%5D%5BplatformVisibility%5D=1&table%5Bdeparture%5D%5Btransport%5D=0%2C1%2C2%2C3%2C4%2C15%2C6&table%5Bdeparture%5D%5BuseAllLines%5D=1&table%5Bdeparture%5D%5BlinesFilter%5D=&table%5Bdeparture%5D%5BoptimizedForStation%5D=0&table%5Bdeparture%5D%5BrowCount%5D=6&table%5Bdeparture%5D%5BrefreshInterval%5D=60&table%5Bdeparture%5D%5Bdistance%5D=0&table%5Bdeparture%5D%5Bmarquee%5D=-1&table%5BsortBy%5D=0";

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

$resp = curl_exec($curl);
curl_close($curl);

$data = json_decode($resp, true);

foreach ($data["departureData"] as $dep) {
    $dir   = $dep["direction"];
    $time  = strftime("%R", $dep["orgFullTime"]);
    if ($dep["delay"] > 0) {
        $time .= " +".$dep["delay"];
    }
    $left  = ($dep["fullTime"] - time())/60;

    printf("+%-3d %-15s %s\n", $left, $time, $dir);
}

Nextride in der Sudbrackstraße

Der nextride-Teil bestand aus einem Haskell-Programm, welches cronjob-gesteuert die Bahn-Seite für die nächstgelegene Straßenbahnhaltestelle abgriff und die Abfahrtszeiten als JSON in eine Datei schrieb. Diese Datei wurde bei Änderung vom Infobeamer (Armageddon_Notifier) per Lua-Script eingelesen und dargestellt.

Diese Lösung funktioniert aus verschiedenen Gründen leider nicht mehr, unter anderem weil das damals genutzte API der Bahn keine Daten anderer Verkehrsbetriebe mehr zur Verfügung stellt.