Como ya mencioné en la primera parte del blog, en esta ocasión me enfocaré primero en algunos fundamentos más teóricos. Luego implementaré un sensor de temperatura y humedad.
Accesorios
Básicamente, el HAP distingue entre puentes y accesorios, por lo que un puente puede combinar hasta 150 accesorios y llevarlos a HomeKit con una sola conexión. Como ejemplo, puede nombrar cualquier puente Zigbee que transfiere todos los productos ZigBee a la red de Homekit añadiendo solo el puente al HomeKit.
Cada accesorio de HomeKit está definido por el modelo de datos de HomeKit, que consiste en accesorios, servicios y características. Además, el HAP define cómo generar el código de configuración de 8 dígitos necesario para la conexión inicial. Esto se debe realizar en el dispositivo en cada configuración inicial, independientemente de los datos únicos del dispositivo, o bien de forma aleatoria para cada dispositivo en la producción, en cuyo caso el código se debe almacenar de acuerdo con el protocolo de clave remota segura. En ambos casos, el generador de números aleatorios para los códigos debe ser criptográficamente seguro. Además, se prohíbe una serie de combinaciones de código muy simples.
Por ejemplo, la siguiente figura muestra el servicio de información que se debe definir para cada accesorio y puente de HomeKit. En el protocolo de accesorios de Homekit, los servicios representan el elemento contextualizador de un accesorio y, dependiendo de qué tipo de accesorio sea, contienen las correspondientes características necesarias y opcionales.
Extracto del protocolo de accesorios de Homekit para el servicio de información. (Apple, Especificación del protocolo de accesorios del HomeKit. Versión no comercial, versión R2, 2019)
La tabla presenta que el servicio de información, por ejemplo, debe contener necesariamente la versión del firmware, el nombre del dispositivo y el número de serie como características. Un ejemplo más complejo del modelo de datos de HomeKit sería un ventilador con una bombilla y un humidificador. Este dispositivo representa un accesorio que consiste en tres servicios, el servicio del ventilador, el servicio de bombilla y el servicio de purificador de aire. Estos tres servicios tienen sus propias características necesarias y opcionales. En la app estándar de HomeKit, este dispositivo se mostraría ahora como un único dispositivo y se permitiría la configuración de los servicios correspondientes. Como alternativa, los tres servicios también se podrían dividir en tres accesorios individuales que se incorporan juntos en HomeKit a través de un puente. En este caso, sería posible ver los dispositivos de forma completamente individual, es decir, colocarlos en diferentes habitaciones en la aplicación Home.
Como también se puede ver en la Figura 2, cada servicio HAP tiene un UUID, y lo mismo se aplica a cada característica HAP. Un UUID es un "Universally Unique Identifier" de 128 bits, tal y como se define en el RFC 4122. Un UUID es un identificador único universal que, debido a su tamaño de 128 bits y el número resultante de posibles identificadores, es único incluso sin un comité de distribución central, sino a través de la generación posible en el RFC 4122 sobre la base de una marca de tiempo. Por lo tanto, los UUIDs ofrecen la posibilidad de identificar de forma única tanto los servicios como las características. Esto es especialmente importante para la comunicación a través de BluetoothLE, ya que para ello se utilizan los "Atributos Genéricos de Bluetooth", GATT por sus siglas en inglés, que se basan en UUIDs como identificadores únicos.
Seguridad
El tema de la seguridad desempeña un papel cada vez más importante en el área "Smarthome", ya que cada vez hay más aparatos domésticos que se integran a esta área y, por lo tanto, también son vulnerables a sufrir ataques. Esto se aplica tanto a los ataques de Internet, en el caso de que estos estén en la red, como directamente a los ataques desde la red local. Por un lado, esto es especialmente relevante para los temas relacionados con la seguridad del hogar, como las cerraduras de las puertas o los sistemas de alarma, y por otro lado, para todos los ámbitos relacionados con la privacidad, como los micrófonos y las cámaras en particular.
Por esta motivo, los dispositivos HomeKit se comunican exclusivamente a través de un cifrado de extremo a extremo, que está garantizado por Apple como parte del Kit de desarrollo de accesorios de HomeKit. La conexión inicial, la denominada "Pair Setup" se implementa mediante un procedimiento de cifrado asimétrico. Esto es explícitamente un proceso único para configurar el dispositivo. Para el intercambio seguro de claves se utiliza el "Stanford Secure Remote Password Protocol". En lugar de la obsoleta función hash SHA-1, se utiliza la función SHA-512 que se basa en SHA-2. El generador aquí está definido por el grupo de 3072 bits en el RFC 5054. Además del método de cifrado asimétrico, el usuario debe ingresar una combinación numérica de 8 dígitos en su dispositivo iOS, que se mapea en consecuencia en el accesorio HomeKit. Después de la inicialización, se realiza el denominado "Pair Verify" para cada sesión posterior, es decir, la comunicación. A continuación, se lleva a cabo un cifrado síncrono con una nueva clave generada para cada sesión. La clave correspondiente se genera según el método de Ephemeral-Diffie-Hellman y, por lo tanto, aunque la clave sea robada, no se podrá descifrar ninguna comunicación previa con ella. Esto se denomina "forward secrecy". Para evitar al máximo el robo de la clave, todas las claves necesarias para el cifrado, es decir, incluso la clave pública necesaria para la configuración del par y todos los procesos relacionados, deben estar especialmente aseguradas en un dispositivo certificado por Apple para HomeKit. Apple recomienda el uso de un chip de seguridad a nivel de hardware para este propósito, pero mientras tanto también permite la seguridad de los procesos por software.
Como se mencionó anteriormente, las cámaras con micrófonos son un aspecto especialmente crítico para la privacidad en el Smarthome. Por este motivo, se introdujo la función "HomeKit Secure Video". Las cámaras deben cifrar sus datos con al menos AES de 128 bits,mejor AES de 256 bits, para obtener la correspondiente certificación de vídeo seguro de HomeKit, además del mismo cifrado de extremo a extremo que se aplica a todos los dispositivos de HomeKit. Con este cifrado, todas las grabaciones se encriptan y se anonimizan durante 7 días en iCloud. Además, todos los análisis del material de imagen, por ejemplo, el reconocimiento de personas, animales o paquetes, tienen lugar localmente en un HomeKit Hub, es decir, un iPad, Apple TV o HomePod y no en iCloud.
Sin embargo, se debe mencionar que a pesar de un cierto nivel de seguridad a través del cifrado, los dispositivos SmartHome del marco HomeKit también conllevan un cierto riesgo de vulnerabilidades de seguridad, que los usuarios debe tener en cuenta y tomar las medidas adecuadas para protegerse. Por ejemplo, los dispositivos HomeKit sin un HomeKit Hub también podrían funcionar localmente hasta cierto rango de funciones. Otras posibilidades serían operar los dispositivos en una VLAN separada de la red principal, es decir, una LAN virtual, o, en el caso de las cámaras, evitar secciones de imagen extremadamente críticas, por ejemplo, en la sala de estar.
Estructura del hardware
Componentes y Pinouts
Para la aplicación se requiere:
número | Componente | anotación |
---|---|---|
1 | ESP-32 Dev Kit C V4 - AZ-Delivery | Alternativamente, también se pueden utilizar otras versiones del ESP32. |
1 | Sensor de temperatura y humedad DHT22 - AZ-Delivery | Alternativamente, también se puede utilizar la placa ya equipada con resistencia de pull-up. |
1 | Kit de Resistencias 525 piezas de resistencia, 0 Ohm -1M Ohm - AZ-Delivery | Una selección de diferentes resistencias, se requiere una resistencia de 10k Ohm. |
1 | Cable puente 3 x 40 pcs. 20 cm M2M / F2M / F2F Raspberry Pi - AZ-Delivery | Se necesitan 4 cables de puente hembra / hembra. Si no está disponible, se recomienda el conjunto especificado. |
A continuación, se presenta la disposición de los pines del ESP32 mencionado anteriormente:
La siguiente es la disposición de los pines del DHT22 mencionado anteriormente:
- Vin - Este es el pin de alimentación. Para utilizarlo con un ESP32, se debe aplicar aquí 3.3 V.
- DATA - Línea de datos. Este pin requiere una resistencia de pull-up de 10K a Vin.
- NULL - Sin función.
- GND - Tierra.
Cableado
Los siguientes pines se deben conectar entre sí para la construcción del circuito:
- El pin Vin del DHT22 se debe conectar al pin de 3.3V del microcontrolador.
- El pin GND del DHT22 se debe conectar a cualquier pin GND del microcontrolador.
- El pin de datos del DHT22 se debe conectar a un pin GPIO del microcontrolador. Además, se debe insertar una resistencia de pull-up al Vin.
Estructura del software
Las librerías que se utilizan en este proyecto son la ya mencionada "HomeSpan" para integrar el protocolo de accesorios del HomeKit y la librería "Adafruit_DHTxx" para la lectura del sensor de temperatura utilizado. Ambas librerías se pueden instalar a través del gestor de librería en el Arduino IDE.
La librería HomeSpan implementa el protocolo de accesorios de HomeKit en la versión de código abierto R2. En este sentido, resulta de especial interés el modelo de datos de HomeKit, es decir, todos los accesorios proporcionados por Apple, incluyendo sus servicios y características. Sólo no se pueden crear dispositivos de sonido y vídeo debido a sus mayores requisitos de hardware. HomeSpan permite la programación completa de los accesorios de HomeKit en el Arduino IDE y también ofrece una interfaz de línea de comandos con un alto nivel de información de depuración y mensajes de error.
Para una estructuración clara, el programa se divide en tres partes. La primera parte "HomeSpan-DHT22-Sensor Temperatura" corresponde a la función principal. Se encarga de definir de los accesorios de HomeKit y crea objetos que representan el servidor HAP de los dispositivos definidos. Además, a diferencia de la primera publicación del blog, el accesorio HomeKit se define como un puente, por lo que se pueden emparejar varios dispositivos a través de una única conexión en el ámbito de este. La segunda parte del programa "DEV_Identify.h" es una función para la creación más clara y rápida de los accesorios de HomeKit. A esta función se le pasan los datos de "Accessory Information Service" como una cadena y luego crea un Accesorio HomeKit a partir de esto llamando a las funciones HAP correspondientes. Además, el proceso de inicialización visible requerido en el HAP se implementa mediante un LED intermitente, pero esto no se representa en el hardware de este proyecto. En la tercera parte del programa "DEV_Sensors.h", se definen todos los demás servicios necesarios u opcionales del accesorio y, además, se crea la rutina de lectura de los datos del sensor o, en el caso de los actuadores, la rutina de ejecución del mismo.
En este caso concreto, el DHT22 se integró como un sensor. Este sensor contiene un sensor de temperatura y un sensor para determinar la humedad. En primer lugar, ambos reciben el "Accessory Information Service" necesario para cada accesorio de HomeKit. Este servicio contiene la versión del firmware, una rutina de identificación, un fabricante, la designación del modelo, un nombre y el número de serie como características. Posteriormente, en el área "DEV_Sensors.h" se implementaron los sensores con sus correspondientes servicios. Para el sensor de temperatura, por ejemplo, se cambió el rango de funcionamiento de la temperatura de 0 a 100 grados Celsius, que se almacenan como estándar en Homekit, se cambió a -50 a 100 grados Celsius, es decir, el rango del sensor de temperatura que se puede tomar de la hoja de datos. Además, se declaró la característica de la temperatura actual. Cada 10 segundos se define el valor de temperatura y, por lo tanto, se transmite a HomeKit. Aquí nos limitamos a cualquier intervalo de tiempo para no sobrecargar innecesariamente la red doméstica.
Lo mismo ocurre con el sensor de humedad.
El código fuente se comenta como un repositorio de Github para descargar y probar.
HomeSpan-DHT22-Temperature-Sensor.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.
*
********************************************************************************/
////////////////////////////////////////////////////////////
// //
// HomeSpan: A HomeKit implementation for the ESP32 //
// ------------------------------------------------ //
// //
////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
homeSpan.begin(Category::Bridges,"AZDelivery Temp Sensor Bridge");
new SpanAccessory();
new DEV_Identify("AZDelivery HomeKit","SmartHomeFactory","123-ABC","HS Bridge","0.9",3);
new Service::HAPProtocolInformation();
new Characteristic::Version("1.1.0");
new SpanAccessory();
new DEV_Identify("DHT22 Temp Sensor","SmartHomeFactory","123-ABC","Sensor","0.9",0);
// Create a Temperature Sensor (see DEV_Sensors.h for definition)
new DEV_TempSensor();
new SpanAccessory();
new DEV_Identify("DHT22 Humidity Sensor","SmartHomeFactory","123-ABC","Sensor","0.9",0);
// Create a Humidity Sensor (see DEV_Sensors.h for definition)
new DEV_HumSensor();
} // 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_Sensors.h
/////////////////////////////////
// DEVICE-SPECIFIC SERVICES //
////////////////////////////////
// reference to the Sensor Objects
DHT dht(DHTPIN, DHTTYPE);
// A standalone Temperature sensor
struct DEV_TempSensor : Service::TemperatureSensor {
// reference to the Current Temperature Characteristic
SpanCharacteristic *temp;
// constructor() method
DEV_TempSensor() : Service::TemperatureSensor() {
// start dhttemp Object
dht.begin();
// instantiate the Current Temperature Characteristic
temp = new Characteristic::CurrentTemperature(-10.0);
// expand the range from the HAP default of 0-100 to -50 to 100 to allow for negative temperatures
temp->setRange(-50, 100);
// initialization message
Serial.print("Configuring Temperature Sensor");
Serial.print("\n");
} // end constructor
void loop() {
// the temperature refreshes every 10 seconds by the elapsed time
if (temp->timeVal() > 10000) {
// read temperature from sensor dht22
float temperature = dht.readTemperature();
// set the new temperature; this generates an Event Notification and also resets the elapsed time
temp->setVal(temperature);
LOG1("Temperature Update: ");
LOG1(temperature);
LOG1(" ; ");
}
} // loop
};
////////////////////////////////////
// A standalone Humidity sensor
struct DEV_HumSensor : Service::HumiditySensor {
// reference to the Current Humidity Characteristic
SpanCharacteristic *hum;
// constructor() method
DEV_HumSensor() : Service::HumiditySensor() {
// start dhthum Object
dht.begin();
// instantiate the Current Temperature Characteristic
hum = new Characteristic::CurrentRelativeHumidity(50);
// expand the range to 30%-100%
hum->setRange(30, 100);
// initialization message
Serial.print("Configuring Humidity Sensor");
Serial.print("\n");
} // end constructor
void loop() {
// the humidity refreshes every 10 seconds by the elapsed time
if (hum->timeVal() > 10000) {
// read humidity from sensor dht22
float humidity = dht.readHumidity();
// set the new humidity; this generates an Event Notification and also resets the elapsed time
hum->setVal(humidity);
LOG1("Humidity Update: ");
LOG1(humidity);
LOG1(" ; ");
}
} // loop
};
//////////////////////////////////
Configuración
Este es el modo de configuración de nuestro sensor de temperatura HomeKit, al que se puede acceder a través de la consola serie en el Arduino IDE. Debe tener en cuenta que se debe ajustar la velocidad de transmisión correcta. La WLAN se puede configurar escribiendo "W".
Aquí, la WLAN ya está configurada y el sensor HomeKit se ha conectado a la red local. Ahora se puede añadir a su hogar HomeKit en su dispositivo iOS con el código de configuración estándar "466-37-726".
Esto se ve así en la aplicación estándar de Homekit, por ejemplo:
¡Espero que se divierta mucho construyéndolo!
16 comentarios
Mike
Gibt es auch für den Raspberry Pi Pico W eine solche HomeKit-Integration?
Andreas Wolter
@Jürgen: könnten Sie die Fehlermeldung genauer beschreiben?
Grüße,
Andreas Wolter
AZ-Delivery Blog
Jürgen
Hallo, leider kann ich den Standard-Code nicht eintragen – das gerät verlangt mehr Feldereingaben. Gibt es einen anderen /neuen Code?
Björn
Hi!
Ich habe meinen Fehler gefunden. Die Meldung „Geräteerkennung fehlgeschlagen“ scheint zu kommen, wenn der Sensor keine korrekten Werte/Daten liefert.
Dies hatte ich mit folgendem Programm getestet:
https://randomnerdtutorials.com/esp32-dht11-dht22-temperature-humidity-sensor-arduino-ide/
Dort kam immer der Lesefehler. Nachdem ich dann auch den korrekten Pin im Board erwischt hatte, lieferte der Sensor korrekte Werte und lies sich auch in Apple HomeKit einbinden.
Jonas
Moin, sieht bei mir genauso aus. Geräterkennung fehlgeschlagen… wäre für jeden tipp dankbar
Björn
Moin!
Bei mir funktioniert fast alles … aber eben nur fast. Beim Einfügen der Bridge ins HomeKit bekomme ich die Fehlermeldung “Geräteerkennung fehlgeschlagen”. Gibt es eine Idee woran dies liegt bzw. was man dagegen tun muss?
Andreas Wolter
@Gonzalo: please check the external repo and documentation of the HomeSpan Library:
https://bytemeta.vip/index.php/repo/HomeSpan/HomeSpan
https://github.com/HomeSpan/HomeSpan/blob/master/docs/Overview.md
Gonzalo
hello. Thank you very much for posting this project. I’m from chile. I have a little problem. the esp32 disconnects many times from the wifi and therefore I cannot access the information of the sensors through the iPhone. Is there a way to automatically reconnect? For it to work properly again, I press the “EN” button and it works again, but ideally it would connect automatically… greetings and excellent work!
Leon
Hallo Oliver,
meinst du die Meldung, dass das Gerät nicht zertifiziert und deswegen möglicherweise nicht kompatibel ist oder eine andere Fehlermeldung?
Die Home App warnt bei der Registrierung immer vor allen nicht ganz offiziell von Apple zertifizierten Geräten.
Mit freundlichen Grüßen
Leon
Oliver
Hi… Ich konnte den ESP32 erfolgreich konfigurieren.
Nur sagt mit meine HOME APP, daß das zu verbindende Gerät nicht kompatibel ist.
Was kann ich tun?
Danke
Leon
Hallo Thomas,
hat sich dein Problem mit der Stromversorgung inzwischen aufgelöst?
Meine Erfahrung heirbei ist, dass man teilweise beim Testen in Situationen gelangt in denen sich der ESP32 entweder nicht mehr mit dem Wlan oder dem entsprechenden Homekit Gerät verbinden will. In dem Fall hilft es häufig über das CLI mit ‘E’ einmal alle Daten zu löschen und den ESP neu mit WLAN und Homekit zu verbinden.
Mit der Anzeige der Luftfeuchtigkeit hatte ich tatsächlich auch öfters Probleme und eine andere Lösung als die Range entsprechend anzupassen ist mir hier leider auch nicht bekannt. Wenn sich hier etwas neues ergibt würde ich mich nochmal melden.
Viele Grüße
Leon
Renhold
Wenn die Range 0..100% konfiguriert ist, stimmt die Anzeige.
hum→setRange(0, 100);
Hendrik
Moin, ich habe auch das Problem, dass in der Übersicht ein knapp 20% geringerer Wert für die Luftfeuchtigkeit angezeigt wird. Wenn ich den Wert direkt anzeigen lasse, wird der korrekte Wert angezeigt.
Thomas Hecker
Hallo Leon,
ich habe da noch eine Nachfrage.
Mein Versuch den Sensor nun unabhängig von einem USB Anschluß zu betreiben scheitert. Weder die Versorgung über 3,3V noch 5V führt zum Erfolg. Die LED des ESP32 leuchtet zwar aber vermutlich kann er sich nicht ins WLAN einloggen. Auf den Serial Monitor kann ich nicht zugreifen es sei denn ich schließe wieder das USB Kabel an. Hast Du da, gerne auch jemand der das Problem bereits gelöst hat, einen Rat?
Viele Grüße
Thomas
Thomas Hecker
Vielen Dank für das schöne Projekt!
Ich bin noch sehr am Anfang mit der Arduino-ESP Bastelei, hatte aber bei der praktischen Umsetzung keine Probleme. Die Theorie dahinter ist noch in mehr oder weniger dichtem Nebel.
Die Anzeige der Bridge in Home weist bei der Feuchtigkeit einen niedrigeren Wert (18%) aus als ich ihn gezeigt bekomme wenn ich mir die einzelnen Komponenten der Bridge anzeigen lasse. Feuchtigkeit 40%.
Lässt sich das im Programmcode anpassen? Umrechnung anders?
Viele Grüße
Thomas
Michael
Hallo, sehr schön Dein Prjekt. Schöner wäre es wenn due einen “GY-BME280” Sensor genommen hättest. Sind genauer.