Nextride

Aus Hackerspace Bielefeld Wiki
Version vom 24. April 2023, 06:13 Uhr von Papayawhip (Diskussion | Beiträge)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

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.