diff --git a/examples/Tutorials/B-Intermediate/05-WorkingLED/05-WorkingLED.ino b/examples/Tutorials/B-Intermediate/05-WorkingLED/05-WorkingLED.ino index 5896ada..66609b3 100644 --- a/examples/Tutorials/B-Intermediate/05-WorkingLED/05-WorkingLED.ino +++ b/examples/Tutorials/B-Intermediate/05-WorkingLED/05-WorkingLED.ino @@ -22,26 +22,25 @@ void setup() { // these control did not actually operate anything on the ESP32. To operate actual devices HomeSpan needs to be programmed to // respond to "update" requests from HomeKit by performing some form of operation. - // Though HomeKit sends "updat" requests to individual Characteristics, this is not intuitive and leads to complex coding requirements + // Though HomeKit itself sends "update" requests to individual Characteristics, this is not intuitive and leads to complex coding requirements // when a Service has more than one Characteristic, such as both "On" and "Brightness." To make this MUCH easier for the user, HomeSpan // uses a framework in which Services are updated instead of individual Characteristics. It does so by calling the update() method of // each Service with flags indicating all the Characteristics in that Service that HomeKit requested to update. The user simply - // implements code to perform the actual operation, and returns a status flag (okay or not okay). HomeSpan takes care of all the underlying - // nuts and bolts. + // implements code to perform the actual operation, and returns either true or false if the update was successful. HomeSpan takes care of all + // the underlying nuts and bolts. // Every Service defined in HomeKit, such as Service:LightBulb and Service:Fan (and even Service::AccessoryInformation) implements an update() - // method that, as a default, does nothing but return a status of okay. To actually operate real devices you need to over-ride this default update() + // method that, as a default, does nothing but returns a value of true. To actually operate real devices you need to over-ride this default update() // method with your own code. The easiest way to do this is by creating a DERIVED class based on one of the built-in HomeSpan Services. // Within this derived class you can perform initial set-up routines (if needed), over-ride the update() method with your own code, and even create // any other methods or class-specific variables you need to fully operate complex devices. Most importantly, the derived class can take arguments - // so that you can make them more generic, re-use them multiple times (as will be seen below), and convert them to standalone modules (see below). + // so that you can make them more generic, re-use them multiple times (as will be seen below), and convert them to standalone modules (also shown below). // All of the HomeKit Services implemented by HomeSpan can be found in the Services.h file. Any can be used as the parent for a derived Service. // We begin by repeating nearly the same code from Example 2, but with a few key changes. For ease of reading, all prior comments have been removed // from lines that simply repeat Example 2, and new comments have been added to explictly show the new code. - Serial.begin(115200); homeSpan.begin(Category::Lighting,"HomeSpan LEDs"); @@ -59,18 +58,18 @@ void setup() { new Service::HAPProtocolInformation(); new Characteristic::Version("1.1.0"); - // In Example 2 we instantiated a LightBulb Service and its "On" Characteristic here. We are going to replace these two lines (by commenting them out)... + // In Example 2 we instantiated a LightBulb Service and its "On" Characteristic here. We are now going to replace these two lines (by commenting them out)... // new Service::LightBulb(); // new Characteristic::On(); // ...with a single new line instantiating a new class we will call DEV_LED(): - new DEV_LED(16); // this instantiates a new LED Service. Where is this defined? What happpened to Characteristic::On? Keep reading... + new DEV_LED(16); // this instantiates a new LED Service. Where is this defined? What happpened to Characteristic::On? Keep reading... // The full definition and code for DEV_LED is implemented in a separate file called "DEV_LED.h" that is specified using the #include at the top of this program. - // The prefix DEV_ is not required but it's a helpful convention to name all your device-specific Services. Note that DEV_LED wil include all the required - // Characterictics of the Service, so you DO NOT have to separately instantiate Characteristic::On --- everything HomeSpan needs for DEV_LED will be implemented + // The prefix DEV_ is not required but it's a helpful convention when naming all your device-specific Services. Note that DEV_LED will include all the required + // Characterictics of the Service, so you DO NOT have to separately instantiate Characteristic::On --- everything HomeSpan needs for DEV_LED should be implemented // in DEV_LED itself (though it's not all that much). Finally, note that we created DEV_LED to take a single integer argument. If you guessed this is // the number of the Pin to which you have attached an LED, you'd be right. See DEV_LED.h for a complete explanation of how it works. diff --git a/examples/Tutorials/B-Intermediate/05-WorkingLED/DEV_LED.h b/examples/Tutorials/B-Intermediate/05-WorkingLED/DEV_LED.h index bd360e8..f3e082c 100644 --- a/examples/Tutorials/B-Intermediate/05-WorkingLED/DEV_LED.h +++ b/examples/Tutorials/B-Intermediate/05-WorkingLED/DEV_LED.h @@ -21,13 +21,13 @@ struct DEV_LED : Service::LightBulb { // First we create a derived } // end constructor - // Finally, we over-ride the default update() method with instructions that actually turn on/off the LED. Note update() returns type "StatusCode" + // Finally, we over-ride the default update() method with instructions that actually turn on/off the LED. Note update() returns type boolean - StatusCode update(){ + boolean update(){ digitalWrite(ledPin,power->getNewVal()); // use a standard Arduino function to turn on/off ledPin based on the return of a call to power->getNewVal() (see below for more info) - return(StatusCode::OK); // return OK status code. There are other possibilties we will explore in later examples. + return(true); // return true to indicate the update was successful (otherwise create code to return false if some reason you could not turn on the LED) } // update }; @@ -40,10 +40,10 @@ struct DEV_LED : Service::LightBulb { // First we create a derived // Whenever a HomeKit controller requests HomeSpan to update a Characteristic, HomeSpan calls the update() method for the SERVICE that contains the // Characteristic. It calls this only one time, even if multiple Characteristics updates are requested for that Service. For example, if you // direct HomeKit to turn on a light and set it to 50% brightness, it will send HomeSpan two requests: one to update the "On" Characteristic of the -// LightBulb Service from "false" to "true" nd another to update the "Brightness" Characteristic of that same Service to 50. This is VERY inefficient +// LightBulb Service from "false" to "true" and another to update the "Brightness" Characteristic of that same Service to 50. This is VERY inefficient // and would require the user to process multiple updates to the same Service. // -// Instead, HomeSpan combines both requests into a single call to update() for the Service itself, where you can process all of thre Characteristics +// Instead, HomeSpan combines both requests into a single call to update() for the Service itself, where you can process all of the Characteristics // that change at the same time. In the example above, we only have a single Characteristic to deal with, so this does not mean much. But in later // examples we'll see how this works with multiple Characteristics. @@ -80,29 +80,21 @@ struct DEV_LED : Service::LightBulb { // First we create a derived // But for Services with two or more Characteristics, update() can be called with a request to update only a subset of the Characteristics. We will // find good use for the updated() method in later, multi-Characteristic examples. -// WHAT THE RETURN CODE FOR update() MEANS -// --------------------------------------- +// UNDER THE HOOD: WHAT THE RETURN CODE FOR UPDATE() DOES +// ------------------------------------------------------ // -// HomeKit requires each Characteristic to return a status code when an attempt to update it's value is made. HomeSpan automatically takes care of -// some of errors, such as a Characteristic not being found, or a request to update a Characteristic that is read only. In these cases update() is never -// even called. But if it is, HomeSpan will apply the return code you specify to each of the Characteristics that were to be updated in that Service. -// By returning StatusCode:OK you tell HomeSpan that the newValues requested are okay and you've made the required updates to the physical device. Upon -// receiving an OK status, HomeSpan updates the Characteristics themselves by copying the "newValue" data elements into the current "value" data elements. -// HomeSpan then sends a message back to HomeKit letting it know that the new values it requested have been sucessfully processed. At no point does -// HomeKit as for, or allow, a value to be sent back from HomeSpan indicating the data in a Characteristic. When requesting an update, HomeKit simply -// expects an okay or not okay. -// -// If for some reason the update() code cannot process an update request, it must return a HAP error code. These are listing in Settings.h. As noted above, -// some are created automatically by HomeSpan and update() is never called. Others can only be determined from within an update() call and should be -// used as the return value. The StatusCodes that can be used in this fashion are: OK, Unable, Busy. Any of the other StatusCode listed in Settings.h -// are automatically handled by HomeSpan and should not be used as a return code, though nothing bad happens if you do. This is because the -// HomeKit application itself only seems to distinguish an "OK" status code from a an not-"OK" code. HomeKit does not seem to process any error code -// differently from any other error code. All error codes lead HomeKit to simply say "Device Not Reponding" in the Controller. This suggests that the -// differences between "Unable" and "Busy" don't mean anything to HomeKit. They are all interpreted as an error, so pick anyone you'd like in the event -// you can't update a characteristic to the requested value. Note that when you do return an error code, HomeSpan will NOT copy the newValue data elements -// requested into the the current value data elements, thus keeping all Characteristics in the Service unchanged. -// -// Final note: There are very few reasons you should need to return an error code since so much checking is done in advance by either HomeSpan or HomeKit +// HomeKit requires each Characteristic to return a special HAP status code when an attempt to update its value is made. HomeSpan automatically takes care of +// most of the errors, such as a Characteristic not being found, or a request to update a Characteristic that is read only. In these cases update() is never +// even called. But if it is, HomeSpan needs to return a HAP status code for each of the Characteristics that were to be updated in that Service. +// By returning "true" you tell HomeSpan that the newValues requested are okay and you've made the required updates to the physical device. Upon +// receiving a true return value, HomeSpan updates the Characteristics themselves by copying the "newValue" data elements into the current "value" data elements. +// HomeSpan then sends a message back to HomeKit with a HAP code representing "OK," which lets the Controller know that the new values it requested have been +// sucessfully processed. At no point does HomeKit ask for, or allow, a data value to be sent back from HomeSpan indicating the data in a Characteristic. +// When requesting an update, HomeKit simply expects a HAP status code of OK, or some other status code representing an error. To tell HomeSpan to send the Controller +// an error code, indicating that you were not able to successfully process the update, simply have update() return a value of "false." HomeSpan converts a +// return of "false" to the HAP status code representing "UNABLE," which will cause the Controller to show that the device is not responding. + +// There are very few reasons you should need to return "false" since so much checking is done in advance by either HomeSpan or HomeKit // itself. For instance, HomeKit does not allow you to use the Controller, or even Siri, to change the brightness of LightBulb to a value outside the -// range of allowable values you specified. This means that any update() requests you receive should only contain newValue data element that are in-range. +// range of allowable values you specified. This means that any update() requests you receive should only contain newValue data elements that are in-range. // diff --git a/examples/Tutorials/B-Intermediate/06-DimmableLED/DEV_LED.h b/examples/Tutorials/B-Intermediate/06-DimmableLED/DEV_LED.h index b668c10..6f24a9c 100644 --- a/examples/Tutorials/B-Intermediate/06-DimmableLED/DEV_LED.h +++ b/examples/Tutorials/B-Intermediate/06-DimmableLED/DEV_LED.h @@ -18,11 +18,11 @@ struct DEV_LED : Service::LightBulb { // ON/OFF LED } // end constructor - StatusCode update(){ // update() method + boolean update(){ // update() method digitalWrite(ledPin,power->getNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; @@ -50,7 +50,7 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED } // end constructor - StatusCode update(){ // update() method + boolean update(){ // update() method // Here we set the duty cycle (brightness) of the LED by callng pwmPin with the appropriate channel. // The second argument should be a number from 0-100 (representing %brightness). HomeKit sets the on/off @@ -62,7 +62,7 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED pwmPin->set(channel,power->getNewVal()*level->getNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; diff --git a/examples/Tutorials/B-Intermediate/07-IdentifyRoutines/DEV_Identify.h b/examples/Tutorials/B-Intermediate/07-IdentifyRoutines/DEV_Identify.h index 17cd16f..45ebaf1 100644 --- a/examples/Tutorials/B-Intermediate/07-IdentifyRoutines/DEV_Identify.h +++ b/examples/Tutorials/B-Intermediate/07-IdentifyRoutines/DEV_Identify.h @@ -47,7 +47,7 @@ struct DEV_Identify : Service::AccessoryInformation { // the specified number of times. This is because when HomeSpan starts up if confirms to user that it has connected // to the WiFi network by turning on the built-in LED. Thus we want to leave it on when blinking is completed. - StatusCode update(){ + boolean update(){ for(int i=0;igetNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; @@ -48,11 +48,11 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED } // end constructor - StatusCode update(){ // update() method + boolean update(){ // update() method pwmPin->set(channel,power->getNewVal()*level->getNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; diff --git a/examples/Tutorials/C-Advanced/08-Bridges/DEV_Identify.h b/examples/Tutorials/C-Advanced/08-Bridges/DEV_Identify.h index 7e6826f..5bd1ef3 100644 --- a/examples/Tutorials/C-Advanced/08-Bridges/DEV_Identify.h +++ b/examples/Tutorials/C-Advanced/08-Bridges/DEV_Identify.h @@ -22,7 +22,7 @@ struct DEV_Identify : Service::AccessoryInformation { pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output } - StatusCode update(){ + boolean update(){ for(int i=0;igetNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; @@ -48,11 +48,11 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED } // end constructor - StatusCode update(){ // update() method + boolean update(){ // update() method pwmPin->set(channel,power->getNewVal()*level->getNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; diff --git a/examples/Tutorials/C-Advanced/09-MessageLogging/DEV_Identify.h b/examples/Tutorials/C-Advanced/09-MessageLogging/DEV_Identify.h index 7e6826f..5bd1ef3 100644 --- a/examples/Tutorials/C-Advanced/09-MessageLogging/DEV_Identify.h +++ b/examples/Tutorials/C-Advanced/09-MessageLogging/DEV_Identify.h @@ -22,7 +22,7 @@ struct DEV_Identify : Service::AccessoryInformation { pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output } - StatusCode update(){ + boolean update(){ for(int i=0;igetNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; @@ -82,7 +82,7 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED } // end constructor - StatusCode update(){ // update() method + boolean update(){ // update() method // Here we output log messages whenever update() is called, // which is helpful for debugging purposes if your physical device @@ -123,7 +123,7 @@ struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED pwmPin->set(channel,power->getNewVal()*level->getNewVal()); - return(StatusCode::OK); // return OK status code + return(true); // return true } // update }; diff --git a/examples/Tutorials/C-Advanced/10-RGB_LED/DEV_Identify.h b/examples/Tutorials/C-Advanced/10-RGB_LED/DEV_Identify.h index 7e6826f..5bd1ef3 100644 --- a/examples/Tutorials/C-Advanced/10-RGB_LED/DEV_Identify.h +++ b/examples/Tutorials/C-Advanced/10-RGB_LED/DEV_Identify.h @@ -22,7 +22,7 @@ struct DEV_Identify : Service::AccessoryInformation { pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output } - StatusCode update(){ + boolean update(){ for(int i=0;isetVal(false); // clear any prior obstruction detection } - return(StatusCode::OK); // return OK status code + return(true); // return true } // update @@ -82,7 +82,7 @@ struct DEV_WindowShade : Service::WindowCovering { // A motorized Window Sha } // end constructor - StatusCode update(){ // update() method + 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 @@ -100,7 +100,7 @@ struct DEV_WindowShade : Service::WindowCovering { // A motorized Window Sha LOG1("Lowering Shade\n"); // ** there is nothing more to do - HomeKit keeps track of the current-position so knows lowering is required } - return(StatusCode::OK); // return OK status code + return(true); // return true } // update diff --git a/examples/Tutorials/D-Expert/13-TargetStates/DEV_Identify.h b/examples/Tutorials/D-Expert/13-TargetStates/DEV_Identify.h index 091c9b6..ec05fbb 100644 --- a/examples/Tutorials/D-Expert/13-TargetStates/DEV_Identify.h +++ b/examples/Tutorials/D-Expert/13-TargetStates/DEV_Identify.h @@ -24,7 +24,7 @@ struct DEV_Identify : Service::AccessoryInformation { pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output } - StatusCode update(){ + boolean update(){ for(int i=0;i