From 22bd16e936cfd594849815d5c6ca4d38938438d1 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 11 Feb 2023 07:49:16 -0600 Subject: [PATCH 01/79] Added ability to set OTA password from within sketch Adds second form of homeSpan.enableOTA(const char *pwd, boolean safeLoad=true) --- src/HAP.cpp | 14 +++++------ src/HomeSpan.cpp | 64 +++++++++++++++++++++++++++++------------------- src/HomeSpan.h | 8 +++--- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/HAP.cpp b/src/HAP.cpp index a922826..3db9f4a 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -40,14 +40,12 @@ void HAPClient::init(){ nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS - if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS - nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // retrieve data - } else { - MD5Builder otaPwdHash; - otaPwdHash.begin(); - otaPwdHash.add(DEFAULT_OTA_PASSWORD); - otaPwdHash.calculate(); - otaPwdHash.getChars(homeSpan.spanOTA.otaPwd); + if(strlen(homeSpan.spanOTA.otaPwd)==0){ // OTA password has not been specified in sketch + if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS... + nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // ...retrieve data. + } else { // otherwise... + homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password + } } if(strlen(homeSpan.pairingCodeCommand)){ // load verification setup code if provided diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index bb8a013..16915bc 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -519,25 +519,20 @@ void Span::checkConnect(){ mdns_service_txt_item_set("_hap","_tcp","sh",setupHash); // Step 4: broadcast the resulting Setup Hash if(spanOTA.enabled){ - if(esp_ota_get_running_partition()!=esp_ota_get_next_update_partition(NULL)){ - ArduinoOTA.setHostname(hostName); + ArduinoOTA.setHostname(hostName); - if(spanOTA.auth) - ArduinoOTA.setPasswordHash(spanOTA.otaPwd); + if(spanOTA.auth) + ArduinoOTA.setPasswordHash(spanOTA.otaPwd); - ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error); - - ArduinoOTA.begin(); - Serial.print("Starting OTA Server: "); - Serial.print(displayName); - Serial.print(" at "); - Serial.print(WiFi.localIP()); - Serial.print("\nAuthorization Password: "); - Serial.print(spanOTA.auth?"Enabled\n\n":"DISABLED!\n\n"); - } else { - Serial.print("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n"); - spanOTA.enabled=false; - } + ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error); + + ArduinoOTA.begin(); + Serial.print("Starting OTA Server: "); + Serial.print(displayName); + Serial.print(" at "); + Serial.print(WiFi.localIP()); + Serial.print("\nAuthorization Password: "); + Serial.print(spanOTA.auth?"Enabled\n\n":"DISABLED!\n\n"); } mdns_service_txt_item_set("_hap","_tcp","ota",spanOTA.enabled?"yes":"no"); // OTA status (info only - NOT used by HAP) @@ -682,13 +677,8 @@ void Span::processSerialCommand(const char *c){ } Serial.print(mask(textPwd,2)); - Serial.print("\n"); - - MD5Builder otaPwdHash; - otaPwdHash.begin(); - otaPwdHash.add(textPwd); - otaPwdHash.calculate(); - otaPwdHash.getChars(spanOTA.otaPwd); + Serial.print("\n"); + spanOTA.setPassword(textPwd); nvs_set_str(otaNVS,"OTADATA",spanOTA.otaPwd); // update data nvs_commit(otaNVS); @@ -2147,11 +2137,35 @@ void SpanWebLog::vLog(boolean sysMsg, const char *fmt, va_list ap){ // SpanOTA // /////////////////////////////// -void SpanOTA::init(boolean _auth, boolean _safeLoad){ +int SpanOTA::init(boolean _auth, boolean _safeLoad, const char *pwd){ + if(esp_ota_get_running_partition()==esp_ota_get_next_update_partition(NULL)){ + Serial.print("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n"); + return(-1); + } + enabled=true; safeLoad=_safeLoad; auth=_auth; homeSpan.reserveSocketConnections(1); + if(pwd==NULL) + return(0); + return(setPassword(pwd)); +} + +/////////////////////////////// + +int SpanOTA::setPassword(const char *pwd){ + if(strlen(pwd)<1 || strlen(pwd)>32){ + Serial.printf("\n*** WARNING: Cannot change OTA password to '%s'. Password length must be between 1 and 32 characters.\n\n",pwd); + return(-1); + } + + MD5Builder otaPwdHash; + otaPwdHash.begin(); + otaPwdHash.add(pwd); + otaPwdHash.calculate(); + otaPwdHash.getChars(homeSpan.spanOTA.otaPwd); + return(0); } /////////////////////////////// diff --git a/src/HomeSpan.h b/src/HomeSpan.h index a7db2d4..bae1df2 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -168,14 +168,15 @@ struct SpanWebLog{ // optional web status/log data struct SpanOTA{ // manages OTA process - char otaPwd[33]; // MD5 Hash of OTA password, represented as a string of hexidecimal characters + char otaPwd[33]=""; // MD5 Hash of OTA password, represented as a string of hexidecimal characters static boolean enabled; // enables OTA - default if not enabled static boolean auth; // indicates whether OTA password is required static int otaPercent; static boolean safeLoad; // indicates whether OTA update should reject any application update that is not another HomeSpan sketch - void init(boolean auth, boolean safeLoad); + int init(boolean auth, boolean safeLoad, const char *pwd); + int setPassword(const char *pwd); static void start(); static void end(); static void progress(uint32_t progress, uint32_t total); @@ -326,7 +327,8 @@ class Span{ void setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS - void enableOTA(boolean auth=true, boolean safeLoad=true){spanOTA.init(auth, safeLoad);} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password + int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password + int enableOTA(const char *pwd, boolean safeLoad=true){return(spanOTA.init(true, safeLoad, pwd));} // enables Over-the-Air updates, with custom authorization password (overrides any password stored with the 'O' command) void enableWebLog(uint16_t maxEntries=0, const char *serv=NULL, const char *tz="UTC", const char *url=DEFAULT_WEBLOG_URL){ // enable Web Logging webLog.init(maxEntries, serv, tz, url); From 5cb29526c3d743e42dde788b0c84229420b0abe0 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 11 Feb 2023 07:57:26 -0600 Subject: [PATCH 02/79] Update OTA.md --- docs/OTA.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/OTA.md b/docs/OTA.md index a524956..408f0c8 100644 --- a/docs/OTA.md +++ b/docs/OTA.md @@ -8,6 +8,8 @@ By default, HomeSpan requires the use of a password whenever you begin an OTA up You can change the password for a HomeSpan device from the [HomeSpan CLI](CLI.md) with the 'O' command. Similar to a device's Setup Code, HomeSpan saves a non-recoverable hashed version of the OTA password you specify in non-volatile storage (NVS). If you forget the password you specified, you'll need to create a new one using the 'O' command, or you can restore the default OTA password by fully erasing the NVS with the 'E' command. +You can also change the password programmatically from within a sketch by calling `homeSpan.enableOTA(const char *pwd)`. This is not as secure as setting the password using the method above since your sketch will contain a plaintext-version, instead of a hashed-version, or your password. Note that setting your password this way causes HomeSpan to ignore, but does not alter, any password you have saved in NVS using the 'O' command. + > :exclamation: Though not recommended, you can override the requirement for a password when enabling OTA for your sketch by including *false* as a parameter to the enabling method as such: `homeSpan.enableOTA(false)`. Use with caution! Anyone who can access the device over your network will now be able to upload a new sketch. Note that in in order for OTA to properly operate, your sketch must be compiled with a partition scheme that includes OTA partitions. Partition schemes are found under the *Tools → Partition Scheme* menu of the Arduino IDE. Select a scheme that indicates it supports OTA. Note that schemes labeled "default" usually include OTA partitions. If unsure, try it out. HomeSpan will let you know if it does or does not. From bd46416b645e81ce35a4fc2dcef4e7849b3dd469 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 11 Feb 2023 08:09:19 -0600 Subject: [PATCH 03/79] Update Reference.md --- docs/Reference.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/Reference.md b/docs/Reference.md index 748f315..54a2912 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -116,6 +116,13 @@ The following **optional** `homeSpan` methods enable additional features and pro * this can be changed via the [HomeSpan CLI](CLI.md) using the 'O' command * note enabling OTA reduces the number of HAP Controller Connections by 1 * OTA Safe Load will be enabled by default unless the second argument is specified and set to *false*. HomeSpan OTA Safe Load checks to ensure that sketches uploaded to an existing HomeSpan device are themselves HomeSpan sketches, and that they also have OTA enabled. See [HomeSpan OTA Safe Load](OTA.md#ota-safe-load) for details + * returns 0 if enabling OTA was successful, or -1 and reports an error to the Serial Monitor if not + +* `int enableOTA(const char *pwd, boolean safeLoad=true)` + * an alternative form of `enableOTA()` that allows you to programmatically change the OTA password to the specified *pwd* + * *pwd* must contain between 1 and 32 characters + * this command causes HomeSpan to ignore, but does not otherwise alter, any password stored using the 'O' command + * returns 0 if enabling OTA was successful, or -1 and reports an error to the Serial Monitor if not * `void enableAutoStartAP()` * enables automatic start-up of WiFi Access Point if WiFi Credentials are **not** found at boot time From 0ecaf2ee7f75d351aef027e739b08fcf3884ae25 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sun, 12 Feb 2023 13:24:19 -0600 Subject: [PATCH 04/79] Add CUSTOM_CHAR_HEADER logic used to include custom Characteristics in a common header without redefining. --- src/Span.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Span.h b/src/Span.h index 23ec984..37bbcd0 100644 --- a/src/Span.h +++ b/src/Span.h @@ -532,6 +532,8 @@ namespace Characteristic { // MACROS TO ADD CUSTOM SERVICES AND CHARACTERISTICS // //////////////////////////////////////////////////////// +#ifndef CUSTOM_CHAR_HEADER + #define CUSTOM_CHAR(NAME,UUID,PERMISISONS,FORMAT,DEFVAL,MINVAL,MAXVAL,STATIC_RANGE) \ HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),FORMAT,STATIC_RANGE}; \ namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore,(FORMAT##_t)MINVAL,(FORMAT##_t)MAXVAL); } }; } @@ -544,9 +546,26 @@ namespace Characteristic { HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),DATA,true}; \ namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val="AA==", boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } +#else + +#define CUSTOM_CHAR(NAME,UUID,PERMISISONS,FORMAT,DEFVAL,MINVAL,MAXVAL,STATIC_RANGE) \ + extern HapChar _CUSTOM_##NAME; \ + namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore,(FORMAT##_t)MINVAL,(FORMAT##_t)MAXVAL); } }; } + +#define CUSTOM_CHAR_STRING(NAME,UUID,PERMISISONS,DEFVAL) \ + extern HapChar _CUSTOM_##NAME; \ + namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } + +#define CUSTOM_CHAR_DATA(NAME,UUID,PERMISISONS) \ + extern HapChar _CUSTOM_##NAME; \ + namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val="AA==", boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } + +#endif + #define CUSTOM_SERV(NAME,UUID) \ namespace Service { struct NAME : SpanService { NAME() : SpanService{#UUID,#NAME,true}{} }; } + //////////////////////////////////////////////////////// // MACROS TO ADD A NEW ACCESSORT WITH OPTIONAL NAME // //////////////////////////////////////////////////////// From 69af3d59a3124735ffda4b9b134f4cb793116567 Mon Sep 17 00:00:00 2001 From: Gregg Date: Thu, 16 Feb 2023 07:23:22 -0600 Subject: [PATCH 05/79] Replaced Service definitions with macros CREATE_SERV and END_SERV This has no effect on the code but the names of the macros can be used as flags for an external script to autogenerate documentation in the form of a list of all services and characteristics supported by HomeSpan --- src/Span.h | 170 +++++++++++++++++++++++++++-------------------------- 1 file changed, 87 insertions(+), 83 deletions(-) diff --git a/src/Span.h b/src/Span.h index 37bbcd0..ff43382 100644 --- a/src/Span.h +++ b/src/Span.h @@ -29,14 +29,18 @@ // SPAN SERVICES (HAP Chapter 8) // /////////////////////////////////// -// Macros to define vectors of required and optional characteristics for each Span Service structure +// Macros to define services, along with vectors of required and optional characteristics for each Span Service structure +// The names of the macros are picked up by external scripts to help generate documentation + +#define CREATE_SERV(NAME,UUID) struct NAME : SpanService { NAME() : SpanService{#UUID,#NAME}{ +#define END_SERV }}; #define REQ(HAPCHAR) req.insert(&hapChars.HAPCHAR) #define OPT(HAPCHAR) opt.insert(&hapChars.HAPCHAR) namespace Service { - struct AccessoryInformation : SpanService { AccessoryInformation() : SpanService{"3E","AccessoryInformation"}{ + CREATE_SERV(AccessoryInformation,3E) REQ(Identify); OPT(FirmwareRevision); OPT(Manufacturer); @@ -45,9 +49,9 @@ namespace Service { OPT(SerialNumber); OPT(HardwareRevision); OPT(AccessoryFlags); - }}; + END_SERV - struct AirPurifier : SpanService { AirPurifier() : SpanService{"BB","AirPurifier"}{ + CREATE_SERV(AirPurifier,BB) REQ(Active); REQ(CurrentAirPurifierState); REQ(TargetAirPurifierState); @@ -55,9 +59,9 @@ namespace Service { OPT(RotationSpeed); OPT(SwingMode); OPT(LockPhysicalControls); - }}; + END_SERV - struct AirQualitySensor : SpanService { AirQualitySensor() : SpanService{"8D","AirQualitySensor"}{ + CREATE_SERV(AirQualitySensor,8D) REQ(AirQuality); OPT(Name); OPT(OzoneDensity); @@ -70,16 +74,16 @@ namespace Service { OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct BatteryService : SpanService { BatteryService() : SpanService{"96","BatteryService"}{ + CREATE_SERV(BatteryService,96) REQ(BatteryLevel); REQ(ChargingState); REQ(StatusLowBattery); OPT(Name); - }}; + END_SERV - struct CarbonDioxideSensor : SpanService { CarbonDioxideSensor() : SpanService{"97","CarbonDioxideSensor"}{ + CREATE_SERV(CarbonDioxideSensor,97) REQ(CarbonDioxideDetected); OPT(Name); OPT(StatusActive); @@ -88,9 +92,9 @@ namespace Service { OPT(StatusLowBattery); OPT(CarbonDioxideLevel); OPT(CarbonDioxidePeakLevel); - }}; + END_SERV - struct CarbonMonoxideSensor : SpanService { CarbonMonoxideSensor() : SpanService{"7F","CarbonMonoxideSensor"}{ + CREATE_SERV(CarbonMonoxideSensor,7F) REQ(CarbonMonoxideDetected); OPT(Name); OPT(StatusActive); @@ -99,34 +103,34 @@ namespace Service { OPT(StatusLowBattery); OPT(CarbonMonoxideLevel); OPT(CarbonMonoxidePeakLevel); - }}; + END_SERV - struct ContactSensor : SpanService { ContactSensor() : SpanService{"80","ContactSensor"}{ + CREATE_SERV(ContactSensor,80) REQ(ContactSensorState); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct Door : SpanService { Door() : SpanService{"81","Door"}{ + CREATE_SERV(Door,81) REQ(CurrentPosition); REQ(TargetPosition); REQ(PositionState); OPT(Name); OPT(HoldPosition); OPT(ObstructionDetected); - }}; + END_SERV - struct Doorbell : SpanService { Doorbell() : SpanService{"121","Doorbell"}{ + CREATE_SERV(Doorbell,121) REQ(ProgrammableSwitchEvent); OPT(Name); OPT(Volume); OPT(Brightness); - }}; + END_SERV - struct Fan : SpanService { Fan() : SpanService{"B7","Fan"}{ + CREATE_SERV(Fan,B7) REQ(Active); OPT(Name); OPT(CurrentFanState); @@ -135,35 +139,35 @@ namespace Service { OPT(RotationSpeed); OPT(SwingMode); OPT(LockPhysicalControls); - }}; + END_SERV - struct Faucet : SpanService { Faucet() : SpanService{"D7","Faucet"}{ + CREATE_SERV(Faucet,D7) REQ(Active); OPT(StatusFault); OPT(Name); - }}; + END_SERV - struct FilterMaintenance : SpanService { FilterMaintenance() : SpanService{"BA","FilterMaintenance"}{ + CREATE_SERV(FilterMaintenance,BA) REQ(FilterChangeIndication); OPT(Name); OPT(FilterLifeLevel); OPT(ResetFilterIndication); - }}; + END_SERV - struct GarageDoorOpener : SpanService { GarageDoorOpener() : SpanService{"41","GarageDoorOpener"}{ + CREATE_SERV(GarageDoorOpener,41) REQ(CurrentDoorState); REQ(TargetDoorState); REQ(ObstructionDetected); OPT(LockCurrentState); OPT(LockTargetState); OPT(Name); - }}; + END_SERV - struct HAPProtocolInformation : SpanService { HAPProtocolInformation() : SpanService{"A2","HAPProtocolInformation"}{ + CREATE_SERV(HAPProtocolInformation,A2) REQ(Version); - }}; + END_SERV - struct HeaterCooler : SpanService { HeaterCooler() : SpanService{"BC","HeaterCooler"}{ + CREATE_SERV(HeaterCooler,BC) REQ(Active); REQ(CurrentTemperature); REQ(CurrentHeaterCoolerState); @@ -175,9 +179,9 @@ namespace Service { OPT(CoolingThresholdTemperature); OPT(HeatingThresholdTemperature); OPT(LockPhysicalControls); - }}; + END_SERV - struct HumidifierDehumidifier : SpanService { HumidifierDehumidifier() : SpanService{"BD","HumidifierDehumidifier"}{ + CREATE_SERV(HumidifierDehumidifier,BD) REQ(Active); REQ(CurrentRelativeHumidity); REQ(CurrentHumidifierDehumidifierState); @@ -189,167 +193,167 @@ namespace Service { OPT(SwingMode); OPT(WaterLevel); OPT(LockPhysicalControls); - }}; + END_SERV - struct HumiditySensor : SpanService { HumiditySensor() : SpanService{"82","HumiditySensor"}{ + CREATE_SERV(HumiditySensor,82) REQ(CurrentRelativeHumidity); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct InputSource : SpanService { InputSource() : SpanService{"D9","InputSource"}{ + CREATE_SERV(InputSource,D9) OPT(ConfiguredName); OPT(IsConfigured); REQ(Identifier); OPT(CurrentVisibilityState); OPT(TargetVisibilityState); - }}; + END_SERV - struct IrrigationSystem : SpanService { IrrigationSystem() : SpanService{"CF","IrrigationSystem"}{ + CREATE_SERV(IrrigationSystem,CF) REQ(Active); REQ(ProgramMode); REQ(InUse); OPT(RemainingDuration); OPT(StatusFault); - }}; + END_SERV - struct LeakSensor : SpanService { LeakSensor() : SpanService{"83","LeakSensor"}{ + CREATE_SERV(LeakSensor,83) REQ(LeakDetected); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct LightBulb : SpanService { LightBulb() : SpanService{"43","LightBulb"}{ + CREATE_SERV(LightBulb,43) REQ(On); OPT(Brightness); OPT(Hue); OPT(Name); OPT(Saturation); OPT(ColorTemperature); - }}; + END_SERV - struct LightSensor : SpanService { LightSensor() : SpanService{"84","LightSensor"}{ + CREATE_SERV(LightSensor,84) REQ(CurrentAmbientLightLevel); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct LockMechanism : SpanService { LockMechanism() : SpanService{"45","LockMechanism"}{ + CREATE_SERV(LockMechanism,45) REQ(LockCurrentState); REQ(LockTargetState); OPT(Name); - }}; + END_SERV - struct Microphone : SpanService { Microphone() : SpanService{"112","Microphone"}{ + CREATE_SERV(Microphone,112) REQ(Mute); OPT(Name); OPT(Volume); - }}; + END_SERV - struct MotionSensor : SpanService { MotionSensor() : SpanService{"85","MotionSensor"}{ + CREATE_SERV(MotionSensor,85) REQ(MotionDetected); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct OccupancySensor : SpanService { OccupancySensor() : SpanService{"86","OccupancySensor"}{ + CREATE_SERV(OccupancySensor,86) REQ(OccupancyDetected); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct Outlet : SpanService { Outlet() : SpanService{"47","Outlet"}{ + CREATE_SERV(Outlet,47) REQ(On); REQ(OutletInUse); OPT(Name); - }}; + END_SERV - struct SecuritySystem : SpanService { SecuritySystem() : SpanService{"7E","SecuritySystem"}{ + CREATE_SERV(SecuritySystem,7E) REQ(SecuritySystemCurrentState); REQ(SecuritySystemTargetState); OPT(Name); OPT(SecuritySystemAlarmType); OPT(StatusFault); OPT(StatusTampered); - }}; + END_SERV - struct ServiceLabel : SpanService { ServiceLabel() : SpanService{"CC","ServiceLabel"}{ + CREATE_SERV(ServiceLabel,CC) REQ(ServiceLabelNamespace); - }}; + END_SERV - struct Slat : SpanService { Slat() : SpanService{"B9","Slat"}{ + CREATE_SERV(Slat,B9) REQ(CurrentSlatState); REQ(SlatType); OPT(Name); OPT(SwingMode); OPT(CurrentTiltAngle); OPT(TargetTiltAngle); - }}; + END_SERV - struct SmokeSensor : SpanService { SmokeSensor() : SpanService{"87","SmokeSensor"}{ + CREATE_SERV(SmokeSensor,87) REQ(SmokeDetected); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct Speaker : SpanService { Speaker() : SpanService{"113","Speaker"}{ + CREATE_SERV(Speaker,113) REQ(Mute); OPT(Name); OPT(Volume); - }}; + END_SERV - struct StatelessProgrammableSwitch : SpanService { StatelessProgrammableSwitch() : SpanService{"89","StatelessProgrammableSwitch"}{ + CREATE_SERV(StatelessProgrammableSwitch,89) REQ(ProgrammableSwitchEvent); OPT(Name); OPT(ServiceLabelIndex); - }}; + END_SERV - struct Switch : SpanService { Switch() : SpanService{"49","Switch"}{ + CREATE_SERV(Switch,49) REQ(On); OPT(Name); - }}; + END_SERV - struct Television : SpanService { Television() : SpanService{"D8","Television"}{ + CREATE_SERV(Television,D8) REQ(Active); OPT(ConfiguredName); OPT(ActiveIdentifier); OPT(RemoteKey); OPT(PowerModeSelection); - }}; + END_SERV - struct TelevisionSpeaker : SpanService { TelevisionSpeaker() : SpanService{"113","TelevisionSpeaker"}{ + CREATE_SERV(TelevisionSpeaker,113) REQ(VolumeControlType); REQ(VolumeSelector); - }}; + END_SERV - struct TemperatureSensor : SpanService { TemperatureSensor() : SpanService{"8A","TemperatureSensor"}{ + CREATE_SERV(TemperatureSensor,8A) REQ(CurrentTemperature); OPT(Name); OPT(StatusActive); OPT(StatusFault); OPT(StatusTampered); OPT(StatusLowBattery); - }}; + END_SERV - struct Thermostat : SpanService { Thermostat() : SpanService{"4A","Thermostat"}{ + CREATE_SERV(Thermostat,4A) REQ(CurrentHeatingCoolingState); REQ(TargetHeatingCoolingState); REQ(CurrentTemperature); @@ -360,9 +364,9 @@ namespace Service { OPT(HeatingThresholdTemperature); OPT(Name); OPT(TargetRelativeHumidity); - }}; + END_SERV - struct Valve : SpanService { Valve() : SpanService{"D0","Valve"}{ + CREATE_SERV(Valve,D0) REQ(Active); REQ(InUse); REQ(ValveType); @@ -372,18 +376,18 @@ namespace Service { OPT(ServiceLabelIndex); OPT(StatusFault); OPT(Name); - }}; + END_SERV - struct Window : SpanService { Window() : SpanService{"8B","Window"}{ + CREATE_SERV(Window,8B) REQ(CurrentPosition); REQ(TargetPosition); REQ(PositionState); OPT(Name); OPT(HoldPosition); OPT(ObstructionDetected); - }}; + END_SERV - struct WindowCovering : SpanService { WindowCovering() : SpanService{"8C","WindowCovering"}{ + CREATE_SERV(WindowCovering,8C) REQ(TargetPosition); REQ(CurrentPosition); REQ(PositionState); @@ -394,7 +398,7 @@ namespace Service { OPT(CurrentVerticalTiltAngle); OPT(TargetVerticalTiltAngle); OPT(ObstructionDetected); - }}; + END_SERV } From 7e3d26fe6e8ee4cc7efc1afadfc2adf99b1587d5 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 18 Feb 2023 22:21:54 -0600 Subject: [PATCH 06/79] Removed initialization of WiFiClient in HAP.h See #508 for details. --- src/HAP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HAP.h b/src/HAP.h index 49c8944..4ae23b3 100644 --- a/src/HAP.h +++ b/src/HAP.h @@ -90,7 +90,7 @@ struct HAPClient { // individual structures and data defined for each Hap Client connection - WiFiClient client=0; // handle to client + WiFiClient client; // handle to client Controller *cPair; // pointer to info on current, session-verified Paired Controller (NULL=un-verified, and therefore un-encrypted, connection) // These keys are generated in the first call to pair-verify and used in the second call to pair-verify so must persist for a short period From 23976e5f45cf79c31eeb55ad40d372ff728fcbf8 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Feb 2023 22:32:47 -0600 Subject: [PATCH 07/79] Update Reference.md --- docs/Reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Reference.md b/docs/Reference.md index 54a2912..d8719a1 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -109,7 +109,7 @@ The following **optional** `homeSpan` methods override various HomeSpan initiali The following **optional** `homeSpan` methods enable additional features and provide for further customization of the HomeSpan environment. Unless otherwise noted, calls **should** be made before `begin()` to take effect: -* `void enableOTA(boolean auth=true, boolean safeLoad=true)` +* `int enableOTA(boolean auth=true, boolean safeLoad=true)` * enables [Over-the-Air (OTA) Updating](OTA.md) of a HomeSpan device, which is otherwise disabled * HomeSpan OTA requires an authorizing password unless *auth* is specified and set to *false* * the default OTA password for new HomeSpan devices is "homespan-ota" From ae7d4ddcb80cc9900838c10df9b2220fdf0917c0 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Feb 2023 22:55:48 -0600 Subject: [PATCH 08/79] Update Reference.md --- docs/Reference.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Reference.md b/docs/Reference.md index d8719a1..a6aff76 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -543,6 +543,8 @@ Note that Custom Characteristics must be created at the global level (i.e. not i > Advanced Tip 1: When presented with an unrecognized Custom Characteristic, *Eve for HomeKit* helpfully displays a *generic control* allowing you to interact with any Custom Characteristic you create in HomeSpan. However, since Eve does not recognize the Characteristic, it will only render the generic control if the Characteristic includes a **description** field, which you can add to any Characteristic using the `setDescription()` method described above. You may also want to use `setUnit()` and `setRange()` so that the Eve App displays a control with appropriate ranges for your Custom Characteristic. > Advanced Tip 2: The DATA format is not currently used by any native Home App Characteristic, though it is part of the HAP-R2 specifications. This format is included in HomeSpan because other applications, such as *Eve for HomeKit* do use these types of Characteristics to create functionality beyond that of the Home App, and are thus provided for advanced users to experiment. + +> Advanced Tip 3: When using multi-file sketches, the compiler will throw a "redefinition error" if you define the same Custom Characteristic in more than one file. To avoid this error and allow the same Custom Characteristic to be used across more than one file, add the line `#define CUSTOM_CHAR_HEADER` *before* `#include "HomeSpan.h"` in each file containing a *duplicate* definition of a previously-defined Custom Characteristic. ### *CUSTOM_SERV(name,uuid)* From 09063fb7dc3478849f0f19d114ea86bd81039b43 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 25 Feb 2023 15:07:02 -0600 Subject: [PATCH 09/79] Extended functionality of setValidValues() to allow INT, UINT8, UINT16, and UINT32 Characteristics --- examples/08-Bridges/08-Bridges.ino | 2 +- src/HomeSpan.cpp | 23 ++++++++--- src/HomeSpan.h | 2 +- src/src.ino | 65 +++++++----------------------- 4 files changed, 33 insertions(+), 59 deletions(-) diff --git a/examples/08-Bridges/08-Bridges.ino b/examples/08-Bridges/08-Bridges.ino index 072daa6..0331f3c 100644 --- a/examples/08-Bridges/08-Bridges.ino +++ b/examples/08-Bridges/08-Bridges.ino @@ -39,7 +39,7 @@ void setup() { - // If the only Service defined in the FIRST Accessory of a mult-Accessory device is the required Accessory Information Service, + // If the only Service defined in the FIRST Accessory of a multi-Accessory device is the required Accessory Information Service, // the device is said to be configured as a "Bridge". Historically there may have been a number of functional differences between bridge // devices and non-bridge devices, but since iOS 15, it's not obvious there are any differences in functionality, with two exceptions: diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 16915bc..2a709e8 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1977,17 +1977,28 @@ unsigned long SpanCharacteristic::timeVal(){ /////////////////////////////// SpanCharacteristic *SpanCharacteristic::setValidValues(int n, ...){ - - if(format!=UINT8){ - setValidValuesError=true; - return(this); - } String s="["; va_list vl; va_start(vl,n); for(int i=0;i SpanCharacteristic *setRange(A min, B max, S step=0){ diff --git a/src/src.ino b/src/src.ino index 3585673..1760ce2 100644 --- a/src/src.ino +++ b/src/src.ino @@ -30,70 +30,33 @@ #include "HomeSpan.h" -struct RemoteTempSensor : Service::TemperatureSensor { - - SpanCharacteristic *temp; - SpanCharacteristic *fault; - SpanPoint *remoteTemp; - const char *name; - float temperature; - - RemoteTempSensor(const char *name, const char*macAddress, boolean is8266=false) : Service::TemperatureSensor(){ - - this->name=name; - - temp=new Characteristic::CurrentTemperature(-10.0); // set initial temperature - temp->setRange(-50,100); // expand temperature range to allow negative values - - fault=new Characteristic::StatusFault(1); // set initial state = fault - - remoteTemp=new SpanPoint(macAddress,0,sizeof(float),1,is8266); // create a SpanPoint with send size=0 and receive size=sizeof(float) - - } // end constructor - - void loop(){ - - if(remoteTemp->get(&temperature)){ // if there is data from the remote sensor - temp->setVal(temperature); // update temperature - fault->setVal(0); // clear fault - - LOG1("Sensor %s update: Temperature=%0.2f\n",name,temperature*9/5+32); - - } else if(remoteTemp->time()>60000 && !fault->getVal()){ // else if it has been a while since last update (60 seconds), and there is no current fault - fault->setVal(1); // set fault state - LOG1("Sensor %s update: FAULT\n",name); - } - - } // loop - -}; +CUSTOM_CHAR(CharFloat, 00000001-0001-0001-0001-46637266EA00, PR+PW+EV, FLOAT, 0, 0, 100, false); +CUSTOM_CHAR(CharUInt8, 00000009-0001-0001-0001-46637266EA00, PR+PW+EV, UINT8, 0, 0, 100, false); +CUSTOM_CHAR(CharUInt16, 00000016-0001-0001-0001-46637266EA00, PR+PW+EV, UINT16, 0, 0, 100, false); +CUSTOM_CHAR(CharUInt32, 00000032-0001-0001-0001-46637266EA00, PR+PW+EV, UINT32, 0, 0, 100, false); +CUSTOM_CHAR(CharInt, 00000002-0001-0001-0001-46637266EA00, PR+PW+EV, INT, 0, 0, 100, false); ////////////////////////////////////// - + void setup() { Serial.begin(115200); homeSpan.setLogLevel(1); - homeSpan.begin(Category::Bridges,"Sensor Hub"); + homeSpan.begin(Category::Other,"HomeSpan Test"); new SpanAccessory(); new Service::AccessoryInformation(); new Characteristic::Identify(); - - new SpanAccessory(); - new Service::AccessoryInformation(); - new Characteristic::Identify(); - new Characteristic::Name("Indoor Temp"); - new RemoteTempSensor("Device 1","AC:67:B2:77:42:20"); // pass MAC Address of Remote Device - - new SpanAccessory(); - new Service::AccessoryInformation(); - new Characteristic::Identify(); - new Characteristic::Name("Outdoor Temp"); - new RemoteTempSensor("Device 2","BC:FF:4D:40:8E:71",true); // pass MAC Address of Remote Device with 8266 flag set (will use AP MAC Address) + new Service::LightBulb(); + new Characteristic::On(); + (new Characteristic::CharFloat())->setValidValues(5,0,1,2,6,7,8); + (new Characteristic::CharUInt8())->setValidValues(5,0,1,2,6,7,8); + (new Characteristic::CharUInt16())->setValidValues(5,0,1<<8,1<<16,0xFFFFFFFF,-1); + (new Characteristic::CharUInt32())->setValidValues(5,0,1<<8,1<<16,0xFFFFFFFF,-1); + (new Characteristic::CharInt())->setValidValues(5,0,255,2000000000,-2000000000,-1); } // end of setup() From 0faadd8ef3cd0a1f8227f8d93b8fec7ee9b2a868 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Feb 2023 15:33:59 -0600 Subject: [PATCH 10/79] Update Reference.md --- docs/Reference.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/Reference.md b/docs/Reference.md index a6aff76..52de4b2 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -334,9 +334,8 @@ This is a **base class** from which all HomeSpan Characteristics are derived, an * `SpanCharacteristic *setValidValues(int n, [int v1, int v2 ...])` * overrides the default HAP Valid Values for Characteristics that have specific enumerated Valid Values with a variable-length list of *n* values *v1*, *v2*, etc. - * an error is thrown if: - * called on a Characteristic that does not have specific enumerated Valid Values, or - * called more than once on the same Characteristic + * works on Characteristics with UINT8, UINT16, UINT32, and INT formats only + * a warning message is thrown, and the request is ignored, if this method is called on a Characteristic with any other format * returns a pointer to the Characteristic itself so that the method can be chained during instantiation * example: `(new Characteristic::SecuritySystemTargetState())->setValidValues(3,0,1,3);` creates a new Valid Value list of length=3 containing the values 0, 1, and 3. This has the effect of informing HomeKit that a SecuritySystemTargetState value of 2 (Night Arm) is not valid and should not be shown as a choice in the Home App From cde3348b79e7dca80e659a905357b4dbee5e47d1 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 25 Feb 2023 15:34:14 -0600 Subject: [PATCH 11/79] Update src.ino --- src/src.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/src.ino b/src/src.ino index 1760ce2..3bb8cfd 100644 --- a/src/src.ino +++ b/src/src.ino @@ -56,7 +56,7 @@ void setup() { (new Characteristic::CharUInt8())->setValidValues(5,0,1,2,6,7,8); (new Characteristic::CharUInt16())->setValidValues(5,0,1<<8,1<<16,0xFFFFFFFF,-1); (new Characteristic::CharUInt32())->setValidValues(5,0,1<<8,1<<16,0xFFFFFFFF,-1); - (new Characteristic::CharInt())->setValidValues(5,0,255,2000000000,-2000000000,-1); + (new Characteristic::CharInt())->setValidValues(5,0,255,2000000000,-2000000000,-1)->setValidValues(1,2); } // end of setup() From d1b6be2236a5dbf6211fd6dd4cc2d26f22e833bc Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Feb 2023 15:41:16 -0600 Subject: [PATCH 12/79] Update Categories.md --- docs/Categories.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Categories.md b/docs/Categories.md index ade5fcc..39fade8 100644 --- a/docs/Categories.md +++ b/docs/Categories.md @@ -1,6 +1,6 @@ # HomeSpan Accessory Categories -Every HomeSpan device must be assigned a HomeKit Accessory Category. HomeSpan implements these categories as C++ Classes with names that exactly match the spelling and capitalization specified by Apple in Section 13 of [HAP-R2](https://developer.apple.com/homekit/specification/), but without any spaces. HomeSpan Accessory Categories are defined in HomeSpan's `Category` namespace. For example, HomeSpan defines the *Garage Door Openers* Category (HAP Category 4) as `Category::GarageDoorOpeners`, which could be used when initializing HomeSpan as follows: +Every HomeSpan device must be assigned a HomeKit Accessory Category. HomeSpan implements these categories as C++ Classes with names that exactly match the spelling and capitalization specified by Apple in Section 13 of HAP-R2, but without any spaces. HomeSpan Accessory Categories are defined in HomeSpan's `Category` namespace. For example, HomeSpan defines the *Garage Door Openers* Category (HAP Category 4) as `Category::GarageDoorOpeners`, which could be used when initializing HomeSpan as follows: ```C++ homeSpan.begin(Category::GarageDoorOpeners,"Acme Garage Door Lifts"); From 57e9c6c36c4ba4723210cefe580b87b6752356d5 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Feb 2023 15:43:32 -0600 Subject: [PATCH 13/79] Update ServiceList.md --- docs/ServiceList.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/ServiceList.md b/docs/ServiceList.md index 52af85d..6134039 100644 --- a/docs/ServiceList.md +++ b/docs/ServiceList.md @@ -1,8 +1,8 @@ # HomeSpan Services and Characteristics -HomeSpan implements all [HAP-R2](https://developer.apple.com/homekit/specification/) Services and Characteristics except for those that involve video or audio streaming, Apple TV, or advanced lock management (i.e. all HAP Services except those that require Characteristics with a TLV8 data type). +HomeSpan implements all HAP-R2 Services and Characteristics except for those that involve video or audio streaming, Apple TV, or advanced lock management (i.e. all HAP Services except those that require Characteristics with a TLV8 data type). -HomeSpan Services and Characteristics are implemented as C++ Classes with names that exactly match the spelling and capitalization specified by Apple in Sections 8 and 9 of [HAP-R2](https://developer.apple.com/homekit/specification/), but without any spaces. HomeSpan Services are defined in HomeSpan's `Service` namespace. HomeSpan Characteristics are defined in HomeSpan's `Characteristic` namespace. For example, HomeSpan defines the *Carbon Dioxide Sensor* Service (HAP Service 8.7) as `Service::CarbonDioxideSensor`, and the *Carbon Dioxide Detected* Characteristic (HAP Characteristic 9.16) as `Characteristic::CarbonDioxideDetected`. +HomeSpan Services and Characteristics are implemented as C++ Classes with names that exactly match the spelling and capitalization specified by Apple in Sections 8 and 9 of HAP-R2, but without any spaces. HomeSpan Services are defined in HomeSpan's `Service` namespace. HomeSpan Characteristics are defined in HomeSpan's `Characteristic` namespace. For example, HomeSpan defines the *Carbon Dioxide Sensor* Service (HAP Service 8.7) as `Service::CarbonDioxideSensor`, and the *Carbon Dioxide Detected* Characteristic (HAP Characteristic 9.16) as `Characteristic::CarbonDioxideDetected`. HomeSpan Services and Characteristics are instantiated with a C++ `new` command. Services do not take any arguments, whereas Characteristics take a single, optional argument that is used to initialize the value of the Characteristic at startup. If this argument is not specified, HomeSpan will apply a reasonable [default value](#characteristic-types-and-defaults) based on the Characteristic's type and allowed range. @@ -15,7 +15,7 @@ new Service::LightBulb(); // instantiate a Light Bulb Se new Characteristic::Name("Living Room Lamp"); // instantiate an optional Name Characteristic for this Service, and set to "Living Room Lamp" ``` -Please see Sections 8 and 9 of [HAP-R2](https://developer.apple.com/homekit/specification/) for a complete description of all HAP Services and Characteristics. Note that HomeSpan's Service and Characteristic Classes already contain all the required HAP fields, such as the UUID, Format, and Permissions, so you don't need to specify any of these parameters. +Please see Sections 8 and 9 of HAP-R2 for a complete description of all HAP Services and Characteristics. Note that HomeSpan's Service and Characteristic Classes already contain all the required HAP fields, such as the UUID, Format, and Permissions, so you don't need to specify any of these parameters. Additionally, when first starting up, HomeSpan begins by validating the device's configuration to ensure each Service you instantiate includes all required Characteristics, but does not include any Characteristics that are neither required nor optional. If any errors are found, HomeSpan reports them to the Arduino Serial Monitor and halts the program. From 513da6a2d9a6219a8e73b8133638bca984a4b8cd Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Feb 2023 16:06:51 -0600 Subject: [PATCH 14/79] Update README.md --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index a102980..c17e912 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,7 @@ Welcome to HomeSpan - a robust and extremely easy-to-use Arduino library for creating your own [ESP32-based](https://www.espressif.com/en/products/modules/esp32) HomeKit devices entirely within the [Arduino IDE](http://www.arduino.cc). -HomeSpan provides a microcontroller-focused implementation of [Apple's HomeKit Accessory Protocol Specification Release R2 (HAP-R2)](https://developer.apple.com/homekit/specification/) designed specifically for the Espressif ESP32 microcontroller running within the Arduino IDE. HomeSpan pairs directly to HomeKit via your home WiFi network without the need for any external bridges or components. With HomeSpan you can use the full power of the ESP32's I/O functionality to create custom control software and/or hardware to automatically operate external devices from the Home App on your iPhone, iPad, or Mac, or with Siri. +HomeSpan provides a microcontroller-focused implementation of Apple's HomeKit Accessory Protocol Specification Release R2 (HAP-R2) designed specifically for the Espressif ESP32 microcontroller running within the Arduino IDE. HomeSpan pairs directly to HomeKit via your home WiFi network without the need for any external bridges or components. With HomeSpan you can use the full power of the ESP32's I/O functionality to create custom control software and/or hardware to automatically operate external devices from the Home App on your iPhone, iPad, or Mac, or with Siri. HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](https://github.com/espressif/arduino-esp32), and has been tested up through version 2.0.6 (recommended). HomeSpan can be run on the original ESP32 as well as Espressif's ESP32-S2, ESP32-C3, and ESP32-S3 chips. @@ -112,9 +112,9 @@ Note that all documentation is version-controlled and tied to each branch. The # External Resources -In addition to HomeSpan resources, developers who are new to HomeKit programming should download Apple's [HomeKit Accessory Protocol Specification, Release R2 (HAP-R2)](https://developer.apple.com/homekit/specification/). The download is free, but Apple requires you to register your Apple ID for access to the document. +In addition to HomeSpan resources, developers who are new to HomeKit programming should download Apple's HomeKit Accessory Protocol Specification, Non-Commercial Version, Release R2 (HAP-R2). This document is unfortunately no longer available from Apple (perhaps because it was last updated July, 2019, and is now somewhat out-of-date). However, you may be able find copies of this document elsewhere on the web. Note Apple has not replaced the HAP-R2 document with any other versions for non-commercial use, and Apple's open-source [HomeKit ADK](https://github.com/apple/HomeKitADK) only reflects the original HAP-R2 specs (rather than all the latest Services and Characteristics available in HomeKit for commercial devices). -You ***do not*** need to read the entire document. The whole point of HomeSpan is that it implements all the required HAP operations under the hood so you can focus on just programming whatever logic is needed to control your real-world appliances (lights, fans, RF remote controls, etc.) with the device. However, you will find Chapters 8 and 9 of the HAP guide to be an invaluable reference as it lists and describes all of the Services and Characteristics implemented in HomeSpan, many of which you will routinely utilize in your own HomeSpan sketches. +You ***do not*** need to read the entire HAP-R2 document. The whole point of HomeSpan is that it implements all the required HAP operations under the hood so you can focus on just programming whatever logic is needed to control your real-world appliances (lights, fans, RF remote controls, etc.) with the device. However, you will find Chapters 8 and 9 of the HAP guide to be an invaluable reference as it lists and describes all of the Services and Characteristics implemented in HomeSpan, many of which you will routinely utilize in your own HomeSpan sketches. --- From 1ea1aef3a266cfdb0017752e2aa203bc8eb28e24 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Feb 2023 16:12:26 -0600 Subject: [PATCH 15/79] Update GettingStarted.md --- docs/GettingStarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index 99a1c9b..6fa3887 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -62,7 +62,7 @@ If you've not yet read through the [HomeSpan API Overview](Overview.md) page, yo Next, explore the tutorial sketches, upload a few, and see how they work. The examples start simple and grow in complexity, taking you through all the functions and features of HomeSpan. Along the way you'll also learn a lot of HomeKit tips and tricks. See [HomeSpan Tutorials](Tutorials.md) for a summary of all the included examples. Find something in a sketch you don't understand? Visit the [HomeSpan API Reference](Reference.md) for details on all HomeSpan objects, functions, and methods. Have a more general question? See if it's been answered on the [HomeSpan FAQ](FAQ.md) page or any of the [Disussion](https://github.com/HomeSpan/HomeSpan/discussions) or [Issues](https://github.com/HomeSpan/HomeSpan/issues) pages. If not, feel free to join the Discusion by adding a new question. -Ready to start creating your own HomeSpan sketches? Check out the [HomeSpan Services and Characteristics](ServiceList.md) page for a full list of all the HomeKit Services and Characteristics supported by HomeSpan, as well as the [HomeSpan Categories](Categories.md) page for a list of all supported HomeKit Categories. And don't forget to use Apple's [HomeKit Accessory Protocol Specification, Release R2 (HAP-R2)](https://developer.apple.com/homekit/specification/) as your go-to reference for details on every Service and Characteristic. +Ready to start creating your own HomeSpan sketches? Check out the [HomeSpan Services and Characteristics](ServiceList.md) page for a full list of all the HomeKit Services and Characteristics supported by HomeSpan, as well as the [HomeSpan Categories](Categories.md) page for a list of all supported HomeKit Categories. And don't forget to use Apple's HomeKit Accessory Protocol Specification, Release R2 (HAP-R2) as your go-to reference for details on every Service and Characteristic. While developing your sketch remember to utilize the Arduino Serial Monitor. HomeSpan produces extensive diagnostics that will help you debug your sketches as well as monitor all aspects of the HomeSpan device. You'll also be able to control various aspects of HomeSpan from the Serial Monitor using the [HomeSpan Command-Line Interface (CLI)](CLI.md), including configuring the device's WiFi Credentials and HomeKit Setup Code. From 9df6f3c50052c696844e758276f46ca2872a724b Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Feb 2023 16:15:22 -0600 Subject: [PATCH 16/79] Update Reference.md --- docs/Reference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Reference.md b/docs/Reference.md index 52de4b2..dc3c2b3 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -268,8 +268,8 @@ The following methods are supported: * note though this functionality is defined by Apple in HAP-R2, it seems to have been deprecated and no longer serves any purpose or has any affect on the Home App * `SpanService *addLink(SpanService *svc)` - * adds *svc* as a Linked Service. Returns a pointer to the calling Service itself so that the method can be chained during instantiation. - * note that Linked Services are only applicable for select HAP Services. See Apple's [HAP-R2](https://developer.apple.com/support/homekit-accessory-protocol/) documentation for full details. + * adds *svc* as a Linked Service. Returns a pointer to the calling Service itself so that the method can be chained during instantiation + * note that Linked Services are only applicable for select HAP Services. See Apple's HAP-R2 documentation for full details * example: `(new Service::Faucet)->addLink(new Service::Valve)->addLink(new Service::Valve);` (links two Valves to a Faucet) * `vector getLinks()` From 75930a1d6eb4f062281aca5dbc436457659e0776 Mon Sep 17 00:00:00 2001 From: Gregg Date: Fri, 17 Mar 2023 22:26:52 -0500 Subject: [PATCH 17/79] Update FeatherPins.h Changed from old ESP32-C3-DevKitM-1 to new ESP32-C3-DevKitC-02 --- src/FeatherPins.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FeatherPins.h b/src/FeatherPins.h index 562f5ad..8998a17 100644 --- a/src/FeatherPins.h +++ b/src/FeatherPins.h @@ -51,8 +51,8 @@ #elif defined(ARDUINO_ESP32C3_DEV) enum { - F27=2,F32=3,F14=10,F16=20,F17=21,F21=19, // Digital Only (6 pins) - F26=0,F25=1,F4=18, // A0/A1/A5 + F27=19,F32=2,F14=10,F16=20,F17=21,F21=18, // Digital Only (6 pins) + F26=0,F25=1,F4=3, // A0/A1/A5 F22=9,F23=8, // I2C SCL/SDA F5=4,F18=6,F19=5,F33=7, // SPI SCK/SDO/SDI/CS BUILTIN_PIXEL=8 // Built-in Neo-Pixel From 6ea9181c08304b0259b9258d82f500ef4945b8c9 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 18 Mar 2023 16:46:13 -0500 Subject: [PATCH 18/79] Move README to top-level folder --- docs/README.md => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/README.md => README.md (100%) diff --git a/docs/README.md b/README.md similarity index 100% rename from docs/README.md rename to README.md From 3a92e9bac8f8ca0ae6f4efcc44528c702f3aa26f Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 16:48:21 -0500 Subject: [PATCH 19/79] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c17e912..9a1fbde 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Welcome to HomeSpan - a robust and extremely easy-to-use Arduino library for cre HomeSpan provides a microcontroller-focused implementation of Apple's HomeKit Accessory Protocol Specification Release R2 (HAP-R2) designed specifically for the Espressif ESP32 microcontroller running within the Arduino IDE. HomeSpan pairs directly to HomeKit via your home WiFi network without the need for any external bridges or components. With HomeSpan you can use the full power of the ESP32's I/O functionality to create custom control software and/or hardware to automatically operate external devices from the Home App on your iPhone, iPad, or Mac, or with Siri. -HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](https://github.com/espressif/arduino-esp32), and has been tested up through version 2.0.6 (recommended). HomeSpan can be run on the original ESP32 as well as Espressif's ESP32-S2, ESP32-C3, and ESP32-S3 chips. +HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](https://github.com/espressif/arduino-esp32), and has been tested up through version 2.0.7 (recommended). HomeSpan can be run on the original ESP32 as well as Espressif's ESP32-S2, ESP32-C3, and ESP32-S3 chips. ### HomeSpan Highlights @@ -52,7 +52,7 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * **SpanPoint support for the ESP8266!** * Use ESP-NOW on an ESP8266 to connect to HomeSpan running on an ESP32 - * See the [SpanPoint Tutorial Page](NOW.md) for more info as well as a detailed ESP8266 example + * See the [SpanPoint Tutorial Page](docs/NOW.md) for more info as well as a detailed ESP8266 example * **SpanPoint WiFi channel scanning upgrade** * SpanPoint now saves the last WiFi channel successfully used for transmission in non-volatile storage From efdeca7b84dd86874f58ffa74b917fccb52d2457 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 16:52:03 -0500 Subject: [PATCH 20/79] Update README.md --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 9a1fbde..eec5b65 100644 --- a/README.md +++ b/README.md @@ -63,22 +63,22 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * Similar to SpanButton, but designed for toggle switches * Integrated de-bounce logic prevents false triggers * Ideal for use with Contact Sensors - * See the [API Reference](Reference.md) for details + * See the [API Reference](docs/Reference.md) for details * **Added Television Speaker Service** * Control the volume of a Television from Apple's Remote App - * See the [Television Services Page](TVServices.md) for details and examples + * See the [Television Services Page](docs/TVServices.md) for details and examples * **Added support for byte-array ("DATA") Characteristics** * Useful for experimentation with other HomeKit applications, such as *Eve for HomeKit* * Includes three new Characteristic methods: `setData()`, `getData()`, and `getNewData()` * Includes new macro `CUSTOM_CHAR_DATA()` to easily create custom byte-array Characteristics - * See the [API Reference](Reference.md) for details + * See the [API Reference](docs/Reference.md) for details * **LedPin upgrade** * New option to invert the PWM signal * Useful for generating two, separate out-of-phase PWM signals (one inverted, one not) to drive certain two-pin devices in a push/pull manner, such as a piezo-electric buzzer - * See the [PWM Page](PWM.md) for details + * See the [PWM Page](docs/PWM.md) for details * **Bug Fixes** * Added logic to prevent the extraneous broadcasting of an Access Point SSID when SpanPoint is being used @@ -89,24 +89,24 @@ See [Releases](https://github.com/HomeSpan/HomeSpan/releases) for details on all HomeSpan includes the following documentation: -* [Getting Started with HomeSpan](GettingStarted.md) - setting up the software and the hardware needed to develop HomeSpan devices -* [HomeSpan API Overview](Overview.md) - an overview of the HomeSpan API, including a step-by-step guide to developing your first HomeSpan Sketch -* [HomeSpan Tutorials](Tutorials.md) - a guide to HomeSpan's tutorial-sketches -* [HomeSpan Services and Characteristics](ServiceList.md) - a list of all HAP Services and Characterstics supported by HomeSpan -* [HomeSpan Accessory Categories](Categories.md) - a list of all HAP Accessory Categories defined by HomeSpan -* [HomeSpan Command-Line Interface (CLI)](CLI.md) - configure a HomeSpan device's WiFi Credentials, modify its HomeKit Setup Code, monitor and update its status, and access detailed, real-time device diagnostics from the Arduino IDE Serial Monitor -* [HomeSpan User Guide](UserGuide.md) - turnkey instructions on how to configure an already-programmed HomeSpan device's WiFi Credentials, modify its HomeKit Setup Code, and pair the device to HomeKit. No computer needed! -* [HomeSpan API Reference](Reference.md) - a complete guide to the HomeSpan Library API -* [HomeSpan QR Codes](QRCodes.md) - create and use QR Codes for pairing HomeSpan devices -* [HomeSpan OTA](OTA.md) - update your sketches Over-the-Air directly from the Arduino IDE without a serial connection -* [HomeSpan PWM](PWM.md) - integrated control of standard LEDs and Servo Motors using the ESP32's on-chip PWM peripheral -* [HomeSpan RFControl](RMT.md) - easy generation of RF and IR Remote Control signals using the ESP32's on-chip RMT peripheral -* [HomeSpan Pixels](Pixels.md) - integrated control of addressable one- and two-wire RGB and RGBW LEDs and LED strips -* [HomeSpan SpanPoint](NOW.md) - facilitates point-to-point, bi-directional communication between ESP32 Devices using ESP-NOW -* [HomeSpan Television Services](TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics -* [HomeSpan Message Logging](Logging.md) - how to generate log messages for display on the Arduino Serial Monitor as well as optionally posted to an integrated Web Log page +* [Getting Started with HomeSpan](docs/GettingStarted.md) - setting up the software and the hardware needed to develop HomeSpan devices +* [HomeSpan API Overview](docs/Overview.md) - an overview of the HomeSpan API, including a step-by-step guide to developing your first HomeSpan Sketch +* [HomeSpan Tutorials](docs/Tutorials.md) - a guide to HomeSpan's tutorial-sketches +* [HomeSpan Services and Characteristics](docs/ServiceList.md) - a list of all HAP Services and Characterstics supported by HomeSpan +* [HomeSpan Accessory Categories](docs/Categories.md) - a list of all HAP Accessory Categories defined by HomeSpan +* [HomeSpan Command-Line Interface (CLI)](docs/CLI.md) - configure a HomeSpan device's WiFi Credentials, modify its HomeKit Setup Code, monitor and update its status, and access detailed, real-time device diagnostics from the Arduino IDE Serial Monitor +* [HomeSpan User Guide](docs/UserGuide.md) - turnkey instructions on how to configure an already-programmed HomeSpan device's WiFi Credentials, modify its HomeKit Setup Code, and pair the device to HomeKit. No computer needed! +* [HomeSpan API Reference](docs/Reference.md) - a complete guide to the HomeSpan Library API +* [HomeSpan QR Codes](docs/QRCodes.md) - create and use QR Codes for pairing HomeSpan devices +* [HomeSpan OTA](docs/OTA.md) - update your sketches Over-the-Air directly from the Arduino IDE without a serial connection +* [HomeSpan PWM](docs/PWM.md) - integrated control of standard LEDs and Servo Motors using the ESP32's on-chip PWM peripheral +* [HomeSpan RFControl](docs/RMT.md) - easy generation of RF and IR Remote Control signals using the ESP32's on-chip RMT peripheral +* [HomeSpan Pixels](docs/Pixels.md) - integrated control of addressable one- and two-wire RGB and RGBW LEDs and LED strips +* [HomeSpan SpanPoint](docs/NOW.md) - facilitates point-to-point, bi-directional communication between ESP32 Devices using ESP-NOW +* [HomeSpan Television Services](docs/TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics +* [HomeSpan Message Logging](docs/Logging.md) - how to generate log messages for display on the Arduino Serial Monitor as well as optionally posted to an integrated Web Log page * [HomeSpan Projects](https://github.com/topics/homespan) - real-world applications of the HomeSpan Library -* [HomeSpan FAQ](FAQ.md) - answers to frequently-asked questions +* [HomeSpan FAQ](docs/FAQ.md) - answers to frequently-asked questions Note that all documentation is version-controlled and tied to each branch. The *master* branch generally points to the latest release. The *dev* branch, when available, will contain code under active development. From 2168dfc9748404b3266960a068d2d7f7727f1c4a Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 16:56:45 -0500 Subject: [PATCH 21/79] Update CLI.md --- docs/CLI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CLI.md b/docs/CLI.md index 1572914..4481176 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -97,7 +97,7 @@ You can extend the HomeSpan CLI with custom functions using `SpanUserCommand()`. --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 8aa3bf81bb10016c7e28665cb4b03453a199e42f Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 16:57:38 -0500 Subject: [PATCH 22/79] Update Categories.md --- docs/Categories.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Categories.md b/docs/Categories.md index 39fade8..ab0fa5f 100644 --- a/docs/Categories.md +++ b/docs/Categories.md @@ -41,5 +41,5 @@ Note that the HomeKit primarily uses the Accessory Category of a device for dete --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 5356453f3610837f51dde59fbeaf1ae947d9a919 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:02:09 -0500 Subject: [PATCH 23/79] Update GettingStarted.md --- docs/GettingStarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index 6fa3887..09b84d0 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -72,4 +72,4 @@ Finally, disconnect your HomeSpan device from the computer and power it directly --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 1824adf9da4a1860eb0f39566deb3a2fd4bccecd Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:02:39 -0500 Subject: [PATCH 24/79] Update FAQ.md --- docs/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index baa47ab..c5e2ba1 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -72,5 +72,5 @@ --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 517a88411b10867e615b0acac8f01e2ca2fec64d Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:03:33 -0500 Subject: [PATCH 25/79] Update Logging.md --- docs/Logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Logging.md b/docs/Logging.md index 4f446f8..6f40b99 100644 --- a/docs/Logging.md +++ b/docs/Logging.md @@ -60,6 +60,6 @@ See [Example 19 - WebLog](Tutorials.md#example-19---weblog) for a tutorial sketc --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 5b62c70f3ebc78a2586825eba1ee82d7ed944d94 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:03:48 -0500 Subject: [PATCH 26/79] Update NOW.md --- docs/NOW.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/NOW.md b/docs/NOW.md index 9628193..40f92bd 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -83,4 +83,4 @@ Examples showing such a configuration can be found in the Arduino IDE under [*Fi * *RemoteDevice8266.ino* - similar in function to *RemoteDevice.ino*, but implemented to run on an ESP8266 device using native ESP-NOW commands (since neither HomeSpan nor SpanPoint support the ESP8266). Note that the "complementary" SpanPoint object on the ESP32 that receives data from the ESP8266 must be configured to use the ESP32's *AP MAC Address* (instead of the *STA MAC Address*) by setting *useAPaddress* to *true* in the SpanPoint constructor --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From b69169398188ae1207c0151d2b92df5dacec3aad Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:04:10 -0500 Subject: [PATCH 27/79] Update OTA.md --- docs/OTA.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/OTA.md b/docs/OTA.md index 408f0c8..5b1ecee 100644 --- a/docs/OTA.md +++ b/docs/OTA.md @@ -38,6 +38,6 @@ Note that these check are *only* applicable when uploading sketches via OTA. Th --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 389f485bc3902c43ee75614062572b95b0e0f2c0 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:04:29 -0500 Subject: [PATCH 28/79] Update Overview.md --- docs/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Overview.md b/docs/Overview.md index eb63eb6..8563964 100644 --- a/docs/Overview.md +++ b/docs/Overview.md @@ -314,5 +314,5 @@ Finally, don't forget to visit the [HomeSpan Command-Line Interface (CLI)](CLI.m --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From ff06c85b30e57de9f98c338eacb739f7b1a3faa9 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:04:57 -0500 Subject: [PATCH 29/79] Update PWM.md --- docs/PWM.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PWM.md b/docs/PWM.md index c8329af..a653639 100644 --- a/docs/PWM.md +++ b/docs/PWM.md @@ -74,4 +74,4 @@ HomeSpan will report a non-fatal error message to the Arduino Serial Monitor whe --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From f6fa5e350d9a791cf0a231b5f86e79a66bde62a2 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:05:12 -0500 Subject: [PATCH 30/79] Update Pixels.md --- docs/Pixels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Pixels.md b/docs/Pixels.md index 77367ae..39b26bc 100644 --- a/docs/Pixels.md +++ b/docs/Pixels.md @@ -124,4 +124,4 @@ For a more complete showcase of the Pixel library , check out [Holiday Lights](h --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From ed595f1ac612e5dfa04075d8f6cc9a5d8596ca44 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:05:26 -0500 Subject: [PATCH 31/79] Update QRCodes.md --- docs/QRCodes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/QRCodes.md b/docs/QRCodes.md index 463e7dc..fbf4955 100644 --- a/docs/QRCodes.md +++ b/docs/QRCodes.md @@ -63,6 +63,6 @@ The result must be 9 digits. If less, pad with leading zeros. --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From c72182351600cdf95c95459ac13c902d06c4ca82 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:05:39 -0500 Subject: [PATCH 32/79] Update RMT.md --- docs/RMT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RMT.md b/docs/RMT.md index fe1c49b..4eda785 100644 --- a/docs/RMT.md +++ b/docs/RMT.md @@ -139,4 +139,4 @@ void loop(){ --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 5f016a9c36f262d9704dcf38192aeea567ceb4ac Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:06:05 -0500 Subject: [PATCH 33/79] Update Reference.md --- docs/Reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Reference.md b/docs/Reference.md index dc3c2b3..843339d 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -600,4 +600,4 @@ If REQUIRED is defined in the main sketch *prior* to including the HomeSpan libr --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From f3dd2f1315c5164afbff71ad2178a8462f25867e Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:06:23 -0500 Subject: [PATCH 34/79] Update ServiceList.md --- docs/ServiceList.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ServiceList.md b/docs/ServiceList.md index 6134039..db56e1c 100644 --- a/docs/ServiceList.md +++ b/docs/ServiceList.md @@ -194,4 +194,4 @@ Additionally, when first starting up, HomeSpan begins by validating the device's --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 3c86e158f119f950680a99315dfa8cdc6a30b503 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:06:39 -0500 Subject: [PATCH 35/79] Update TVServices.md --- docs/TVServices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/TVServices.md b/docs/TVServices.md index 3b35514..ee0754e 100644 --- a/docs/TVServices.md +++ b/docs/TVServices.md @@ -79,4 +79,4 @@ Much thanks to @unreality for the PR to include Television codes and associated --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From d392dcec010c5159d5a1fb624048d58caf0ac78d Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:06:59 -0500 Subject: [PATCH 36/79] Update Tutorials.md --- docs/Tutorials.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Tutorials.md b/docs/Tutorials.md index d321446..006ed86 100644 --- a/docs/Tutorials.md +++ b/docs/Tutorials.md @@ -137,4 +137,4 @@ Demonstrates how SpanPoint can be used to transmit messages from battery-powered --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From 61665c677634f263affe462e5866442b60b397e4 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 18 Mar 2023 17:07:14 -0500 Subject: [PATCH 37/79] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 39a84e8..a2cb90d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -159,6 +159,6 @@ Note that if you can’t find *Scancardium* listed as a font choice in either th --- -[↩️](README.md) Back to the Welcome page +[↩️](../README.md) Back to the Welcome page From ecd97e6e71875109e625e89d74c1a92bb540fc79 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 25 Mar 2023 10:58:03 -0500 Subject: [PATCH 38/79] Added option to set Priority and CPU in autoPoll() Also added vTaskDelay(5) in pollTask to make sure competing tasks can operate (for example, if priority was set to greater than 2, touch sensor did not operate). Adding vTaskDelay(5) solved this problem. --- src/HomeSpan.cpp | 2 ++ src/HomeSpan.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 2a709e8..213c671 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -309,6 +309,8 @@ void Span::pollTask() { } statusLED->check(); + + vTaskDelay(5); } // poll diff --git a/src/HomeSpan.h b/src/HomeSpan.h index 3e40729..3b4a20d 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -341,7 +341,10 @@ class Span{ va_end(ap); } - void autoPoll(uint32_t stackSize=CONFIG_ARDUINO_LOOP_STACK_SIZE){xTaskCreateUniversal([](void *parms){for(;;)homeSpan.pollTask();}, "pollTask", stackSize, NULL, 1, &pollTaskHandle, 0);} // start pollTask() + void autoPoll(uint32_t stackSize=8192, uint32_t priority=1, uint32_t cpu=0){ // start pollTask() + xTaskCreateUniversal([](void *parms){for(;;)homeSpan.pollTask();}, "pollTask", stackSize, NULL, priority, &pollTaskHandle, cpu); + Serial.printf("\n*** AutoPolling Task started with priority=%d\n\n",uxTaskPriorityGet(pollTaskHandle)); + } void setTimeServerTimeout(uint32_t tSec){webLog.waitTime=tSec*1000;} // sets wait time (in seconds) for optional web log time server to connect From 899260ac921ee2271ded17725180d4317a327bd9 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 25 Mar 2023 11:16:19 -0500 Subject: [PATCH 39/79] Update Reference.md --- docs/Reference.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/Reference.md b/docs/Reference.md index 843339d..c653e6f 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -221,12 +221,15 @@ The following **optional** `homeSpan` methods provide additional run-time functi The following `homeSpan` methods are considered experimental, since not all use cases have been explored or debugged. Use with caution: -* `void autoPoll(uint32_t stackSize)` - * an *optional* method to create a task with *stackSize* bytes of stack memory that repeatedly calls `poll()` in the background. This frees up the Ardino `loop()` method for any user-defined code to run in parallel that would otherwise block, or be blocked by, calling `poll()` in the `loop()` method +* `void autoPoll(uint32_t stackSize, uint32_t priority, uint32_t cpu)` + + * an *optional* method to create a separate task that repeatedly calls `poll()` in the background. This frees up the Ardino `loop()` method for any user-defined code to run in parallel that would otherwise block, or be blocked by, calling `poll()` in the `loop()` method. Parameters, and their default values if unspecified, are as follows: + + * *stackSize* - size of stack, in bytes, used by the polling task. Default=8192 if unspecified + * *priority* - priority at which task runs. Minimum is 1. Maximum is typically 24, but it depends on how the ESP32 operating system is configured. If you set it to an arbitrarily high value (e.g. 999), it will be set to the maximum priority allowed. Default=1 if unspecified + * *cpu* - specifies the CPU on which the polling task will run. Valid values are 0 and 1. This paramater is ignored on single-cpu boards. Default=0 if unspecified * if used, **must** be placed in a sketch as the last line in the Arduino `setup()` method * HomeSpan will throw and error and halt if both `poll()`and `autoPoll()` are used in the same sketch - either place `poll()` in the Arduino `loop()` method **or** place `autoPoll()` at the the end of the Arduino `setup()` method - * can be used with both single-core and dual-core ESP32 boards. If used with a dual-core board, the polling task is created on the free processor that is typically not running other Arduino functions - * if *stackSize* is not specified, defaults to the size used by the system for the normal Arduino `loop()` task (typically 8192 bytes) * if this method is used, and you have no need to add your own code to the main Arduino `loop()`, you can safely skip defining a blank `void loop(){}` function in your sketch * warning: if any code you add to the Arduino `loop()` method tries to alter any HomeSpan settings or functions running in the background `poll()` task, race conditions may yield undefined results From 6079b8edf7c10cc1af487e01bd6dd320ab6b1b36 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 25 Mar 2023 12:19:08 -0500 Subject: [PATCH 40/79] Bump version to 1.7.2 --- src/Settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Settings.h b/src/Settings.h index f170d04..9dcdb7a 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -36,7 +36,7 @@ #define HS_MAJOR 1 #define HS_MINOR 7 -#define HS_PATCH 1 +#define HS_PATCH 2 #define STRINGIFY(x) _STR(x) #define _STR(x) #x From a79b7569d13fb8592f2c47647222b42c131fa241 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 25 Mar 2023 23:05:22 -0500 Subject: [PATCH 41/79] Begin implementation of hardware LEDC fade --- src/src/extras/PwmPin.cpp | 26 +++++++++++++++++++++----- src/src/extras/PwmPin.h | 1 + src/src/extras/extras.ino | 26 +++++++++----------------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/src/extras/PwmPin.cpp b/src/src/extras/PwmPin.cpp index 8ba7123..b019dfd 100644 --- a/src/src/extras/PwmPin.cpp +++ b/src/src/extras/PwmPin.cpp @@ -81,7 +81,7 @@ LedC::LedC(uint8_t pin, uint16_t freq, boolean invert){ /////////////////// LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(pin, freq, invert){ - + if(!channel) Serial.printf("\n*** ERROR: Can't create LedPin(%d) - no open PWM channels and/or Timers ***\n\n",pin); else @@ -95,8 +95,9 @@ LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(p channel->flags.output_invert?"(inverted)":"" ); - set(level); - + ledc_fade_func_install(0); + + set(level); } /////////////////// @@ -110,9 +111,24 @@ void LedPin::set(float level){ level=100; float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; + channel->duty=d; - ledc_channel_config(channel); - + ledc_channel_config(channel); +} + +/////////////////// + +void LedPin::fade(float level, uint32_t fadeTime){ + + if(!channel) + return; + + if(level>100) + level=100; + + float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; + + ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,(uint32_t)d,fadeTime,LEDC_FADE_NO_WAIT); } /////////////////// diff --git a/src/src/extras/PwmPin.h b/src/src/extras/PwmPin.h index 53e409e..68751ca 100644 --- a/src/src/extras/PwmPin.h +++ b/src/src/extras/PwmPin.h @@ -77,6 +77,7 @@ class LedPin : public LedC { public: LedPin(uint8_t pin, float level=0, uint16_t freq=DEFAULT_PWM_FREQ, boolean invert=false); // assigns pin to be output of one of 16 PWM channels initial level and frequency void set(float level); // sets the PWM duty to level (0-100) + void fade(float level, uint32_t fadeTime); // sets the PWM duty to level (0-100) within fadeTime in milliseconds static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B }; diff --git a/src/src/extras/extras.ino b/src/src/extras/extras.ino index 0097f00..a982c54 100644 --- a/src/src/extras/extras.ino +++ b/src/src/extras/extras.ino @@ -28,12 +28,7 @@ // This is a placeholder .ino file that allows you to easily edit the contents of this files using the Arduino IDE, // as well as compile and test from this point. This file is ignored when the library is included in other sketches. -#include "Blinker.h" -#include "Pixel.h" -#include - -Blinker p(new Pixel(2),10); -//Blinker p(NULL,10); +#include "PwmPin.h" void setup() { @@ -41,19 +36,16 @@ void setup() { Serial.flush(); delay(1000); // wait for interface to flush - Serial.println("\n\nHomeSpan Blinker Example\n"); - Serial.printf("Pins = %d\n",p.getPin()); + Serial.println("\n\nHomeSpan LED Fade Test\n"); + + LedPin led(26,50); + Serial.printf("Start\n"); + led.fade(0,10000); + Serial.printf("End\n"); + + while(1); - p.on(); - delay(2000); - p.off(); - delay(2000); - p.start(300,0.25,4,1000); - delay(5000); - Serial.printf("New Pattern\n"); - p.start(200,0.2,2,200); } void loop(){ - p.check(); } From c2df57815c290235f2127a40bfbb3409a46b5806 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sun, 26 Mar 2023 07:39:06 -0500 Subject: [PATCH 42/79] Added fadeTime parameter to LedPin::set() --- src/src/extras/PwmPin.cpp | 27 ++++++++------------------- src/src/extras/PwmPin.h | 3 +-- src/src/extras/extras.ino | 8 ++++++-- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/src/extras/PwmPin.cpp b/src/src/extras/PwmPin.cpp index b019dfd..404105f 100644 --- a/src/src/extras/PwmPin.cpp +++ b/src/src/extras/PwmPin.cpp @@ -102,7 +102,7 @@ LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(p /////////////////// -void LedPin::set(float level){ +void LedPin::set(float level, uint32_t fadeTime){ if(!channel) return; @@ -110,25 +110,14 @@ void LedPin::set(float level){ if(level>100) level=100; - float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; - - channel->duty=d; - ledc_channel_config(channel); -} + float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; -/////////////////// - -void LedPin::fade(float level, uint32_t fadeTime){ - - if(!channel) - return; - - if(level>100) - level=100; - - float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; - - ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,(uint32_t)d,fadeTime,LEDC_FADE_NO_WAIT); + if(fadeTime==0){ + channel->duty=d; + ledc_channel_config(channel); + } else { + ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,(uint32_t)d,fadeTime,LEDC_FADE_NO_WAIT); + } } /////////////////// diff --git a/src/src/extras/PwmPin.h b/src/src/extras/PwmPin.h index 68751ca..b6c6452 100644 --- a/src/src/extras/PwmPin.h +++ b/src/src/extras/PwmPin.h @@ -76,8 +76,7 @@ class LedPin : public LedC { public: LedPin(uint8_t pin, float level=0, uint16_t freq=DEFAULT_PWM_FREQ, boolean invert=false); // assigns pin to be output of one of 16 PWM channels initial level and frequency - void set(float level); // sets the PWM duty to level (0-100) - void fade(float level, uint32_t fadeTime); // sets the PWM duty to level (0-100) within fadeTime in milliseconds + void set(float level, uint32_t fadeTime=0); // sets the PWM duty to level (0-100) within fadeTime in milliseconds static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B }; diff --git a/src/src/extras/extras.ino b/src/src/extras/extras.ino index a982c54..43b2fbd 100644 --- a/src/src/extras/extras.ino +++ b/src/src/extras/extras.ino @@ -38,9 +38,13 @@ void setup() { Serial.println("\n\nHomeSpan LED Fade Test\n"); - LedPin led(26,50); + LedPin led(26); + for(int i=10;i<=100;i+=10){ + led.set(i); + delay(1000); + } Serial.printf("Start\n"); - led.fade(0,10000); + led.set(0,5000); Serial.printf("End\n"); while(1); From fab94722d8094f422fc13ad6b35df19ca43fc832 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sun, 26 Mar 2023 07:48:22 -0500 Subject: [PATCH 43/79] Revert "Added fadeTime parameter to LedPin::set()" This reverts commit c2df57815c290235f2127a40bfbb3409a46b5806. --- src/src/extras/PwmPin.cpp | 27 +++++++++++++++++++-------- src/src/extras/PwmPin.h | 3 ++- src/src/extras/extras.ino | 8 ++------ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/src/extras/PwmPin.cpp b/src/src/extras/PwmPin.cpp index 404105f..b019dfd 100644 --- a/src/src/extras/PwmPin.cpp +++ b/src/src/extras/PwmPin.cpp @@ -102,7 +102,7 @@ LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(p /////////////////// -void LedPin::set(float level, uint32_t fadeTime){ +void LedPin::set(float level){ if(!channel) return; @@ -110,14 +110,25 @@ void LedPin::set(float level, uint32_t fadeTime){ if(level>100) level=100; - float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; + float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; + + channel->duty=d; + ledc_channel_config(channel); +} - if(fadeTime==0){ - channel->duty=d; - ledc_channel_config(channel); - } else { - ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,(uint32_t)d,fadeTime,LEDC_FADE_NO_WAIT); - } +/////////////////// + +void LedPin::fade(float level, uint32_t fadeTime){ + + if(!channel) + return; + + if(level>100) + level=100; + + float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; + + ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,(uint32_t)d,fadeTime,LEDC_FADE_NO_WAIT); } /////////////////// diff --git a/src/src/extras/PwmPin.h b/src/src/extras/PwmPin.h index b6c6452..68751ca 100644 --- a/src/src/extras/PwmPin.h +++ b/src/src/extras/PwmPin.h @@ -76,7 +76,8 @@ class LedPin : public LedC { public: LedPin(uint8_t pin, float level=0, uint16_t freq=DEFAULT_PWM_FREQ, boolean invert=false); // assigns pin to be output of one of 16 PWM channels initial level and frequency - void set(float level, uint32_t fadeTime=0); // sets the PWM duty to level (0-100) within fadeTime in milliseconds + void set(float level); // sets the PWM duty to level (0-100) + void fade(float level, uint32_t fadeTime); // sets the PWM duty to level (0-100) within fadeTime in milliseconds static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B }; diff --git a/src/src/extras/extras.ino b/src/src/extras/extras.ino index 43b2fbd..a982c54 100644 --- a/src/src/extras/extras.ino +++ b/src/src/extras/extras.ino @@ -38,13 +38,9 @@ void setup() { Serial.println("\n\nHomeSpan LED Fade Test\n"); - LedPin led(26); - for(int i=10;i<=100;i+=10){ - led.set(i); - delay(1000); - } + LedPin led(26,50); Serial.printf("Start\n"); - led.set(0,5000); + led.fade(0,10000); Serial.printf("End\n"); while(1); From ce36174f9393247e03f050a28ba2976e6ec719e5 Mon Sep 17 00:00:00 2001 From: Gregg Date: Fri, 31 Mar 2023 22:07:31 -0500 Subject: [PATCH 44/79] Completed LED fading functionality; added new Fading LED example (in Other Examples) --- .../Other Examples/FadingLED/FadingLED.ino | 113 ++++++++++++++++++ src/src/extras/PwmPin.cpp | 37 +++++- src/src/extras/PwmPin.h | 19 ++- src/src/extras/extras.ino | 28 ++++- 4 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 examples/Other Examples/FadingLED/FadingLED.ino diff --git a/examples/Other Examples/FadingLED/FadingLED.ino b/examples/Other Examples/FadingLED/FadingLED.ino new file mode 100644 index 0000000..9ca5a81 --- /dev/null +++ b/examples/Other Examples/FadingLED/FadingLED.ino @@ -0,0 +1,113 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2020-2023 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 Fading-LED Example. Demonstrates use of: +// +// LedPin::fade() and LedPin::fadeStatus() methods +// +// In this sketch we control a single dimmable LED using the Home App as well as a SpanButton. +// You can control the brightness of the LED from the Home App, but the SpanButton only turns the +// LED either fully on (if it's off) or fully off (if it's already on). +// +// Rather than set the LED to a specific brightness, this sketch uses the ESP32's hardware-based fading +// functionality to fade the LED from one level to the next. We set the timing for each fade to be 2000 ms, +// proportional to the difference between the current brightness and the desired brightness. This means it +// will take a full 2 seconds to fade the LED from 0-100, but only 1 second to fade from half-brightness to +// off. + +#include "HomeSpan.h" +#include "extras/PwmPin.h" // library of various PWM functions + +//////////////////////////////////// + +struct FadingLED : Service::LightBulb { + + LedPin *ledPin; // reference to Led Pin + SpanCharacteristic *power; // reference to the On Characteristic + SpanCharacteristic *level; // reference to the Brightness Characteristic + + FadingLED(int _ledPin, int _buttonPin) : Service::LightBulb(){ + + power=new Characteristic::On(); + level=new Characteristic::Brightness(0); + ledPin=new LedPin(_ledPin); + new SpanButton(_buttonPin); + + } + + boolean update(){ + + ledPin->fade(power->getNewVal()*level->getNewVal(),2000,LedPin::PROPORTIONAL); // use fade() to set new level; timing=2 seconds, proportional scale + while(ledPin->fadeStatus()==LedPin::FADING); // wait until fading is completed + + return(true); + + } + + void button(int pin, int pressType) override { + + // Below we turn LED fully on or off depending on whether power is on + // Unlike above, we will NOT wait for the fading to complete, but will return immediately + + if(ledPin->fade(100-(power->getVal())*100,2000,LedPin::PROPORTIONAL)!=0) // use fade to either turn fully on or fully off; check return status to see if call was successful + Serial.printf("Button Press Ignored\n"); + } + + void loop() override { + + // Below we set power and level once fading from a button press is completed + + if(ledPin->fadeStatus()==LedPin::COMPLETED){ + power->setVal(1-power->getVal()); + level->setVal(power->getVal()?100:0); + } + } + +}; + +////////////////////////////////// + +void setup() { + + Serial.begin(115200); + + homeSpan.begin(Category::Lighting,"Fading LED"); + + new SpanAccessory(); + new Service::AccessoryInformation(); + new Characteristic::Identify(); + + new FadingLED(26,4); // first argument is LED Pin, second argument is PushButton Pin + +} + +////////////////////////////////////// + +void loop(){ + + homeSpan.poll(); +} diff --git a/src/src/extras/PwmPin.cpp b/src/src/extras/PwmPin.cpp index b019dfd..d5eab95 100644 --- a/src/src/extras/PwmPin.cpp +++ b/src/src/extras/PwmPin.cpp @@ -96,6 +96,8 @@ LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(p ); ledc_fade_func_install(0); + ledc_cbs_t fadeCallbackList = {.fade_cb = fadeCallback}; // for some reason, ledc_cb_register requires the function to be wrapped in a structure + ledc_cb_register(channel->speed_mode,channel->channel,&fadeCallbackList,this); set(level); } @@ -118,21 +120,48 @@ void LedPin::set(float level){ /////////////////// -void LedPin::fade(float level, uint32_t fadeTime){ +int LedPin::fade(float level, uint32_t fadeTime, int fadeType){ if(!channel) - return; + return(1); + + if(fadeState==FADING) // fading already in progress + return(1); // return error if(level>100) level=100; - float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; + float d=level*(pow(2,(int)timer->duty_resolution)-1)/100.0; - ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,(uint32_t)d,fadeTime,LEDC_FADE_NO_WAIT); + if(fadeType==PROPORTIONAL) + fadeTime*=fabs((float)ledc_get_duty(channel->speed_mode,channel->channel)-d)/(float)(pow(2,(int)timer->duty_resolution)-1); + + fadeState=FADING; + ledc_set_fade_time_and_start(channel->speed_mode,channel->channel,d,fadeTime,LEDC_FADE_NO_WAIT); + return(0); } /////////////////// +int LedPin::fadeStatus(){ + if(fadeState==COMPLETED){ + fadeState=NOT_FADING; + return(COMPLETED); + } + + return(fadeState); +} + +/////////////////// + +bool IRAM_ATTR LedPin::fadeCallback(const ledc_cb_param_t *param, void *arg){ + ((LedPin *)arg)->fadeState=COMPLETED; + return(false); +} + +/////////////////// + + void LedPin::HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ){ // The algorithm below was provided on the web at https://www.cs.rit.edu/~ncs/color/t_convert.html diff --git a/src/src/extras/PwmPin.h b/src/src/extras/PwmPin.h index 68751ca..fe5dae5 100644 --- a/src/src/extras/PwmPin.h +++ b/src/src/extras/PwmPin.h @@ -74,10 +74,27 @@ class LedC { class LedPin : public LedC { + public: + enum { + NOT_FADING, + COMPLETED, + FADING + }; + + enum { + ABSOLUTE, + PROPORTIONAL + }; + + private: + int fadeState=NOT_FADING; + static bool fadeCallback(const ledc_cb_param_t *param, void *arg); + public: LedPin(uint8_t pin, float level=0, uint16_t freq=DEFAULT_PWM_FREQ, boolean invert=false); // assigns pin to be output of one of 16 PWM channels initial level and frequency void set(float level); // sets the PWM duty to level (0-100) - void fade(float level, uint32_t fadeTime); // sets the PWM duty to level (0-100) within fadeTime in milliseconds + int fade(float level, uint32_t fadeTime, int fadeType=ABSOLUTE); // sets the PWM duty to level (0-100) within fadeTime in milliseconds, returns success (0) or fail (1) + int fadeStatus(); // returns fading state static void HSVtoRGB(float h, float s, float v, float *r, float *g, float *b ); // converts Hue/Saturation/Brightness to R/G/B }; diff --git a/src/src/extras/extras.ino b/src/src/extras/extras.ino index a982c54..072d8d9 100644 --- a/src/src/extras/extras.ino +++ b/src/src/extras/extras.ino @@ -38,13 +38,31 @@ void setup() { Serial.println("\n\nHomeSpan LED Fade Test\n"); - LedPin led(26,50); - Serial.printf("Start\n"); - led.fade(0,10000); - Serial.printf("End\n"); + LedPin red(33,0); + LedPin green(32,0); + LedPin blue(14,0); - while(1); + int redLevel=0; + for(int i=100;i<=100;i+=10){ + while(red.fadeStatus()==LedPin::FADING); + red.fade(i,1000,LedPin::PROPORTIONAL); + } + + while(1); + + + while(1){ + delay(1000); + if(red.fade(redLevel,5000)) + Serial.printf("Failed\n"); + else{ + Serial.printf("Success\n"); + redLevel=100-redLevel; + } + + } + } void loop(){ From 8a0de9097c343c2f53e74126ba6e20639951b27b Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 08:17:01 -0500 Subject: [PATCH 45/79] Update PWM.md --- docs/PWM.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/PWM.md b/docs/PWM.md index a653639..e58e6d8 100644 --- a/docs/PWM.md +++ b/docs/PWM.md @@ -18,6 +18,28 @@ Creating an instance of this **class** configures the specified *pin* to output * `void set(float level)` * sets the PWM %duty-cycle to *level*, where *level* ranges from 0 (LED completely off) to 100 (LED fully on) + +* `int fade(float level, uint32_t fadeTime, int fadeType=LedPin::ABSOLUTE)` + + * uses the ESP32's PWM hardware to smoothly fade the LED to *level* (from 0-100) over a maximum of *fadeTime* milliseconds + * if *fadeType* is set to **LedPin::ABSOLUTE** (the default), fading will take the full amount of time specified by *fadeTime* + * if *fadeType* is set to **LedPin::PROPORTIONAL**, the fading time will be scaled down proportionally according to the difference between the current level and the level specified. For example, if the current level is set to 30, then + * `fade(20, 1000, LedPin::ABSOLUTE)` sets the level to 20 over the course of 1 second, whereas + * `fade(20, 1000, LedPin::PROPORTIONAL)` sets the level to 20 over the course of 100 milliseconds (since the level only needs to change by 10 out of 100 units) + * this is a **NON-BLOCKING** method and will return immediately. Fading occurs in the background controlled by the ESP32 hardware + * note: once fading begins it CANNOT be stopped or changed until completed (this is a limitation of the ESP32 hardware) + * this method returns 0 if the fading has successfully started, or 1 if fading is already in progress and cannot yet be changed (new requests for fading while fading is already in progress for a specific LedPin are simply ignored) + * use the *fadeStatus* method (below) to determine the current fading status of any given LedPin + +* `int fadeStatus()` + + * returns the fading status of an LedPin. Return values are as follows: + + * **LedPin::NOT_FADING** - the LedPin is not currently fading + * **LedPin::FADING** - fading on LedPin is currently in progress and cannot be changed/stopped + * **LedPin::COMPLETED** - fading has just completed + * once this value is returned, subsequent calls to `fadeStatus()` will return **LedPin::NOT_FADING** (unless you called `fade()` again) + * by checking for `fadeStatus()==LedPin::COMPLETED` in a `loop()` method, you can thus trigger a new action (if desired) once fading is completed * `int getPin()` From f466e12c7abca42fb650664c85f52679b583f80c Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 1 Apr 2023 12:16:15 -0500 Subject: [PATCH 46/79] some cleanup of LedPin comments in examples Removed old references to "channels" which should have been deleted many versions ago --- examples/06-DimmableLED/06-DimmableLED.ino | 4 ++-- examples/10-RGB_LED/DEV_LED.h | 2 +- examples/15-RealPushButtons/DEV_LED.h | 3 --- src/src/extras/PwmPin.cpp | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/06-DimmableLED/06-DimmableLED.ino b/examples/06-DimmableLED/06-DimmableLED.ino index f81ea0f..804b116 100644 --- a/examples/06-DimmableLED/06-DimmableLED.ino +++ b/examples/06-DimmableLED/06-DimmableLED.ino @@ -53,8 +53,8 @@ void setup() { // output to drive the brightness of an LED. The ESP32 code base itself includes a set of functions to create PWM output // and the ESP32 chip has built-in PWM functionality specifically for this purpose. There are numerous libraries // you can download that mimics or reproduces analogWrite() in some form or another. HomeSpan conveniently comes with - // it own version of a wrapper around the ESP32 PWM classes that make it very easy to define PWM "channel," attach a pin, - // and set the PWM level (or duty cycle) from 0-100%. These functions are encapsualted in the LedPin class, as defined in + // its own version of a wrapper around the ESP32 PWM classes that make it very easy to define LED pins, and set the + // PWM level (or duty cycle) from 0-100%. These functions are encapsualted in the LedPin class, as defined in // extras/PwmPin.h. We will include this file in our updated DEV_LED.h for use with DEV_DimmableLED. Serial.begin(115200); diff --git a/examples/10-RGB_LED/DEV_LED.h b/examples/10-RGB_LED/DEV_LED.h index 833b8ad..480f3ce 100644 --- a/examples/10-RGB_LED/DEV_LED.h +++ b/examples/10-RGB_LED/DEV_LED.h @@ -182,7 +182,7 @@ struct DEV_RgbLED : Service::LightBulb { // RGB LED (Command Cathode) sprintf(cBuf,"RGB=(%d,%d,%d)\n",R,G,B); LOG1(cBuf); - redPin->set(R); // update the ledPin channels with new values + redPin->set(R); // update each ledPin with new values greenPin->set(G); bluePin->set(B); diff --git a/examples/15-RealPushButtons/DEV_LED.h b/examples/15-RealPushButtons/DEV_LED.h index 1f03838..93a3657 100644 --- a/examples/15-RealPushButtons/DEV_LED.h +++ b/examples/15-RealPushButtons/DEV_LED.h @@ -20,7 +20,6 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED int powerPin; // NEW! pin with pushbutton to turn on/off LED int raisePin; // NEW! pin with pushbutton to increase brightness int lowerPin; // NEW! pin with pushButton to decrease brightness - int channel; // PWM channel used for this LED (should be unique for each LED) SpanCharacteristic *power; // reference to the On Characteristic SpanCharacteristic *level; // reference to the Brightness Characteristic int favoriteLevel=50; // NEW! keep track of a 'favorite' level @@ -53,8 +52,6 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED Serial.print("Configuring Dimmable LED: Pin="); // initialization message Serial.print(ledPin->getPin()); - Serial.print(" Channel="); - Serial.print(channel); Serial.print("\n"); } // end constructor diff --git a/src/src/extras/PwmPin.cpp b/src/src/extras/PwmPin.cpp index d5eab95..d39b704 100644 --- a/src/src/extras/PwmPin.cpp +++ b/src/src/extras/PwmPin.cpp @@ -85,7 +85,7 @@ LedPin::LedPin(uint8_t pin, float level, uint16_t freq, boolean invert) : LedC(p if(!channel) Serial.printf("\n*** ERROR: Can't create LedPin(%d) - no open PWM channels and/or Timers ***\n\n",pin); else - Serial.printf("LedPin=%d: mode=%d channel=%d, timer=%d, freq=%d Hz, resolution=%d bits %s\n", + Serial.printf("LedPin=%d: mode=%d, channel=%d, timer=%d, freq=%d Hz, resolution=%d bits %s\n", channel->gpio_num, channel->speed_mode, channel->channel, From f3db7fe810472d88626c99ee2c0afcbd1b7f3d1a Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:24:24 -0500 Subject: [PATCH 47/79] Update Tutorials.md --- docs/Tutorials.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/Tutorials.md b/docs/Tutorials.md index 006ed86..6b858f0 100644 --- a/docs/Tutorials.md +++ b/docs/Tutorials.md @@ -133,7 +133,10 @@ Demonstrates how to create Custom Services and Custom Characteristics in HomeSpa Demonstrates how to implement a fully programmable Light Accessory Hub that allows the user to *dynamically* add/delete up to 12 Light Accessories directly through a device-hosted *web interface* or via HomeSpan's *command-line inteface*. Each light can be configured as dimmable/non-dimmable with either no color control, full RGB color control, or color-temperature control. Builds upon many of the techniques used in [Example 20](../examples/20-AdvancedTechniques) ### [RemoteSensors](../Other%20Examples/RemoteSensors) -Demonstrates how SpanPoint can be used to transmit messages from battery-powered Remote Devices running light-weight sketches that measure the local temperature, to a wall-powered Main Device running a full HomeSpan sketch implementing Temperature Sensor Accessories. See [SpanPoint: Point-to-Point Communication between ESP32 Devices](NOW.md) for full details regarding the SpanPoint class and all of its methods. +Demonstrates how *SpanPoint* can be used to transmit messages from battery-powered Remote Devices running light-weight sketches that measure the local temperature, to a wall-powered Main Device running a full HomeSpan sketch implementing Temperature Sensor Accessories. See [SpanPoint: Point-to-Point Communication between ESP32 Devices](NOW.md) for full details regarding the *SpanPoint* class and all of its methods. + +### [FadingLED](../Other%20Examples/FadingLED) +Demonstrates how the *LedPin* class can use the ESP32's built-in fading control to automatically fade an LED from from one level of brightness to another over a specified period of time. See the [LedPin](PWM.md#pulse-width-modulation-pwm) page for full details --- From 6bd9f6f5318f9b2ffd3ffecfeef8ae349ab72f52 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:26:36 -0500 Subject: [PATCH 48/79] Update Tutorials.md --- docs/Tutorials.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Tutorials.md b/docs/Tutorials.md index 6b858f0..9305bc2 100644 --- a/docs/Tutorials.md +++ b/docs/Tutorials.md @@ -111,7 +111,7 @@ Example 20 illustrates a number of advanced techniques through the implementatio The following examples showcase a variety of HomeSpan and HomeKit functionality as referenced in different sections of the HomeSpan documentation. The sketches can be found in the Arduino IDE under *File → Examples → HomeSpan → Other Examples* -### [TableLamp](../Other%20Examples/TableLamp) +### [TableLamp](../examples/Other%20Examples/TableLamp) A basic implementation of a Table Lamp Accessory. Used as the tutorial in [HomeSpan API Overview](Overview.md) ### [RemoteControl](../Other%20Examples/RemoteControl) From c0299e2d6b4b3f32eeb6bba4fa9f3f1525c47e23 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:27:27 -0500 Subject: [PATCH 49/79] Update Tutorials.md --- docs/Tutorials.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/Tutorials.md b/docs/Tutorials.md index 9305bc2..558f9a4 100644 --- a/docs/Tutorials.md +++ b/docs/Tutorials.md @@ -114,28 +114,28 @@ The following examples showcase a variety of HomeSpan and HomeKit functionality ### [TableLamp](../examples/Other%20Examples/TableLamp) A basic implementation of a Table Lamp Accessory. Used as the tutorial in [HomeSpan API Overview](Overview.md) -### [RemoteControl](../Other%20Examples/RemoteControl) +### [RemoteControl](../examples/Other%20Examples/RemoteControl) A standalone example that shows how to use HomeSpan's *RFControl* class to produce a custom pulse train. For illustrative purposes the pulse widths are very long and suitable for output to an LED so you can "see" the pulse train. See the [RF/IR Generation](RMT.md) page for full details -### [ServoControl](../Other%20Examples/ServoControl) +### [ServoControl](../examples/Other%20Examples/ServoControl) An implementation of a Window Shade that uses HomeSpan's *ServoPin* class to control the horizontal tilt of the slats. See [ServoPin](PWM.md#servopinuint8_t-pin-double-initdegrees-uint16_t-minmicros-uint16_t-maxmicros-double-mindegrees-double-maxdegrees) for full details -### [Television](../Other%20Examples/Television) +### [Television](../examples/Other%20Examples/Television) An example of HomeKit's *undocumented* Television Service showing how different Characteristics can be used to control a TV's power, input sources, and a few other functions. See the [Television Services and Characteristics](TVServices.md) page for full details -### [Pixel](../Other%20Examples/Pixel) +### [Pixel](../examples/Other%20Examples/Pixel) Demonstrates how to use HomeSpan's *Pixel* and *Dot* classes to control one- and two-wire Addressable RGB and RGBW LEDs. See the [Addressable RGB LEDs](Pixels.md) page for full details -### [CustomService](../Other%20Examples/CustomService) +### [CustomService](../examples/Other%20Examples/CustomService) Demonstrates how to create Custom Services and Custom Characteristics in HomeSpan to implement an Atmospheric Pressure Sensor recognized by the *Eve for HomeKit* app. See [Custom Characteristics and Custom Services Macros](Reference.md#custom-characteristics-and-custom-services-macros) for full details -### [ProgrammableHub](../Other%20Examples/ProgrammableHub) +### [ProgrammableHub](../examples/Other%20Examples/ProgrammableHub) Demonstrates how to implement a fully programmable Light Accessory Hub that allows the user to *dynamically* add/delete up to 12 Light Accessories directly through a device-hosted *web interface* or via HomeSpan's *command-line inteface*. Each light can be configured as dimmable/non-dimmable with either no color control, full RGB color control, or color-temperature control. Builds upon many of the techniques used in [Example 20](../examples/20-AdvancedTechniques) -### [RemoteSensors](../Other%20Examples/RemoteSensors) +### [RemoteSensors](../examples/Other%20Examples/RemoteSensors) Demonstrates how *SpanPoint* can be used to transmit messages from battery-powered Remote Devices running light-weight sketches that measure the local temperature, to a wall-powered Main Device running a full HomeSpan sketch implementing Temperature Sensor Accessories. See [SpanPoint: Point-to-Point Communication between ESP32 Devices](NOW.md) for full details regarding the *SpanPoint* class and all of its methods. -### [FadingLED](../Other%20Examples/FadingLED) +### [FadingLED](../examples/Other%20Examples/FadingLED) Demonstrates how the *LedPin* class can use the ESP32's built-in fading control to automatically fade an LED from from one level of brightness to another over a specified period of time. See the [LedPin](PWM.md#pulse-width-modulation-pwm) page for full details --- From edbb419c192651a925f2e421c95d562c3cf7bd42 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:32:24 -0500 Subject: [PATCH 50/79] Update PWM.md --- docs/PWM.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PWM.md b/docs/PWM.md index e58e6d8..b37da71 100644 --- a/docs/PWM.md +++ b/docs/PWM.md @@ -56,7 +56,7 @@ LedPin also includes a static class function that converts Hue/Saturation/Bright * *g* - output Green value, range 0-1 * *b* - output Blue value, range 0-1 -See tutorial sketch [#10 (RGB_LED)](../examples/10-RGB_LED) for an example of using LedPin to control an RGB LED. +See tutorial sketch [#10 (RGB_LED)](../examples/10-RGB_LED) for an example of using LedPin to control an RGB LED. Also see [*File → Examples → HomeSpan → Other Examples → FadingLED*](../examples/Other%20Examples/FadingLED) for an example of to use the ESP32's built-in fading controls. ## *ServoPin(uint8_t pin [,double initDegrees [,uint16_t minMicros, uint16_t maxMicros, double minDegrees, double maxDegrees]])* From d2e89e4ba0bfdf75243d7b28b1ee76c855af4431 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:33:40 -0500 Subject: [PATCH 51/79] Update PWM.md --- docs/PWM.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/PWM.md b/docs/PWM.md index b37da71..dbd67dc 100644 --- a/docs/PWM.md +++ b/docs/PWM.md @@ -79,7 +79,7 @@ The *minMicros* parameter must be less than the *maxMicros* parameter, but setti * returns the pin number (or -1 if ServoPin was not successfully initialized) -A worked example showing how ServoPin can be used to control the Horizontal Tilt of a motorized Window Shade can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → ServoControl*](../Other%20Examples/ServoControl). +A worked example showing how ServoPin can be used to control the Horizontal Tilt of a motorized Window Shade can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → ServoControl*](../examples/Other%20Examples/ServoControl). ### PWM Resource Allocation and Limitations From 82e5e827bb7e2c9b356a6ca34aa7d80d36acd642 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:38:04 -0500 Subject: [PATCH 52/79] Update Reference.md --- docs/Reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Reference.md b/docs/Reference.md index c653e6f..956d273 100644 --- a/docs/Reference.md +++ b/docs/Reference.md @@ -557,7 +557,7 @@ Creates a custom Service for use with third-party applications (such as *Eve for Custom Services may contain a mix of both Custom Characteristics and standard HAP Characteristics, though since the Service itself is custom, the Home App will ignore the entire Service even if it contains some standard HAP Characterstics. Note that Custom Services must be created prior to calling `homeSpan.begin()` -A fully worked example showing how to use both the ***CUSTOM_SERV()*** and ***CUSTOM_CHAR()*** macros to create a Pressure Sensor Accessory that is recognized by *Eve for HomeKit* can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → CustomService*](../Other%20Examples/CustomService). +A fully worked example showing how to use both the ***CUSTOM_SERV()*** and ***CUSTOM_CHAR()*** macros to create a Pressure Sensor Accessory that is recognized by *Eve for HomeKit* can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → CustomService*](../examples/Other%20Examples/CustomService). ## Other Macros From 91c0af589af3d8694ea300b57a6e5e8f09528db0 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:38:38 -0500 Subject: [PATCH 53/79] Update RMT.md --- docs/RMT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RMT.md b/docs/RMT.md index 4eda785..f75cf09 100644 --- a/docs/RMT.md +++ b/docs/RMT.md @@ -84,7 +84,7 @@ rf.start(pulseTrain,3,4,1000); // start transmission using the same parameters ## Example RFControl Sketch -Below is a complete sketch that produces two different pulse trains with the signal output linked to the ESP32 device's built-in LED (rather than an RF or IR transmitter). For illustrative purposes the tick duration has been set to a very long 100𝛍s, and pulse times range from of 1000-10,000 ticks, so that the individual pulses are easily discernable on the LED. Note this example sketch is also available in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → RemoteControl*](../Other%20Examples/RemoteControl). +Below is a complete sketch that produces two different pulse trains with the signal output linked to the ESP32 device's built-in LED (rather than an RF or IR transmitter). For illustrative purposes the tick duration has been set to a very long 100𝛍s, and pulse times range from of 1000-10,000 ticks, so that the individual pulses are easily discernable on the LED. Note this example sketch is also available in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → RemoteControl*](../examples/Other%20Examples/RemoteControl). ```C++ /* HomeSpan Remote Control Example */ From 3a7b7caf23fc5c28ce37d2a018ca0d47b588e912 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:39:53 -0500 Subject: [PATCH 54/79] Update Pixels.md --- docs/Pixels.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Pixels.md b/docs/Pixels.md index 39b26bc..54dad24 100644 --- a/docs/Pixels.md +++ b/docs/Pixels.md @@ -118,9 +118,9 @@ Unlike the **Pixel** class, the **Dot** class does *not* utilize the ESP32's RMT ### Example Sketches -A fully worked example showing how to use the Pixel library within a HomeSpan sketch to control an RGB Pixel Device, an RGBW Pixel Device, and an RGB DotStar Device, all from the Home App on your iPhone, can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → Pixel*](../Other%20Examples/Pixel). +A fully worked example showing how to use the Pixel library within a HomeSpan sketch to control an RGB Pixel Device, an RGBW Pixel Device, and an RGB DotStar Device, all from the Home App on your iPhone, can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → Pixel*](../examples/Other%20Examples/Pixel). -For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro](https://github.com/HomeSpan/HomeSpan/blob/master/docs/Reference.md#define-custom_charnameuuidpermsformatdefaultvalueminvaluemaxvaluestaticrange) to implement a special-effects "selector" button for use in the Eve for HomeKit App. +For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro](Reference.md#define-custom_charnameuuidpermsformatdefaultvalueminvaluemaxvaluestaticrange) to implement a special-effects "selector" button for use in the Eve for HomeKit App. --- From 8c5b54acd52fb1268a44c24a05530159dbb28ad2 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:41:08 -0500 Subject: [PATCH 55/79] Update Pixels.md --- docs/Pixels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Pixels.md b/docs/Pixels.md index 54dad24..d364e43 100644 --- a/docs/Pixels.md +++ b/docs/Pixels.md @@ -120,7 +120,7 @@ Unlike the **Pixel** class, the **Dot** class does *not* utilize the ESP32's RMT A fully worked example showing how to use the Pixel library within a HomeSpan sketch to control an RGB Pixel Device, an RGBW Pixel Device, and an RGB DotStar Device, all from the Home App on your iPhone, can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → Pixel*](../examples/Other%20Examples/Pixel). -For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro](Reference.md#define-custom_charnameuuidpermsformatdefaultvalueminvaluemaxvaluestaticrange) to implement a special-effects "selector" button for use in the Eve for HomeKit App. +For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro]([Reference.md#define-custom_charnameuuidpermsformatdefaultvalueminvaluemaxvaluestaticrange](Reference.md#custom-characteristics-and-custom-services-macros)) to implement a special-effects "selector" button for use in the Eve for HomeKit App. --- From 395392d2958988305e2b60eaa077a0ef3d00d3e3 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:41:58 -0500 Subject: [PATCH 56/79] Update Pixels.md --- docs/Pixels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Pixels.md b/docs/Pixels.md index d364e43..9b6b269 100644 --- a/docs/Pixels.md +++ b/docs/Pixels.md @@ -120,7 +120,7 @@ Unlike the **Pixel** class, the **Dot** class does *not* utilize the ESP32's RMT A fully worked example showing how to use the Pixel library within a HomeSpan sketch to control an RGB Pixel Device, an RGBW Pixel Device, and an RGB DotStar Device, all from the Home App on your iPhone, can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → Pixel*](../examples/Other%20Examples/Pixel). -For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro]([Reference.md#define-custom_charnameuuidpermsformatdefaultvalueminvaluemaxvaluestaticrange](Reference.md#custom-characteristics-and-custom-services-macros)) to implement a special-effects "selector" button for use in the Eve for HomeKit App. +For a more complete showcase of the Pixel library , check out [Holiday Lights](https://github.com/HomeSpan/HolidayLights) on the [HomeSpan Projects page](https://github.com/topics/homespan). This sketch demonstrates how the Pixel library can be used to generate a variety of special effects with a 60-pixel RGBW strip. The sketch also showcases the use of HomeSpan's [Custom Characteristic macro](Reference.md#custom-characteristics-and-custom-services-macros) to implement a special-effects "selector" button for use in the Eve for HomeKit App. --- From f93fe16b6ec04571187b5f7bb031f5aa5aa66c02 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:43:10 -0500 Subject: [PATCH 57/79] Update NOW.md --- docs/NOW.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/NOW.md b/docs/NOW.md index 40f92bd..eb63b48 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -75,7 +75,7 @@ Also note that regardless of whether or not the queue if full, if the size of a One of the primary reasons for using SpanPoint is to enable the deployement of battery-powered devices. Since HomeKit requires an always-on WiFi connection, wall-power is a must. But ESP-NOW does not require always-on connectivity to a central WiFi network, which makes it possible to power things like remote-sensor devices with just a battery. Such battery-powered "Remote Devices" can take periodic local measurements and transmit them via SpanPoint messages to a wall-powered "Main Device" that is running a full HomeSpan sketch connected to HomeKit via a central WiFi network. -Examples showing such a configuration can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → RemoteSensors*](../Other%20Examples/RemoteSensors). This folder contains the following sketches: +Examples showing such a configuration can be found in the Arduino IDE under [*File → Examples → HomeSpan → Other Examples → RemoteSensors*](../examples/Other%20Examples/RemoteSensors). This folder contains the following sketches: * *MainDevice.ino* - a full HomeSpan sketch that implements two Temperature Sensor Accessories, but instead of taking its own temperature measurements, it uses SpanPoint to read messages containing temperature updates from other Remote Devices * *RemoteDevice.ino* - a lightweight sketch that simulates taking periodic temperature measurements, which are then transmitted to the Main Device via SpanPoint From 49ddbb0407893ae9f4cd281677af74c66cfd3e91 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Sat, 1 Apr 2023 12:44:05 -0500 Subject: [PATCH 58/79] Update FAQ.md --- docs/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index c5e2ba1..8b0a0ad 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -60,7 +60,7 @@ #### Can you add a Web Server to HomeSpan? -* Yes, provided you implement your Web Server using standard ESP32-Arduino libraries, such as `WebServer.h`. See [ProgrammableHub](../Other%20Examples/ProgrammableHub) for an illustrative example of how to easily integrate a Web Server into HomeSpan. This project also covers various other advanced topics, including TCP slot management, dynamic creation of Accessories, and saving arbitrary data in the ESP32's NVS. +* Yes, provided you implement your Web Server using standard ESP32-Arduino libraries, such as `WebServer.h`. See [ProgrammableHub](../examples/Other%20Examples/ProgrammableHub) for an illustrative example of how to easily integrate a Web Server into HomeSpan. This project also covers various other advanced topics, including TCP slot management, dynamic creation of Accessories, and saving arbitrary data in the ESP32's NVS. #### Can you add *custom* Services and Characteristics to HomeSpan? From 2ba75c13eae220336ba15889f52884976a7a4989 Mon Sep 17 00:00:00 2001 From: Gregg Date: Mon, 3 Apr 2023 08:28:51 -0500 Subject: [PATCH 59/79] Add CLI commands 'p' and 'P' to clone device pairing data --- src/HomeSpan.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 213c671..90e4c12 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1043,6 +1043,86 @@ void Span::processSerialCommand(const char *c){ } break; + case 'p': { + + Serial.printf("\n*** Pairing Data used for Cloning another Device\n\n"); + size_t olen; + TempBuffer tBuf(256); + mbedtls_base64_encode((uint8_t *)tBuf.buf,256,&olen,(uint8_t *)&HAPClient::accessory,sizeof(struct Accessory)); + Serial.printf("Accessory data: %s\n",tBuf.buf); + for(int i=0;i tBuf(200); + size_t olen; + + tBuf.buf[0]='\0'; + Serial.print(">>> Accessory data: "); + readSerial(tBuf.buf,199); + if(strlen(tBuf.buf)==0){ + Serial.printf("(cancelled)\n\n"); + return; + } + mbedtls_base64_decode((uint8_t *)&HAPClient::accessory,sizeof(struct Accessory),&olen,(uint8_t *)tBuf.buf,strlen(tBuf.buf)); + if(olen!=sizeof(struct Accessory)){ + Serial.printf("\n*** Error in size of Accessory data - cloning cancelled. Restarting...\n\n"); + reboot(); + } else { + HAPClient::charPrintRow(HAPClient::accessory.ID,17); + Serial.printf("\n"); + } + + for(int i=0;i>> Controller data: "); + readSerial(tBuf.buf,199); + if(strlen(tBuf.buf)==0){ + Serial.printf("(done)\n"); + while(i Date: Mon, 3 Apr 2023 17:15:51 -0500 Subject: [PATCH 60/79] Update HomeSpan.cpp --- src/HomeSpan.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 90e4c12..d5119eb 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1043,7 +1043,7 @@ void Span::processSerialCommand(const char *c){ } break; - case 'p': { + case 'P': { Serial.printf("\n*** Pairing Data used for Cloning another Device\n\n"); size_t olen; @@ -1060,7 +1060,7 @@ void Span::processSerialCommand(const char *c){ } break; - case 'P': { + case 'C': { Serial.printf("\n*** Clone Pairing Data from another Device\n\n"); TempBuffer tBuf(200); @@ -1142,6 +1142,9 @@ void Span::processSerialCommand(const char *c){ Serial.print(" U - unpair device by deleting all Controller data\n"); Serial.print(" H - delete HomeKit Device ID as well as all Controller data and restart\n"); Serial.print("\n"); + Serial.print(" P - output Pairing Data that can be saved offline to clone a new device\n"); + Serial.print(" C - clone Pairing Data previously saved offline from another device\n"); + Serial.print("\n"); Serial.print(" R - restart device\n"); Serial.print(" F - factory reset and restart\n"); Serial.print(" E - erase ALL stored data and restart\n"); From a9f16c7cfedd1a6c5e9ac2c31bc06defeaa5d194 Mon Sep 17 00:00:00 2001 From: Gregg Date: Mon, 3 Apr 2023 17:17:26 -0500 Subject: [PATCH 61/79] Create Cloning.md --- docs/Cloning.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs/Cloning.md diff --git a/docs/Cloning.md b/docs/Cloning.md new file mode 100644 index 0000000..fbf4955 --- /dev/null +++ b/docs/Cloning.md @@ -0,0 +1,68 @@ +# Pairing with QR Codes + +Pairing a HomeKit device using its 8-digit *Setup Code* requires you to: + +* Select the specific HomeKit device to pair from a list of unpaired HomeKit devices the Home App finds on your local network +* Input the *Setup Code* for that device into the Home App. + +The order of the steps above depends on whether you manually type the *Setup Code*, or scan it from a printed tag. + +In contrast, pairing a HomeKit device with a **QR Code** requires you to only scan the QR Code. You do not need to identify the device you want to pair. The Home App will instead search for it on your local network and, if found, pair with it automatically. + +This is possible because the QR Code includes a 4-character *Setup ID* that is unique to the device associated with the QR Code. The QR Code also embeds other paring information about the device, such as its Category (e.g. Light, Fan, Door) and its 8-digit *Setup Code*. + +HomeSpan supports pairing with QR Codes and uses "HSPN" as its default *Setup ID*. However, if you have more than one device that you intend on pairing with a QR Code, you'll need to enure each has a unique *Setup ID*. You can change the *Setup ID* on your device in one of two ways: + +* Store a new code in the device NVS by typing 'O \' into the HomeSpan [Command Line Interface](https://github.com/HomeSpan/HomeSpan/blob/master/docs/CLI.md); or +* Specify the QR *Setup ID* directly in your sketch using the method `homeSpan.setQRID(const char *ID)`. + +The order of preference is as follows: If your sketch contains a call to `homeSpan.setQRID(const char *ID)`, the specified ID is used. If not, HomeSpan will instead search the NVS for a stored *Setup ID*. If not found, HomeSpan defaults to using "HSPN" as the *Setup ID*. + +Note that if you do not intend on pairing your devices with QR Codes, it is fine for them to all retain the default *Setup ID* of "HSPN" since this ID is only used to initiate the pairing process via a QR code and serves no other purpose. + +### Creating Scannable QR Codes + +Just as you can create your own scannable tag based on a HomeSpan device's *Setup Code* (see the [HomeSpan User Guide](https://github.com/HomeSpan/HomeSpan/blob/master/docs/UserGuide.md#creating-a-scannable-tag), you can also create your own scannable QR Code for pairing a HomeSpan device. Perhaps the easiest method is to use Apple's HomeKit QR Code generator including with its [HomeKit Accessory Simulator](https://developer.apple.com/documentation/homekit/testing_your_app_with_the_homekit_accessory_simulator) add-on for Xcode. + +![QR Code Generator](images/QRCode.png) + +As shown above, the Simulator's QR Code Generator requires the input of the following fields: + +* **Version**. Always set this to zero, else the Home App will not recognize the QR Code. +* **Reserved**. Always set this to zero, else the Home App will not recognize the QR Code. +* **Category**. Set this to match the Category of your HomeSpan device (e.g. Lightbulb, Fan, Door Lock). Note the Home App only uses this for display purposes when you first scan the QR Code. The Home App does not actually check that the Category listed in the QR Code matches the Category of the device you are pairing. +* **Setup Flags**. These flags provide information on which methods of pairing are supported by a HomeKit device. HomeSpan only supports IP Pairing, so you check that box and leave the other two blank. However, it does not seem to matter which boxes (if any) you check since the Home App does not appear to use this information for anything. +* **Setup Code**. This is the 8-digit *Setup Code* you set for your device using either the [HomeSpan Command-Line Interface (CLI)](https://github.com/HomeSpan/HomeSpan/blob/master/docs/CLI.md) or [HomeSpan's WiFi Setup Web Page](https://github.com/HomeSpan/HomeSpan/blob/master/docs/UserGuide.md#setting-homespans-wifi-credentials-and-setup-code). Note the code shown in the above screenshot is the default HomeSpan uses if you do not set your own. +* **Setup ID**. This is the 4-character *Setup ID* you set for your HomeSpan device from within your sketch using the method `homeSpan.setQRID(const char *id)`. If you do not specify a QR Setup ID in your sketch, HomeSpan uses a default value of "HSPN" (as shown in the example above) unless you've updated the default for this device via the [CLI](CLI.md) using the 'Q' command. Note case matters! HSPN is not the same as "hspn". +* **Setup Payload**. This is the output that results from the above inputs, and is the text that is represented by the QR Code shown. The Setup Payload for a HomeKit device always begins with "X-HM://", followed by 9 alphanumeric characters, and ending with the *Setup ID* in plain text. If you've not changed HomeSpan's default *Setup Code* or *Setup ID*, you can pair your device by scanning this graphic with the Home App. Even easier is to scan it right from your camera - your iPhone will recognize that this is a HomeKit QR Code and open the Home App for you. + +You probably noticed that the QR Code contains extra graphics, such as Apple's HomeKit logo in the upper left. This is purely cosmetic and not required by the Home App for pairing. Similarly, having the device's 8-digit *Setup Code* shown in big numerals in the upper right is also cosmetic and not needed for pairing, though it may be handy if you have problems scanning the QR Code and want to manually type the *Setup Code* into the Home App. + +The only portion of the full graphic actually scanned by the Home App is the QR Code itself, which means you can create a HomeKit-compatible QR Code using any generic QR Code generator that allows you to input arbitrary text. The text you'll need to input to such a QR Code generator is of course the Setup Payload. There is a relatively straightfoward algorithm you can follow to produce the correct Setup Payload text for each of your HomeSpan devices, but its even easier to let HomeSpan do this for you. + +This is because HomeSpan automatically displays the Setup Payload text needed for a HomeSpan device on the Arduino Serial Monitor whenever you set or change the *Setup Code*. **Simply copy the Setup Payload text shown on the Serial Monitor into a generic QR Code generator, and viola — you've created a scannable QR Code ready to be used to pair your HomeSpan device.** + +### Setup Payload Algorithm (*optional reading*) + +The Setup Payload for a HomeKit device always begins with "X-HM://", followed by nine base-36 digits that encode all the device's pairing parameters, and ending with the *Setup ID* for the device in plain text. + +> Base-36 digits use the characters 0-9 and A-Z (capitals only!) to represent the numbers 0-35 in the same fashion that the hexidecimal digits 0-9 and A-F represent the numbers 0-15. For example, the decimal number 91 would be represented as 2S in base-36 (91 = 2 * 36 + 19) + +The nine base-36 digits should encode a 45-bit word formed from the following data elements (listed from most- to least-significant bit): + +* Bits 45-43 - The "Version" field (0-7). Always set to 0 +* Bits 42-39 - The "Reserved" field (0-15). Always set to 0 +* Bits 38-31 - The device's Accessory Category (0-255) +* Bit 30 - Always set to 0 +* Bit 29 - Set to 1 if the device supports BLTE pairing, else set to 0 +* Bit 28 - Set to 1 if the device supports IP pairing, else set to 0 +* Bit 27 - Set to 1 if the device supports NFC pairing, else set to 0 +* Bits 26-0 - The device's 8-digit *Setup Code* (from 0-99999999) + +The result must be 9 digits. If less, pad with leading zeros. + +--- + +[↩️](../README.md) Back to the Welcome page + + From ef8728af5f591676cda29d92b020c0c76fed101e Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Mon, 3 Apr 2023 18:06:17 -0500 Subject: [PATCH 62/79] Update Cloning.md --- docs/Cloning.md | 83 +++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index fbf4955..09f6cbd 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -1,65 +1,46 @@ -# Pairing with QR Codes +# Cloning Pairing Data from one Device to another -Pairing a HomeKit device using its 8-digit *Setup Code* requires you to: +Every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). these keys are randomly generated for permanent stoorage in a new HomeSpan device, but can be subsequently erased and randomly re-generated with the 'H' CLI Command. -* Select the specific HomeKit device to pair from a list of unpaired HomeKit devices the Home App finds on your local network -* Input the *Setup Code* for that device into the Home App. +Similarly, every HomeKit Controller (e.g. the Home App on an iPhone) has unique 36-character Device ID and a unique 32-byte LTPK. -The order of the steps above depends on whether you manually type the *Setup Code*, or scan it from a printed tag. +When a HomeSpan Accessory is first paired with a HomeKit Controller (using either the Accessory's QR code or its 8-digit Pairing Code), the Accessory and the Controller securely transmit to eachother their Device IDs and LTPKs, which are in turn also permanently stored. Thus, after pairing, HomeSpan will have in storage its own Device ID, LTPK and LTSK, and the Device ID and LTPK of the paired Controller. Collectively this information is known as *Pairing Data*. -In contrast, pairing a HomeKit device with a **QR Code** requires you to only scan the QR Code. You do not need to identify the device you want to pair. The Home App will instead search for it on your local network and, if found, pair with it automatically. +Pairing Data is used every time a HomeKit Controller opens up a new secure connection with a HomeKit Accessory. Without this data, the Home App will no longer be able to open a connection to HomeSpan. -This is possible because the QR Code includes a 4-character *Setup ID* that is unique to the device associated with the QR Code. The QR Code also embeds other paring information about the device, such as its Category (e.g. Light, Fan, Door) and its 8-digit *Setup Code*. +Once an Accessory is paired to a Controller, if cannot be paired to a second Controller. But yet you can operate a HomeSpan device from multiple iPhones, HomePods, Macs, etc., as long as they are on the same network. This is because in the background HomeKit shares the Pairing Data of a HomeSpan Accessory with other Controllers. When opening their own connections to HomeSpan, those Controllers use the same Pairing Data. However, sometimes HomeKit decides to create one or more additional sets of Pairing Data for other Controllers to use by sending such new Pairing Data securely to a HomeSpan Accessory. HomeSpan can store up to 16 sets of Pairing Data. -HomeSpan supports pairing with QR Codes and uses "HSPN" as its default *Setup ID*. However, if you have more than one device that you intend on pairing with a QR Code, you'll need to enure each has a unique *Setup ID*. You can change the *Setup ID* on your device in one of two ways: +You can view the Pairing Data for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: + +``` +*** HomeSpan Status *** + +IP Address: 192.168.1.11 + +Accessory ID: 77:D2:F6:99:CE:65 LTPK: 346A544A876B124E50F9E3CC276A29D23E8B5DD0590138AA59C833A0D2096E37 +Paired Controller: A487DE69-81C3-B5ED-8762-C3B9A987F967 (admin) LTPK: EE12A678DD56C4E9C0D935A341B8E6C6C098A6B3E6D4C5F5F914A54C9E85BA76 +Paired Controller: 449AD09E-109D-3EB5-25B4-8A04E5C57D65 (admin) LTPK: 34A6B57DE881A75B647D2C9C68E76745A3B466577D19E4C78A67A68C4ED959B8 + +Connection #0 192.168.1.29 on Socket 3/16 ID=A487DE69-81C3-B5ED-8762-C3B9A987F967 (admin) +Connection #1 (unconnected) +Connection #2 (unconnected) +Connection #3 (unconnected) +Connection #4 (unconnected) +Connection #5 (unconnected) +Connection #6 (unconnected) +Connection #7 (unconnected) +Connection #8 (unconnected) +Connection #9 (unconnected) +Connection #10 (unconnected) +Connection #11 (unconnected) + +*** End Status *** +``` -* Store a new code in the device NVS by typing 'O \' into the HomeSpan [Command Line Interface](https://github.com/HomeSpan/HomeSpan/blob/master/docs/CLI.md); or -* Specify the QR *Setup ID* directly in your sketch using the method `homeSpan.setQRID(const char *ID)`. - -The order of preference is as follows: If your sketch contains a call to `homeSpan.setQRID(const char *ID)`, the specified ID is used. If not, HomeSpan will instead search the NVS for a stored *Setup ID*. If not found, HomeSpan defaults to using "HSPN" as the *Setup ID*. - -Note that if you do not intend on pairing your devices with QR Codes, it is fine for them to all retain the default *Setup ID* of "HSPN" since this ID is only used to initiate the pairing process via a QR code and serves no other purpose. ### Creating Scannable QR Codes -Just as you can create your own scannable tag based on a HomeSpan device's *Setup Code* (see the [HomeSpan User Guide](https://github.com/HomeSpan/HomeSpan/blob/master/docs/UserGuide.md#creating-a-scannable-tag), you can also create your own scannable QR Code for pairing a HomeSpan device. Perhaps the easiest method is to use Apple's HomeKit QR Code generator including with its [HomeKit Accessory Simulator](https://developer.apple.com/documentation/homekit/testing_your_app_with_the_homekit_accessory_simulator) add-on for Xcode. -![QR Code Generator](images/QRCode.png) - -As shown above, the Simulator's QR Code Generator requires the input of the following fields: - -* **Version**. Always set this to zero, else the Home App will not recognize the QR Code. -* **Reserved**. Always set this to zero, else the Home App will not recognize the QR Code. -* **Category**. Set this to match the Category of your HomeSpan device (e.g. Lightbulb, Fan, Door Lock). Note the Home App only uses this for display purposes when you first scan the QR Code. The Home App does not actually check that the Category listed in the QR Code matches the Category of the device you are pairing. -* **Setup Flags**. These flags provide information on which methods of pairing are supported by a HomeKit device. HomeSpan only supports IP Pairing, so you check that box and leave the other two blank. However, it does not seem to matter which boxes (if any) you check since the Home App does not appear to use this information for anything. -* **Setup Code**. This is the 8-digit *Setup Code* you set for your device using either the [HomeSpan Command-Line Interface (CLI)](https://github.com/HomeSpan/HomeSpan/blob/master/docs/CLI.md) or [HomeSpan's WiFi Setup Web Page](https://github.com/HomeSpan/HomeSpan/blob/master/docs/UserGuide.md#setting-homespans-wifi-credentials-and-setup-code). Note the code shown in the above screenshot is the default HomeSpan uses if you do not set your own. -* **Setup ID**. This is the 4-character *Setup ID* you set for your HomeSpan device from within your sketch using the method `homeSpan.setQRID(const char *id)`. If you do not specify a QR Setup ID in your sketch, HomeSpan uses a default value of "HSPN" (as shown in the example above) unless you've updated the default for this device via the [CLI](CLI.md) using the 'Q' command. Note case matters! HSPN is not the same as "hspn". -* **Setup Payload**. This is the output that results from the above inputs, and is the text that is represented by the QR Code shown. The Setup Payload for a HomeKit device always begins with "X-HM://", followed by 9 alphanumeric characters, and ending with the *Setup ID* in plain text. If you've not changed HomeSpan's default *Setup Code* or *Setup ID*, you can pair your device by scanning this graphic with the Home App. Even easier is to scan it right from your camera - your iPhone will recognize that this is a HomeKit QR Code and open the Home App for you. - -You probably noticed that the QR Code contains extra graphics, such as Apple's HomeKit logo in the upper left. This is purely cosmetic and not required by the Home App for pairing. Similarly, having the device's 8-digit *Setup Code* shown in big numerals in the upper right is also cosmetic and not needed for pairing, though it may be handy if you have problems scanning the QR Code and want to manually type the *Setup Code* into the Home App. - -The only portion of the full graphic actually scanned by the Home App is the QR Code itself, which means you can create a HomeKit-compatible QR Code using any generic QR Code generator that allows you to input arbitrary text. The text you'll need to input to such a QR Code generator is of course the Setup Payload. There is a relatively straightfoward algorithm you can follow to produce the correct Setup Payload text for each of your HomeSpan devices, but its even easier to let HomeSpan do this for you. - -This is because HomeSpan automatically displays the Setup Payload text needed for a HomeSpan device on the Arduino Serial Monitor whenever you set or change the *Setup Code*. **Simply copy the Setup Payload text shown on the Serial Monitor into a generic QR Code generator, and viola — you've created a scannable QR Code ready to be used to pair your HomeSpan device.** - -### Setup Payload Algorithm (*optional reading*) - -The Setup Payload for a HomeKit device always begins with "X-HM://", followed by nine base-36 digits that encode all the device's pairing parameters, and ending with the *Setup ID* for the device in plain text. - -> Base-36 digits use the characters 0-9 and A-Z (capitals only!) to represent the numbers 0-35 in the same fashion that the hexidecimal digits 0-9 and A-F represent the numbers 0-15. For example, the decimal number 91 would be represented as 2S in base-36 (91 = 2 * 36 + 19) - -The nine base-36 digits should encode a 45-bit word formed from the following data elements (listed from most- to least-significant bit): - -* Bits 45-43 - The "Version" field (0-7). Always set to 0 -* Bits 42-39 - The "Reserved" field (0-15). Always set to 0 -* Bits 38-31 - The device's Accessory Category (0-255) -* Bit 30 - Always set to 0 -* Bit 29 - Set to 1 if the device supports BLTE pairing, else set to 0 -* Bit 28 - Set to 1 if the device supports IP pairing, else set to 0 -* Bit 27 - Set to 1 if the device supports NFC pairing, else set to 0 -* Bits 26-0 - The device's 8-digit *Setup Code* (from 0-99999999) - -The result must be 9 digits. If less, pad with leading zeros. --- From 314403ba332d8be6077e6653965c60f9697dcdf0 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Mon, 3 Apr 2023 18:31:30 -0500 Subject: [PATCH 63/79] Update Cloning.md --- docs/Cloning.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 09f6cbd..2245e6c 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -1,5 +1,7 @@ # Cloning Pairing Data from one Device to another +### HomeSpan Pairing Data + Every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). these keys are randomly generated for permanent stoorage in a new HomeSpan device, but can be subsequently erased and randomly re-generated with the 'H' CLI Command. Similarly, every HomeKit Controller (e.g. the Home App on an iPhone) has unique 36-character Device ID and a unique 32-byte LTPK. @@ -10,7 +12,7 @@ Pairing Data is used every time a HomeKit Controller opens up a new secure conne Once an Accessory is paired to a Controller, if cannot be paired to a second Controller. But yet you can operate a HomeSpan device from multiple iPhones, HomePods, Macs, etc., as long as they are on the same network. This is because in the background HomeKit shares the Pairing Data of a HomeSpan Accessory with other Controllers. When opening their own connections to HomeSpan, those Controllers use the same Pairing Data. However, sometimes HomeKit decides to create one or more additional sets of Pairing Data for other Controllers to use by sending such new Pairing Data securely to a HomeSpan Accessory. HomeSpan can store up to 16 sets of Pairing Data. -You can view the Pairing Data for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: +You can view most of the Pairing Data for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: ``` *** HomeSpan Status *** @@ -37,8 +39,20 @@ Connection #11 (unconnected) *** End Status *** ``` +The only Pairing Data not shown on the CLI is the Accessory's LTSK (the long-term secret key). + +### Cloning a HomeSpan Device + +Though you can run the same sketch on two different HomeSpan devices, each device will have a unique Device ID, will need to be separately paired with HomeKit, and each will operate as an independent device (perhaps controlling separate lights). This is the normal use case for running the same sketch on more than one device. + +However, sometimes you may want to *replace* one HomeSpan device with another running the exact same sketch. Maybe the first device has malfunctioned or was damaged. Typically when this occurs, you unpair the first (broken) device from HomeKit and then pair the new device to HomeKit. Unfortunately, once you unpair the old device, HomeKit forgets any automations, scenes, customizatons, etc., related to this device that you may have made using the Home App. When you pair the new device, even though it is running the same sketch, HomeKit will treat it as a completely new device. It will not apply any name-changes you may have made in the Home App, nor recreate any of the prior device's automations. + +To solve this problem, you need to be able to replace the broken device with a new device, but *without* unpairing the old device or re-pairing the new device. This would require the new device to be initialized with the same Pairing Data as the old device, including having the same long-term secret key. + +Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3, etc. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. + +Cloning HomeSpan's pairing data is a two-step process. First, type 'P' into the CLI for the device you wish to clone. This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). -### Creating Scannable QR Codes From 013af8332b22822af9ee139b15889e34ef393a49 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Mon, 3 Apr 2023 20:44:12 -0500 Subject: [PATCH 64/79] Update Cloning.md --- docs/Cloning.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 2245e6c..787623a 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -51,7 +51,17 @@ To solve this problem, you need to be able to replace the broken device with a n Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3, etc. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. -Cloning HomeSpan's pairing data is a two-step process. First, type 'P' into the CLI for the device you wish to clone. This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). +Cloning HomeSpan's pairing data is a two-step process. First, type 'P' into the CLI for the device you wish to clone. This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). HomeSpan will output its Pairing Data in base-64. Here is an example: + +``` +*** Pairing Data used for Cloning another Device + +Accessory data: ZzbH11I8uNx47Y3Bapq3axQfY5uPOrDfC8D2Q6ke2NwWqat/IGa/6ll8xyY8AShMYO2q6h8gZr/qWXzHJjwBKExg7arqFnNsfXUjy43HgNzc6RDI6RjY6OTk6Q0U6NjUb7mHwbmWzrEWca+5frayfmp= +Controller data: YaNJH5JYDAQE4NjI0NTAwNy02Mi1FRUY4ODNENTA2NjdDvTRGLTRBRDEtQjkwRXFM1On32PKvumS+0YgVMaEo53X/TYNzg== +Controller data: MEUwLTREMEUtODk3Ni0yMjBDREQ2RDUxMjjmah3s+Je0GkmAQE0NDQ1NUE2Ni1ExIUkujzeyWfCCRWol/xecsVkjAIYDRQ== + +*** End Pairing Data +``` From 9dc1ac0b4832f4e99a7de4242d94e7ab9f895974 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Mon, 3 Apr 2023 21:26:45 -0500 Subject: [PATCH 65/79] Update Cloning.md --- docs/Cloning.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 787623a..7b0a34c 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -51,7 +51,7 @@ To solve this problem, you need to be able to replace the broken device with a n Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3, etc. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. -Cloning HomeSpan's pairing data is a two-step process. First, type 'P' into the CLI for the device you wish to clone. This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). HomeSpan will output its Pairing Data in base-64. Here is an example: +Cloning HomeSpan's pairing data is a two-step process. **First, type 'P' into the CLI for the device you wish to clone.** This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). HomeSpan will output its Pairing Data in base-64. Here is an example reflecting a system with Pairing Data for two Controllers (similar to above): ``` *** Pairing Data used for Cloning another Device @@ -63,9 +63,28 @@ Controller data: MEUwLTREMEUtODk3Ni0yMjBDREQ2RDUxMjjmah3s+Je0GkmAQE0NDQ1NUE2Ni1E *** End Pairing Data ``` +The first line completely encodes the Pairing Data for the HomeSpan Accessory. The second two lines encode the Pairing Data for two Controllers that HomeKit is using to control the HomeSpan device. Note your system may only have one Controller. Or it may have more than two. The number of Controllers depends on your HomeKit network, how it is configured, what devices you have (Apple TVs, HomePods, etc.) and what version of iOS you are running. +Copy this data, exactly as is, from the CLI and save it in a text file. Make sure not to lose any trailing equal signs - they are part of the base64 data! +Next, power down the device, or at least remove it from the WiFi network to avoid potential duplications two devices running on the same network with identical Pairing Data (HomeKit will likely not behave if this occurs). +**Then, open the Serial Monitor on the new replacement device that is already running the *exact* same HomeSpan sketch as the first device and type 'C' to begin the cloning process.** + +HomeSpan will begin by asking you for the Accessory Pairing Data. Copy and paste the base64 data for the Accessory that you save in the text file directly into the Serial Monitor input window and hit return. If you copied the data correctly it will be accepted and HomeSpan will display the Device ID that was encoded in the data (it does not bother to display the LTPK and LTSK data). The Device ID should match that of the orignal device. + +If you copied or pasted the data incorrectly, HomeSpan will let you know there is a problem, cancel the process, and reboot without making any changes. You can also cancel the process by simply hitting return after typing 'P' *without* entering any data (this does not cause a reboot, since no data was changed). + +After the Accessory data is accepted, HomeSpan will then ask for Controller data. Copy and paste the base64 data from one of the Controllers in the saved text file directly into the Serial Monitor input window and hit return. As before, if you copied and pasted correctly, HomeSpan will accept the data and display the Device ID of the Controller. If you copied and pasted incorrectly, HomeSpan will inform you of the error, cancel the process, and reboot without making any changes. + +Assuming the data for the first Controller has been accepted, HomeSpan will ask you to repeat the process for any other Controllers you may have. Keep repeating the process for copying and pasting the Pairing Data for each Controller. When you have input the Pairing Data for each Controller, simply hit hit return without entering any data when asked for the next Controller. An empty response tells HomeSpan you are done adding Controller data. + +Finally, HomeSpan will ask you to confirm saving the new data. Type either 'y' to confirm (yes) or 'n' to cancel (no). If you type 'n', HomeSpan will reboot without saving any of the changes. + +If you type 'y', HomeSpan will save all of the new Pairing Data in the ESP32's permanent storage and reboot. Upon restarting, HomeSpan will be a clone of the original device and HomeKit should recognize it as if it were the original. You will not need to re-pair the device or make any other changes to the Home App. + +❗Caution: Do NOT run two devices on the same HomeKit network with the same Pairing Data. If you want to experiment by Cloning a working device onto a second device, make sure to unplug the first device before cloning the data onto the second device. When you are experimenting, type 'H' into the CLI of the device to erase the Controller Pairing Data and regenerate a new, random set of Accessory Pairing Data, allowing you to plug both devices in at the same time without conflict. + --- [↩️](../README.md) Back to the Welcome page From 71e89605b01930e599a9bdfe073a97ff83d968a2 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Mon, 3 Apr 2023 22:13:43 -0500 Subject: [PATCH 66/79] Update Cloning.md --- docs/Cloning.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 7b0a34c..d09353c 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -2,7 +2,7 @@ ### HomeSpan Pairing Data -Every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). these keys are randomly generated for permanent stoorage in a new HomeSpan device, but can be subsequently erased and randomly re-generated with the 'H' CLI Command. +Every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). These data are randomly generated by every new HomeSpan device. Once generated, HomeSpan permanently saves the data in the device's non-volatile storage partition, but this data can be subsequently erased and randomly re-generated with the 'H' CLI Command. Similarly, every HomeKit Controller (e.g. the Home App on an iPhone) has unique 36-character Device ID and a unique 32-byte LTPK. @@ -10,7 +10,7 @@ When a HomeSpan Accessory is first paired with a HomeKit Controller (using eithe Pairing Data is used every time a HomeKit Controller opens up a new secure connection with a HomeKit Accessory. Without this data, the Home App will no longer be able to open a connection to HomeSpan. -Once an Accessory is paired to a Controller, if cannot be paired to a second Controller. But yet you can operate a HomeSpan device from multiple iPhones, HomePods, Macs, etc., as long as they are on the same network. This is because in the background HomeKit shares the Pairing Data of a HomeSpan Accessory with other Controllers. When opening their own connections to HomeSpan, those Controllers use the same Pairing Data. However, sometimes HomeKit decides to create one or more additional sets of Pairing Data for other Controllers to use by sending such new Pairing Data securely to a HomeSpan Accessory. HomeSpan can store up to 16 sets of Pairing Data. +Once an Accessory is paired to a Controller, it cannot be paired to a second Controller. But yet you can operate a HomeSpan device from multiple iPhones, HomePods, Macs, etc., as long as they are on the same network. This is because in the background HomeKit shares the Pairing Data of a HomeSpan Accessory with other Controllers. When opening their own connections to HomeSpan, those Controllers use the same Pairing Data. However, sometimes HomeKit decides to create one or more additional sets of Pairing Data for other Controllers to use by sending such new Pairing Data securely to a HomeSpan Accessory. HomeSpan can store up to 16 sets of Pairing Data. You can view most of the Pairing Data for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: @@ -47,11 +47,15 @@ Though you can run the same sketch on two different HomeSpan devices, each devic However, sometimes you may want to *replace* one HomeSpan device with another running the exact same sketch. Maybe the first device has malfunctioned or was damaged. Typically when this occurs, you unpair the first (broken) device from HomeKit and then pair the new device to HomeKit. Unfortunately, once you unpair the old device, HomeKit forgets any automations, scenes, customizatons, etc., related to this device that you may have made using the Home App. When you pair the new device, even though it is running the same sketch, HomeKit will treat it as a completely new device. It will not apply any name-changes you may have made in the Home App, nor recreate any of the prior device's automations. -To solve this problem, you need to be able to replace the broken device with a new device, but *without* unpairing the old device or re-pairing the new device. This would require the new device to be initialized with the same Pairing Data as the old device, including having the same long-term secret key. +To solve this problem, you need to be able to replace the broken device with a new device, but *without* unpairing the old device or re-pairing the new device. This requires the new device to be initialized not with a new set of randomly-generated Device IDs, LTPKs and LTSKs, but rather with the *same* Pairing Data as the old device. -Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3, etc. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. +Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. -Cloning HomeSpan's pairing data is a two-step process. **First, type 'P' into the CLI for the device you wish to clone.** This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). HomeSpan will output its Pairing Data in base-64. Here is an example reflecting a system with Pairing Data for two Controllers (similar to above): +Cloning HomeSpan's pairing data is a two-step process. + +* **First, type 'P' into the CLI for the device you wish to clone.** + +This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). HomeSpan will output its Pairing Data in base-64. Here is an example reflecting a system with Pairing Data for two Controllers (similar to above): ``` *** Pairing Data used for Cloning another Device From 17361d28e49f8cd786ebcd90f5f248ce4b6edefa Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:03:31 -0500 Subject: [PATCH 67/79] Update Cloning.md --- docs/Cloning.md | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index d09353c..80866de 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -2,17 +2,11 @@ ### HomeSpan Pairing Data -Every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). These data are randomly generated by every new HomeSpan device. Once generated, HomeSpan permanently saves the data in the device's non-volatile storage partition, but this data can be subsequently erased and randomly re-generated with the 'H' CLI Command. +Even though two different ESP32 devices may be running the exact same sketch, they are nevertheless distinct. This is because every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). When HomeSpan is run for the first time on a new device, it looks for these data in the device's non-volatile storage (NVS) memory. If it is found, the data is loaded for use. If not found, HomeSpan generates a new set of random keys, and saves this data in the NVS. The data is permanently stored, though can be erased by typing 'H' into the CLI, which causes HomeSpan to generate a new set of random keys upon the next reboot. -Similarly, every HomeKit Controller (e.g. the Home App on an iPhone) has unique 36-character Device ID and a unique 32-byte LTPK. +When HomeSpan is initially paired to HomeKit, the 36-character Device ID and 32-byte LTPK for one or more HomeKit Controllers is securely transmitted to the HomeSpan Accessory. The Controllers keys are also saved in the device's NVS for permanent retention (though this data is also erased with the 'H' CLI command). -When a HomeSpan Accessory is first paired with a HomeKit Controller (using either the Accessory's QR code or its 8-digit Pairing Code), the Accessory and the Controller securely transmit to eachother their Device IDs and LTPKs, which are in turn also permanently stored. Thus, after pairing, HomeSpan will have in storage its own Device ID, LTPK and LTSK, and the Device ID and LTPK of the paired Controller. Collectively this information is known as *Pairing Data*. - -Pairing Data is used every time a HomeKit Controller opens up a new secure connection with a HomeKit Accessory. Without this data, the Home App will no longer be able to open a connection to HomeSpan. - -Once an Accessory is paired to a Controller, it cannot be paired to a second Controller. But yet you can operate a HomeSpan device from multiple iPhones, HomePods, Macs, etc., as long as they are on the same network. This is because in the background HomeKit shares the Pairing Data of a HomeSpan Accessory with other Controllers. When opening their own connections to HomeSpan, those Controllers use the same Pairing Data. However, sometimes HomeKit decides to create one or more additional sets of Pairing Data for other Controllers to use by sending such new Pairing Data securely to a HomeSpan Accessory. HomeSpan can store up to 16 sets of Pairing Data. - -You can view most of the Pairing Data for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: +Collectively, the Accessory Device ID, LTPK and LTSK, along with the Device ID and LTPK for each paired Controller, is known as the *Pairing Data* for the device. You can view the Pairing Data (except for the LTSK) for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: ``` *** HomeSpan Status *** @@ -39,23 +33,21 @@ Connection #11 (unconnected) *** End Status *** ``` -The only Pairing Data not shown on the CLI is the Accessory's LTSK (the long-term secret key). - ### Cloning a HomeSpan Device -Though you can run the same sketch on two different HomeSpan devices, each device will have a unique Device ID, will need to be separately paired with HomeKit, and each will operate as an independent device (perhaps controlling separate lights). This is the normal use case for running the same sketch on more than one device. +Because every device has a unique set of Pairing Data, it is not possible to simply swap a device that is already paired to HomeKit with another one that is not yet paired - the Device IDs will be different and the second device will need to be separately paired. -However, sometimes you may want to *replace* one HomeSpan device with another running the exact same sketch. Maybe the first device has malfunctioned or was damaged. Typically when this occurs, you unpair the first (broken) device from HomeKit and then pair the new device to HomeKit. Unfortunately, once you unpair the old device, HomeKit forgets any automations, scenes, customizatons, etc., related to this device that you may have made using the Home App. When you pair the new device, even though it is running the same sketch, HomeKit will treat it as a completely new device. It will not apply any name-changes you may have made in the Home App, nor recreate any of the prior device's automations. +This can present a problem if you need to swap out a device (perhaps because it has malfunctioned or was damaged) and you have created a lot of custom automations and scenes for the device from within the Home App. The new device you use to replace the old device will be seen as a completely new Accessory by HomeKit, and will not be connected with any automations or scenes associated with the old device. In fact, if your unpair the old device, automations and scenes specific to that device will be lost. To solve this problem, you need to be able to replace the broken device with a new device, but *without* unpairing the old device or re-pairing the new device. This requires the new device to be initialized not with a new set of randomly-generated Device IDs, LTPKs and LTSKs, but rather with the *same* Pairing Data as the old device. Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. -Cloning HomeSpan's pairing data is a two-step process. +Cloning HomeSpan's Pairing Data is a two-step process. First you output the Pairing Data from one device to the Serial Monitor, then you copy and paste this data into the Serial Monitor of the second device. Of course if the first device is completely broken you will not be able to output its Pairing Data - if you create a lot of automations in HomeKit you may want to output the Pairing Data from your devices and save it in a plain text file for later use should the device need to be replaced in the future. -* **First, type 'P' into the CLI for the device you wish to clone.** +**To output the Pairing Data from one device type 'P' into the CLI** -This necessarily means the device must still be working well enough for HomeSpan to run (if the device is completely dead, you will not be able to clone its Pairing Data). HomeSpan will output its Pairing Data in base-64. Here is an example reflecting a system with Pairing Data for two Controllers (similar to above): +Unlike the 'S' commnand, the 'P' command compresses all the data into base64 chunks as follows: ``` *** Pairing Data used for Cloning another Device @@ -67,13 +59,13 @@ Controller data: MEUwLTREMEUtODk3Ni0yMjBDREQ2RDUxMjjmah3s+Je0GkmAQE0NDQ1NUE2Ni1E *** End Pairing Data ``` -The first line completely encodes the Pairing Data for the HomeSpan Accessory. The second two lines encode the Pairing Data for two Controllers that HomeKit is using to control the HomeSpan device. Note your system may only have one Controller. Or it may have more than two. The number of Controllers depends on your HomeKit network, how it is configured, what devices you have (Apple TVs, HomePods, etc.) and what version of iOS you are running. +The first line completely encodes the Pairing Data for the HomeSpan Accessory. The second two lines encode the Pairing Data for two Controllers that HomeKit is using to control the HomeSpan device. Note your system may only have one Controller, or it may have more than two. The number of Controllers depends on your HomeKit network, how it is configured, what devices you have (Apple TVs, HomePods, etc.) and what version of iOS you are running. Copy this data, exactly as is, from the CLI and save it in a text file. Make sure not to lose any trailing equal signs - they are part of the base64 data! -Next, power down the device, or at least remove it from the WiFi network to avoid potential duplications two devices running on the same network with identical Pairing Data (HomeKit will likely not behave if this occurs). +Next, power down the device, or at least remove it from the WiFi network to avoid potential duplications of two devices running on the same network with identical Pairing Data (HomeKit will likely not behave if this occurs). -**Then, open the Serial Monitor on the new replacement device that is already running the *exact* same HomeSpan sketch as the first device and type 'C' to begin the cloning process.** +**To clone the Pairing Data onto a second device, type 'C' into the CLI for that device.** HomeSpan will begin by asking you for the Accessory Pairing Data. Copy and paste the base64 data for the Accessory that you save in the text file directly into the Serial Monitor input window and hit return. If you copied the data correctly it will be accepted and HomeSpan will display the Device ID that was encoded in the data (it does not bother to display the LTPK and LTSK data). The Device ID should match that of the orignal device. @@ -81,13 +73,13 @@ If you copied or pasted the data incorrectly, HomeSpan will let you know there i After the Accessory data is accepted, HomeSpan will then ask for Controller data. Copy and paste the base64 data from one of the Controllers in the saved text file directly into the Serial Monitor input window and hit return. As before, if you copied and pasted correctly, HomeSpan will accept the data and display the Device ID of the Controller. If you copied and pasted incorrectly, HomeSpan will inform you of the error, cancel the process, and reboot without making any changes. -Assuming the data for the first Controller has been accepted, HomeSpan will ask you to repeat the process for any other Controllers you may have. Keep repeating the process for copying and pasting the Pairing Data for each Controller. When you have input the Pairing Data for each Controller, simply hit hit return without entering any data when asked for the next Controller. An empty response tells HomeSpan you are done adding Controller data. +Assuming the data for the first Controller has been accepted, HomeSpan will ask you to repeat the process for any other Controllers you may have. Keep repeating the process for copying and pasting the Pairing Data for each Controller. When you have input the Pairing Data for all Controllers, simply hit hit return without entering any data when asked for the next Controller. An empty response tells HomeSpan you are done adding Controller data. Finally, HomeSpan will ask you to confirm saving the new data. Type either 'y' to confirm (yes) or 'n' to cancel (no). If you type 'n', HomeSpan will reboot without saving any of the changes. -If you type 'y', HomeSpan will save all of the new Pairing Data in the ESP32's permanent storage and reboot. Upon restarting, HomeSpan will be a clone of the original device and HomeKit should recognize it as if it were the original. You will not need to re-pair the device or make any other changes to the Home App. +If you type 'y', HomeSpan will save all of the new Pairing Data in the new device's NVS and reboot. Upon restarting, HomeSpan will be a clone of the original device and HomeKit should recognize it as if it were the original. You will not need to re-pair the device or make any other changes to the Home App. -❗Caution: Do NOT run two devices on the same HomeKit network with the same Pairing Data. If you want to experiment by Cloning a working device onto a second device, make sure to unplug the first device before cloning the data onto the second device. When you are experimenting, type 'H' into the CLI of the device to erase the Controller Pairing Data and regenerate a new, random set of Accessory Pairing Data, allowing you to plug both devices in at the same time without conflict. +❗Caution: Do NOT run two devices on the same HomeKit network with the same Pairing Data. If you want to experiment by Cloning a working device onto a second device, make sure to unplug the first device before cloning the data onto the second device. When you are finished experimenting, type 'H' into the CLI of one of the devices so the cloned Pairing Data will be erased and re-generated into something once again unique, allowing you to plug both devices in at the same time without conflict. --- From ba02cefa433465be95e8c3dbed16e80df283174b Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:18:49 -0500 Subject: [PATCH 68/79] Update Cloning.md --- docs/Cloning.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 80866de..214670d 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -4,9 +4,9 @@ Even though two different ESP32 devices may be running the exact same sketch, they are nevertheless distinct. This is because every HomeSpan Accessory has unique 17-character Device ID, a unique 32-byte long-term public key (LTPK), and a unique 64-byte long-term secret key (LTSK). When HomeSpan is run for the first time on a new device, it looks for these data in the device's non-volatile storage (NVS) memory. If it is found, the data is loaded for use. If not found, HomeSpan generates a new set of random keys, and saves this data in the NVS. The data is permanently stored, though can be erased by typing 'H' into the CLI, which causes HomeSpan to generate a new set of random keys upon the next reboot. -When HomeSpan is initially paired to HomeKit, the 36-character Device ID and 32-byte LTPK for one or more HomeKit Controllers is securely transmitted to the HomeSpan Accessory. The Controllers keys are also saved in the device's NVS for permanent retention (though this data is also erased with the 'H' CLI command). +When HomeSpan is initially paired to HomeKit, the 36-character Device ID and 32-byte LTPK for one or more HomeKit Controllers is securely transmitted to the HomeSpan Accessory. These keys are then saved in the device's NVS for permanent retention (though can be erased by the 'H' command). -Collectively, the Accessory Device ID, LTPK and LTSK, along with the Device ID and LTPK for each paired Controller, is known as the *Pairing Data* for the device. You can view the Pairing Data (except for the LTSK) for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: +Collectively, the Accessory Device ID, LTPK and LTSK, along with the Device ID and LTPK for each paired Controller, is known as the device's *Pairing Data*. You can view the Pairing Data (except for the LTSK) for any HomeSpan Accessory by typing 'S' into the CLI. Here is an example: ``` *** HomeSpan Status *** @@ -39,15 +39,15 @@ Because every device has a unique set of Pairing Data, it is not possible to sim This can present a problem if you need to swap out a device (perhaps because it has malfunctioned or was damaged) and you have created a lot of custom automations and scenes for the device from within the Home App. The new device you use to replace the old device will be seen as a completely new Accessory by HomeKit, and will not be connected with any automations or scenes associated with the old device. In fact, if your unpair the old device, automations and scenes specific to that device will be lost. -To solve this problem, you need to be able to replace the broken device with a new device, but *without* unpairing the old device or re-pairing the new device. This requires the new device to be initialized not with a new set of randomly-generated Device IDs, LTPKs and LTSKs, but rather with the *same* Pairing Data as the old device. +To solve this problem you need to be able to replace the broken device with a new device, but *without* unpairing the old device or re-pairing the new device. This requires the new device to be initialized not with a new set of randomly-generated Device IDs, LTPKs and LTSKs, but rather with the *same* Pairing Data as the old device. Fortunately, HomeSpan provides a methods for "cloning" the Pairing Data from one device to another. This means you can swap out a broken device for a new device without HomeKit knowing the difference (provided it is running the same sketch of course). In fact, you can even swap out an ESP32 for an ESP32-S2, or ESP32-C3. As long as the sketch is the same, once you clone the Pairing Data the devices are effectively hot-swappable. -Cloning HomeSpan's Pairing Data is a two-step process. First you output the Pairing Data from one device to the Serial Monitor, then you copy and paste this data into the Serial Monitor of the second device. Of course if the first device is completely broken you will not be able to output its Pairing Data - if you create a lot of automations in HomeKit you may want to output the Pairing Data from your devices and save it in a plain text file for later use should the device need to be replaced in the future. +Cloning HomeSpan's Pairing Data is a two-step process. First you output the Pairing Data from one device to the Serial Monitor, then you copy and paste this data into the Serial Monitor of the second device. Of course if the first device is completely broken you will not be able to output its Pairing Data. If you create a lot of automations in HomeKit you may want to output the Pairing Data from each of your devices and save it in a plain text file for later use should any device need to be replaced in the future. -**To output the Pairing Data from one device type 'P' into the CLI** +#### Step 1: Type 'P' into the Serial Monitor CLI of the first device to output its Pairing Data -Unlike the 'S' commnand, the 'P' command compresses all the data into base64 chunks as follows: +Unlike the 'S' command, the 'P' command compresses all the Pairing Data into *base-64* chunks to make it easier to copy and paste as follows: ``` *** Pairing Data used for Cloning another Device @@ -61,9 +61,11 @@ Controller data: MEUwLTREMEUtODk3Ni0yMjBDREQ2RDUxMjjmah3s+Je0GkmAQE0NDQ1NUE2Ni1E The first line completely encodes the Pairing Data for the HomeSpan Accessory. The second two lines encode the Pairing Data for two Controllers that HomeKit is using to control the HomeSpan device. Note your system may only have one Controller, or it may have more than two. The number of Controllers depends on your HomeKit network, how it is configured, what devices you have (Apple TVs, HomePods, etc.) and what version of iOS you are running. -Copy this data, exactly as is, from the CLI and save it in a text file. Make sure not to lose any trailing equal signs - they are part of the base64 data! +Copy this data, exactly as is, from the CLI and save it in a text file. Make sure not to lose any trailing equal signs as they are part of the base-64 data! -Next, power down the device, or at least remove it from the WiFi network to avoid potential duplications of two devices running on the same network with identical Pairing Data (HomeKit will likely not behave if this occurs). +Next, power down the first device, or at least remove it from the WiFi network to avoid potential duplications of two devices running on the same network with identical Pairing Data (HomeKit will likely not behave if this occurs). If the second device is not plugged in, do so now and open its Serial Monitor. + +#### Step 2: Type 'C' into the Serial Monitor CLI of the second device to input the Pairing Data you just saved from the first device **To clone the Pairing Data onto a second device, type 'C' into the CLI for that device.** From be80a2c0d10ed3c78d77956e6cda47cf0ebf240c Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:27:16 -0500 Subject: [PATCH 69/79] Update Cloning.md --- docs/Cloning.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 214670d..7e930d5 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -67,19 +67,17 @@ Next, power down the first device, or at least remove it from the WiFi network t #### Step 2: Type 'C' into the Serial Monitor CLI of the second device to input the Pairing Data you just saved from the first device -**To clone the Pairing Data onto a second device, type 'C' into the CLI for that device.** - -HomeSpan will begin by asking you for the Accessory Pairing Data. Copy and paste the base64 data for the Accessory that you save in the text file directly into the Serial Monitor input window and hit return. If you copied the data correctly it will be accepted and HomeSpan will display the Device ID that was encoded in the data (it does not bother to display the LTPK and LTSK data). The Device ID should match that of the orignal device. +HomeSpan will begin by asking you for the Accessory Pairing Data. Copy and paste this data (it's the first set of base-64 data output in Step 1 above) directly into the Serial Monitor input window and hit return. If you copied the data correctly it will be accepted and HomeSpan will display the Device ID that was encoded in the data (it does not bother to display the LTPK and LTSK data). The Device ID should match that of the orignal device. If you copied or pasted the data incorrectly, HomeSpan will let you know there is a problem, cancel the process, and reboot without making any changes. You can also cancel the process by simply hitting return after typing 'P' *without* entering any data (this does not cause a reboot, since no data was changed). -After the Accessory data is accepted, HomeSpan will then ask for Controller data. Copy and paste the base64 data from one of the Controllers in the saved text file directly into the Serial Monitor input window and hit return. As before, if you copied and pasted correctly, HomeSpan will accept the data and display the Device ID of the Controller. If you copied and pasted incorrectly, HomeSpan will inform you of the error, cancel the process, and reboot without making any changes. +After the Accessory data is accepted, HomeSpan will then ask for Controller data. Copy and paste this base-64 data from one of the Controllers in the saved text file directly into the Serial Monitor input window and hit return. As before, if you copied and pasted correctly, HomeSpan will accept the data and display the Device ID of the Controller. If you copied and pasted incorrectly, HomeSpan will inform you of the error, cancel the process, and reboot without making any changes. -Assuming the data for the first Controller has been accepted, HomeSpan will ask you to repeat the process for any other Controllers you may have. Keep repeating the process for copying and pasting the Pairing Data for each Controller. When you have input the Pairing Data for all Controllers, simply hit hit return without entering any data when asked for the next Controller. An empty response tells HomeSpan you are done adding Controller data. +Assuming the data for the first Controller has been accepted, HomeSpan will ask you to repeat the process for any other Controllers you may have. Keep repeating the process for copying and pasting the Pairing Data for each Controller. When you have input the Pairing Data for all Controllers, simply hit return without entering any data when asked for the next Controller. An empty response tells HomeSpan you are done adding Controller data. Finally, HomeSpan will ask you to confirm saving the new data. Type either 'y' to confirm (yes) or 'n' to cancel (no). If you type 'n', HomeSpan will reboot without saving any of the changes. -If you type 'y', HomeSpan will save all of the new Pairing Data in the new device's NVS and reboot. Upon restarting, HomeSpan will be a clone of the original device and HomeKit should recognize it as if it were the original. You will not need to re-pair the device or make any other changes to the Home App. +If you type 'y', HomeSpan will save all of the new Pairing Data in the device's NVS and reboot. Upon restarting, this second device will be a perfect clone of the first device and HomeKit should recognize it as if it were the original. You will not need to re-pair the device or make any other changes to the Home App. ❗Caution: Do NOT run two devices on the same HomeKit network with the same Pairing Data. If you want to experiment by Cloning a working device onto a second device, make sure to unplug the first device before cloning the data onto the second device. When you are finished experimenting, type 'H' into the CLI of one of the devices so the cloned Pairing Data will be erased and re-generated into something once again unique, allowing you to plug both devices in at the same time without conflict. From 476678e1ce4f087ae52de0e07c0ce07bcd25900a Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:31:18 -0500 Subject: [PATCH 70/79] Update CLI.md --- docs/CLI.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/CLI.md b/docs/CLI.md index 4481176..bfa005a 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -71,8 +71,14 @@ In addition to listening for incoming HAP requests, HomeSpan also continuously p * **H** - delete HomeKit Device ID as well as all Controller data and restart * In addition to deleting all Controller data (as if the 'U' command was run), this command also deletes the device's HomeKit ID. This unique ID is broadcast to all HomeKit Controllers so the device can be uniquely recognized. When HomeSpan first runs on a new device, it creates this unique ID and stores it permanently in an NVS partition. Normally, this ID should not changed once set. However, if you are actively developing and testing a HomeSpan sketch, you may find that HomeKit is cacheing information about your device and the changes you have made to your HAP Accessory Database are not always reflected in the Home App. Sometimes simply unpairing and re-pairing the device solves this HomeKit issue. If not, deleting your device's HomeKit ID with this command forces HomeSpan to generate a new one after restarting, which means HomeKit will think this is a completely different device, thereby ignoring any prior data it had cached. - * This command also restores the device's default Setup ID, which is used for optional pairing with QR codes, to "HSPN". + * This command also restores the device's default Setup ID, which is used for optional pairing with QR codes, to "HSPN". +* **P** - prints the device's Pairing Data in base-64 chunks + * Used for [Cloning](Cloning.md) the Pairing Data from one device to another + +* **C** - prompts you to input the Pairing Data from another device in base-64 chunks + * Used for [Cloning](Cloning.md) the Pairing Data from one device to another + * **R** - restart the device * This command simply reboots HomeSpan. From 94ebee230832d0d20123cea3120f400d0a04d667 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:33:54 -0500 Subject: [PATCH 71/79] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index eec5b65..9ae032b 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ HomeSpan includes the following documentation: * [HomeSpan SpanPoint](docs/NOW.md) - facilitates point-to-point, bi-directional communication between ESP32 Devices using ESP-NOW * [HomeSpan Television Services](docs/TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics * [HomeSpan Message Logging](docs/Logging.md) - how to generate log messages for display on the Arduino Serial Monitor as well as optionally posted to an integrated Web Log page +* [Device Cloning](docs.Cloning.md) - seamlessly swap a broken device for a new one without needing to re-pair and lose HomeKit automations * [HomeSpan Projects](https://github.com/topics/homespan) - real-world applications of the HomeSpan Library * [HomeSpan FAQ](docs/FAQ.md) - answers to frequently-asked questions From c8cbfd8ebe2e58e035adbb695f4fc29c06d4ab76 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:34:21 -0500 Subject: [PATCH 72/79] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ae032b..528f64b 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ HomeSpan includes the following documentation: * [HomeSpan SpanPoint](docs/NOW.md) - facilitates point-to-point, bi-directional communication between ESP32 Devices using ESP-NOW * [HomeSpan Television Services](docs/TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics * [HomeSpan Message Logging](docs/Logging.md) - how to generate log messages for display on the Arduino Serial Monitor as well as optionally posted to an integrated Web Log page -* [Device Cloning](docs.Cloning.md) - seamlessly swap a broken device for a new one without needing to re-pair and lose HomeKit automations +* [Device Cloning](docs/Cloning.md) - seamlessly swap a broken device for a new one without needing to re-pair and lose HomeKit automations * [HomeSpan Projects](https://github.com/topics/homespan) - real-world applications of the HomeSpan Library * [HomeSpan FAQ](docs/FAQ.md) - answers to frequently-asked questions From 043fc33e5cec6de1da9b5b36d290c2518c28428e Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 20:34:51 -0500 Subject: [PATCH 73/79] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 528f64b..46933ab 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ HomeSpan includes the following documentation: * [HomeSpan SpanPoint](docs/NOW.md) - facilitates point-to-point, bi-directional communication between ESP32 Devices using ESP-NOW * [HomeSpan Television Services](docs/TVServices.md) - how to use HomeKit's undocumented Television Services and Characteristics * [HomeSpan Message Logging](docs/Logging.md) - how to generate log messages for display on the Arduino Serial Monitor as well as optionally posted to an integrated Web Log page -* [Device Cloning](docs/Cloning.md) - seamlessly swap a broken device for a new one without needing to re-pair and lose HomeKit automations +* [HomeSpan Device Cloning](docs/Cloning.md) - seamlessly swap a broken device for a new one without needing to re-pair and lose HomeKit automations * [HomeSpan Projects](https://github.com/topics/homespan) - real-world applications of the HomeSpan Library * [HomeSpan FAQ](docs/FAQ.md) - answers to frequently-asked questions From 485d99a03a4e1554e89a675af25fc358b99274ec Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 21:02:31 -0500 Subject: [PATCH 74/79] Update README.md --- README.md | 55 +++++++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 46933ab..369e346 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * Command-line interface with a variety of info, debugging, and configuration commands * Built-in database validation to ensure your configuration meets all HAP requirements * Dedicated classes that utilize the ESP32's 16-channel PWM peripheral for easy control of: - * LED Brightness + * LED Brightness (including auto-fading) * Servo Motors * Integrated Push Button and Toggle Switch functionality supporting single, double, and long presses of: * Physical pushbuttons that connect an ESP32 pin to either ground or VCC @@ -48,40 +48,35 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * Launch the WiFi Access Point * A standalone, detailed End-User Guide -## ❗Latest Update - HomeSpan 1.7.1 (2/4/2023) +## ❗Latest Update - HomeSpan 1.7.2 (4/6/2023) -* **SpanPoint support for the ESP8266!** - * Use ESP-NOW on an ESP8266 to connect to HomeSpan running on an ESP32 - * See the [SpanPoint Tutorial Page](docs/NOW.md) for more info as well as a detailed ESP8266 example - -* **SpanPoint WiFi channel scanning upgrade** - * SpanPoint now saves the last WiFi channel successfully used for transmission in non-volatile storage - * Avoids the need for SpanPoint to restart a full scan of all channels upon reboot - * Dramatically extends battery life when used in conjunction with deep-sleep functionality - -* **New SpanToggle class** - * Similar to SpanButton, but designed for toggle switches - * Integrated de-bounce logic prevents false triggers - * Ideal for use with Contact Sensors +* New ability to set OTA password from within sketch + * See the [OTA Page](docs/OTA.md) for details + +* Added logic to allow duplicates of the same Custom Characteristic to be "defined" in more than one file in a sketch + * Allows the use of the same Custom Characteristic across multiple files in the same sketch without the compiler throwing a "redefinition error" * See the [API Reference](docs/Reference.md) for details - -* **Added Television Speaker Service** - * Control the volume of a Television from Apple's Remote App - * See the [Television Services Page](docs/TVServices.md) for details and examples - -* **Added support for byte-array ("DATA") Characteristics** - * Useful for experimentation with other HomeKit applications, such as *Eve for HomeKit* - * Includes three new Characteristic methods: `setData()`, `getData()`, and `getNewData()` - * Includes new macro `CUSTOM_CHAR_DATA()` to easily create custom byte-array Characteristics + +* Extended functionality of `setValidValues()` to work with more than just UINT8 Characteristics + * Now works with INT, UINT16, and UINT32 Characteristics, as well as UINT8 Characteristics * See the [API Reference](docs/Reference.md) for details - -* **LedPin upgrade** - * New option to invert the PWM signal - * Useful for generating two, separate out-of-phase PWM signals (one inverted, one not) to drive certain two-pin devices in a push/pull manner, such as a piezo-electric buzzer + +* New parameters added to `autoPoll()` that allow the user to set priority and chose CPU + * Provides for enhanced performance on dual-processor chips + * See the [API Reference](docs/Reference.md) for details + +* Automatic LED Fading! + * Added new methods to LedPin class that enable use of the ESP32's built-in fade controls + * Allows user to specify speed of fade + * Runs in background without consuming any CPU resources * See the [PWM Page](docs/PWM.md) for details -* **Bug Fixes** - * Added logic to prevent the extraneous broadcasting of an Access Point SSID when SpanPoint is being used +* Added ability to Clone the Pairing Data from one device to another + * Adds new 'P' and 'C' commands to the CLI + * Enables a broken device to be swapped for a new device (running the same sketch) without the need to unpair the old device or pair the new device + * Avoids loss of automations, scenes, and any other Home App customizations associated with device + * New and old device can be different chips (e.g. ESP32-S2 versus ESP32-C3) + * See the new [Cloning Page](Cloning.MD) for details See [Releases](https://github.com/HomeSpan/HomeSpan/releases) for details on all changes and bug fixes included in this update. From d912009ced09c4a26c485fed6e5be835da346627 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 21:03:55 -0500 Subject: [PATCH 75/79] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 369e346..3c54c47 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * Enables a broken device to be swapped for a new device (running the same sketch) without the need to unpair the old device or pair the new device * Avoids loss of automations, scenes, and any other Home App customizations associated with device * New and old device can be different chips (e.g. ESP32-S2 versus ESP32-C3) - * See the new [Cloning Page](Cloning.MD) for details + * See the new [Cloning Page](Cloning.md) for details See [Releases](https://github.com/HomeSpan/HomeSpan/releases) for details on all changes and bug fixes included in this update. From 2d012f7e0a1e73c6a329d74d137054cddea23627 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 21:04:30 -0500 Subject: [PATCH 76/79] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c54c47..0156340 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * Enables a broken device to be swapped for a new device (running the same sketch) without the need to unpair the old device or pair the new device * Avoids loss of automations, scenes, and any other Home App customizations associated with device * New and old device can be different chips (e.g. ESP32-S2 versus ESP32-C3) - * See the new [Cloning Page](Cloning.md) for details + * See the new [Cloning Page](docs/Cloning.md) for details See [Releases](https://github.com/HomeSpan/HomeSpan/releases) for details on all changes and bug fixes included in this update. From 7baa3013c778c8524eac5834af77fa28313a2ded Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 21:06:46 -0500 Subject: [PATCH 77/79] Update Cloning.md --- docs/Cloning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Cloning.md b/docs/Cloning.md index 7e930d5..5e16a5f 100644 --- a/docs/Cloning.md +++ b/docs/Cloning.md @@ -61,7 +61,7 @@ Controller data: MEUwLTREMEUtODk3Ni0yMjBDREQ2RDUxMjjmah3s+Je0GkmAQE0NDQ1NUE2Ni1E The first line completely encodes the Pairing Data for the HomeSpan Accessory. The second two lines encode the Pairing Data for two Controllers that HomeKit is using to control the HomeSpan device. Note your system may only have one Controller, or it may have more than two. The number of Controllers depends on your HomeKit network, how it is configured, what devices you have (Apple TVs, HomePods, etc.) and what version of iOS you are running. -Copy this data, exactly as is, from the CLI and save it in a text file. Make sure not to lose any trailing equal signs as they are part of the base-64 data! +Copy this data, exactly as is, from the CLI and save it in a text file. Make sure not to lose any trailing equal signs as they are part of the base‑64 data! Next, power down the first device, or at least remove it from the WiFi network to avoid potential duplications of two devices running on the same network with identical Pairing Data (HomeKit will likely not behave if this occurs). If the second device is not plugged in, do so now and open its Serial Monitor. From 687ffb6750e84763182417e1b6a308be260b299d Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 21:09:30 -0500 Subject: [PATCH 78/79] Update library.properties --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 27bcd43..d531b0c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=HomeSpan -version=1.7.1 +version=1.7.2 author=Gregg maintainer=Gregg sentence=A robust and extremely easy-to-use HomeKit implementation for the Espressif ESP32 running on the Arduino IDE. From 9c2b40576f4c66c21960a4d7d41364aa24cfd293 Mon Sep 17 00:00:00 2001 From: HomeSpan Date: Wed, 5 Apr 2023 21:10:38 -0500 Subject: [PATCH 79/79] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0156340..f822744 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ HomeSpan requires version 2.0.0 or later of the [Arduino-ESP32 Board Manager](ht * Launch the WiFi Access Point * A standalone, detailed End-User Guide -## ❗Latest Update - HomeSpan 1.7.2 (4/6/2023) +## ❗Latest Update - HomeSpan 1.7.2 (4/5/2023) * New ability to set OTA password from within sketch * See the [OTA Page](docs/OTA.md) for details