IoT-Stimmungslicht mit ESP8266 steuerbar über Internet via iOS-App
Written by Bastian Raschke.
Published 2016-08-31 in the category Smart Home.
Available translations: en
In meinem letzten Artikel habe ich bereits ein cooles RGB-Stimmungslicht mit einem Raspberry Pi und einer Web-App realisiert. Allerdings hat es mich im täglichen Gebrauch gestört, dass immer ein komplettes Linux auf dem Pi läuft, dabei unnötig 5 Watt verbraucht und das System auch nicht ohne schlechtes Gewissen schnell mal aus der Steckdose gezogen werden kann, ohne korrektes Herunterfahren. Und natürlich hat das Booten auch ca. 30-40 Sekunden gedauert. Alles in allem nicht so mega praxistauglich. Aber dann habe ich den ESP8266 kennengelernt.
ESP8266 - perfekt für IoT
Der ESP8266 war für mich anfänglich nur ein Bauteil, mit dem ich einen Arduino an WLAN anbinden kann. Nach meinen weiteren Nachforschungen und Tests habe ich dann erfahren, dass dieses kleine beliebte Bauteil, dass es bei Ebay für 3-8€ zu kaufen gibt, völlig autonom ohne einen Arduino läuft. Und das Beeindruckende dabei ist, dass der ESP8266 trotz des geringen Preisen viel mehr Leistung als ein kompletter Arduino hat! Satte 1 Megabyte (!) Flash-Speicherplatz stehen für das eigene Programm zur Verfügung (statt nur 32 Kilobyte). Der ESP8266 taktet weiterhin mit 80 MHz und nicht mir 16MHz oder weniger. Und eben das WLAN-Feature gibt es einfach mal dazu. Und bei dem erwähnten Preis ein wahres IoT-Wunder.
Die Krönung des Glücks ist die Tatsache, dass es die Community geschafft hat, den ESP8266 direkt mit der Arduino IDE programmierbar zu machen. Die Einstiegshürden sind also sehr niedrig. Den ESP8266 gibt es in x Ausführungen - ich habe mich für eine Platine entschieden, die einen Seriellwandler und die Spannungsversorgung bereits an Bord hat, sodass die Platine direkt per Micro-USB versorgt und programmiert werden kann. Die „NodeMCU“ genannte Platine gibt es mit mehreren USB-Seriell-Wandlern, ich habe mich für die etwas teurere CP2102-Variante entschieden, da ich mit diesem Chip bisher immer gute Erfahrung hatte.
ESP8266 als NodeMCU mit CP2102 für ca. 7€
Vernetzt mit MQTT
Nun hatte ich die perfekte Plattform für ein vernetztes VibeLight 2.0. Nun fehlte mir noch ein geeignetes, schmalspuriges Kommunikationsprotokoll. Ich wollte, dass die ESP8266s mit einem Push-Verfahren sofort über eine Änderung informiert werden (um das Licht zu schalten). Anfänglich bin ich zwischen HTTP als Polling-Lösung und Websockets mit nativerem Echtzeit-Push beschwankt. Beides war aber nicht das Gelbe vom Ei. Glücklicherweise habe ich dann von dem MQTT-Protokoll erfahren, dass für IoT-Anwendungen entwickelt wurde und extrem leichtgewichtig ist (also fast keinen Overhead produziert).
Das Protokoll ist derart leichtgewichtig, dass eine Änderung innerhalb von unter einer Sekunde abgewickelt ist - und trotz dass der Broker im öffentlichen Internet steht. Was mich besonders beeindruckt hat, dass dies selbst bei mobilem Internet mit langsamen EDGE (2G) im gleichen Zeitrahmen möglich ist! Bei MQTT können sich N Geräte auf beliebige Channels subscriben oder darauf publishen. Ein zentraler Server (Broker) verwaltet alle Operationen. Der Broker wickelt auch weiterhin die Benutzerauthentifizierung ab. Ich nutze die freie MQTT-Server-Implementierung Mosquitto, die leistungsfähig und detailliert konfigurierbar ist. Für Arduino bzw. den ESP8266 gibt es einige MQTT-Bibliotheken, wobei ich mich für die PubSubClient-Bibliothek von Nick O'Leary entschieden habe.
Eine weitere Vorraussetzung war es für mich als sicherheitsbewussten Entwickler natürlich, dass die Verbindung zwischen dem Broker und den Geräten verschlüsselt erfolgt. Doch auch hierfür dank der Community bereits eine Lösung, sodass Verbindungen seitens des ESP8266 mit TLS 1.1 abgesichert werden können. Dabei musste ich die oben erwähnte PubSubClient-Bibliothek minimal verändern, sodass der Fingerprint des TLS-Zertifikats auch verifiziert wird - ansonsten wären MITM-Angriffe problemlos möglich.
Beliebig viele vernetzte Lichtaktoren
Dadurch dass sich N Clients auf dem gleichen Channel subcriben können, ist es möglich, nahezu unbegrenzt viele Lichtaktoren in seiner Wohnung aufzustellen. Wenn man auf einen Channel published (z.B. welche Lichtszene man wünscht), erhalten sofort an alle Clients, die auf dem Channel subcribed sind, die Nachricht, ihre Lichtszene zu ändern. Ich habe die Firmware in der Art geschrieben, dass sowohl Lichtstreifen für indirekte Beleuchtung als auch z.B. Lampen mit weniger LEDs möglichst gleich cool aussehen. Es gibt verschiedene Lichtszenen (z.B. Farbverlauf, halbierte Farben): die Lichtszene definiert lediglich in welchem Muster die LEDs geschaltet werden, die eigentlichen Farben sind jedesmal frei setzbar ohne eine Firmwareänderung.
Aufbau der Hardware
Ich habe zwei Lichtaktoren gebaut: Meine bestehende Lichtleiste wurde umgerüstet und zusätzlich habe ich noch eine Ikea Fado-Lampe umgerüstet mit dem VibeLight 2.0-System. So sehen die Komponenten aus:
Umgerüstete Lichtleiste und umgebaute Ikea Fado-Lampe mit VibeLight 2.0
Die geöffnete Hardware der Ikea Fado-Lampe:
Innenleben der umgebaute Ikea Fado-Lampe
Das Innenleben der Lichtleiste:
Innenleben der umgerüsteten Lichtleiste und absteckbare Lichtleiste
Beide Lichter verwenden nahezu die identische Platine, wobei ich bei der Lichtleiste ja bereits aus Version 1 ein 1000µF-Kondensator verbaut war, weswegen dieser auf der Platine nicht angelötet wurde. Hier seht ihr hingegen die vollausgestattete Platine mit dem Kondensator:
Die Platine von VibeLight 2.0 im Vollausbau
Einrichtung von Mosquitto
Zunächst installiert ihr Mosquitto:
~# apt-get install mosquitto
TLS-Zertifikate erzeugen
Zunächst erzeugt ihr einen Schlüssel und Zertifikat für eure Zertifizierungsstelle (CA). Dies ist leider nötig:
~# echo "01" > "/etc/mosquitto/ca_serial.txt"
~# openssl ecparam -genkey -name prime256v1 -noout -out "/etc/mosquitto/ca.key" -outform PEM
~# openssl req -new -x509 -days 3650 -subj "/CN=VibeLight 2.0 CA" -key "/etc/mosquitto/ca.key" -out "/etc/mosquitto/ca.crt" -outform PEM
Nun erzeugt ihr den Schlüssel und das Zertifikat für eure eigentliche Server-Domain:
~# openssl ecparam -genkey -name prime256v1 -noout -out "/etc/mosquitto/mqtt.sicherheitskritisch.key" -outform PEM
~# openssl req -new -subj "/CN=mqtt.sicherheitskritisch.de" -key "/etc/mosquitto/mqtt.sicherheitskritisch.key" -out "/etc/mosquitto/mqtt.sicherheitskritisch.csr"
~# openssl x509 -req -days 3650 -CA "/etc/mosquitto/ca.crt" -CAkey "/etc/mosquitto/ca.key" -CAserial "/etc/mosquitto/ca_serial.txt" -in "/etc/mosquitto/mqtt.sicherheitskritisch.csr" -out "/etc/mosquitto/mqtt.sicherheitskritisch.crt"
Wichtig: Der Wert mqtt.sicherheitskritisch.de
in den Befehlen ist natürlich beispielhaft für meinen Server gedacht und muss jeweils an eure Gegebenheiten angepasst werden.
Nun wollen wir für einen späteren Schritt noch den SHA1-Fingerprint eueres Zertifikates ausgeben:
~$ openssl x509 -in /etc/mosquitto/mqtt.sicherheitskritisch.crt -outform DER | sha1sum | cut -c 1-42 | fold -w 2 | paste -s -d ' '
Der Befehl sollte etwas in der folgenden Art ausgeben:
57 36 77 fe e4 3e a9 ae c2 3c 33 dc 60 82 56 18 18 4d 60 50
Konfiguration anpassen
Nun wird direkt die Konfiguration /etc/mosquitto/mosquitto.conf
wie folgt geändert:
bind_address mqtt.sicherheitskritisch.de
port 8883
pid_file /var/run/mosquitto.pid
log_dest file /var/log/mosquitto/mosquitto.log
persistence true
persistence_location /var/lib/mosquitto/
cafile /etc/mosquitto/ca.crt
certfile /etc/mosquitto/mqtt.sicherheitskritisch.crt
keyfile /etc/mosquitto/mqtt.sicherheitskritisch.key
## The cipher "AES256-SHA" is the highest cipher that the ESP8266 supports
ciphers ECDHE-RSA-AES256-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-SHA
## The ESP8266 supports only TLS 1.1 or below
tls_version tlsv1.1
allow_anonymous false
password_file /etc/mosquitto/passwd
## Include other configurations /etc/mosquitto/conf.d/*.conf
include_dir /etc/mosquitto/conf.d
Bei der Angabe bind_address
müsst ihr natürlich die IP-Adresse oder Domain eures Servers angeben. Weiterhin muss bei certfile
und keyfile
der Pfad zu eurem TLS-Zertifikat bzw. Schlüssel angepasst werden.
Dann werden 2 spätere Benutzerzugänge angelegt:
~# mosquitto_passwd -U /etc/mosquitto/passwd bastian
~# mosquitto_passwd -U /etc/mosquitto/passwd device_abcdefghijklm
Der erste Benutzer bastian
wird später in der App verwendet, der Benutzer device_abcdefghijklm
wird euer erster Lichtaktor sein. Vergebt jeweils unterschiedliche Passwörter für die Benutzer.
Abschließend kann Mosquitto neugestartet werden:
~# systemctl restart mosquitto
Flashen der Firmware
Die Firmware wird per Arduino IDE auf den ESP8266 geflasht. Wie ihr die Arduino IDE für die ESP8266-Hardware nutzbar macht, ist im Internet an vielen Stellen zu lesen, weswegen ich dies hier nicht erneut erläutern werde. Für den NodeMCU habe ich in der Arduino-IDE die folgende Flash-Konfiguration genutzt:
Wert | |
---|---|
Platine: | NodeMCU 1.0 (ESP-12E Module) |
CPU Frequency: | 80 Mhz |
Flash Size: | 4M (1M SPIFFS) |
Upload Speed: | 115200 |
Aber bevor ihr die Firmware flasht, müsst ihr noch einige Werte in der Firmware an eure Gegebenheiten anpassen:
#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
#define MQTT_CLIENTID "Vibelight Device 1.0 xxxxxxxxxxxxx"
#define MQTT_SERVER "mqtt.sicherheitskritisch.de"
#define MQTT_SERVER_TLS_FINGERPRINT "57 36 77 fe e4 3e a9 ae c2 3c 33 dc 60 82 56 18 18 4d 60 50"
#define MQTT_PORT 8883
#define MQTT_USERNAME "device_abcdefghijklm"
#define MQTT_PASSWORD "YOUR_MQTT_PASSWORD"
...
#define NEOPIXELS_COUNT 60
Zunächst müsst ihr bei WIFI_SSID
und WIFI_PASSWORD
eure korrekten WLAN-Zugangsdaten eintragen, damit der ESP8266 mit dem Internet kommunizieren kann. Bei MQTT_CLIENTID
solltet ihr die x-Platzhalter gegen eine beliebige alphanumerische Zeichenkette austauschen. Bei MQTT_SERVER
müsst ihr die öffentlich erreichbare Adresse eures MQTT-Brokers angeben. Mit der Angabe MQTT_SERVER_TLS_FINGERPRINT
erfolgt der mit Leerzeichen getrennte SHA1-Fingerprint des TLS-Zertifikates eures Servers (diesen haben wir uns bei der Zertifikatserstellung bereits ausgeben lassen). Und natürlich müsst ihr bei MQTT_USERNAME
und MQTT_PASSWORD
die korrekten MQTT-Benutzerdaten eingeben, damit sich eurer Gerät dem Server gegenüber authentisieren kann.
Wichtig: Für jedes Gerät muss ein unterschiedlicher MQTT-Benutzer sowie eine eigene Client-ID genutzt werden, wenn beide Geräte parallel funktionieren sollen! Ansonsten funktioniert die Anmeldung auf beiden Geräten nicht!
Und abschließend tragt ihr bei NEOPIXELS_COUNT
die Anzahl der verwendeten LEDs eures Lichtaktors ein.
Erster Funktionstest
Wenn das Flashen abgeschlossen ist, dann könnt ihr euren Lichtaktor nun testen. Ich empfehle das Aktivieren des seriellen Monitors um eventuell auftretende Fehler (z.B. falsche Benutzerdaten) nachvollziehen zu können. Ich empfehle euch auf euren Rechner das Paket mosquitto-clients
zu installieren, damit ihr das Kommandozeilenprogramm mosquitto_pub
zum testen nutzen könnt:
~$ mosquitto_pub -h mqtt.sicherheitskritisch.de -p 8883 \
-u "YOUR_MQTT_USERNAME" \
-P "YOUR_MQTT_PASSWORD" \
--tls-version tlsv1.1 \
--cafile /path/to/ca.crt \
-t '/vibelight/api/1.0/' \
-m '2A92CCECE2C2C'
Mit diesem Befehl sendet ihr an alle angeschlossenen VibeLight-Geräte den Befehl, Lichtscene 2 (halbierte Farben) mit den beiden Farben 0xA92CCE und 0xCE2C2C anzuzeigen (Parameter -m
mit 2A92CCECE2C2C).
Wichtig: Wie immer müsst ihr natürlich die Adresse eures Brokers anpassen und bei --cafile
müsst ihr dieselbe Datei /etc/mosquitto/ca.crt
nutzen, die bei dem „TLS-Zertifikate erzeugen“-Schritt erstellt wurde.
iOS-App installieren
Zunächst müsst ihr „Cocoapods“ installiert haben (die Installation sollte auf der Herstellerseite beschrieben sein). Mit eurem Xcode (ich habe mit Version 7.3.1 gearbeitet) öffnet ihr das Projekt VibeLight.xcworkspace
. Vermutlich müsst ihr dann noch euer Entwicklerzertifikat für das Projekt konfigurieren. Und dann solltet ihr die App auf euer iOS-Gerät überspielen und starten können.
Notwendige Anpassungen
Einige Werte in der App sind zurzeit noch hardkodiert:
- Die IP-Adresse/Domain des MQTT-Brokers in der Datei
MQTTConnection.swift
- Das Root-Zertifikat der CA (aktuell die Datei
VibeLight/Resources/KlosterTrust_Root_CA.crt
) und referenziert ebenfalls in der DateiMQTTConnection.swift
. Hier müsst ihr dieselbe Datei/etc/mosquitto/ca.crt
nutzen, die bei dem „TLS-Zertifikate erzeugen“-Schritt erstellt wurde.
Beide Werte müsst ihr natürlich anpassen an eure Gegebenheiten.
Die Constraints in dem SettingsViewController
nicht korrekt gesetzt, sodass die Eingabefelder nicht in der Mitte ausgerichtet sind. Da ich aber gerade kein MacBook zur Verfügung habe, lässt sich das nicht ändern ;-)
Folgend seht ihr ein paar Screens der App:
Viel Spaß mit dem Projekt :-)
Quellcode auf Github
Der Quellcode kann via Github bezogen werden:
Tags: LED, WS2812B, ESP8266, DIY, Internet of Things, IOT, MQTT