In den letzten Folgen haben wir mit dem ESP32 Pico Kit und etwas Beschaltung ein IoT-Gerät realisiert, das Sensorwerte in die Cloud sendet und von dort aus auch steuerbar ist. Als Cloud-Plattform haben wir die Maker-Variante von AllThingsTalk genutzt. Zum kostenlosen Zugang nach einfacher Registrierung gehören mehrere Webseiten, die sich der User selbst konfigurieren kann. Hier lassen sich Sensorwerte in Diagrammen anzeigen, aber auch kleine Steuerungsoberflächen stricken.

Amazon Web Services

Es gibt freilich noch jede Menge andere Cloud-Plattformen. Sehr viele der IoT-Lösungen, die man zum Beispiel auf Messen wie der Embedded World sehen kann, nutzen die Amazon Web Services (AWS). Diese Plattform ist sehr mächtig, robust und sicher und deshalb schon zu einer Art „Industriestandard“ geworden. Bekannte Dienste wie zum Beispiel Dropbox setzen hier auf. Speziell für das Internet of Things hat Amazon „AWS IoT Core“ entwickelt. Unternehmen und private Nutzer können hier theoretisch Millionen Sensorboards registrieren, die Datenflut in einer Datenbank sammeln, Big-Data-Auswertungen vornehmen, betriebliche Abläufe als Regeln in das System einführen und vieles mehr. Abgerechnet wird pro Million Verbindungsminuten und Million Nachrichten. Wer das Ganze – so wie ich – einmal ausprobieren will, bekommt für 12 Monate ein kostenloses Kontingent von 500.000 Nachrichten zur Verfügung gestellt.

Eines vorab: Der Einstieg in die Arbeit mit den AWS und die Programmierung eines entsprechenden Sensorboards ist nichts, das man mal schnell zwischen Tür und Angel erledigen kann. Das beginnt beim Anlegen eines AWS-Kontos. Hier registriert man sich nicht nur mit E-Mail-Adresse und Passwort, man muss auch eine Post-Adresse, eine Kreditkarten-Nummer für die Abrechnung und eine Telefonnummer angeben. Letztere wird sogar verifiziert: Man wird von einem Robot angerufen und aufgefordert, auf dem Telefon eine vierstellige Nummer eingeben, die man auf dem PC-Bildschirm angezeigt bekommt. Im Telefonnummern-Feld muss man die Telefonnummer übrigens vollständig (mit Landes-Vorwahl) und ohne Leerzeichen eingeben, sonst bleibt der Anruf aus.

Als Nächstes folgt man am besten dem Tutorial Erste Schritte mit AWS IoT. Man braucht ein wenig, um sich mit der „AWS-Sprache“ vertraut zu machen. Das Ganze wird nicht leichter, indem einige der englischen Begriffe mal übersetzt, mal nicht übersetzt werden (außerdem tauchen im deutschen Tutorial Screenshots mit den englischen Menüpunkten auf). Hier zwei Hinweise: Mit Registry ist die riesige AWS-Datenbank gemeint, in der man seine Geräte einträgt. Ein Device (Gerät) und ein Thing (Objekt) sind näherungsweise das Gleiche (genau genommen ist ein Thing ein virtuelles Gerät, das in der Cloud ein echtes Gerät repräsentiert).

Sicherheit geht vor

Viel Know-How ist in das Thema Sicherheit geflossen. Alle Boards, Smartphones und Computer in der weiten Welt kommunizieren mit den AWS nämlich immer verschlüsselt, und zwar über das Protokoll Transport Layer Security (TLS), das auf TCP/IP aufsetzt. Ich zitiere kurz aus der deutschen Wikipedia, denn dort wird die Funktionsweise recht gut zusammengefasst:

Der Client baut eine Verbindung zum Server auf. Der Server authentifiziert sich gegenüber dem Client mit einem Zertifikat. Der Client überprüft hierbei die Vertrauenswürdigkeit des X.509-Zertifikats und ob der Servername mit dem Zertifikat übereinstimmt. Optional kann sich der Client mit einem eigenen Zertifikat auch gegenüber dem Server authentifizieren. Dann schickt entweder der Client dem Server eine mit dem öffentlichen Schlüssel des Servers verschlüsselte geheime Zufallszahl, oder die beiden Parteien berechnen mit dem Diffie-Hellman-Schlüsselaustausch ein gemeinsames Geheimnis. Aus dem Geheimnis wird dann ein kryptographischer Schlüssel abgeleitet. Dieser Schlüssel wird in der Folge benutzt, um alle Nachrichten der Verbindung mit einem symmetrischen Verschlüsselungsverfahren zu verschlüsseln und zum Schutz von Nachrichten-Integrität und Authentizität durch einen Message Authentication Code abzusichern.

Für die Kommunikation eines Boards mit den AWS über TLS-geschütztes TCP/IP benötigen wir drei kryptische Zeichenfolgen; diese müssen später in die Firmware eingebunden werden:
  1. Certificate (Zertifikat)
  2. Private Key (privater Schlüssel)
  3. Root Certificate
Zur TLS-Kommunikation gehört noch eine vierte Zeichenfolge, der Public Key, dieser muss dem Board allerdings nicht bekannt sein. Das Zertifikat und der Private Key werden von den AWS individuell generiert, wenn man ein Gerät gemäß Tutorial registriert. Dabei entstehen zwei Dateien mit Zeichenfolgen, die heruntergeladen werden müssen und sich mit einem Editor wie Notepad++ öffnen lassen. Damit ist es allerdings noch nicht getan. Für das Gerät müssen noch Policies (Richtlinien) festgelegt werden. Im Wesentlichen sind das Regeln, was das Gerät in der Cloud „darf“. Hier kommt wieder MQTT ins Spiel. Wie bei AllThingsTalk auch wird sich unser Gerät nämlich später als MQTT-Client mit einem MQTT-Broker verbinden, den die AWS zur Verfügung stellen. Um Messwerte in die Cloud zu senden, brauchen wir wie immer die MQTT-Befehle CONNECT und PUBLISH. Wir müssen dem Gerät also erlauben, dass es sich mit dem Broker verbinden und dass es Nachrichten unter einem bestimmten Topic veröffentlichen darf. Am besten folgt man hier dem Tutorial Schritt für Schritt. Dieses schlägt vor, in das Feld des erlaubten Topics zum Beispiel
 
arn:aws:iot:us-east-1:123456789012:topic/my/topic/here

einzutragen. Statt „my/topic/here“ sollten Sie allerdings das Topic „$aws/things/<DEVICENAME>/shadow/update“ verwenden. Insgesamt muss in das Feld eingetragen werden:
 
arn:aws:iot:<REGION>:<ACCOUNTID>:topic/$aws/things/<DEVICENAME>/shadow/update

Die Account-ID/Konto-ID finden Sie, wenn Sie in der AWS IoT Management Console oben rechts auf den Nutzernamen klicken und „My Account“ anwählen. Über diesen Webzugang wickelt man alles ab, was mit dem eigenen AWS-Konto zu tun hat. Nachdem ich alle Schritte des Tutorials durchlaufen hatte, sah die Management Console bei mir so aus wie hier im Screenshot.



Sie sehen, dass ich mein erstes AWS-Device „MyJourneyIoTDevice“ genannt habe. Sie sehen weiterhin, dass die Menüführung in der Landessprache gehalten ist (bei den internationalen Lesern muss ich mich dafür entschuldigen, keine englischen Screenshots abbilden zu können). Und drittens sehen Sie, dass ich vergessen hatte, die Region von „Ohio“ auf „EU (Frankfurt)“ umzustellen. Bei mir ist deshalb <REGION> im obigen Ausdruck = „us-east-2“.

ESP32 lernt TLS

Uff – das war wenigstens schon einmal die halbe Miete. Nun musste ich meinem Board noch beibringen, mit den AWS zu kommunizieren. Ich habe eine Menge googeln und ausprobieren müssen, bis ich meine TCP/IP-Library so umstricken konnte, dass statt „normalem“ TCP/IP das sichere TLS über TCP/IP benutzt wird. Sie erinnern sich vielleicht, dass meine TCP-Library im Wesentlichen ein Wrapper um die Funktionen der Arduino-Klasse WiFiClient ist, die uns die Entwickler von Espressif freundlicherweise für den ESP32 implementiert haben. Und nicht nur das, es gibt auch eine Klasse WiFiClientSecure, die für TLS-geschützte TCP/IP-Operationen zuständig ist. Um rasch fertig zu werden, habe ich kurzerhand meine TCP/IP-Library dupliziert, und an die Datei- bzw. Klassennamen ebenfalls noch ein „Secure“ angehängt. Die eigentlichen Änderungen im Code der neuen TCPClientSecure- gegenüber der TCPClient-Library sind minimal, siehe Screenshot.



Im Konstruktor des Objekts werden dem Compiler die erwähnten drei Zeichenfolgen für die TLS-Kommunikation mitgeteilt. Diese kann man im Programm hardcodiert ablegen, dabei sind immer Pakete von 64 Zeichen durch ein \n zu trennen. Das Root-Zertifikat kann ich Ihnen hier übrigens gefahrlos zeigen – es ist sowieso immer gleich. Für die beiden anderen Zeichenfolgen habe ich eine eigene Datei namens AWS_Certificate.h erstellt, die über eine include-Anweisung in TCPClientSecure.cpp eingebunden wird. Sie finden ein Template für diese Datei im Download, müssen diese dann natürlich noch mit Ihrem Zertifikat beziehungsweise Schlüssel füllen.

Da die MQTT-Library ein Objekt vom Typ TCPClient erwartet, ich aber nun eines vom Typ TCPClientSecure benötige, habe ich auch die MQTT-Library noch verdoppelt und hier ebenfalls immer „Secure“ an Datei- und Klassennamen angehangen. Es gibt nun also jeweils eine TCP/IP- und eine MQTT-Lib für die normale und für die TLS-geschützte Kommunikation.

Schatten-Update

Für eine kleine Demo habe ich die Hardware und das Hauptprogramm aus Folge 23 als Basis benutzt. Laden Sie dort einmal den Code herunter und vergleichen Sie ihn mit dem neuen Sketch, den Sie unten downloaden können. Als individuelle Parameter benötigen wir natürlich wieder die SSID und das Password unseres Router-WLANs. Auch eine Device ID gibt es (wie bei der Arbeit mit AllThingsTalk), in meinem Fall heißt sie „MyJourneyIoTDevice“. Ein Device Token gibt es dagegen nicht mehr, da die Authentifizierung ja durch die Zertifikate sichergestellt wird. Dafür ist die Adresse des MQTT-Brokers bei den AWS individuell. Ich habe die Konfigurations-Webseite deshalb so angepasst, dass im 5. Textfeld die Broker-Adresse einzugeben ist. Die Serveradresse Ihres Brokers finden Sie, wenn Sie in der Management Console auf das Device klicken und dann im Device-Menü auf „Interagieren“ gehen. Die Server-Adresse bekommen Sie ganz oben angezeigt. Im nächsten grauen Feld sehen Sie das Topic, um Messwerte zu einem Schatten zu senden, bei mir lautet es
 
$aws/things/MyJourneyIoTDevice/shadow/update

(siehe Screenshot).



Was ist ein Schatten(objekt) nun schon wieder? Ein Schatten ist nichts anderes als eine Repräsentation von Zuständen eines IoT-Knotens (Sensor oder Aktor), in Form eines JSON-Dokuments. Wir erinnern uns, dass wir auch zum Übersenden von Messwerten an AllThingsTalk die JSON-Notation benutzt haben. Hier bei den AWS sieht ein gültiges JSON-Dokument beispielsweise so aus:
{
  "desired": {
    "temp": "32"
  }
}

Dieses Dokument habe ich auf der Device-Webseite unter dem Menüpunkt „Schatten“ in den JSON-Editor eingetragen (siehe Screenshot), um festzulegen, welche Werte mein Sensorboard verschicken kann.



Für erste Versuche habe ich mich damit begnügt, den periodisch von 10 bis 40 hochgezählten „Temperaturwert“ zu den AWS zu übermitteln (siehe den kommentierten Sketch). Als Lohn der Mühe konnte ich mich nach jedem Versand einer MQTT-Nachricht an einem Refresh der Schatten-Anzeige (mit einem neuen Temperaturwert) erfreuen. Übrigens habe ich auch über Stunden hinweg keine Verbindungsabbrüche bemerkt.

Weiter geht es in der nächsten Folge!