diff --git a/examples/01-SimpleLightBulb/01-SimpleLightBulb.ino b/examples/01-SimpleLightBulb/01-SimpleLightBulb.ino index 6487c48..1932f43 100644 --- a/examples/01-SimpleLightBulb/01-SimpleLightBulb.ino +++ b/examples/01-SimpleLightBulb/01-SimpleLightBulb.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * @@ -51,9 +51,6 @@ // NOTE: All HomeSpan examples are best understood when reviewed in conjunction with the documentation provided on the HomeSpan GitHub page. // See https://github.com/HomeSpan/HomeSpan for details and references. In particular, you may want to review the HomeSpan API Overview // page before proceeding. - - // These examples also make frequent reference to Apple's HomeKit Accessory Protocol Specification, known as HAP. You can download this - // directly from Apple at https://developer.apple.com/support/homekit-accessory-protocol. // LET'S GET STARTED... diff --git a/examples/02-TwoSimpleLightBulbs/02-TwoSimpleLightBulbs.ino b/examples/02-TwoSimpleLightBulbs/02-TwoSimpleLightBulbs.ino index a5367eb..775d7bc 100644 --- a/examples/02-TwoSimpleLightBulbs/02-TwoSimpleLightBulbs.ino +++ b/examples/02-TwoSimpleLightBulbs/02-TwoSimpleLightBulbs.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/03-CeilingFanWithLight/03-CeilingFanWithLight.ino b/examples/03-CeilingFanWithLight/03-CeilingFanWithLight.ino index 2bd976f..ceb6c3f 100644 --- a/examples/03-CeilingFanWithLight/03-CeilingFanWithLight.ino +++ b/examples/03-CeilingFanWithLight/03-CeilingFanWithLight.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/04-AdvancedCeilingFan/04-AdvancedCeilingFan.ino b/examples/04-AdvancedCeilingFan/04-AdvancedCeilingFan.ino index 574fcc4..e265d42 100644 --- a/examples/04-AdvancedCeilingFan/04-AdvancedCeilingFan.ino +++ b/examples/04-AdvancedCeilingFan/04-AdvancedCeilingFan.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/05-WorkingLED/05-WorkingLED.ino b/examples/05-WorkingLED/05-WorkingLED.ino index b9d3263..76388f5 100644 --- a/examples/05-WorkingLED/05-WorkingLED.ino +++ b/examples/05-WorkingLED/05-WorkingLED.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/06-DimmableLED/06-DimmableLED.ino b/examples/06-DimmableLED/06-DimmableLED.ino index edeba4b..0b17b5e 100644 --- a/examples/06-DimmableLED/06-DimmableLED.ino +++ b/examples/06-DimmableLED/06-DimmableLED.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/07-AccessoryNames/07-AccessoryNames.ino b/examples/07-AccessoryNames/07-AccessoryNames.ino index 3830d46..4a9c2db 100644 --- a/examples/07-AccessoryNames/07-AccessoryNames.ino +++ b/examples/07-AccessoryNames/07-AccessoryNames.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/08-Bridges/08-Bridges.ino b/examples/08-Bridges/08-Bridges.ino index 0331f3c..80b0daf 100644 --- a/examples/08-Bridges/08-Bridges.ino +++ b/examples/08-Bridges/08-Bridges.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/09-MessageLogging/09-MessageLogging.ino b/examples/09-MessageLogging/09-MessageLogging.ino index f973669..c8c1146 100644 --- a/examples/09-MessageLogging/09-MessageLogging.ino +++ b/examples/09-MessageLogging/09-MessageLogging.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/10-RGB_LED/10-RGB_LED.ino b/examples/10-RGB_LED/10-RGB_LED.ino index 0d07250..c3b9d29 100644 --- a/examples/10-RGB_LED/10-RGB_LED.ino +++ b/examples/10-RGB_LED/10-RGB_LED.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/11-ServiceNames/11-ServiceNames.ino b/examples/11-ServiceNames/11-ServiceNames.ino index c529843..60c6485 100644 --- a/examples/11-ServiceNames/11-ServiceNames.ino +++ b/examples/11-ServiceNames/11-ServiceNames.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/12-ServiceLoops/12-ServiceLoops.ino b/examples/12-ServiceLoops/12-ServiceLoops.ino index c53878c..430b5ea 100644 --- a/examples/12-ServiceLoops/12-ServiceLoops.ino +++ b/examples/12-ServiceLoops/12-ServiceLoops.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/13-TargetStates/13-TargetStates.ino b/examples/13-TargetStates/13-TargetStates.ino index 4fa0871..aa20200 100644 --- a/examples/13-TargetStates/13-TargetStates.ino +++ b/examples/13-TargetStates/13-TargetStates.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * @@ -60,18 +60,19 @@ void setup() { // guesses the actions a device is taking, and updates it tile's icon accordingly, by comparing the value of the target state // Characteristic it sets, and the current state Characteristic it receives in the form of Event Notifications. When they are the same, // HomeKit assumes the physical device has reached the required position. When they differ, HomeKit assumes something will be opening, - // closing, raising, lowering, etc. The details of this process for each Service is outlined in the HAP documentation, but beware - // the document is not always up to date with the lastest version of the HomeKit application. Sometimes a little experimenting and a lot - // of trial and error is required to fully understand how each Service responds to different combinations of Characteristic values. + // closing, raising, lowering, etc. Sometimes a little experimenting and a lot of trial and error is required to fully understand how + // each Service responds to different combinations of Characteristic values. // As always, we won't be connecting our ESP32 to an actual garage door or window shade but will instead simulate their responses and // actions for illustrative purposes. In some ways the code is more complicated because of the need to simulate values - it might be // easier if we actually were connecting to a garage door or window shade! // Fully commented code for both of our derived Services can be found in DEV_DoorsWindows.h. These examples do not introduce any new - // HomeSpan functions or features. Rather we are combining everything learned so far into two reasonably complex Services. You may - // want to reference the HAP documentation for these two parent Services to fully understand the meaning of the different value settings - // for each of the Services' Characteristics. + // HomeSpan functions, but you will see how to use HomeSpan's ENUMERATED CONSTANTS, instead of just plain integers, to set the values + // of Characteristics where the values represent discrete states (e.g. "lowering", "opening"). + + // Please see HomeSpan's Services and Characteristics page for a complete list of the enumerated constants available for Characteristics + // where they are applicable. Serial.begin(115200); diff --git a/examples/13-TargetStates/DEV_DoorsWindows.h b/examples/13-TargetStates/DEV_DoorsWindows.h index e3aa128..e5467c4 100644 --- a/examples/13-TargetStates/DEV_DoorsWindows.h +++ b/examples/13-TargetStates/DEV_DoorsWindows.h @@ -3,17 +3,33 @@ // DEVICE-SPECIFIC LED SERVICES // //////////////////////////////////// -struct DEV_GarageDoor : Service::GarageDoorOpener { // A Garage Door Opener +struct DEV_GarageDoor : Service::GarageDoorOpener { // A Garage Door Opener - Characteristic::CurrentDoorState *current; // reference to the Current Door State Characteristic (specific to Garage Door Openers) + Characteristic::CurrentDoorState *current; // reference to the Current Door State Characteristic (specific to Garage Door Openers) Characteristic::TargetDoorState *target; // reference to the Target Door State Characteristic (specific to Garage Door Openers) - SpanCharacteristic *obstruction; // reference to the Obstruction Detected Characteristic (specific to Garage Door Openers) + SpanCharacteristic *obstruction; // reference to the Obstruction Detected Characteristic (specific to Garage Door Openers) - DEV_GarageDoor() : Service::GarageDoorOpener(){ // constructor() method + DEV_GarageDoor() : Service::GarageDoorOpener(){ // constructor() method + + // Below we use enumerated constants rather than integers to set the values of the Characteristics. + // Using enumerated constants means not having to remember the integer code for each state. You'll find + // a complete list of all available enumerated constants on HomeSpan's Services and Characteristics page. + // Note the use of enumerated constants is optional - you can always use the integer code representing + // each state instead. - current=new Characteristic::CurrentDoorState(1); // initial value of 1 means closed - target=new Characteristic::TargetDoorState(1); // initial value of 1 means closed - obstruction=new Characteristic::ObstructionDetected(false); // initial value of false means NO obstruction is detected + current=new Characteristic::CurrentDoorState(Characteristic::CurrentDoorState::CLOSED); // here we use the fully-qualified name of the constant "CLOSED" + target=new Characteristic::TargetDoorState(target->CLOSED); // here we use the name of the object instead of the fully-qualified name (much less typing) + + // Below we must use the fully-qualified name of the enumerated constant and cannot use "obstruction->NOT_DETECTED". + // Why? Because above we declared "obstruction" to be a pointer to a generic SpanCharacteristic instead of a pointer to + // the more specific Characteristic::ObstructionDetected. Either is fine, and it's just a matter of programming preference + // (as you can see we use both conventions in this sketch). But the downside of using SpanCharacteristic to declare a + // Characteristic that contains enumerated constants is that the object itself does not know about these constants. This is + // because all enumerated constants are uniquely defined within their respective specific Characteristic classes, and not in the + // generic SpanCharacteristic class from which all specific Characterstics are derived. + + obstruction=new Characteristic::ObstructionDetected(Characteristic::ObstructionDetected::NOT_DETECTED); // this works +// obstruction=new Characteristic::ObstructionDetected(obstruction->NOT_DETECTED); // this would produce a compiler error (try it and see) Serial.print("Configuring Garage Door Opener"); // initialization message Serial.print("\n"); @@ -24,13 +40,13 @@ struct DEV_GarageDoor : Service::GarageDoorOpener { // A Garage Door Opener // see HAP Documentation for details on what each value represents - if(target->getNewVal()==0){ // if the target-state value is set to 0, HomeKit is requesting the door to be in open position + if(target->getNewVal()==target->OPEN){ // HomeKit is requesting the door to be in OPEN position LOG1("Opening Garage Door\n"); - current->setVal(2); // set the current-state value to 2, which means "opening" - obstruction->setVal(false); // clear any prior obstruction detection + current->setVal(current->OPENING); // set the current-state value to OPENING + obstruction->setVal(false); // clear any prior obstruction detection - note we do not bother using an enumerated constant here } else { - LOG1("Closing Garage Door\n"); // else the target-state value is set to 1, and HomeKit is requesting the door to be in the closed position - current->setVal(3); // set the current-state value to 3, which means "closing" + LOG1("Closing Garage Door\n"); // else HomeKit must be requesting the door to be in the CLOSED position + current->setVal(current->CLOSING); // set the current-state value to CLOSING obstruction->setVal(false); // clear any prior obstruction detection } @@ -43,13 +59,13 @@ struct DEV_GarageDoor : Service::GarageDoorOpener { // A Garage Door Opener if(current->getVal()==target->getVal()) // if current-state matches target-state there is nothing do -- exit loop() return; - if(current->getVal()==3 && random(100000)==0){ // here we simulate a random obstruction, but only if the door is closing (not opening) - current->setVal(4); // if our simulated obstruction is triggered, set the curent-state to 4, which means "stopped" - obstruction->setVal(true); // and set obstruction-detected to true + if(current->getVal()==current->CLOSING && random(100000)==0){ // here we simulate a random obstruction, but only if the door is closing (not opening) + current->setVal(current->STOPPED); // if our simulated obstruction is triggered, set the curent-state to STOPPED + obstruction->setVal(true); // and set obstruction-detected to true LOG1("Garage Door Obstruction Detected!\n"); } - if(current->getVal()==4) // if the current-state is stopped, there is nothing more to do - exit loop() + if(current->getVal()==current->STOPPED) // if the current-state is stopped, there is nothing more to do - exit loop() return; // This last bit of code only gets called if the door is in a state that represents actively opening or actively closing. @@ -83,15 +99,6 @@ struct DEV_WindowShade : Service::WindowCovering { // A motorized Window Sha boolean update(){ // update() method - // The logic below is based on how HomeKit appears to operate in practice, which is NOT consistent with - // HAP documentation. In that document HomeKit seems to support fully opening or fully closing a window shade, with - // an optional control to HOLD the window shade at a given in-between position while it is moving. - - // In practice, HomeKit does not appear to implement any form of a HOLD control button, even if you instantiate that - // Characteristic. Instead, HomeKit provides a full slider control, similar to the brightness control for a lightbulb, - // that allows you to set the exact position of the window shade from 0-100%. This obviates the need to any sort of HOLD button. - // The resulting logic is also very simple: - if(target->getNewVal()>current->getVal()){ // if the target-position requested is greater than the current-position, simply log a "raise" message LOG1("Raising Shade\n"); // ** there is nothing more to do - HomeKit keeps track of the current-position so knows raising is required } else @@ -116,10 +123,7 @@ struct DEV_WindowShade : Service::WindowCovering { // A motorized Window Sha // the user in the Home App. If it finds current and target positions are the same, it knows the shade is stopped. Otherwise // it will report the shade is raising or lowering depending on whether the specified target state is greater or less than // the current state. - - // According to HAP, the Characteristic Position State is also required. However, this seems duplicative and is NOT needed - // at all given the way HomeKit uses current position. - + } // loop }; diff --git a/examples/14-EmulatedPushButtons/14-EmulatedPushButtons.ino b/examples/14-EmulatedPushButtons/14-EmulatedPushButtons.ino index 7469386..f0ce6e8 100644 --- a/examples/14-EmulatedPushButtons/14-EmulatedPushButtons.ino +++ b/examples/14-EmulatedPushButtons/14-EmulatedPushButtons.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * @@ -40,7 +40,7 @@ void setup() { // Though HomeKit and the HomeKit Accessory Protocol (HAP) Specification provide a very flexible framework - // for creating iOS- and MacOS-controlled devices, they does not contain every possible desired feature. + // for creating iOS- and MacOS-controlled devices, they do not contain every possible desired feature. // // One very common Characteristic HomeKit does not seem to contain is a simple pushbutton, like the type you // would find on a remote control. Unlike switches that can be "on" or "off", a pushbutton has no state. diff --git a/examples/15-RealPushButtons/15-RealPushButtons.ino b/examples/15-RealPushButtons/15-RealPushButtons.ino index 25f3fd1..56fb7c2 100644 --- a/examples/15-RealPushButtons/15-RealPushButtons.ino +++ b/examples/15-RealPushButtons/15-RealPushButtons.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/16-ProgrammableSwitches/16-ProgrammableSwitches.ino b/examples/16-ProgrammableSwitches/16-ProgrammableSwitches.ino index 47383ec..e39409b 100644 --- a/examples/16-ProgrammableSwitches/16-ProgrammableSwitches.ino +++ b/examples/16-ProgrammableSwitches/16-ProgrammableSwitches.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/17-LinkedServices/17-LinkedServices.ino b/examples/17-LinkedServices/17-LinkedServices.ino index c9bc469..bf40635 100644 --- a/examples/17-LinkedServices/17-LinkedServices.ino +++ b/examples/17-LinkedServices/17-LinkedServices.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2020-2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * @@ -113,7 +113,7 @@ struct Shower : Service::Faucet { // this is our Shower structur struct WaterValve : Service::Valve { // here we define our WaterValve structure as a child class of the HomeSpan Valve Service SpanCharacteristic *active=new Characteristic::Active(1);; // the Active Characteristic is used to specify whether the Valve is Active (open) or Inactive (closed) - SpanCharacteristic *inUse=new Characteristic::InUse(); // the InUser Characteristic is used to specify whether water is actually flowing through value + SpanCharacteristic *inUse=new Characteristic::InUse(); // the InUse Characteristic is used to specify whether water is actually flowing through value Shower *shower; // storage for the pointer to the "controlling" Shower Service WaterValve(Shower *s){ // this is constructor for WaterValve. It takes a single argument that points to the "controlling" Shower Service diff --git a/examples/18-SavingStatus/18-SavingStatus.ino b/examples/18-SavingStatus/18-SavingStatus.ino index 821913e..e5eaabd 100644 --- a/examples/18-SavingStatus/18-SavingStatus.ino +++ b/examples/18-SavingStatus/18-SavingStatus.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2021-2022 Gregg E. Berman + * Copyright (c) 2021-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/19-WebLog/19-WebLog.ino b/examples/19-WebLog/19-WebLog.ino index ce1e080..9ccd0ac 100644 --- a/examples/19-WebLog/19-WebLog.ino +++ b/examples/19-WebLog/19-WebLog.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2022 Gregg E. Berman + * Copyright (c) 2020-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * diff --git a/examples/20-AdvancedTechniques/20-AdvancedTechniques.ino b/examples/20-AdvancedTechniques/20-AdvancedTechniques.ino index 90c0c88..00244b5 100644 --- a/examples/20-AdvancedTechniques/20-AdvancedTechniques.ino +++ b/examples/20-AdvancedTechniques/20-AdvancedTechniques.ino @@ -1,7 +1,7 @@ /********************************************************************************* * MIT License * - * Copyright (c) 2022 Gregg E. Berman + * Copyright (c) 2022-2024 Gregg E. Berman * * https://github.com/HomeSpan/HomeSpan * @@ -123,7 +123,7 @@ void addLight(int n){ char name[32]; sprintf(name,"Light-%d",n); // create the name of the device using the specified "ID" char sNum[32]; - sprintf(sNum,"%0.10d",n); // create serial number from the ID - this is helpful in case we rename the Light to something else using the Home App + sprintf(sNum,"%010d",n); // create serial number from the ID - this is helpful in case we rename the Light to something else using the Home App Serial.printf("Adding Accessory: %s\n",name); diff --git a/examples/21-AccessoryIdentifier/21-AccessoryIdentifier.ino b/examples/21-AccessoryIdentifier/21-AccessoryIdentifier.ino index ad30093..7603f57 100644 --- a/examples/21-AccessoryIdentifier/21-AccessoryIdentifier.ino +++ b/examples/21-AccessoryIdentifier/21-AccessoryIdentifier.ino @@ -138,15 +138,23 @@ void setup() { homeSpan.setLogLevel(1); homeSpan.begin(Category::Lighting,"HomeSpan LEDS"); - + +// Here we replace the usual construct: + +// new SpanAccessory(); +// new Service::AccessoryInformation(); +// new Characteristic::Identify(); + +// with this: + new SpanAccessory(); - new DEV_INFO(13); // Here we instantiate the new DEV_INFO structure, instead of simply instantiating Characteristic::Name() and Characteristic::Identity() as in all previous examples + new DEV_INFO(13); // instantiate a new DEV_INFO structure that will run our custom identification routine to blink an LED on pin 13 three times new SpanAccessory(); new DEV_INFO(16); // Note we instantiate a new DEV_INFO structure for each Accessory in this device new DEV_LED(16); // Here we instantiate the usual DEV_LED structure that controls the LED during normal operation - new SpanAccessory(); // Here we add a second LED + new SpanAccessory(); // Here we add a second LED Accessory new DEV_INFO(17); new DEV_LED(17); }