From 9cecc0a31a4b091d8eaf7ac0bec5eb3408d06c01 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sun, 16 Aug 2020 21:46:58 -0500 Subject: [PATCH] Updated Example 13 Completed new framework for using loop() methods and deleted all code related to new SpanEvent() and event() loops. Re-worked Example 13 to utilize new framework and validated it functions as expected. --- .../13-EventNotifications.ino | 93 -------------- .../13-ServiceLoops/13-ServiceLoops.ino | 121 ++++++++++++++++++ .../DEV_Identify.h | 0 .../DEV_Sensors.h | 74 +++++------ .../14-TargetStates/14-TargetStates.ino | 2 +- src/HAP.cpp | 40 ------ src/HAP.h | 1 - src/HomeSpan.cpp | 17 --- src/HomeSpan.h | 12 -- 9 files changed, 154 insertions(+), 206 deletions(-) delete mode 100644 examples/Expert/13-EventNotifications/13-EventNotifications.ino create mode 100644 examples/Expert/13-ServiceLoops/13-ServiceLoops.ino rename examples/Expert/{13-EventNotifications => 13-ServiceLoops}/DEV_Identify.h (100%) rename examples/Expert/{13-EventNotifications => 13-ServiceLoops}/DEV_Sensors.h (63%) diff --git a/examples/Expert/13-EventNotifications/13-EventNotifications.ino b/examples/Expert/13-EventNotifications/13-EventNotifications.ino deleted file mode 100644 index 071f4c5..0000000 --- a/examples/Expert/13-EventNotifications/13-EventNotifications.ino +++ /dev/null @@ -1,93 +0,0 @@ - -//////////////////////////////////////////////////////////// -// // -// HomeSpan: A HomeKit implementation for the ESP32 // -// ------------------------------------------------ // -// // -// Example 13: Event Notifications // -// * implementing a Temperature Sensor // -// * implementing an Air Quality Sensor // -// // -//////////////////////////////////////////////////////////// - -#include "HomeSpan.h" -#include "DEV_Identify.h" -#include "DEV_Sensors.h" - -void setup() { - - // HomeKit is designed for two-way communication: HomeSpan devices not only receive and act on operational instructions from HomeKit Controllers, but - // HomeSpan can also send HomeKit unsolicited messages regarding changes to the state of the device. Though it may not be apparent, this has already been - // ocurring in the background in all prior examples. This is because when a HomeKit Controller sends an operational request to any HomeKit device, it expects - // to receive a status message back indicating whether the request was successful or not. This is the purpose of returning StatusCode:OK in custom update() - // methods. With this information returned, HomeKit can update its own status and properly reflect a change in the device, such as by showing a light is now - // turned on instead of off. However, HomeKit unfortunately does NOT inform any other HomeKit Controllers of this new information. So if you have two iPhones - // and use one to turn on a light, the other first iPhone does not relay a message to the second iPhone that a light has been turned on. This is the case even - // if you are using an AppleTV or HomePod as a central hub for HomeKit. - - // Normally this does not matter much, since the second iPhone will naturally update itself as to the status of all HomeKit devices as soon as the HomeKit - // application is launched on that iPhone. It does this by sending every HomeKit device a message asking for a status update. In this fashion the second - // iPhone quickly synchronizes itself as soon as the HomeKit app is opened, but ONLY when it is first opened (or re-opened if you first close it). But if you - // have two iPhones BOTH opened to the HomeKit app (or one iPhone and one Mac opened to the HomeKit app) and you use one Controller app to turn on a light, the - // resulting change in status of that light will NOT be reflected in the second Controller app, unless you close tha app and re-open (at which point it goes - // through the request procedure discussed above). This is very annoying and counterintuitive. - - // Fortunately, HomeKit provides a solution to this in the form of an Event Notification protcol. This protcol allows a device to send unsoliciated messages - // to all Controllers that have previously registered themselves with the device indicating the Characteristics for which they would like to receive an event - // message from the device whenever there is a change in the status of one or more of those Characteristics. - - // The good news is that HomeSpan takes care of this automatically. To see this for yourself, use two iPhones (or an iPhone and Mac) with any of the previous examples - // and open the HomeKit app on both. Any changes you make to the device using one of the Controllers, such as turning on an LED, is immediately reflected - // in the other Controller. Not quite magic, but close. - - // A different use of Event Notifications was also working behind in the scenes in Example 10 - Timed Resets. In this case, HomeSpan sent an unsolited Event message - // to all registered Controllers letting them know that a device that was previously turned on, is now in fact turned off. - - // In this Example 13 we explore the explicit use of Event Notifications to support Services that require constants updates from the device to all HomeKit Controllers. - // The two Services we will use below are a Temperature Sensor and an Air Quality Sensor. Neither of these Services have any operational controls. They cannot be - // turn on or off, or operated in any way. As such, they do not need to implement an update() method, since HomeKit Controllers will never ask them to change - // any of their Characteristics. - - // Rather, HomeKit is expecting to get periodic Event Notification messages from such Services so that the HomeKit Controllers can accurately reflect the status - // and values of the Characteristics for those Services, such as the temperature, in the HomeKit Controller. - - // There are two steps to accomplishing this. The first is to implement an event() method for each Service that uses a setVal() function to change the values - // for one or more Characteristics for that Service. The second step is to instantiate a new SpanEvent() object for each Service that you want HomeSpan to invoke your - // event() method. The SpanEvent object take only one argument - the number of milliseconds to wait between calls to a Service's event() method. - - // As usual, all of the logic for this is encapsulated in new standalone derived Services. You'll find fully-commented definitions for the DEV_TempSensor() and - // the DEV_AirQualitySensor() Services instantiated below, in the DEV_Sensors.h file. Note that this example is for instructional purposes only -- we do not actually - // connect a Temperature Sensor or Air Quality Sensor to our ESP32 device. As such, we did not define the Services to take any arguments to specify pin numbers or any - // other information needed to implement an actual sensor. Instead, in order to see how real a device would work, we will send Event messages by manufacturing simulated - // updates. See DEV_Sensors.h for complete details. - - // Once you understand these examples, you should be able to use Event Notifications for any combination of HomeKit Services with Characteristics that require your device to - // send periodic update messages to HomeKit Controllers, ranging from Smoke Alarms to Door Sensors. - - Serial.begin(115200); - - homeSpan.begin(Category::Bridges,"HomeSpan Bridge"); - - - new SpanAccessory(); - new DEV_Identify("Bridge #1","HomeSpan","123-ABC","HS Bridge","0.9",3); - new Service::HAPProtocolInformation(); - new Characteristic::Version("1.1.0"); - - new SpanAccessory(); - new DEV_Identify("Temp Sensor","HomeSpan","123-ABC","Sensor","0.9",0); - new DEV_TempSensor(); // Create a Temperature Sensor (see DEV_Sensors.h for definition) - - new SpanAccessory(); - new DEV_Identify("Air Quality","HomeSpan","123-ABC","Sensor","0.9",0); - new DEV_AirQualitySensor(); // Create an Air Quality Sensor (see DEV_Sensors.h for definition) - -} // end of setup() - -////////////////////////////////////// - -void loop(){ - - homeSpan.poll(); - -} // end of loop() diff --git a/examples/Expert/13-ServiceLoops/13-ServiceLoops.ino b/examples/Expert/13-ServiceLoops/13-ServiceLoops.ino new file mode 100644 index 0000000..422abd2 --- /dev/null +++ b/examples/Expert/13-ServiceLoops/13-ServiceLoops.ino @@ -0,0 +1,121 @@ + +//////////////////////////////////////////////////////////// +// // +// HomeSpan: A HomeKit implementation for the ESP32 // +// ------------------------------------------------ // +// // +// Example 13: Service Loops (and Event Notifications) // +// * implementing a Temperature Sensor // +// * implementing an Air Quality Sensor // +// // +//////////////////////////////////////////////////////////// + +#include "HomeSpan.h" +#include "DEV_Identify.h" +#include "DEV_Sensors.h" + +void setup() { + + // So far we've seen that HomeSpan allows you to create derived Services with their own constructors and update() methods. For many applications, this + // will be all that is needed. However, for many other types of applications you may need to take action or perform some background operations without + // any prompting or requests from HomeKit. + + // To perform background operations and actions, every Service implements a loop() method. The default loop() method is to do nothing, which has been + // fine for all our prior examples. But if you need to perform some continuous background action, all you need to do is implement a loop() method for + // your derived Service. At the end of each HomeSpan polling cycle, the loop() method is called for each Service that implements its own code. + // In this fashion, the loop() method is similar to the main loop() method in the Arduino IDE itself - except it can be customized for each Service. + + // In this Example 13 we explore the use of loop() methods to implement two new accessories - a Temperature Sensor and an Air Quality Sensor. Of course + // we won't actually have these physical devices attached to the ESP32 for the purpoe of this example, but we will simulate "reading" their properties. + // This is one of the main purposes of implementing a loop() method. It allows you to read a sensor or perform some sort of repetitive, Service-specific + // action. + + // Once you read (or simulate reading) a sensor's values in a loop() method, you need to somehow communicate this back to HomeKit so the new values can be + // reflected in the HomeKit Controller. This may be strictly for information purposes (such as a temperature sensor) or could be used by HomeKit itself + // to trigger other devices (as might occur if implementing a Door Sensor). + + // Fortunately, HomeSpan makes communicating the values of Characteristics back to HomeKit easy. In prior examples we saw how getVal() and getNewVal() + // are used to read current and updated Characteristic values requested by HomeKit. To perform the reverse, we simply use a method called setVal(). + // Setting the value of a Characteristic with this function does two things. First, it causes HomeSpan to send an Event Notification message back to HomeKit + // letting HomeKit know the new value of the Characteristic. Since messages create network traffic, HomeSpan keeps track of all setVal() changes across + // all Services and creates one a single Event Notification message reporting all the changes togther at the end of each polling cycle. + + // The second thing that HomeSpan does when you change the value of a Characteristic with setVal() is to reset an internal timer for that Characteristic that + // keeps track of how long it's been since the last modification, whether from a previous setVal() instruction, or by HomeKit itself via a call to update(). + // You can query the time since the last modificaton using the method timeVal() which returns the elapsed time in milliseconds. By calling this function from + // within loop() you can determine when it's time for a new sensor read, or when to perform some other action. + + // NOTE: It it NOT recommended to continuously change Characteristic values using setVal() as this will generate a lot of network traffic since HomeSpan + // sends Event Notifications bck to all registered HomeKit Controllers. It's fine to perform internal calculations, generate signals on different pins, + // and perform any other internal actions you may need as frequently as you require. But limit the use of setVal() to a reasonable frequency, such as maybe + // one per minute for a temperature sensor. Do not use setVal() unless the value of the Characteristic changes, but do use it to immediately inform HomeKit of + // something time-sensitive, such as a door opening, or a smoke alarm triggering. + + // As usual, all of the logic for this example are encapsulated in new standalone derived Services. You'll find fully-commented definitions for the DEV_TempSensor() and + // the DEV_AirQualitySensor() Services instantiated below, in the DEV_Sensors.h file. As noted, this example is for instructional purposes only -- we do not actually + // connect a Temperature Sensor or Air Quality Sensor to our ESP32 device. As such, we did not define the Services to take any arguments to specify pin numbers or any + // other information needed to implement an actual sensor. Instead, in order to see how real a device would work, we simulate periodic changes by modifying Characteristic + // values using setVal() with either a sequence of repeating values, or random values. See DEV_Sensors.h for complete details. + + // Once you understand these examples, you should be able to use implement your own loop() method and utilize setVal() along with timeVal() for any combination of + // HomeKit Services with Characteristics that require your device to send periodic update messages to HomeKit Controllers, ranging from Smoke Alarms to Door Sensors. + + Serial.begin(115200); + + homeSpan.begin(Category::Bridges,"HomeSpan Bridge"); + + new SpanAccessory(); + new DEV_Identify("Bridge #1","HomeSpan","123-ABC","HS Bridge","0.9",3); + new Service::HAPProtocolInformation(); + new Characteristic::Version("1.1.0"); + + new SpanAccessory(); + new DEV_Identify("Temp Sensor","HomeSpan","123-ABC","Sensor","0.9",0); + new DEV_TempSensor(); // Create a Temperature Sensor (see DEV_Sensors.h for definition) + + new SpanAccessory(); + new DEV_Identify("Air Quality","HomeSpan","123-ABC","Sensor","0.9",0); + new DEV_AirQualitySensor(); // Create an Air Quality Sensor (see DEV_Sensors.h for definition) + +} // end of setup() + +////////////////////////////////////// + +void loop(){ + + homeSpan.poll(); + +} // end of loop() + +////////////////////////////////////// + + +// Additional Technical Notes about Event Notifications in HomeKit +// --------------------------------------------------------------- + +// HomeKit is designed for two-way communication: HomeSpan devices not only receive and act on operational instructions from HomeKit Controllers, but +// HomeSpan can also send HomeKit unsolicited messages regarding changes to the state of the device. Though it may not be apparent, this has already been +// ocurring in the background in all prior examples. This is because when a HomeKit Controller sends an operational request to any HomeKit device, it expects +// to receive a status message back indicating whether the request was successful or not. This is the purpose of returning StatusCode:OK in custom update() +// methods. With this information returned, HomeKit can update its own status and properly reflect a change in the device, such as by showing a light is now +// turned on instead of off. However, HomeKit unfortunately does NOT inform any other HomeKit Controllers of this new information. So if you have two iPhones +// and use one to turn on a light, this iPhone does not relay a message to the second iPhone that a light has been turned on. This is the case even +// if you are using an AppleTV or HomePod as a central hub for HomeKit. + +// Normally this does not matter much, since the second iPhone will automatically update itself as to the status of all HomeKit devices as soon as the HomeKit +// application is launched on that iPhone. It does this by sending every HomeKit device a message asking for a status update. In this fashion the second +// iPhone quickly synchronizes itself as soon as its HomeKit app is opened, but ONLY when it is first opened (or re-opened if you first close it). However, if you +// have two iPhones BOTH opened to the HomeKit app (or one iPhone and one Mac opened to the HomeKit app) and you use one Controller app to turn on a light, the +// resulting change in status of that light will NOT be reflected in the second Controller app, unless you close tha app and re-open (at which point it goes +// through the request procedure discussed above). This can be very annoying and counterintuitive. + +// Fortunately, HomeKit provides a solution to this in the form of an Event Notification protcol. This protcol allows a device to send unsoliciated messages +// to all Controllers that have previously registered themselves with the device indicating the Characteristics for which they would like to receive an event +// message from the device whenever there is a change in the status of one or more of those Characteristics. + +// HomeSpan takes care of this automatically, and has being doing so in the background in all prior examples. To see this for yourself, use two iPhones +// (or an iPhone and Mac) with any of the previous examples and open the HomeKit app on both. Any changes you make to the device using one of the Controllers, +// such as turning on an LED, is immediately reflected in the other Controller. Not quite magic, but close. + +// As described above, and fully explored in this example, HomeSpan automatically generates Event Notification messages and transmis them to all registered +// Controllers every time you change the value of a Characteristic using the setVal() function from within a derived Service's loop() method. diff --git a/examples/Expert/13-EventNotifications/DEV_Identify.h b/examples/Expert/13-ServiceLoops/DEV_Identify.h similarity index 100% rename from examples/Expert/13-EventNotifications/DEV_Identify.h rename to examples/Expert/13-ServiceLoops/DEV_Identify.h diff --git a/examples/Expert/13-EventNotifications/DEV_Sensors.h b/examples/Expert/13-ServiceLoops/DEV_Sensors.h similarity index 63% rename from examples/Expert/13-EventNotifications/DEV_Sensors.h rename to examples/Expert/13-ServiceLoops/DEV_Sensors.h index f611988..1248f10 100644 --- a/examples/Expert/13-EventNotifications/DEV_Sensors.h +++ b/examples/Expert/13-ServiceLoops/DEV_Sensors.h @@ -8,16 +8,8 @@ struct DEV_TempSensor : Service::TemperatureSensor { // A standalone Tempera SpanCharacteristic *temp; // reference to the Current Temperature Characteristic DEV_TempSensor(ServiceType sType=ServiceType::Regular) : Service::TemperatureSensor(sType){ // constructor() method - - // We begin by defining a new SpanEvent. This instructs HomeSpan to call the Service's event() method (defined below) periodically. - // The argument to SpanEvent() defines the periodicity, in milliseconds. In this case we are instructing HomeSpan to check this Service for - // updates every 5 seconds. Checking takes time, and updates use network traffic, so choose your periodicity wisely. In practice you could - // probably set the periodicity for a temperature sensor to 60 seconds or more. But for illustrative purposes we are specifying more frequent - // updates so you can see how the this example works without needing to wait a full minute for each change. - new SpanEvent(5000); // check for events on this Service every 5 seconds - - // Next we instantiate the main Characteristic for a Temperature Sensor, namely the Current Temperature, and set its initial value + // First we instantiate the main Characteristic for a Temperature Sensor, namely the Current Temperature, and set its initial value // to 20 degrees. For a real sensor, we would take a reading and initialize it to that value instead. NOTE: HomeKit uses // Celsius for all temperature settings. HomeKit will DISPLAY temperatures in the HomeKit app according to the settings on your iPhone. // Though the HAP documentation includes a Characteristic that appears to allow the device to over-ride this setting by specifying a display @@ -25,35 +17,38 @@ struct DEV_TempSensor : Service::TemperatureSensor { // A standalone Tempera temp=new Characteristic::CurrentTemperature(20.0); // instantiate the Current Temperature Characteristic - Serial.print("Configuring Temperature Sensor"); // initialization message + Serial.print("Configuring Temperature Sensor"); // initialization message Serial.print("\n"); } // end constructor - // Lastly, we create the event() method. This method take no arguments and returns no values. It will be called every 5 seconds - // as specified above in the instantiation of SpanEvent(). In order to simulate a temperature change from an actual sensor we - // will read the current value of the temp Characteristic using the getVal() function, with as the template parameter; - // add 0.5 degrees Celsius; and then store the result in a float variable named "temperature." This will simulate an increment of - // 0.5 degrees Celsius (a little less than 1 degree F) every 5 seconds. We will cap the temperature to 35.0 degrees C, after which - // it resets to 10.0 and starts over. + // Next we create the loop() method. This method take no arguments and returns no values. In order to simulate a temperature change + // from an actual sensor we will read the current value of the temp Characteristic using the getVal() function, with as the + // template parameter; add 0.5 degrees Celsius; and then store the result in a float variable named "temperature." This will simulate + // an increment of 0.5 degrees Celsius (a little less than 1 degree F). We will cap the temperature to 35.0 degrees C, after which + // it resets to 10.0 and starts over. Most importantly, we will do this once every 5 seconds by checking the elapsed time since the + // previous modification using timeVal(). - // All of the action happens in the last line, in which we set the value of the temp Characteristic to the new value of temperature. + // All of the action happens in the setVal() line where we set the value of the temp Characteristic to the new value of temperature. // This tells HomeKit to send an Event Notification message to all available Controllers making them aware of the new temperature. // Note that setVal() is NOT a template function and does not require you to specify as a template parameter. This is because // setVal() can determine the type from the argument you specify. If there is any chance of ambiguity, you can always specifically // cast the argument such: setVal((float)temperature). - void event(){ - - float temperature=temp->getVal()+0.5; // here we "simulate" a half-degree temperature change... - if(temperature>35.0) // ...but cap the maximum at 35 degrees before starting over at 10 degrees - temperature=10.0; - - temp->setVal(temperature); // don't forgot to update the temperature Characteristic to the new value! - - } // event - void loop(){ + + if(temp->timeVal()>5000){ // check time elapsed since last update and proceed only if greater than 5 seconds + float temperature=temp->getVal()+0.5; // "simulate" a half-degree temperature change... + if(temperature>35.0) // ...but cap the maximum at 35C before starting over at 10C + temperature=10.0; + + temp->setVal(temperature); // set the new temperature; this generates an Event Notification andalso resets the elapsed time + + LOG1("Temperature Update: "); + LOG1(temperature*9/5+32); + LOG1("\n"); + } + } // loop }; @@ -70,8 +65,6 @@ struct DEV_AirQualitySensor : Service::AirQualitySensor { // A standalone Ai SpanCharacteristic *no2Density; // reference to the Nitrogen Dioxide Characteristic, which is a float from 0 to 1000 DEV_AirQualitySensor(ServiceType sType=ServiceType::Regular) : Service::AirQualitySensor(sType){ // constructor() method - - new SpanEvent(10000); // check for events on this Service every 10 seconds airQuality=new Characteristic::AirQuality(1); // instantiate the Air Quality Characteristic and set initial value to 1 o3Density=new Characteristic::OzoneDensity(300.0); // instantiate the Ozone Density Characteristic and set initial value to 300.0 @@ -82,17 +75,18 @@ struct DEV_AirQualitySensor : Service::AirQualitySensor { // A standalone Ai } // end constructor - void event(){ - - airQuality->setVal((airQuality->getVal()+1)%6); // simulate a change in Air Quality by incrementing the current value by one, and keeping in range 0-5 - o3Density->setVal((double)random(200,500)); // change the Ozone Density to some random value between 200 and 499. Note use of (double) cast since random returns an integer + void loop(){ // Note we are NOT updating the Nitrogen Dioxide Density Characteristic. This should therefore remain steady at its initial value of 700.0 - - } // event - void loop(){ + if(airQuality->timeVal()>5000) // modify the Air Quality Characteristic every 5 seconds + airQuality->setVal((airQuality->getVal()+1)%6); // simulate a change in Air Quality by incrementing the current value by one, and keeping in range 0-5 + + if(o3Density->timeVal()>10000) // modify the Ozone Density Characteristic value every 10 seconds + o3Density->setVal((double)random(200,500)); // simulate a change with a random value between 200 and 499. Note use of (double) cast since random() returns an integer + } // loop + }; ////////////////////////////////// @@ -113,13 +107,9 @@ struct DEV_AirQualitySensor : Service::AirQualitySensor { // A standalone Ai // never use setVal() to update this Characteristic. // If you run HomeSpan at a VERBOSITY level of 2 (as specified in the library's Settings.h file), you can see that under the hood HomeSpan is sending Event Notification -// messages to all registered controllers every 5 seconds for the Temp Sensor, and every 10 seconds for the Air Quality Sensor. If you look carefully you'll see that +// messages to all registered controllers every 5 seconds for the Temp Sensor, and every 5 and 10 seconds for the Air Quality Sensor. If you look carefully you'll see that // the Event Notification message for the Air Quality Sensor only include two values - one for the Air Quality state and one for the Ozone Density. HomeSpan is NOT -// sending a value for the Nitrogen Dioxide Density Characteristic since it has not been changed with a setVal() function. This is an important design feature and -// shows that the instantiation of a new SpanEvent only determines how often the event() method is checked by HomeSpan, not whether Event Notifications are actually sent. -// If the event() method ALWAYS updates a Characteristic, then an Event Notification will always be generated. However, if event() does not update a Characteristic, -// or only updates it under certain circumstances, then no message will be generated. This allows you to create a SpanEvent that frequenty checks a Service for an -// event update, without generating Event Notifications that simply repeat the existing value of a Characteristic. We will see how this comes into play in the next example. +// sending a value for the Nitrogen Dioxide Density Characteristic since it has not been changed with a setVal() function. // FINAL NOTE: The number of decimals HomeKit displays for temperature in the HomeKit app is independent of the step size of the value itself. This seems to be // hardcoded by HomeKit: for Fahrenheit a Temperature Sensor tile shows no decimals and ROUNDS to the nearest whole degree (e.g. 72, 73, 74 degrees); for Celsius diff --git a/examples/Expert/14-TargetStates/14-TargetStates.ino b/examples/Expert/14-TargetStates/14-TargetStates.ino index e0ae5dd..d987fb8 100644 --- a/examples/Expert/14-TargetStates/14-TargetStates.ino +++ b/examples/Expert/14-TargetStates/14-TargetStates.ino @@ -64,7 +64,7 @@ void setup() { Serial.begin(115200); - homeSpan.begin(Category::Bridges,"HomeSpan Bridge Test"); + homeSpan.begin(Category::Bridges,"HomeSpan Bridge"); new SpanAccessory(); diff --git a/src/HAP.cpp b/src/HAP.cpp index f716a13..115920a 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -1185,46 +1185,6 @@ void HAPClient::checkNotifications(){ ////////////////////////////////////// -void HAPClient::checkEvents(){ - - unsigned long cTime=millis(); // current time - vector spanBuf; // vector to SpanBuf objects - - for(int i=0;ihomeSpan.Events[i]->alarmTime){ // if alarm time has passed - - homeSpan.Events[i]->alarmTime=cTime+homeSpan.Events[i]->period; // set new alarm time to current time plus alarm period - homeSpan.Events[i]->service->event(); // check service for new EVENTS - - for(int j=0;jservice->Characteristics.size();j++){ // loop over all characteristics - if(homeSpan.Events[i]->service->Characteristics[j]->isUpdated){ // if characteristic is updated - - SpanBuf sb; // create SpanBuf object - sb.characteristic=homeSpan.Events[i]->service->Characteristics[j]; // set characteristic - sb.status=StatusCode::OK; // set status - sb.val=""; // set dummy "val" so that sprintfNotify knows to consider this "update" - spanBuf.push_back(sb); - - LOG1("Event Notification for aid="); - LOG1(homeSpan.Events[i]->service->Characteristics[j]->aid); - LOG1(" iid="); - LOG1(homeSpan.Events[i]->service->Characteristics[j]->iid); - LOG1("\n"); - - homeSpan.Events[i]->service->Characteristics[j]->isUpdated=false; // reset isUpdated flag - - } // if characteristic is updated - } // characteristic loop - } // alarm triggered - } // events loop - - if(spanBuf.size()>0) // if updated items are found - eventNotify(&spanBuf[0],spanBuf.size()); // transmit EVENT Notifications - -} - -////////////////////////////////////// - void HAPClient::checkTimedResets(){ unsigned long cTime=millis(); // current time diff --git a/src/HAP.h b/src/HAP.h index 681eb57..57ca5c2 100644 --- a/src/HAP.h +++ b/src/HAP.h @@ -114,7 +114,6 @@ struct HAPClient { static void printControllers(); // prints IDs of all allocated (paired) Controller static void checkTimedResets(); // checks for Timed Resets and reports to controllers as needed (HAP Section 6.8) static void callServiceLoops(); // call the loop() method for any Service with that over-rode the default method - static void checkEvents(); // checks for Event Notifications and reports to controllers as needed (HAP Section 6.8) static void checkNotifications(); // checks for Event Notifications and reports to controllers as needed (HAP Section 6.8) static void checkTimedWrites(); // checks for expired Timed Write PIDs, and clears any found (HAP Section 6.7.2.4) static void eventNotify(SpanBuf *pObj, int nObj, int ignoreClient=-1); // transmits EVENT Notifications for nObj SpanBuf objects, pObj, with optional flag to ignore a specific client diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 6f82de7..9e3651f 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1158,23 +1158,6 @@ SpanTimedReset::SpanTimedReset(int waitTime){ } -/////////////////////////////// -// SpanEvent // -/////////////////////////////// - -SpanEvent::SpanEvent(int period){ - - if(homeSpan.Accessories.empty() || homeSpan.Accessories.back()->Services.empty() ){ - Serial.print("*** FATAL ERROR: Can't create new Timed Reset without a defined Service. Program halted!\n\n"); - while(1); - } - - this->service=homeSpan.Accessories.back()->Services.back(); - this->period=period; - homeSpan.Events.push_back(this); - -} - /////////////////////////////// // SpanRange // /////////////////////////////// diff --git a/src/HomeSpan.h b/src/HomeSpan.h index d01348c..499027a 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -26,7 +26,6 @@ struct SpanCharacteristic; struct SpanRange; struct SpanBuf; struct SpanTimedReset; -struct SpanEvent; /////////////////////////////// @@ -50,7 +49,6 @@ struct Span{ SpanConfig hapConfig; // track configuration changes to the HAP Accessory database; used to increment the configuration number (c#) when changes found vector Accessories; // vector of pointers to all Accessories vector TimedResets; // vector of pointers to all TimedResets - vector Events; // vector of pointer to all Events vector Loops; // vector of pointer to all Services that have over-ridden loop() methods vector Notifications; // vector of SpanBuf objects that store info for Characteristics that are updated with setVal() and require a Notification Event unordered_map TimedWrites; // map of timed-write PIDs and Alarm Times (based on TTLs) @@ -247,16 +245,6 @@ struct SpanTimedReset{ SpanTimedReset(int waitTime); }; -/////////////////////////////// - -struct SpanEvent{ - SpanService *service; // service to check for events - int period; // time period between checks (in milliseconds) - unsigned long alarmTime=0; // alarm time to trigger next check - - SpanEvent(int period); -}; - ///////////////////////////////////////////////// // Extern Variables