WORK THE DATA @ WHAT THE DATA Teil 1: Warm-Up

WORK THE DATA @ WHAT THE DATA Teil 1: Warm-Up

Damit ihr euch jetzt schon auf den WHAT THE DATA!? Hackathon vorbereiten könnt, haben wir euch bereits vorab ein paar Daten freigegeben. Damit ihr euch am Hackathon Wochenende nicht mit Basics aufhaltet, könnt ihr schon jetzt ein bisschen üben.

Getting Started: MQTT

Eine MQTT Bibliothek ist für praktisch jede Programmiersprache verfügbar. Es sollte in der Regel nur wenige Minuten dauern, erste Daten zu erhalten, denn MQTT ist nicht kompliziert. Eine Liste von Client-Libraries für alle Programmiersprachen findet ihr hier.

Zum Debuggen und für den schnellen Schnellstart gibt es auch Web-Clients, z.B. http://www.hivemq.com/demos/websocket-client/ und für alle komplexeren Prototyping Aufgaben empfehlen wir Node-RED (https://www.nodered.org), für das wir demnächst nochmal einen eigenen Artikel veröffentlichen.

Egal welche Technologie eingesetzt wird, die Interaktion mit MQTT erfolgt immer in den gleichen Schritten:

  1. Connect
  2. Publish oder Subscribe
  3. Unsubscribe / Disconnect (Optional)

Im Folgenden schreiben wir eine ganz oberflächliche, erste Einführung in MQTT. Wer sich genauer informieren möchte, sei auf die unzähligen Ressourcen im Internet verwiesen.

Connect

Die Verbindung zwischen einem Client und dem Broker ist immer eine dauerhafte TCP Verbindung und nicht – wie bei HTTP – auf einen einzelnen Request beschränkt. Für die Verbindung benötigt man:

  • zwingend: Broker-Hostname und Port (Default: 1883 für MQTT, 8883 für MQTT/TLS, 80 für MQTT over Websockets, 443 für MQTT over Secure Websockets)
  • optional: ClientID (best practice: ClientID === Username)
  • optional: Username und Password (je nach Authentifizierungs-Mechanismus)
  • optional: Client-Zertifikat (je nach Authentifizierungsmechanismus)
  • CleanSession Flag (per default `true`). Wenn `false` bedeutet das, dass der Broker die subscriptions auch nach Verbindungsabbruch speichert und Nachrichten zwischenpuffert die auflaufen, während der Client offline ist. Es ist dann nicht erforderlich, nach einem Reconnect neu zu subscriben, weiterhin werden beim nächsten connect alle Nachrichten nachgeliefert.

Beispiel in Javascript

const mqtt = require('mqtt')

const client = mqtt.connect(
 'mqtts://energie-campus.cybus.io', {
 clientId: 'my-user-name',
 username: 'my-user-name',
 password: 'something-secret',
 clean: true
})

Publish

Eine MQTT Nachricht besteht immer aus dem so genannten Topic und einem Payload. Das Topic ist hierarchisch aufgebaut und besteht aus alphanumerischen Zeichen, getrennt durch `/`. In der Regel können Clients nur in bestimmten Topics publishen, dies wird durch ACL (Access Control Lists) geregelt. Der Payload einer Nachricht kann bis zu 256 MByte groß sein und MQTT trifft keine Annahmen über das Format des Payloads. Wichtig: Der Payload ist immer ein rein binäres Datenpaket. Das Format, in dem die Daten kodiert sind, muss also beim Client bekannt sein.

Bei Cybus gibt es per Konvention genau zwei Arten von Payloads:

  • Rohdaten, die direkt, unverarbeitet und ungeparsed aus Maschinen ausgelesen werden. Der Client muss diese Daten noch in das richtige Format (float, int, …) umwandeln
  • Qualitative Daten, die immer im JSON Format als String im Payload kodiert sind. Ein solches JSON Objekt enthält in der Regel mindestens die Felder `value` und `timestamp` und ggf. noch weitere Metadaten.

Beispiel in Javascript:

const data = {timestamp: Date.now(), value: 42}
client.publish('some/topic/to/publish/on', JSON.stringify(data))

Subscribe

Subscriptions beziehen sich immer auf bestimmte Topics, wobei hier zusätzlich Wildcards eingesetzt werden können, um größere Topic Scopes auf einmal zu abbonnieren. Es gibt folgende Wildcards:

  • `+` kann innerhalb des Topics benutzt werden und gilt für genau eine Hierarchie-Ebene
  • `#` kann nur am Ende des Topics benutzt werden und gilt für beliebig viele Hierarchie-Ebenen

Beispiele:

Subscribe                    Matches                     Does not match
-----------------------------------------------------------------------------------------

some/thing                   some/thing                  some/thing/else
                                                         some/otherthing

some/+/thing                 some/thing/thing            some/thing
                             some/other/thing            some/totally/other/thing

some/+/+/thing               some/totally/other/thing    some/other/thing
                                                         some/totally/other/thong

some/#                       some/thing                  some
                             some/other/thing            other/thing
                             some/really/other/thing

In Folge einer Subscription werden asynchron Nachrichten zugestellt. Dazu muss in der Regel eine Callback Funktion übergeben werden.

In Javascript sieht das z.B. so aus:

 client.subscribe('some/+/topic')
 client.on('message', function(topic, payload) {
 console.log('received message ', payload, ' on topic ', topic)
 })

Auch das Subscribe ist abhängig davon, dass der jeweilige Client die entsprechenden Lese-Berechtigungen hat. Bei Cybus ist es sehr wichtig, dass eine Subscription immer eine Teilmenge der erteilten Berechtigungen bildet. Hat ein Client beispielsweise die Berechtigung, auf `some/+/topic` zu lesen, sind beispielsweise folgende Subscriptions gültig: `some/+/topic`, `some/specific/topic`, aber nicht: `some/#`, `#` oder `some/+/+`.

Achtung Falle! Standardmäßig beziehen sich Subscriptions nur auf die aktuelle Verbindung. Die meisten Client-Bibliotheken kümmern sich selbständig um ein Reconnect im Fall eines Verbindungsabbruchs. Nach einem solchen Reconnect muss in der Regel die `subscribe` Funktion erneut aufgerufen werden, außer es wird das Flag `cleanSession: false` benutzt.

Unsubscribe

Sollen auf einem bestimmten Topic keine Daten mehr empfangen werden, kann mit Hilfe des `unsubscribe` Befehls das Abonnement beendet werden. Wichtig: Die Topics inkl. Wildcards im Unsubscribe müssen exakt denen entsprechen, die vorher im Subscribe übergeben wurden.

In Javascript:

 client.unsubscribe('some/+/topic')

Disconnect

Am Ende einer Verbindung steht wie immer das Disconnect. Es ist nicht notwendig, die Subscriptions vor dem Disconnect abzubauen, außer die Verbindung wurde mit `cleanSession: false` aufgebaut und es sollen keine Offline-Nachrichten gespeichert werden.

 client.end()

Praktisches Beispiel

Wir haben für euch einen Datenpunkt am Energie-Campus der HAW zum Aufwärmen für den Hackathon öffentlich verfügbar gemacht. Meldet euch mit einem MQTT Client eurer Wahl an unter:

  • Server: energie-campus.cybus.io
  • Port: 8883
  • MQTT over TLS
  • Username: warm-up
  • Passwort: warm-up-what-the-data-2017

Für den warm-up Client sind folgende Permissions gesetzt:

READ_DATA: io/cybus/energie-campus/energie/hausanschluss/scheinleistung/gesamt
READ_DATA: io/cybus/energie-campus/warm-up/#
WRITE_DATA: io/cybus/energie-campus/warm-up/#

Hier ein vollständiges Code-Beispiel in Javascript. Forked gern auch unser Beispiel-Projekt auf Github.

const mqtt = require('mqtt')

const client =  mqtt.connect(
  'mqtts://energie-campus.cybus.io',
  {
    username: 'warm-up',
    password: 'warm-up-what-the-data-2017'
  }
)

client.on('connect', () => {
  client.subscribe('io/cybus/energie-campus/energie/hausanschluss/scheinleistung/gesamt')
  client.subscribe('io/cybus/energie-campus/warm-up/#')
})

client.on('message', (topic, payload) => {
    console.log(topic, payload.toString())
})

setTimeout(() => {
  client.publish('io/cybus/energie-campus/warm-up/hello', 'world')
}, 2000)

Leave a Reply

Your email address will not be published. Required fields are marked *