From f3f8996c8a96ad3be008b11741144b00aeb3509c Mon Sep 17 00:00:00 2001 From: Gregg Date: Fri, 24 Jul 2020 16:53:53 -0500 Subject: [PATCH] Created Example 5 --- .../1-SimpleLightBulb/1-SimpleLightBulb.ino | 0 .../2-TwoSimpleLightBulbs.ino | 0 .../3-CeilingFanWithLight.ino | 0 .../4-AdvancedCeilingFan.ino | 0 .../5-WorkingLED/5-WorkingLED.ino | 101 ++++++++++++++++++ examples/Intermediate/5-WorkingLED/DEV_LED.h | 35 ++++++ 6 files changed, 136 insertions(+) rename examples/{ => Basic}/1-SimpleLightBulb/1-SimpleLightBulb.ino (100%) rename examples/{ => Basic}/2-TwoSimpleLightBulbs/2-TwoSimpleLightBulbs.ino (100%) rename examples/{ => Basic}/3-CeilingFanWithLight/3-CeilingFanWithLight.ino (100%) rename examples/{ => Basic}/4-AdvancedCeilingFan/4-AdvancedCeilingFan.ino (100%) create mode 100644 examples/Intermediate/5-WorkingLED/5-WorkingLED.ino create mode 100644 examples/Intermediate/5-WorkingLED/DEV_LED.h diff --git a/examples/1-SimpleLightBulb/1-SimpleLightBulb.ino b/examples/Basic/1-SimpleLightBulb/1-SimpleLightBulb.ino similarity index 100% rename from examples/1-SimpleLightBulb/1-SimpleLightBulb.ino rename to examples/Basic/1-SimpleLightBulb/1-SimpleLightBulb.ino diff --git a/examples/2-TwoSimpleLightBulbs/2-TwoSimpleLightBulbs.ino b/examples/Basic/2-TwoSimpleLightBulbs/2-TwoSimpleLightBulbs.ino similarity index 100% rename from examples/2-TwoSimpleLightBulbs/2-TwoSimpleLightBulbs.ino rename to examples/Basic/2-TwoSimpleLightBulbs/2-TwoSimpleLightBulbs.ino diff --git a/examples/3-CeilingFanWithLight/3-CeilingFanWithLight.ino b/examples/Basic/3-CeilingFanWithLight/3-CeilingFanWithLight.ino similarity index 100% rename from examples/3-CeilingFanWithLight/3-CeilingFanWithLight.ino rename to examples/Basic/3-CeilingFanWithLight/3-CeilingFanWithLight.ino diff --git a/examples/4-AdvancedCeilingFan/4-AdvancedCeilingFan.ino b/examples/Basic/4-AdvancedCeilingFan/4-AdvancedCeilingFan.ino similarity index 100% rename from examples/4-AdvancedCeilingFan/4-AdvancedCeilingFan.ino rename to examples/Basic/4-AdvancedCeilingFan/4-AdvancedCeilingFan.ino diff --git a/examples/Intermediate/5-WorkingLED/5-WorkingLED.ino b/examples/Intermediate/5-WorkingLED/5-WorkingLED.ino new file mode 100644 index 0000000..565751b --- /dev/null +++ b/examples/Intermediate/5-WorkingLED/5-WorkingLED.ino @@ -0,0 +1,101 @@ + +//////////////////////////////////////////////////////////// +// // +// HomeSpan: A HomeKit implementation for the ESP32 // +// ------------------------------------------------ // +// // +// Example 5: Two working on/off LEDs based on the // +// LightBulb Service // +// // +//////////////////////////////////////////////////////////// + + +#include "HomeSpan.h" +#include "DEV_LED.h" // NEW! Include this new file, DEV_LED.h, which will be fully explained below + +void setup() { + + // First light! Control an LED from HomeKit! + + // Example 5 expands on Example 2 by adding in the code needed to actually control LEDs connected to the ESP32 from HomeKit. + // In Example 2 we built out all the functionality to create a "Tile" Acessories inside HomeKit that displayed an on/off light, but + // 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 "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 "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. + + // 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 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 Example 7). + + // 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"); + + new SpanAccessory(); + + new Service::AccessoryInformation(); + new Characteristic::Name("LED #1"); + new Characteristic::Manufacturer("HomeSpan"); + new Characteristic::SerialNumber("123-ABC"); + new Characteristic::Model("20mA LED"); + new Characteristic::FirmwareRevision("0.9"); + new Characteristic::Identify(); + + 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)... + + // 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... + + // 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 + // 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. + + new SpanAccessory(); + + new Service::AccessoryInformation(); + new Characteristic::Name("LED #2"); + new Characteristic::Manufacturer("HomeSpan"); + new Characteristic::SerialNumber("123-ABC"); + new Characteristic::Model("20mA LED"); + new Characteristic::FirmwareRevision("0.9"); + new Characteristic::Identify(); + + new Service::HAPProtocolInformation(); + new Characteristic::Version("1.1.0"); + + // new Service::LightBulb(); // Same as above, this line is deleted... + // new Characteristic::On(); // This line is also deleted... + + new DEV_LED(17); // ...and replaced with a single line that instantiates a second DEV_LED Service on Pin 17 + +} // end of setup() + +////////////////////////////////////// + +void loop(){ + + homeSpan.poll(); + +} // end of loop() diff --git a/examples/Intermediate/5-WorkingLED/DEV_LED.h b/examples/Intermediate/5-WorkingLED/DEV_LED.h new file mode 100644 index 0000000..b45f1d4 --- /dev/null +++ b/examples/Intermediate/5-WorkingLED/DEV_LED.h @@ -0,0 +1,35 @@ + +//////////////////////////////////// +// DEVICE-SPECIFIC LED SERVICES // +//////////////////////////////////// + +// HERE'S WHERE WE DEFINE OUR NEW LED SERVICE! + +struct DEV_LED : Service::LightBulb { // First we create a derived class from the HomeSpan LightBulb Service + + int ledPin; // this variable stores the pin number defined for this LED + SpanCharacteristic *power; // here we create a generic pointer to a SpanCharacteristic named "power" that we will use below + + // Next we define the constructor for DEV_LED. Note that it takes one argument, ledPin, + // which specifies the pin to which the LED is attached. + + DEV_LED(int ledPin) : Service::LightBulb(){ + + power=new Characteristic::On(); // this is where we create the On Characterstic we had previously defined in setup(). Save this in the pointer created above, for use below + this->ledPin=ledPin; // don't forget to store ledPin... + pinMode(ledPin,OUTPUT); // ...and set the mode for ledPin to be an OUTPUT (standard Arduino function) + + } // end constructor + + // Finally, we over-ride the default update() method with instructions that actually turn on/off the LED. Note update() returns type "statusCode" + + statusCode update(){ + + digitalWrite(ledPin,power->newValue.BOOL); // use a standard Arduino function to turn on/off ledPin based on the boolean variable power->newValue.BOOL + + return(SC_OK); // return OKAY status code. There are other possibilties we will explore in later examples. + + } // update +}; + +//////////////////////////////////