Created Example 15
Initial implementation of SpanButton PushButton object and check() logic
This commit is contained in:
parent
9bbea69816
commit
c997ca3462
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// HomeSpan: A HomeKit implementation for the ESP32 //
|
||||
// ------------------------------------------------ //
|
||||
// //
|
||||
// Example 15: Real PushButtons //
|
||||
// * manually controlling an LED //
|
||||
// //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#include "HomeSpan.h"
|
||||
#include "DEV_LED.h"
|
||||
#include "DEV_Identify.h"
|
||||
|
||||
void setup() {
|
||||
|
||||
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("Switched LED","HomeSpan","123-ABC","20mA LED","0.9",0);
|
||||
new DEV_DimmableLED(0,17);
|
||||
|
||||
} // end of setup()
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void loop(){
|
||||
|
||||
homeSpan.poll();
|
||||
|
||||
} // end of loop()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
//////////////////////////////////
|
||||
// DEVICE-SPECIFIC SERVICES //
|
||||
//////////////////////////////////
|
||||
|
||||
struct DEV_Identify : Service::AccessoryInformation {
|
||||
|
||||
int nBlinks; // number of times to blink built-in LED in identify routine
|
||||
SpanCharacteristic *identify; // reference to the Identify Characteristic
|
||||
|
||||
// NEW! modified constructor() method to include optional ServiceType argument
|
||||
|
||||
DEV_Identify(char *name, char *manu, char *sn, char *model, char *version, int nBlinks, ServiceType sType=ServiceType::Regular) : Service::AccessoryInformation(sType){
|
||||
|
||||
new Characteristic::Name(name); // create all the required Characteristics with values set based on above arguments
|
||||
new Characteristic::Manufacturer(manu);
|
||||
new Characteristic::SerialNumber(sn);
|
||||
new Characteristic::Model(model);
|
||||
new Characteristic::FirmwareRevision(version);
|
||||
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
|
||||
|
||||
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
|
||||
|
||||
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
|
||||
}
|
||||
|
||||
StatusCode update(){
|
||||
|
||||
for(int i=0;i<nBlinks;i++){
|
||||
digitalWrite(LED_BUILTIN,LOW);
|
||||
delay(250);
|
||||
digitalWrite(LED_BUILTIN,HIGH);
|
||||
delay(250);
|
||||
}
|
||||
|
||||
return(StatusCode::OK);
|
||||
|
||||
} // update
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
////////////////////////////////////
|
||||
// DEVICE-SPECIFIC LED SERVICES //
|
||||
////////////////////////////////////
|
||||
|
||||
#include "extras/PwmPin.h" // library of various PWM functions
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
struct DEV_DimmableLED : Service::LightBulb { // Dimmable LED
|
||||
|
||||
PwmPin *pwmPin; // reference to PWM Pin
|
||||
int ledPin; // pin number defined for this LED
|
||||
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
|
||||
|
||||
DEV_DimmableLED(int channel, int ledPin, ServiceType sType=ServiceType::Regular) : Service::LightBulb(sType){ // // NEW! modified constructor() method
|
||||
|
||||
power=new Characteristic::On();
|
||||
|
||||
level=new Characteristic::Brightness(50); // Brightness Characteristic with an initial value of 50%
|
||||
new SpanRange(5,100,1); // sets the range of the Brightness to be from a min of 5%, to a max of 100%, in steps of 1%
|
||||
|
||||
new SpanButton(19);
|
||||
|
||||
this->channel=channel; // save the channel number (from 0-15)
|
||||
this->ledPin=ledPin; // save LED pin number
|
||||
this->pwmPin=new PwmPin(channel, ledPin); // configure the PWM channel and attach the specified ledPin
|
||||
|
||||
Serial.print("Configuring Dimmable LED: Pin="); // initialization message
|
||||
Serial.print(ledPin);
|
||||
Serial.print(" Channel=");
|
||||
Serial.print(channel);
|
||||
Serial.print("\n");
|
||||
|
||||
} // end constructor
|
||||
|
||||
StatusCode update(){ // update() method
|
||||
|
||||
LOG1("Updating Dimmable LED on pin=");
|
||||
LOG1(ledPin);
|
||||
LOG1(": Current Power=");
|
||||
LOG1(power->getVal()?"true":"false");
|
||||
LOG1(" Current Brightness=");
|
||||
LOG1(level->getVal());
|
||||
|
||||
if(power->updated()){
|
||||
LOG1(" New Power=");
|
||||
LOG1(power->getNewVal()?"true":"false");
|
||||
}
|
||||
|
||||
if(level->updated()){
|
||||
LOG1(" New Brightness=");
|
||||
LOG1(level->getNewVal());
|
||||
}
|
||||
|
||||
LOG1("\n");
|
||||
|
||||
pwmPin->set(channel,power->getNewVal()*level->getNewVal());
|
||||
|
||||
return(StatusCode::OK); // return OK status code
|
||||
|
||||
} // update
|
||||
|
||||
void button(int pin, boolean isLong){
|
||||
|
||||
Serial.print("Found button press on pin: ");
|
||||
Serial.print(pin);
|
||||
Serial.print(" type: ");
|
||||
Serial.print(isLong?"LONG":"SHORT");
|
||||
Serial.print("\n");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
21
src/HAP.cpp
21
src/HAP.cpp
|
|
@ -102,7 +102,16 @@ void HAPClient::init(){
|
|||
homeSpan.Loops.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
for(int i=0;i<homeSpan.PushButtons.size();i++){
|
||||
Serial.print("PushButton Found on pin: ");
|
||||
Serial.print(homeSpan.PushButtons[i]->pin);
|
||||
Serial.print(" iid: ");
|
||||
Serial.print(homeSpan.PushButtons[i]->service->iid);
|
||||
Serial.print("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
|
@ -1173,6 +1182,16 @@ void HAPClient::callServiceLoops(){
|
|||
homeSpan.Loops[i]->loop(); // call the loop() method
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void HAPClient::checkPushButtons(){
|
||||
|
||||
for(int i=0;i<homeSpan.PushButtons.size();i++) // loop over all defined pushbuttons
|
||||
homeSpan.PushButtons[i]->check(); // check if long- or short-pressed, which calls button() method in attached Service if needed
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void HAPClient::checkNotifications(){
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ struct HAPClient {
|
|||
static void removeController(uint8_t *id); // removes specific Controller. If no remaining admin Controllers, remove all others (if any) as per HAP requirements.
|
||||
static void printControllers(); // prints IDs of all allocated (paired) Controller
|
||||
static void callServiceLoops(); // call the loop() method for any Service with that over-rode the default method
|
||||
static void checkPushButtons(); // checks for PushButton presses and calls button() method of attached Services when found
|
||||
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
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ void Span::poll() {
|
|||
} // for-loop over connection slots
|
||||
|
||||
HAPClient::callServiceLoops();
|
||||
HAPClient::checkPushButtons();
|
||||
HAPClient::checkNotifications();
|
||||
HAPClient::checkTimedWrites();
|
||||
|
||||
|
|
@ -1152,4 +1153,52 @@ SpanRange::SpanRange(int min, int max, int step){
|
|||
homeSpan.Accessories.back()->Services.back()->Characteristics.back()->range=this;
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// SpanButton //
|
||||
///////////////////////////////
|
||||
|
||||
SpanButton::SpanButton(int pin, unsigned long longTime, unsigned long shortTime){
|
||||
|
||||
if(homeSpan.Accessories.empty() || homeSpan.Accessories.back()->Services.empty()){
|
||||
Serial.print("*** FATAL ERROR: Can't create new PushButton without a defined Service. Program halted!\n\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
Serial.print("Configuring PushButton: Pin="); // initialization message
|
||||
Serial.print(pin);
|
||||
Serial.print("\n");
|
||||
|
||||
this->pin=pin;
|
||||
this->shortTime=shortTime;
|
||||
this->longTime=longTime;
|
||||
service=homeSpan.Accessories.back()->Services.back();
|
||||
|
||||
homeSpan.PushButtons.push_back(this);
|
||||
|
||||
pinMode(pin,INPUT_PULLUP);
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
void SpanButton::check(){
|
||||
|
||||
if(state==UNTRIGGERED && !digitalRead(pin)){
|
||||
state=TRIGGERED;
|
||||
unsigned long cTime=millis();
|
||||
shortAlarm=cTime+shortTime;
|
||||
longAlarm=cTime+longTime;
|
||||
} else
|
||||
|
||||
if(state==TRIGGERED && digitalRead(pin)){
|
||||
unsigned long cTime=millis();
|
||||
if(cTime>longAlarm)
|
||||
service->button(pin, true);
|
||||
else if(cTime>shortAlarm)
|
||||
service->button(pin, false);
|
||||
state=UNTRIGGERED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ struct SpanService;
|
|||
struct SpanCharacteristic;
|
||||
struct SpanRange;
|
||||
struct SpanBuf;
|
||||
struct SpanButton;
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ struct Span{
|
|||
vector<SpanAccessory *> Accessories; // vector of pointers to all Accessories
|
||||
vector<SpanService *> Loops; // vector of pointer to all Services that have over-ridden loop() methods
|
||||
vector<SpanBuf> Notifications; // vector of SpanBuf objects that store info for Characteristics that are updated with setVal() and require a Notification Event
|
||||
vector<SpanButton *> PushButtons; // vector of pointer to all PushButtons
|
||||
unordered_map<uint64_t, uint32_t> TimedWrites; // map of timed-write PIDs and Alarm Times (based on TTLs)
|
||||
|
||||
void begin(Category catID,
|
||||
|
|
@ -105,7 +107,8 @@ struct SpanService{
|
|||
int sprintfAttributes(char *cBuf); // prints Service JSON records into buf; return number of characters printed, excluding null terminator
|
||||
virtual StatusCode update() {return(StatusCode::OK);} // update Service and return final statusCode based on updated Characteristics - should be overridden by DEVICE-SPECIFIC Services
|
||||
virtual void event(){} // event generation for Services that create their own events and need to notify HomeKit of a new Characteristic value(s)
|
||||
virtual void loop(){} // loops for each service
|
||||
virtual void loop(){} // loops for each Service
|
||||
virtual void button(int pin, boolean isLong){} // method called for a Service when a button attached to "pin" has a Short-Press or Long-Press, according to "isLong"
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
|
|
@ -231,6 +234,28 @@ struct SpanBuf{ // temporary storage buffer for us
|
|||
SpanCharacteristic *characteristic=NULL; // Characteristic to update (NULL if not found)
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
struct SpanButton{
|
||||
|
||||
int pin; // pin number
|
||||
unsigned long shortTime; // time (in millis) required to register a short press
|
||||
unsigned long longTime; // time (in millis) required to register a long press
|
||||
unsigned long shortAlarm; // alarm time to trigger a short press
|
||||
unsigned long longAlarm; // alarm time to triger a long press
|
||||
SpanService *service; // Service to which this PushButton is attached
|
||||
|
||||
enum {
|
||||
UNTRIGGERED,
|
||||
TRIGGERED,
|
||||
SHORT,
|
||||
LONG
|
||||
} state=UNTRIGGERED;
|
||||
|
||||
SpanButton(int pin, unsigned long longTime=2000, unsigned long shortTime=5);
|
||||
void check();
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// Extern Variables
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue