Was für Jedi die Konstruktion des eigenen Lichtschwerts, ist für IoT-Einsteiger der Bau der ersten Raspberry Pi «Wetterstation». Das folgende Tutorial beschreibt Schritt für Schritt Installation, Inbetriebnahme und Vernetzung einer solchen Sensor- und Datenstation: Messdaten wie Temperatur, Luftdruck und relative Luftfeuchtigkeit des Sense HAT Moduls werden mit Python 3 ausgelesen, an Amazon Web Services geschickt und dort gespeichert. In der Kür wird ausserdem die Visualisierung in einem Online-Dashboard mit Hilfe von AWS DynamoDB und Lambda gestreift.
1. Voraussetzungen
Zur Realisierung dieses Projektes werden folgende Elemente benötigt:
- Raspberry Pi 4 4G Model B (ARMv8)
- Raspberry Sense HAT
- Raspberry Pi 4 Power Adapter (Netzteil)
- Raspberry Pi 16GB MicroSD Karte inkl. SD Kartenadapter mit Noobs Installationsassistent
- Raspberry Pi micro HDMI to HDMI
- OKdo Raspberry Pi 4 Model B Gehäuse (optional)
Diese Komponenten sind bei diversen Anbietern in Sets für ca. CHF 160.– erhältlich. (z.B. bei Digitec).
Zur Inbetriebnahme, Steuerung und Konnektivität des Raspberry Pi werden ausserdem folgende Elemente vorausgesetzt:
- Monitor mit HDMI-Anschluss
- Maus (USB)
- Keyboard (USB)
- WLAN-Heimnetz mit Internetverbindung
- AWS-Konto
- Heimcomputer mit Internetverbindung für Inbetriebnahme, Steuerung, Coding, etc.
2. Zusammenbau
Nach dem Auspacken der Komponenten wird das Sense HAT Modul auf die Raspberry Pi Platine gesteckt und mit den mitgelieferten Verbindungselementen und Schrauben befestigt. Die MicroSD Karte mit Noobs wird nun vorsichtig aus dem SD Adapter entfernt und in den Slot auf dem Raspberry Pi eingeführt. (Alternativ kann auch selber eine SD Karte mit dem Betriebssystem vorbereitet werden, wie in diesem Tutorial beschrieben wird).
Wahlweise kann auch das Gehäuse montiert werden, um das Gerät zu schützen. Mit dem montierten Sense HAT passt das Standard-Case nicht optimal, mit ein wenig Zwängen ist es aber möglich. (Speziell für diesen Anwendungsbereich konzipierte Gehäuse sind im Netz erhältlich).
An dieser Stelle sei erwähnt, dass die Temperatur-Messungen aufgrund der Hitzeausstrahlung des CPUs nicht verlässlich sind und nur mithilfe von Kalibrierung oder – besser noch – mittels mehr Abstand und eines Verlängerungskabels zwischen Raspberry Pi und Sense HAT korrigiert werden können.
So oder so werden nun Tastatur, Monitor und Maus per Kabel mit dem Raspberry Pi verbunden. Am Schluss wird das Netzteil eingesteckt und an die Stromversorgung angeschlossen.
Da das Gerät über keinen Hauptschalter verfügt, wird es sofort gestartet. (Ich empfehle, dabei nicht direkt in das Sense HAT Display zu schauen, da es beim Starten sehr hell aufleuchtet, falls sonst keine Anzeige verbunden ist).
Auf dem angeschlossenen Monitor sollten nach einem Moment Startbildschirm und Benutzeroberfläche erscheinen:
3. Inbetriebnahme und Konfiguration
Ein Installationsassistent führt nun durch die nötigen Schritte, das Gerät in Betrieb zu nehmen:
- Start
- Sprache, Ort, Zeit, Tastatur
- Passwort setzen
- Set Up Screen
- Select WiFi Network
- Password WiFi Network
- Connecting to WiFi
- Update Software
- Restart
Nach dem Neustart wird mit folgenden Befehlen im Standard-Terminal LXTerminal sichergestellt, dass das System auf dem neuesten Stand ist.
sudo apt-get update sudo apt-get upgrade sudo apt-get install sense-hat sudo reboot
Optional: Mit folgenden Befehlen installieren wir Python 3, falls nicht schon die aktuellste Version (z.B. 3.8.2) auf dem Gerät vorhanden ist. Sie kann auf der offiziellen Webseite heruntergeladen werden. (Die mit ↱ markierten Linien gehören auf die vorhergehende Zeile. Das Pfeil-Symbol dient nur der Darstellung in diesem Beitrag und muss vor dem Ausführen gelöscht werden).
sudo apt-get update -y sudo apt-get install build-essential ↱ tk-dev libncurses5-dev ↱ libncursesw5-dev ↱ libreadline6-dev ↱ libdb5.3-dev ↱ libgdbm-dev ↱ libsqlite3-dev ↱ libssl-dev ↱ libbz2-dev ↱ libexpat1-dev ↱ liblzma-dev ↱ zlib1g-dev ↱ libffi-dev -y wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz tar xf Python-3.8.2.tar.xz cd Python-3.8.2 ./configure make -j 4 sudo make altinstall sudo reboot
Damit ist der Raspberry Pi betriebsbereit. Damit er später auch ohne Anschluss an die Peripherie gesteuert werden kann, aktivieren wir über die Raspberry Pi Konfiguration SSH und VNC. Damit kann das Gerät per SSH und/oder Remote-Desktop von einem anderen Computer über das Heimnetzwerk kontrolliert werden:
Dies ermöglicht auch einen vereinfachten Datenaustausch zwischen dem Heimcomputer und dem Raspberry Pi, was wir später noch benötigen werden. Während bei Windows die Remote-Desktop-Verbindung bereits vorhanden ist, existieren für Mac diverse Drittlösungen, z.B. VNC Connect Viewer, dessen Gegenstück, der VNC Server, mit der mitgelieferten MicroSD Karte bereits auf dem Raspberry Pi installiert wurde.
Um die Verbindung zwischen den Geräten herstellen zu können, benötigt man nebst Login und Passwort die IP Adresse des Raspberry Pi im Heimnetzwerk. Man findet sie z.B. im Terminal mit dem Befehl:
ifconfig
Damit diese Adresse im Heimnetzwerk bestehen bleibt, kann sie für die gewünschten Geräte in den DHCP (Dynamic Host Configuration Protocol)-Einstellungen Ihres Routers reserviert werden (optional). Für Hilfe zu diesem Schritt konsultieren Sie am besten die FAQs Ihres Internet-Providers.
4. Steuerung und Abfrage von Sense HAT mit Python 3
Höchste Zeit, nun erste Schritte mit dem Sense HAT Modul zu machen. Dafür starten wir die integrierte Python Entwicklungsumgebung Thonny. Falls diese IDE nicht schon vorinstalliert ist, kann sie in über das Menu Einstellungen -> Recommended Software hinzugefügt werden.
In Thonny Python IDE erstellen wir ein neues Python Dokument «hello-world.py» mit dem folgenden Inhalt. Wir speichern es und führen es in Thonny aus.
from sense_hat import SenseHat sense = SenseHat() while True: msg = "Hello World" sense.show_message(msg, scroll_speed=0.05)
Mit dem nächsten Skript werden die Sense HAT Sensoren ausgelesen und die Daten auf dem integrierten Display angezeigt:
from sense_hat import SenseHat sense = SenseHat() while True: t = sense.get_temperature() p = sense.get_pressure() h = sense.get_humidity() t = round(t,1) p = round(p,1) h = round(h,1) msg = "Temperature = %s, Pressure=%s, Humidity=%s" % (t,p,h) sense.show_message(msg, scroll_speed=0.05)
In den nächsten Abschnitten wird beschrieben, wie diese Sensordaten nicht mehr auf dem integrierten Display angezeigt, sondern zu AWS gesendet und dort gespeichert werden. (Neben Amazon Webservices bieten auch andere Anbieter ihre eigenen Cloud-basierten IoT Lösungen an, z.B. Microsoft’s Azure IoTHub oder IBM’s Watson IoT Platform).
5. Raspberry Pi in AWS IoT Core registrieren
Wir öffnen https://aws.amazon.com/de/iot/ im Browser, melden uns bei der AWS-Konsole an und registrieren unseren Raspberry Pi als neues Objekt («Thing»).
Danach erstellen wir per Klick ein neues Zertifikat und laden es anschliessend zusammen mit den passenden Keys und einem Stammzertifikat (Amazon Root CA 1) herunter und speichern die heruntergeladenen Files z.B. in einem Ordner «certs».
Nun wird im AWS IoT Menu-Punkt «Sicher» eine Richtlinie (Policy) erstellt.
Wir wählen einen Namen und schreiben in die Felder Aktion und Ressourcen-ARN «iot.*» bzw. «*».
Wir kehren zurück zu unserem vorhin erstellten Zertifikat, wählen es aus und fügen ihm die soeben erstellte Richtlinie an.
Bevor wir fürs Erste die AWS-Konsole verlassen und uns wieder im Raspberry Pi einloggen, navigieren wir zum Navigationspunkt «Interagieren» unseres Objekts und notieren den HTTPS Rest API-Endpunkt.
Die soeben heruntergeladenen Zertifikate im Ordner «certs» übertragen wir mit der Remote-Desktop-Verbindung oder VNC in ein dafür erstelltes Verzeichnis «py» auf dem Raspberry Pi.
6. AWSIoTPython SDK
Damit der Raspberry Pi mit AWS zusammenarbeiten kann, wird per Terminal das passende Software Development Kit installiert (AWSIoTPython).
sudo pip3 install AWSIoTPythonSDK
7. Python 3 Skripts
Mit den folgenden Skripts werden die Sensordaten von Sense HAT ausgelesen und per MQTT (Message Queuing Telemetry Transport) an AWS IoT Core gesendet. Die im vorigen Kapitel erstellten Schlüssel und Zertifikate identifizieren unser Gerät dabei und sichern die Kommunikation zwischen AWS und Raspberry Pi.
Im Ordner «py» erstellen wir ein File «config.py» mit folgendem Inhalt:
HOST_NAME = "<REPLACE-WITH-YOUR-ENDPOINT>.iot.eu-central-1.amazonaws.com" HOST_PORT = 8883 PRIVATE_KEY = "certs/private.pem.key" DEVICE_CERT = "certs/certificate.pem.crt" ROOT_CERT = "certs/root-ca.crt" SENSOR_TOPIC = "tower/senseHat" QOS_LEVEL = 0
Wichtig dabei ist, als HOST_NAME den vorhin notierten API-Endpunkt anzugeben und sicherzustellen, dass die Pfade und Dateinamen von Private Key und Zertifikaten korrekt sind. Als SENSOR_TOPIC wählen wir einen passenden Namen, z.B. «tower/senseHat».
Mit unserem Hauptskript «sense.py», das wir mit folgendem Inhalt im Ordner «py» abspeichern, nähern wir uns dem ersten Höhepunkt dieses Tutorials: Mit der AWS MQTT Client API werden damit alle 5 Minuten die Sense HAT Daten ausgelesen und publiziert. (Nebst Temperatur, Luftdruck und Luftfeuchtigkeit werden auch Daten des eingebauten Beschleunigungssensors, die Prozessor-Temperatur sowie eine Geräte-ID zur Identifikation und ein Zeitstempel mitgeschickt).
Das folgende Skript ist auf ein Minimum reduziert und bietet u.a. kein Error-Handling, wenn beispielsweise die Netzwerkverbindung unterbrochen oder das Skript beendet wird.
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient from sense_hat import SenseHat import config import os import time import json from datetime import datetime sense = SenseHat() sense.clear() def get_cpu_temp(): res = os.popen("vcgencmd measure_temp").readline() t = float(res.replace("temp=","").replace("'C\n","")) return(t) # Define function to collect weather data def get_weather(id): deviceId = 1 humidity = float(sense.get_humidity()) pressure = float(sense.get_pressure()) timestamp = str(datetime.now()) temp_humidity = float(sense.get_temperature_from_humidity()) temp_pressure = float(sense.get_temperature_from_pressure()) temp = float(sense.get_temperature()) temp_cpu = float(get_cpu_temp()) # Calibration Factor may vary! temperature = float(temp - ((temp_cpu-temp)/0.065)) acc = sense.get_accelerometer_raw() acc_x = acc["x"] acc_y = acc["y"] acc_z = acc["z"] measures = {'ID': id, 'DeviceId': deviceId, ↱ 'Temperature': temperature, 'Humidity': humidity, ↱ 'Pressure': pressure, 'Temperature_Sensor': temp, ↱ 'Temperature_CPU': temp_cpu, 'Temperature_HS': temp_humidity, ↱ 'Temperature_PS': temp_pressure, 'Acceleration_X': acc_x, ↱ 'Acceleration_Y': acc_y, 'Acceleration_Z': acc_z, ↱ 'Timestamp': timestamp } return measures # Define variable for MQTT topic from config file sensor_topic = config.SENSOR_TOPIC # Initialize MQTT client client = AWSIoTMQTTClient('') # Configure client endpoint, port information, certs client.configureEndpoint(config.HOST_NAME, config.HOST_PORT) client.configureCredentials(config.ROOT_CERT, config.PRIVATE_KEY, config.DEVICE_CERT) client.configureOfflinePublishQueueing(-1) client.configureDrainingFrequency(2) client.configureConnectDisconnectTimeout(10) client.configureMQTTOperationTimeout(5) # Loop through metrics, publish every 300 seconds id = 0 metrics = ['Temperature', 'Humidity', 'Pressure', ↱ 'Temperature_Sensor','Temperature_CPU', ↱ 'Temperature_HS','Temperature_PS', ↱ 'Acceleration_X','Acceleration_Y', ↱ 'Acceleration_Z'] while True: # Connect print('Connecting to endpoint ' + config.HOST_NAME) client.connect() for metric in metrics: data = {key: get_weather(id)[key] for key in (metric, 'ID', 'DeviceId', 'Timestamp')} sub_topic = sensor_topic.split('/')[0] + '/metrics/' + metric #client.publish(sub_topic, json.dumps(data), config.QOS_LEVEL) print('' + metric + ' in Device '+str(data["DeviceId"])+' is ' + str(data[metric])) client.publish(sensor_topic, json.dumps(get_weather(id)), config.QOS_LEVEL) print(str(datetime.now())+' Published message on topic ' + sensor_topic) id += 1 print('Disconnecting ' + config.HOST_NAME) client.disconnect() time.sleep(300)
Um das Skript zu testen, öffnen wir es in der Thonny Python IDE und führen es aus. Falls keine Fehlermeldung erscheint, werden nun alle 300 Sekunden die Daten publiziert und im Ausgabefenster angezeigt. (Zum Testen empfiehlt es sich, die Sleep-Zeit auf z.B. 5 Sekunden herunterzusetzen).
Sobald wir mit unserem Skript zufrieden sind, können wir Thonny schliessen und es per Terminal (oder über SSH) ausführen, indem wir zum Verzeichnis «py» navigieren und das Skript starten:
python3 sense.py
Mit dem folgenden Befehlen können ausserdem sämtliche aktiven Python 3 Prozesse in einem neuen Terminal-Fenster angezeigt und einzelne Skripts beendet werden:
watch -n 1 "ps u -C python3" pkill -f sense.py
Wenn dies alles geklappt hat, wechseln wir wieder zu AWS IoT Core während das Skript «sense.py» weiter ausgeführt wird.
8. Empfangen der Daten in AWS IoT Core und Speicherung in Datastore und Datasets
Im AWS IoT Menu-Punkt «Überwachen» stellen wir sicher, dass unsere Verbindung erfolgreich initialisiert wurde:
Um die gesendeten Daten auch zu speichern, wechseln wir in der AWS Konsole zum AWS IoT Analyse Service und erstellen einen Kanal sowie Pipeline, Datenspeicher und ein Dataset.
Der Schnellstart hilft uns dabei und stellt sicher, dass alle Berechtigungen korrekt sind. (Eine Hilfe zur manuellen Einrichtung von Pipeline, Datenspeicher und Datasets findet sich hier).
Hierbei ist darauf zu achten, dass wir das Topic gleich benennen wie in unserem Python-Skript, z.B. «tower/senseHat».
Um die gespeicherten Daten zu sehen, wechseln wir auf «Datasets», wählen das eben erstellte Dataset und führen es mittels Kontext-Menu aus:
In den Menu-Punkten «Details» und «Inhalt» wird die Abfrage quittiert und eine Vorschau des Ergebnisses bestätigt, dass unsere Wetterdaten erfolgreich publiziert und abgespeichert worden sind.
In den Einstellungen im Punkt «Details» können nun noch Zeitplan für eine periodische Ausführung und die Aufbewahrungsdauer der Daten gewählt werden.
Statt in einem nächsten Schritt die Daten mit den integrierten Jupyter Notebooks und Amazon SageMaker weiter zu verarbeiten, lehnen wir uns nun zurück und geniessen den Anblick der Daten, die wir als CSV-File im Menu-Punkt «Inhalt» herunterladen können. Welch eine Augenweide:
9. Online Dashboard
An dieser Stelle enden die meisten Anleitungen zum Thema «Raspberry Pi, Sense HAT und AWS IoT».
Mit gutem Grund: Würde man die Weiterverarbeitung der Daten bis hin zur Visualisierung ins Tutorial miteinschliessen wollen, müssten weitere Themen beschrieben und abgehandelt werden, die nur begrenzt mit IoT zu tun haben und den Umfang dieses Beitrages bei weitem sprengen würden.
Stattdessen möchte ich für all jene, deren Begeisterung sich beim Anblick des obigen CSV-Files in Grenzen hielt, hier das Endresultat meiner weiterführenden Abenteuer mit DynamoDB, Lambda, API-Gateway und charts.js präsentieren und auf mein eigenes Raspberry Pi Sense HAT Dashboard verweisen:
http://casiot.tower.rafenew.world/
10: Sneak Peek: AWS Lambda Function & DynamoDB
Als Bonus hier noch ein Screenshot, wie die finale Lambda-Function mit HTTP API zum Erstellen des Datenfeeds in JSON – basierend auf den in DynamoDB gespeicherten Daten – aufgebaut sein könnte:
Nun wünsche ich viel Spass und Geduld beim Ausprobieren – oder, um es mit den Worten von C-3PO, R2-D2 und MQ-TT zu sagen:
May the Force be with you! ???
Quellen und weiterführende Links
- https://www.raspberrypi.org/
- https://tutorials-raspberrypi.de/raspberry-pi-einstieg-wie-starte-ich/
- https://pythonhosted.org/sense-hat/
- https://www.elektronik-kompendium.de/sites/raspberry-pi/1906281.htm
- https://www.tutonaut.de/anleitung-raspberry-pi-via-vnc-fernsteuern/
- https://www.realvnc.com/de/connect/download/viewer/
- https://www.bitblokes.de/sense-hat-fuer-den-raspberry-pi-was-kann-man-damit-machen/
- Sending Sense Hat data to Amazon (AWS) IoT Service
- https://www.balena.io/blog/use-a-raspberry-pi-to-communicate-with-amazon-aws-iot/
- https://docs.aws.amazon.com/iot/latest/developerguide/iot-moisture-raspi-setup.html
- https://docs.aws.amazon.com/iot/latest/developerguide/create-iot-policy.html
- https://samx18.io/blog/2018/09/05/python3_raspberrypi.html
- https://dujm.github.io/Iot_EdgeComputing/aws_iot.html
- https://github.com/aws/aws-iot-device-sdk-python
- https://stackoverflow.com/questions/41150975/how-to-display-list-of-running-processes-python
- https://aws.amazon.com/de/getting-started/hands-on/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/module-3/
- https://gist.github.com/SeppPenner/6a5a30ebc8f79936fa136c524417761d