Apple HomeKit mit ESP32 - Teil 1 (2023)

Hallo und Willkommen zu meinem ersten Blogbeitrag bei AZ-Delivery!

Im heutigen Blog, dem ersten Teil einer neuen Blog Serie, geht es um das Thema der Hausautomatisierung mit Apple HomeKit. HomeKit ist hierbei ein Smarthome Framework für iOS-Geräte, welches den Benutzern in einer einzigen App Zugriff auf alle Smarthomegeräte in ihrem Zuhause bietet. HomeKit umfasst hierbei den gesamten Entwicklungsprozess. Ein wichtiger Grundsatz hierbei ist, dass die entsprechenden Smarthomegeräte, wie zum Beispiel Glühlampen, Thermostate oder Kameras, direkt über Bluetooth oder WLAN mit dem zu steuernden Applegerät kommunizieren können.

HomeKit umfasst hierfür zwei Frameworks. Das HomeKit Framework zur Entwicklung von eigenen HomeKit Applikationen auf iOS und das HomeKit Accessory Protokoll für die Entwicklung von entsprechendem Smarthome Zubehör (siehe folgende Abbildung).

Apple HomeKit mit ESP32 - Teil 1 (1)

Das HomeKit Accessory Protokoll, kurz HAP, wurde hierbei als Open Source Projekt veröffentlicht. Die Implementation des HomeKit Accessory Protokoll findet hierbei auf einem ESP32, einem kleinen und kostengünstigen Mikrocontroller der Firma Espressif, statt. Als Bibliothek zur Implementation des HAP Standards kommt die speziell für den ESP32 und die Arduino IDE entwickelte HomeSpan Bibliothek zum Einsatz. Dies ermöglicht mit wenigen und günstigen Bauteilen, sowie einem vertretbaren Aufwand, verschiedene HomeKit Accessories umzusetzen.

Im Folgenden werde Ich Ihnen zuerst einige Grundlagen des HomeKit Accessory Protokolls näher bringen und anschließend die Umsetzung einer HomeKit fähigen, dimmbaren LED vorstellen.

HomeKit Accessory Protokoll

Wie bereits angekündigt konzentriere ich mich in diesem Blog Beitrag auf das HomeKit Accessory Protokoll, da das HomeKit Framework der Anwendungsentwicklung zur Bedienung der eigenen Smarthomegeräte dient. Im Folgenden erläutere ich einige theoretische Grundlagen zu dem HAP, konkretere Informationen zu einem HomeKit Accessory und dem Aspekt der Sicherheit in HomeKit werden im zweiten Part dieser Blog Reihe folgen.

Das HomeKit Accessory Protokoll definiert hierbei die Anforderungen an das entsprechend zu entwickelnde Gerät und die Anbindung an das HomeKit Framework. Berücksichtigt wird hierbei das HomeKit Accessory Development Kit, welches Aufgaben wie die Verschlüsselung für den Entwickler übernimmt, so dass dieser sich auf die Anwendungslogik konzentrieren kann.

Das HAP startet hierbei mit der Definition der geforderten Netzwerktransportebene, welche Bluetooth Low Energy und IP basierte Protokolle, vor allem WLAN, umfassen. Für IP basierte Accessories, welche auch die im Rahmen dieses Blogs entwickelte dimmbare LED betrifft, gelten einige Anforderungen. Die wichtigsten sind hierbei der gleichzeitige Support von IPv4 und IPv6 Verbindungen, die Implementation von Bonjour, vor allem in Bezug auf Multicast DNS Dienste und das Zulassen von acht zeitgleichen TCP Verbindungen auf einen HAP Accessory Server. Zusätzlich müssen HAP Server die Generierung und Serialisierung von JavaScript Object Notation, kurz JSON, im Rahmen des RFC 7159 beherrschen und JSON im UTF-8 Format codieren und decodieren. Zudem werden im HAP diverse Sicherheitsanforderungen definiert, auf welche ich im nächsten Blogbeitrag noch genauer eingehe. Weiterhin wird im HAP auf die verschiedenen Rollen eingegangen. Hierbei ist der HAP Client, also in der Regel ein iPhone oder iPad, immer der Controller, welcher Anfragen an den HAP Accessory Server, also das Smarthome Gerät, sendet und entsprechende Statusrückmeldungen erhält. Außerdem muss der Client Nachrichten vom HAP Server registrieren und verarbeiten, also zum Beispiel eine Aktualisierung eines Farbwertes registrieren und verarbeiten. Des Weiteren muss der HAP Server HTTP kompatibel, nach RFC 7230 und RFC 7231, sein und auf HTTP Anfragen mit entsprechenden HTTP Antworten und entsprechenden HTTP Status Codes antworten können.

Der nächste große Punkt im HAP Standard ist das Datenmodell. Dieses definiert, wie Accessories selbst, welche auch als Profile bezeichnet werden und das Gerät generell beschreiben, strukturiert sein müssen. Hierzu bestehen Accessories aus Service Objekten und Charakteristiken, auf welche ich ebenfalls im nächsten Teil dieser Blog Serie noch näher eingehen werde. Dies betrifft auch die Anforderungen an den Setup Prozess, welche im nächsten Blogbeitrag genauer behandelt werden.

Weitere wichtige Anforderungen, an HomeKit Accessory Protokoll entsprechende Geräte, sind im Falle eines WLAN Gerätes die Notwendigkeit, sich im selben Netzwerk wie der HomeKit Client zu befinden, im Falle einer möglichen Kommunikation sowohl über WLAN, als auch über BluetoothLE, auf beiden Kommunikationswegen dieselben Informationen zur Verfügung zu stellen und keine Firmware Herabstufungen zu erlauben.

Hardwareaufbau

Bauteile und Pinouts

Für die Umsetzung wird benötigt:

AnzahlBauteilAnmerkung
1ESP-32 Dev Kit C V4Als Alternative können auch andere Versionen des ESP32 genutzt werden.
1KY-009 RGB LED SMD Modul SensorDa wir die LEDs nicht als RGB LED nutzen möchten, geht natürlich auch jede einfache LED mit entsprechendem Vorwiderstand.
1Jumper Wire Kabel 3 x 40 STK. je 20 cm M2M/ F2M / F2F Raspberry Pi BreEs werden 4 female / female Jumper Wire benötigt. Falls nicht vorhanden empfiehlt sich das angegebene Set.


Nachfolgend das Pin Layout des oben angegeben ESP32:

Apple HomeKit mit ESP32 - Teil 1 (2)

Nachfolgend das Pin Layout des oben angegebenen SMD Moduls:

Apple HomeKit mit ESP32 - Teil 1 (3)

- Ground
+ Grün
+ Rot
+ Blau

Verdrahtung

Apple HomeKit mit ESP32 - Teil 1 (4)

Für den Schaltungsaufbau müssen folgende Pins miteinander verbunden werden:

  1. Der GND Pin des RGB LED Moduls muss mit einem beliebigen GND Pin des Mikrocontrollers verbunden werden.
  2. Der R Pin des RGB LED Moduls muss mit einem GPIO Pin des Mikrocontrollers verbunden werden.
  3. Der G Pin des RGB LED Moduls muss mit einem GPIO Pin des Mikrocontrollers verbunden werden.
  4. Der B Pin des RGB LED Moduls muss mit einem GPIO Pin des Mikrocontrollers verbunden werden.

Verdrahtung Alternativ

Apple HomeKit mit ESP32 - Teil 1 (5)

Bei einer LED, welche nicht bereits mit Vorwiderstand auf einer Platine verlötet ist, muss auf die korrekte Verdrahtung geachtet werden. Hierzu müssen die Anode, welche der längere Draht sein sollte, an den gewünschten GPIO Pin angeschlossen werden und die Kathode an den Ground. Zu beachten ist die Notwendigkeit eines passenden Vorwiderstandes. Dieser sollte in der Regel passend zu der verwendeten LED nach berechnet werden. Als Alternative eignen sich für LEDs in der Regel Vorwiderstände im Bereich 150 Ohm bis 220 Ohm. Zu bedenken ist hierbei allerdings, dass ein zu geringer Vorwiderstand zu einem unzulässig hohen Strom und somit zur Zerstörung der LED führen kann.

Softwareaufbau

Als Bibliothek kommt in diesem Projekt die bereits benannte „HomeSpan“ Bibliothek zur Integration des HomeKit Accessory Protokolls zum Einsatz. Außerdem wird zum dimmen der LED eine PWM-Integration benötigt. Diese kann entweder beliebig selbst implementiert werden, oder alternativ kann die in HomeSpan verwendete Funktionalität für die Ansteuerung von LEDs mittels PWM genutzt werden. In diesem Beispiel werde ich letzteres präsentieren, um die Umsetzung möglichst übersichtlich und einfach zu gestalten. Die HomeSpan Bibliothek kann hierbei über den Bibliotheken Manager in der Arduino IDE installiert werden.

Die HomeSpan Bibliothek übernimmt die Implementierung des HomeKit Accessory Protokoll in der Open Source Variante R2. Hierbei ist vor allem das HomeKit Daten Modell, also alle von Apple vorgesehenen Accessories inklusive ihrer Services und Charakteristiken interessant. Einzig Sound- und Videogeräte können aufgrund ihrer erhöhten Hardwareanforderungen nicht erstellt werden. HomeSpan ermöglicht eine komplette Programmierung des HomeKit-Zubehörs in der Arduino IDE und bietet ebenfalls ein Kommandozeileninterface mit einem hohen Maß an Debug-Informationen und Fehlermeldungen.

Zur ordentlichen Strukturierung ist das Programm in drei Teile aufgeteilt. Der erste Teil „dimmable_LED“ entspricht der main Funktion und kümmert sich um die Definition der HomeKit Accessories und erstellt Objekte, welche den HAP Server der definierten Geräte repräsentieren. Der zweite Teil des Programms „DEV_Identify.h“ ist eine Funktion zur übersichtlicheren und schnelleren Erstellung von HomeKit Accessories. Dieser Funktion übergibt man die Daten des “Accessory Information Service” als String, so dass die Funktion anschließend aus diesen ein HomeKit Accessory erstellt, indem sie die entsprechen HAP Funktionen aufruft. Außerdem wird der im HAP geforderte sichtbare Initialisierungsprozess durch eine blinkende LED umgesetzt, die in diesem Projekt allerdings keine Hardwareseitige Repräsentation findet. Sie können diese Funktion allerdings ohne Probleme durch den Anschluss einer LED im Bereich „DEV_Identify.h“ definierten Output Pin für die Blinks umsetzten. In meinem Beispiel habe ich diesen auf GPIO 4 gesetzt. Bei der Verwendung des oben genannten LED Moduls könnte für die Hardwareumsetzung zum Beispiel eine der drei einzeln ansteuerbaren LEDs dienen. Im dritten Programmteil „DEV_Sensors.h“ werden alle anderen benötigten oder optionalen Services des Accessory definiert und außerdem die Routine zum Auslesen der Sensordaten, oder im Falle von Aktoren, die Routine zum Ausführen des Aktors erstellt.

In diesem konkreten Fall wurde eine dimmbare LED integriert. Die verwendete LED wird mit Hilfe der PWM-Funktionalität des ESP32 gedimmt. Als erste erhält die LED den Accessory Information Service, welcher für jedes HomeKit Zubehör notwendig ist. Dieser Service enthält als Charakteristiken die Firmware Version, eine Identifizierungsroutine, einen Hersteller, die Modellbezeichnung, einen Namen und die Seriennummer. Anschließend wurden im Bereich „DEV_LED.h“ die LED mit ihren entsprechenden Services implementiert.

Bei einer dimmbaren LED gibt es den Power Service zur Beschreibung, ob die LED eingeschaltet oder ausgeschaltet ist und einen Level Service, welcher die eingestellte Helligkeit der LED beschreibt. Für den Level Service wird ein Startwert festgelegt, welche angenommen wird, wenn die LED eingeschaltet wird, ohne dass die Helligkeit fest definiert wird. Außerdem wird für die LED ein Arbeitsbereich festgelegt, in welchem die Helligkeit vom Nutzer in der entsprechenden HomeKit App eingestellt werden kann.

Der Quellcode ist kommentiert als GitHub Repo zum Runterladen und ausprobieren vorhanden.

Im Folgenden ist er nochmal als Quelltext dargestellt:

Dimmable_LED.ino:

/*********************************************************************************
* MIT License
*
* Copyright (c) 2020 Gregg E. Berman
*
* https://github.com/HomeSpan/HomeSpan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
********************************************************************************/

#include "HomeSpan.h"
#include "DEV_LED.h"
#include "DEV_Identify.h"

void setup() {

Serial.begin(115200);

homeSpan.begin(Category::Lighting,"HomeSpan LED");

// Create an Dimmable LED attached to pin 16
new SpanAccessory();
new DEV_Identify("Dimmable LED","AZ-Delivery","123-ABC","LED","0.9",0);
new Service::HAPProtocolInformation();
new Characteristic::Version("1.1.0");
new DEV_DimmableLED(16);

} // end of setup()

//////////////////////////////////////

void loop(){

homeSpan.poll();

} // end of loop()

DEV_Identify.h:


//////////////////////////////////
// DEVICE-SPECIFIC SERVICES //
//////////////////////////////////

struct DEV_Identify : Service::AccessoryInformation {

int nBlinks; // number of times to blink built-in LED in identify routine
SpanCharacteristic *identify; // reference to the Identify Characteristic

DEV_Identify(const char *name, const char *manu, const char *sn, const char *model, const char *version, int nBlinks) : Service::AccessoryInformation(){

new Characteristic::Name(name); // create all the required Characteristics with values set based on above arguments
new Characteristic::Manufacturer(manu);
new Characteristic::SerialNumber(sn);
new Characteristic::Model(model);
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below

this->nBlinks=nBlinks; // store the number of times to blink the LED

pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}

boolean update(){

for(int i=0;i<nBlinks;i++){
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

return(true); // return true

} // update

};

DEV_LED.h:


////////////////////////////////////
// DEVICE-SPECIFIC LED SERVICES //
////////////////////////////////////

// library of various PWM functions
#include "extras/PwmPin.h"

////////////////////////////////////

// Dimmable LED
struct DEV_DimmableLED : Service::LightBulb {

// reference to Led Pin
LedPin *ledPin;
// reference to the On Characteristic
SpanCharacteristic *power;
// reference to the Brightness Characteristic
SpanCharacteristic *level;

// constructor() method
DEV_DimmableLED(int pin) : Service::LightBulb(){

power=new Characteristic::On();

// Brightness Characteristic with an initial value of 50%
level=new Characteristic::Brightness(50);
// sets the range of the Brightness to be from a min of 5%, to a max of 100%, in steps of 1%
level->setRange(5,100,1);

// configures a PWM LED for output to the specified pin
this->ledPin=new LedPin(pin);

// initialization message
Serial.print("Configuring Dimmable LED: Pin=");
Serial.print(ledPin->getPin());
Serial.print("\n");

} // end constructor

// update() method
boolean update(){

// displays information about what is updated
LOG1("Updating Dimmable LED on pin=");
LOG1(ledPin->getPin());
LOG1(": Current Power=");
LOG1(power->getVal()?"true":"false");
LOG1(" Current Brightness=");
LOG1(level->getVal());

if(power->updated()){
LOG1(" New Power=");
LOG1(power->getNewVal()?"true":"false");
}

if(level->updated()){
LOG1(" New Brightness=");
LOG1(level->getNewVal());
}

LOG1("\n");

// updates the actual PWM Pin
ledPin->set(power->getNewVal()*level->getNewVal());

return(true);

} // update
};

////////////////////////////////////

Konfiguration

Dies ist der Konfigurationsmodus unserer HomeKit LED, welche über die serielle Konsole in der Arduino IDE erreicht werden kann. Zu beachten ist die Einstellung der korrekten Baud Rate.

Apple HomeKit mit ESP32 - Teil 1 (6)

Durch eintippen eines „W“ kann das WLAN konfiguriert werden:

Apple HomeKit mit ESP32 - Teil 1 (7)Hier ist das WLAN nun konfiguriert und der HomeKit Sensor hat sich mit dem lokalen Netzwerk, in diesem Fall dem Hotspot meines iPhones, verbunden. Nun kann dieser an Ihrem iOS-Gerät mit dem Standardsetup Code „466-37-726“ zu ihrem Home hinzugefügt werden.

Dies sieht dann zum Beispiel so in der Home App aus:

Apple HomeKit mit ESP32 - Teil 1 (8)

Im nächsten Beitrag dieser Blogreihe werde ich die theoretischen Grundlagen zum HomeKit Accessory Protokoll noch etwas vertiefen und Ihnen die oben genannten Themen zu den Accessories und dem Thema Sicherheit näher bringen. Außerdem werde ich Ihnen das Konzept einer Bridge in HomeKit etwas näher bringen. Umgesetzt wird dann ein Temperatur- und Luftfeuchtigkeitssensor.

Ich hoffe Sie haben viel Spaß beim Nachbauen!

Hier geht's weiter: Teil 2

References

Top Articles
Latest Posts
Article information

Author: Saturnina Altenwerth DVM

Last Updated: 13/11/2023

Views: 5586

Rating: 4.3 / 5 (44 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Saturnina Altenwerth DVM

Birthday: 1992-08-21

Address: Apt. 237 662 Haag Mills, East Verenaport, MO 57071-5493

Phone: +331850833384

Job: District Real-Estate Architect

Hobby: Skateboarding, Taxidermy, Air sports, Painting, Knife making, Letterboxing, Inline skating

Introduction: My name is Saturnina Altenwerth DVM, I am a witty, perfect, combative, beautiful, determined, fancy, determined person who loves writing and wants to share my knowledge and understanding with you.