Apple HomeKit mit ESP32 - Teil 1

Hello and welcome to my first blog post at AZ-Delivery!

In today's blog, the first part of a new blog series, it's about the topic of home automation with Apple HomeKit. HomeKit is a SmartHome Framework for iOS devices that offers users in a single app access to all smart homes in your home. HomeKit includes the entire development process. An important principle here is that the corresponding smart homes, such as incandescent lamps, thermostats or cameras, can communicate directly via Bluetooth or WLAN with the applicator to be controlled.

HomeKit includes two frameworks for this. The HomeKit Framework for developing own homekit applications on iOS and the HomeKit Accessory protocol for the development of corresponding SmartHome accessories (see the following figure).

HomeKit Framework

The HomeKit Accessory protocol, short HAP, was here as Open Source Project released. The implementation of the HomeKit Accessory protocol will take place on an ESP32, a small and cost-effective microcontroller of Espressif. As a library for implementing the HAP standard, the specifically for the ESP32 and the Arduino IDE developed Homespan library for use. This allows for a few and beneficial components, as well as a reasonable effort to implement various homeKit accessories.

In the following, I will first bring you some foundations of the HomeKit Accessory protocol and then introduce the implementation of a homekit, dimmable LED.

HomeKit Accessory protocol

As already announced, I concentrate in this blog post on the HomeKit Accessory protocol, as the Homekit Framework serves application development to operate its own smart homes. In the following, I explain some theoretical foundations to the HAP, more concrete information on a homekit accessory and the aspect of security in homekit will follow in the second part of this blog series.

The HomeKit Accessory protocol defines the requirements for the device according to the device and the connection to the HomeKit Framework. This is considered the HomeKit Accessory Development Kit, which assumes tasks such as encryption for the developer, so that it can focus on the application logic.

The HAP starts with the definition of the required network transport plane, which include Bluetooth Low Energy and IP based protocols, especially Wi-Fi. For IP based accessories, which also concerns the dimmable LED developed in this blog, some requirements apply. The most important are the simultaneous support of IPv4 and IPv6 connections, the implementation of Bonjour, especially in terms of Multicast DNS services and allow eight simple TCP connections to a HAP Accessory Server. In addition, HAP Server must generate and serialize JavaScript Object Notation, short JSON, in the context of the RFC 7159 Coding and decoding JSON in UTF-8 format. In addition, various safety requirements are defined in the HAP, which I enter more closely in the next blog post. Furthermore, the hap is discussed on the different roles. Here, the HAP Client, that is, usually an iPhone or iPad, always the controller, which requests requests to the HAP Accessory Server, ie the SmartHome device, and receives appropriate status returns. In addition, the client must register and process messages from the HAP server, ie, for example, an update of a color value register and process. Furthermore, the Hap Server HTTP must be compatible, after RFC 7230 and RFC 7231, Be and respond to HTTP requests with corresponding HTTP responses and answers corresponding HTTP status codes.

The next big point in the HAP standard is the data model. This defines how accessories themselves, which are also called profiles and the device generally describe, must be structured. There are accessories from service objects and characteristics, which I will also take more detail in the next part of this blog series. This also applies to the requirements for the setup process, which are treated more in more detail in the next blog post.

Other important requirements, to HOMEKIT Accessory protocol, are the need to be in the same network as the HomeKit Client in the case of a WLAN device, in the case of a possible communication both via WLAN and via Bluetoothle, on both communication channels the same information to provide and not allow firmware downgrades.

Hardware structure

Components and pinouts

For the implementation is required:


Quantity Component Note
1 ESP-32 DEV KIT C V4 Alternatively, other versions of the ESP32 can be used.
1 KY-009 RGB LED SMD Module Sensor Since we do not want to use the LEDs as RGB LED, of course, every simple LED with appropriate forward resistor.
1 Jumper wire cable 3 x 40 pcs. 20 cm M2m / F2M / F2F Raspberry Pi Bre 4 female / female jumper wire are needed. If not available, the specified set recommends.


Below the pin layout of the above mentioned above ESP32:

ESP32 Pinout

Below the PIN layout of the SMD module specified above:

RGB SMD

- Ground
Greens
+ Red
+ Blue

wiring

Fritzing circuit diagram

The following pins must be connected to each other for the circuit structure:

  1. The GND pin of the RGB LED module must be connected to any GND pin of the microcontroller.
  2. The R pin of the RGB LED module must be connected to a GPIO pin of the microcontroller.
  3. The G pin of the RGB LED module must be connected to a GPIO pin of the microcontroller.
  4. The B pin of the RGB LED module must be connected to a GPIO pin of the microcontroller.

Wiring alternative

Fritzing circuit diagram alternatively

For an LED, which is not already soldered with series resistor on a board, care must be taken to the correct wiring. For this purpose, the anode, which should be the longer wire, are connected to the desired GPIO pin and the cathode to the ground. Note is the need for suitable forward resistance. This should usually be calculated according to the LED used after. Alternatively, LEDs are usually suitable for resistances in the range 150 ohms to 220 ohms. It should be considered, however, that too low resistance to an inadmissibly high current and thus can lead to the destruction of the LED.

Software structure

As a library, this project uses the already named "HomeSpan" library for integrating the HomeKit Accessory protocol. In addition, a PWM integration is needed to dim the LED. This can either be implemented as your own itself, or alternatively, the functionality used in Homespan can be used for the control of LEDs by means of PWM. In this example, I will present the latter to make the implementation as clear and easy. The HomeSpan library can be installed via the libraries manager in the Arduino IDE.

The HomeSpan library assumes the implementation of the HomeKit Accessory protocol in the open source variant R2. Above all, the HomeKit data model, ie all accessories provided by Apple, is interesting, including its services and characteristics. Only sound and video devices can not be created due to their increased hardware requirements. Homespan allows a complete programming of the homekit accessories in the Arduino IDE and also offers a command line interface with a high degree of debug information and error messages.

For ordinary structuring, the program is divided into three parts. The first part "Dimmable_LED" corresponds to the main function and takes care of the definition of homeKit accessories and creates objects representing the HAP server of the defined devices. The second part of the program "DEV_Identify.h" is a function for a clearer and faster creation of HomeKit Accessories. This function is transferred to the data of the "Accessory Information Service" as a string, so that the function is then created from these a HomeKit Accessory by calling the corresponding HAP functions. In addition, the visible initialization process required in the HAP is implemented by a flashing LED, which, however, does not find a hardware-side representation in this project. However, you can replace this feature without any problems by connecting an LED in the "dev_identify.h" area defined output PIN for the flashes. In my example, I set this to GPIO 4. When using the above-mentioned LED module, for example, one of the three individually controllable LEDs could be used for the hardware implementation. In the third program section "dev_sensors.h", all other required or optional services of the accessory are defined and also the routine for reading the sensor data, or in the case of actuators, which creates routine for executing the actuator.

In this concrete case, a dimmable LED was integrated. The LED used is dimmed with the help of the PWM functionality of the ESP32. First, the LED receives the Accessory Information Service, which is necessary for each homeKit accessories. This service contains as characteristics the firmware version, an identification routine, a manufacturer, the model name, a name and the serial number. Subsequently, the LED with its corresponding services were implemented in the "DEV_LED.H" area.

For a dimmable LED, there is the POWER service for describing if the LED is turned on or off and a level service that describes the set brightness of the LED. For the Level Service, a start value is determined, which is accepted when the LED is turned on without the brightness is defined. In addition, a work area is set for the LED in which the brightness can be adjusted by the user in the corresponding HomeKit App.

The source code is commented as GitHub Repo To download and try it.

In the following, it is shown again as a source code:

Dimmable_Led.ino:

 /*********************************************************************************
  * With 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
 };
 
 ////////////////////////////////////

configuration

This is the configuration mode of our HomeKit LED, which can be achieved via the serial console in the Arduino IDE. Note is the setting of the correct baud rate.

configuration

By typing a "W", the WLAN can be configured:

configurationHere, the WLAN is now configured and the HomeKit sensor has been connected to the local network, in this case the hotspot of my iPhone. Now this can be added to your home on your iOS device with the standard setup code "466-37-726".

This then looks like this in the home app:

Example app

In the next contribution of this blog series, I will deepen the theoretical foundations of the HomeKit Accessory protocol a bit and bring you closer to the above topics to the accessories and the topic of security. In addition, I will bring you the concept of a Bridge in Homekit. Then a temperature and humidity sensor is reacted.

I hope you have a lot of fun reading!

Esp-32Projects for beginnersSmart home

3 comments

Leon Ehring

Leon Ehring

Hallo Elias,
nein im Normalfall kannst du das ganz normal zu deinem Heimnetzwerk hinzufügen. Dann kannst du das als normales HomeKit Zubehör nutzen.
Die Verbindung mit dem Hotspot des IPhone ist eher ein minimal Beispiel, womit man externe Fehlerquellen ausschließen kann.

Mit freundlichen Grüßen

Carsten

Carsten

Hallo,
Danke erstmal für den Blog Eintrag, musste ich gleich mal ausprobieren :-)
Leider bekomme ich keine Verbindung zu meiner FritzBox (MAC Adressen Filter ist ausgeschaltet) und ich sehe auch keinen Verbindungsaufbauversuch im Log des Routers.
Im Seriellen Monitor habe ich die Credentials eingegeben und der ESP versucht “etwas”, allerdings kommt nur:
E (187432) wifi:AP has neither DSSS parameter nor HT Information, drop it
E (187495) wifi:AP has neither DSSS parameter nor HT Information, drop it
Trying to connect to XXXX. Waiting 2 second(s) for response…
….. wiederholt sich immer wieder
Hat dazu jemand vielleicht eine Idee?
Besten Dank und Grüße!

Elias

Elias

Hallo Leon,
Danke für den Beitrag! Das Thema kannte ich noch nicht und es ist super über diesen Blog darauf zu stoßen direkt mit einer kleinen Implementierung!

Funktioniert das HomeKit Netz nur in den persönlichen Hotspots der Geräte oder kann man die smarten Geräte auch im WLAN der Wohnung anmelden und dann mit einem Apple Geräte welches im gleichen WLAN ist Steuern?

Grüße
Weiter so!

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN