PubliBike Stations Info auf SmartMirror

Ich bin zur Zeit immer wieder mit Velos von PubliBike in Bern unterwegs. Bei der mir am nächsten liegende Station kommt es leider häufig mal vor, dass keine Velos, oder nur E-Bikes (ein E-Bike vom Ostring in die Stadt hinunter macht macht nicht viel Sinn) vorhanden sind. Daher habe ich mir überlegt, es wäre doch cool, wenn ich direkt auf meinem SmartMirror sehen könnte, ob es noch Velos an der Station hat (als Alternative zur Mobile-App). Doch sind die PubliBike Stationsinfos überhaupt öffentlich verfügbar?

Auf der Webseite von PubliBike lässt sich eine Karte mit allen Standorten anzeigen. Auf der Karte sind auch die Velo-Verfügbarkeiten pro Station angegeben.

Und da die Informationen ja irgendwie auf die Karte müssen, gehe ich davon aus, dass ich auch irgendwie darauf zugreifen kann. Ich zoome also mal auf die mir nächstgelegene Station (damit ich nur noch die Daten von dieser Station habe) und öffne die Entwicklerkonsole in meinem Browser. Mit Hilfe des Network-Tab schaue ich mir die Kommunikation der Webseite an. Schnell sehe ich folgenden Request:

Das sieht doch schon vielversprechend aus. Schauen wir uns doch mal die Response dazu an:

{
  "id": 332,
  "latitude": 46.943804,
  "longitude": 7.4694264,
  "state": {
    "id": 1,
    "name": "Aktiv"
  },
  "name": "Egelgasse-Ostring",
  "address": "Egelgasse 72",
  "zip": "3006",
  "city": "Bern",
  "vehicles": [
    {
      "id": 1965,
      "name": "501989",
      "type": {
        "id": 2,
        "name": "E-Bike"
      }
    },
    {
      "id": 2367,
      "name": "102526",
      "type": {
        "id": 1,
        "name": "Velo"
      }
    }
  ],
  "network": {
    "id": 5,
    "name": "Bern",
    "background_img": null,
    "logo_img": "https://www.publibike.ch/static-content/Netz5.svg",
    "sponsors": []
  },
  "sponsors": []
}

Voilà, genau was ich will.

Als nächstes müssen diese Daten auf meinen SmartMirror. Für die Anzeige von Temperaturen verwende ich bereits das Plugin MMM-haas. Dieses kann Sensor-Daten aus meinem Home-Assistant auslesen und auf der SmartMirror darstellen. Die Sensor-Daten wiederum sende ich per MQTT an Home-Assistant. Daher will ich für die PubliBike Daten den gleichen Weg gehen. Bei mir läuft unter anderen auch eine Node-Red Instanz, diese verwende ich nun um die API-Daten von PubliBike zu Verarbeiten und in einen MQTT Channel zu pushen. Der Node-Red Flow dafür sieht wie folgt aus:

Am Anfang des Flows verwende ich einen Inject-Node. Dieser injected einen Payload manuell oder in einem festgelegten Intervall in den Flow. Ich injecte damit die ID der gewünschten PubliBike Station. Danach kommt eine Function-Node der mir den HTTP-Request vorbereitet, d.H. die URL zusammenbaut (mit der ID aus dem vorherigen Node). Nun folgt ein HTTP Request Node der dann effektiv die PubliBike API aufruft und ein geparstes JSON-Objekt zurückliefern. Natürlich hätte ich auf einfach nur den HTTP Request Node verwenden können und die API URL gleich da drin zu speichern. Wie oben im JSON sichtbar, zeigt mir die API alle Velos (und E-Bikes) der aktuellen Station an. Nun muss ich diese aber noch zählen. Dazu verwende ich wieder einen Function-Node mit etwas JavaScript:

var bike = 0;
var ebike = 0;

var vehicles = msg.payload.vehicles;
var stationname = msg.payload.name

for (var x in vehicles) {
    
    vehicle = vehicles[x];
    
    if (vehicle.type.name == "E-Bike") {
      ebike++;
    }
  
    if (vehicle.type.name == "Velo") {
      bike++
    }
}

msg.payload = { "velo": bike, "ebike": ebike, "stationname" : stationname, }
msg.topic = "publibike/" + msg.payload.stationname

return msg;

Der Payload dieser Funktion kommt dann anschliessend in einen MQTT Out Node, der eine Message im ensprechenden Channel (Topic) erstellt. Damit habe ich mal die Anzahl Velos und E-Bikes regelmässig auf einem MQTT-Topic. Der Inject-Node habe ich übrigens mit einem 5 Minuten Intervall konfiguriert. Als nächsten Schritt sollen diese Daten nun von einem Home-Assistant Sensor ausgelesen werden.

Home-Assistant hat dafür einen MQTT-Sensor, ich erstelle also die Konfiguration und lade Home-Assistant neu.

sensor:
  - platform: mqtt
    name: "Publibike Egelgasse-Ostring - Velos"
    state_topic: "publibike/Egelgasse-Ostring"
    value_template: "{{ value_json['velo'] | int }}"
  - platform: mqtt
    name: "Publibike Egelgasse-Ostring - E-Bike"
    state_topic: "publibike/Egelgasse-Ostring"
    value_template: "{{ value_json['ebike'] | int }}"

In Home-Assistant sieht das dann wie folgt aus:

Jetzt fehlt noch die Konfiguration des MMM-haas Modul für den SmartMirror:

{
    module: "MMM-HASS",
    position: "bottom_left",
    config: {
        host: "....",
        port: "8123",
        https: false,
        hassiotoken: true,
        devices: [{
            deviceLabel: "publibike",
            deviceReadings: [{
                sensor: "sensor.publibike_egelgasse_ostring_velos",
                icon: "fa fa-bicycle",
                suffix: ""
                },
                {
                sensor: "sensor.publibike_egelgasse_ostring_e_bike",
                icon: "fa fa-plug",
                suffix: ""
                }
            ]
            },
        ]
    }
}

Auf dem SmartMirror ist nun das gewünschte Resultat zu sehen:

Übrigens, wie auf dem Bild zu sehen, habe ich auch die Daten von aare.guru auf den SmartMirror integriert. Das Vorgehen da war praktisch gleich (Node-Red -> MQTT -> HomeAssistant Sensor -> SmartMirror):

MagicMirror – Finalisierung

Gestern konnte ich endlich mein MagicMirror Projekt (zum Grössten Teil) abschliessen. Nach dem ersten Versuch mit Spionspiegel Folie, habe ich Alternativen gesucht. Dazu startete ich zwei Anfragen bei Glasereien. Eine davon wurde bis heute leider nicht beantwortet, bei der zweiten habe ich eine Offerte für ein Spionspiegel aus Glas erhalten. Leider wäre der Spiegel ca 300.- CHF teuer gewesen, 6mm Dick und ca 2.7 Kg schwer. Das ist mir erstens zu teuer und auch von den Massen unpassend. Dann bin ich auf einen Acrylglas-Spiegel 2W gestossen, den ich über die Firma Kunststoffpark bestellen konnte. Preis inkl. Mwst und Versand waren etwas über 90.- CHF. Diesen Acryglas-Spiegel 2W kann ich empfehlen, wenn jemand ein ähnliches Projekt machen will. Den Spiegel habe ich auch schnell erhalten und konnte dann endlich mein MagicMirror fertigstellen.

Damit ich das Display im Spiegel ein- und ausschalten kann, habe ich via Banggood ein 250V Relais bestellt, welches über die GPIO Schnittstelle des Raspberry Pi angesteuert wird. Auch das ist nach etwa 2 Wochen eingetroffen. Mit Python habe ich einen kleinen Daemon geschrieben, der das Relais ansteuert (via SIGUSR1 und SIGUSR2 Signals). Weiter habe ich eine MQTT Schnittstelle in den  Daemon eingebaut, damit ich das Display auch Remote ein- und ausschalten kann. Damit ist nun auch ein produktiver Einsatz von Node-Red. welches ich früher schon Mal erwähnt habe, möglich. Via Node-Red Dashboard habe ich ein einfaches Dashboard erstellt, um das Display An- und Auszuschalten. 

Aktuell steuere ich das Display über einen MQTT Channel smartmirror/command an den ich ein JSON sende. Z.B. {„screen“:“on“} um einzuschalten oder {„status“:“get“} um den Status abzufragen. Beim Status Command wird auf dem Channel smartmirror/status den aktuellen Status via JSON ausgesendet. Das geschieht auch automatisch bei jedem Statuswechsel (von on zu off oder umgekehrt). Vermutlich werde ich diese Schnittstelle aber noch umbauen, ich muss mich noch schlau machen, was hier die gängigen Standards sind um IOT Geräte via MQTT zu steuern. Vermutlich werde ich es so umbauen, dass es nur einen Channel smartmirror/display/power gibt. In den Channel wird dann eine einfache 0 oder 1 gesendet um die Stromzufuhr zum Display zu steuern. Der gleiche Channel kann auch für die Status-Response verwenden werden.

Was noch fehlt, ist ein kleiner Push-Button am MagicMirror, um das Display auch ohne Dashboard Ein-und Auszuschalten. Aktuell habe ich ein via Cronjob getriggertes Script am laufen, um das Display zeitgesteuert Ein- und Auszuschalten (in der Nacht sowie ab spätem Morgen bis spätem Nachmittag läuft das Display z.B. nicht).

Update 22. Mai 2018

Hier ein kurzes Video wie der Spiegel live aussieht

MagicMirror mit Wort Uhr in Berndeutsch

Kennt Ihr Magic Mirrors? Es gibt dazu einige spannende Projekte. Ich selbst hatte Lust, mal so einen zu bauen. Wie genau das geht, erkläre hier aber nicht, dazu gibt es viele gute Anleitungen (z.B. hier) und schliesslich kann man das auch auf viele verschiedene Arten tun. Nur die paar wichtigsten Infos aus meinem Projekt.

  • Ich hatte noch ein altes Raspberry Pi rumliegen, dass ich dafür verwendet habe. Als Betriebssystem kommt Raspian zum Einsatz. Als Software für die Anzeige habe ich MagicMirror genommen. Da ich aber nur die erste Generation vom Raspberry habe, musste ich die Backend Komponente von MagicMirror in einem Docker Container auf meinem Synology NAS laufen lassen. Auf dem Raspberry läuft dann nur ein Browser im Fullscreen Modus.
  • In Magic Mirror sind bereits viele coole Module vorhanden. zwei davon möchte ich aber speziell erwählen:
  • Links oben werden bei mir die Trams von einer Haltestelle hier in Bern angezeigt. Die Daten dazu werden von https://transport.opendata.ch/  zur verfügung gestellt. Dazu verwenden ich ein MagicMIrror Modul von Beny habe es aber ein wenig an meine Bedürfnisse angepasst. Unter anderem habe ich eine Funktion eingefügt, welche Trams (oder Züge) rot einfärbt, wenn es nicht mehr erreicht werden kann, da der Fussweg zulange ist (die Dauer lässt sich natürlich konfigurieren)
  • Als zweites habe ich eine Wort Uhr erstellt, welche die aktuelle Uhrzeit in Berndeutsch ausgibt. Auch diese könnt ich bei mir auf Github herunterladen wenn ihr selbst damit spielen wollt.

Leider fehlt aber noch der Spiegel um das Projekt zu beenden. Mein erster Versuch mit einer Spiegelfolie war leider nicht erfolgreich. Der Spiegeleffekt ist zu klein, es kommt zu viel Licht vom Display hindurch. Ausserdem ist es auch fast nicht möglich, die Folie sauber auf ein Plexiglas oder normales Glas aufzuziehen. Ich habe jetzt verschiedene Anfragen für ein sog. Spionspiegel bei Glasereien und einem Kunststoffhersteller offen und hoffe somit dem MagicMirror bald fertig zu stellen. Hat jemand aus der Schweiz bereits Erfahrungen damit gesammelt? Ich freue mich auf Kommentare dazu.