ESP32 IoT SmartConfig WLAN Provisioning Bibliothek
Die große Stärke des ESP32 von Espressif ist das integrierte WLAN Modul. Dadurch eignet sich der Mikrocontroller perfekt für IoT Projekte, weil für die Konnektivität keine zusätzliche Hardware benötigt wird. Mit nur wenigen Zeilen Code kann der ESP32 in ein Netzwerk eingebunden werden. Voraussetzung ist natürlich, dass der Mikrocontroller sowohl die SSID als auch das WLAN Passwort kennt. Aber wie kommt er zu diesen Daten?
Bei Geräten wie Notebooks oder Smartphones gibt man die Zugangsdaten einfach über eine Tastatur ein. Bei sogenannten Headless-Geräten, also Geräten ohne eine Eingabemöglichkeit, braucht man eine andere Methode. Den Vorgang, ein Headless-Gerät in ein WLAN Netzwerk zu bringen, wird im Allgemeinen Provisioning genannt, wobei man zwischen In-band Provisioning und Out-of-band Provisioning unterscheidet. Beim In-band Provisioning wird ausschließlich das WLAN Funknetzwerk verwendet, um die Netzinformationen an das nicht provisionierte Gerät zu senden. Das hat den Vorteil, dass keine zusätzlichen Schnittstellen oder Hardware erforderlich sind. Im Gegensatz dazu wird beim Out-of-band Provisioning ein anderes Medium verwendet. Hier erfolgt die Übertragung entweder kabelgebunden oder drahtlos über ein anderes Funknetz. Das erhöht zwar die Flexibilität, macht das Provisioning aber auch aufwändiger.
Die folgende Liste gibt einen kurzen Überblick über einige auf dem Markt verbreitete Methoden:
In-band Provisioning
- Wi-Fi protected setup (WPS): Von der Wi-Fi Alliance entwickelter Standard zur einfachen Einrichtung eines drahtlosen, lokalen Netzwerks mit Verschlüsselung. Das Ziel von WPS war es, das Hinzufügen von Geräten zu einem bestehenden Netzwerk zu vereinfachen. Er gilt als unsicher und sollte nicht mehr verwendet werden.
- Access point mode: Das nicht provisionierte Gerät gibt sich zunächst als Access Point mit vordefinierter SSID aus. Ein Client kann sich so mit dem Headless-Gerät verbinden, das über einen eingebetteten Webserver eine Seite zum Konfigurieren bereitstellt. Nachdem die Konfiguration abgeschlossen ist, kann sich das Gerät mit dem angegebenen WLAN Netzwerk verbinden.
- SmartConfig: Eine von Texas Instruments entwickelte Methode, um ein neues Gerät mit einem WLAN-Netzwerk zu verbinden. Die Netzwerk-Zugangsdaten werden über ein spezielles Protokoll von einem Client an das unprovisionierte Gerät übertragen.
Out-of-band Provisioning
- USB Interface: Die Zugangsdaten werden über die USB Schnittstelle, beispielsweise via USB-Stick, übertragen. Das setzt natürlich voraus, dass das Gerät einen freien und zugänglichen USB Port besitzt.
- NFC: Der Near Field Communication Übertragungsstandard wird für die Übertragung der Zugangsdaten verwendet. Da der ESP32 diesen Standard nicht unterstützt, ist dies nur mit zusätzlicher Hardware möglich.
- Bluetooth: Die Übertragung erfolgt über den Bluetooth Standard.
Neben diesen Methoden gibt es noch zahlreiche andere Möglichkeiten, die nötigen Zugangsdaten an ein WLAN-fähiges Gerät zu schicken. So können beispielsweise auch Lichtsignale oder Töne als Übertragungsmedium verwendet werden. Mit dem WPA3 Sicherheitsstandard hat die Wi-Fi Alliance ein neues Protokoll namens Wi-Fi Easy Connect, auch Device Provisioning Protocol (DPP) genannt, eingeführt. Damit können Geräte über QR-Codes oder NFC-Tags ins Netzwerk eingebunden werden.
Das SDK von Espressif unterstützt von Haus aus SmartConfig, SoftAP, Bluetooth und Easy Connect. Für meine Projekte verwende ich SmartConfig, da ich die Idee dahinter sehr spannend finde und das Provisioning per Smartphone sehr bequem ist.
SmartConfig
Wie funktioniert nun SmartConfig? Dazu muss man zunächst das eigentliche Problem verstehen. Ein Gerät im verschlüsselten WLAN-Netzwerk möchte einem anderen Gerät die SSID und das Passwort mitteilen. Da aber die Kommunikation ausschließlich verschlüsselt erfolgt, kann das neue Gerät die Nachrichten nicht verstehen. Aber auch wenn das neue Gerät die versendeten Nachrichten nicht entschlüsseln kann, gibt es doch einige Informationen, die für das neue Gerät sichtbar sind. Dazu gehört die MAC Adresse des Senders und Empfängers, sowie der Typ eines Datenpakets. So können alle Pakete ignoriert werden, die nicht von einem bestimmten Typ sind. Die wichtigste sichtbare Information ist die Länge der Datenpakete. Diese ändert sich zwar durch die Verschlüsselung, ist aber für alle Pakete gleich.
Genau darin liegt das Geheimnis von SmartConfig. Statt die Daten direkt zu schicken, werden die Zeichen durch die Länge von Datenpaketen kodiert. Der Inhalt ist egal, da er von dem neuen Gerät sowieso nicht gelesen werden kann. Das sendende Gerät schickt diese Daten so lange per UDP ins Netzwerk, bis das neue Gerät die relevanten Pakete herausgefiltert hat und sich im WLAN anmelden kann. Anschließend schickt es eine Erfolgsmeldung an den Sender, womit der SmartConfig Prozess abgeschlossen ist.
ESP SmartConfig Bibliothek
Die Bibliothek für den ESP32 basiert im Wesentlichen auf dem Code-Beispiel von Espressif. Da aber in dem Code nur der reine Verbindungsaufbau per SmartConfig enthalten ist, habe ich das Beispiel, um das Speichern der Anmeldedaten im Non-volatile storage (NVS) und den normalen Verbindungsaufbau nach dem Provisioning, erweitert. Eine Übersicht des Ablaufs zeigt das folgende Diagramm:
Die SmartConfig Implementierung von Espressif bietet mehrere Protokolle an. Ich verwende ESPTouch v2. Diese Protokoll ermöglicht es, neben SSID und Passwort auch noch reserved data zu übertragen. Damit wird zusätzlich zu den Verbindungsdaten auch noch die Zeitzone übermittelt. Dadurch ist es möglich, mit der Konfiguration eines NTP Servers die aktuelle Uhrzeit des ESP32 zu setzen und über SNTP-Zeitsynchronisierung auch aktuell zu halten. Die Zeitzone wird auch im NVS gespeichert, wodurch bei einem Neustart die Zeit wieder richtig gesetzt wird.
Die Verwendung der Komponente ist denkbar einfach und schaut folgendermaßen aus:
void app_main(){ esp_err_t ret; static wifi_conf_t wifi_conf = { .aes_key = "ESP32EXAMPLECODE", .hostname = "ESP32", .ntp_server = "pool.ntp.org", }; wifi_t *smartconfig = wifi_new_smartconfig(&wifi_conf); if (smartconfig->init(smartconfig) == ESP_OK) { do { ret = smartconfig->connect(smartconfig); } while (ret != ESP_OK); smartconfig->init_sntp(smartconfig); smartconfig->init_timezone(smartconfig); } }
Aber wie werden die Daten an den ESP32 verschickt? Auch dafür bietet Espressif eine fertige Lösung in Form von Smartphone Apps an. Auf GitHub gibt es den Source Code für Android und iOS. Die folgenden zwei Screenshots zeigen, wie einfach man damit den ESP32 in ein WLAN bringen kann:
Abschließend noch einige Worte zur Sicherheit dieser Lösung. Natürlich dürfen die Zugangsdaten nicht einfach im Klartext verschickt werden, da sonst theoretisch eine dritte Person die Daten abfangen könnte. Aus diesem Grund werden die übertragenen Daten mit dem AES Verschlüsselungsverfahren abgesichert. Den dazu nötigen AES-Schlüssel dürfen nur der Sender und der Empfänger kennen. Bei einem kommerziellen Produkt muss man daher unbedingt dafür sorgen, dass der Schlüssel nicht aus dem ESP32 ausgelesen werden kann. Dazu eignet sich Secure Boot V2, womit der ESP32 gegen den Zugriff von außen abgesichert werden kann. Wie schwierig diese Absicherung ist, zeigt dieses YouTube Video sehr eindrucksvoll.
Den kompletten Source Code der ESP32 Komponente gibt es auf GitHub. Über Feedback oder Verbesserungsvorschläge würde ich mich sehr freuen.