diff --git a/examples/20-DynamicBridge/20-DynamicBridge.ino b/examples/20-DynamicBridge/20-DynamicBridge.ino new file mode 100644 index 0000000..e25382a --- /dev/null +++ b/examples/20-DynamicBridge/20-DynamicBridge.ino @@ -0,0 +1,151 @@ +/********************************************************************************* + * MIT License + * + * Copyright (c) 2022 Gregg E. Berman + * + * https://github.com/HomeSpan/HomeSpan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************************************/ + +#include "HomeSpan.h" + +#define MAX_LIGHTS 10 + +nvs_handle savedData; +int accNum[MAX_LIGHTS]={0}; + +////////////////////////////////////// + +void setup() { + + Serial.begin(115200); + + size_t len; + nvs_open("SAVED_DATA",NVS_READWRITE,&savedData); // open SAVED DATA + if(!nvs_get_blob(savedData,"ACC_NUM",NULL,&len)) // if ACCESSORY NUMBER data found + nvs_get_blob(savedData,"ACC_NUM",&accNum,&len); // retrieve data + + homeSpan.setLogLevel(1); + + homeSpan.begin(Category::Bridges,"HomeSpan Bridge"); + + new SpanAccessory(); + new Service::AccessoryInformation(); + new Characteristic::Identify(); + new Characteristic::Model("HomeSpan Dynamic Bridge"); + + for(int i=0;i0) + addLight(accNum[i]); + + new SpanUserCommand('a'," add a new light accessory with id=num",addAccessory); + new SpanUserCommand('d'," delete a light accessory with id=num",deleteAccessory); + new SpanUserCommand('u',"update configuration database",[](const char *buf){homeSpan.updateDatabase();}); + +} + +////////////////////////////////////// + +void loop(){ + + homeSpan.poll(); + +} + +/////////////////////////// + +void addLight(int n){ + + char name[32]; + sprintf(name,"Light-%d",n); + char sNum[32]; + sprintf(sNum,"%0.10d",n); + + Serial.printf("Adding Accessory: %s\n",name); + + new SpanAccessory(n+1); // add 1, since first Accessory is reserved for the bridge + new Service::AccessoryInformation(); + new Characteristic::Identify(); + new Characteristic::Name(name); + new Characteristic::SerialNumber(sNum); + new Service::LightBulb(); + new Characteristic::On(0,true); +} + +/////////////////////////// + +void addAccessory(const char *buf){ + + int n=atoi(buf+1); + + if(n<1){ + Serial.printf("Invalid Accessory number!\n"); + return; + } + + int i; + for(i=0;i0 && accNum[i]!=n;i++); + + if(i==MAX_LIGHTS){ + Serial.printf("Can't add any more lights - max is %d!\n",MAX_LIGHTS); + return; + } + + if(accNum[i]>0){ + Serial.printf("Accessory Light-%d already implemented!\n",n); + return; + } + + accNum[i]=n; + nvs_set_blob(savedData,"ACC_NUM",&accNum,sizeof(accNum)); // update data + nvs_commit(savedData); + + addLight(n); +} + +/////////////////////////// + +void deleteAccessory(const char *buf){ + + int n=atoi(buf+1); + + if(n<1){ + Serial.printf("Invalid Accessory number!\n"); + return; + } + + SpanAccessory *acc=homeSpan.getAccessory(n+1); + + if(!acc){ + Serial.printf("No such Accessory: Light-%d\n",n); + return; + } + + Serial.printf("Deleting Accessory: Light-%d\n",n); + delete acc; + + int i; // delete entry in accNum + for(i=0;accNum[i]!=n;i++); + accNum[i]=0; + + nvs_set_blob(savedData,"ACC_NUM",&accNum,sizeof(accNum)); // update data + nvs_commit(savedData); +} diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index c0a1281..757eddd 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1032,7 +1032,7 @@ void Span::processSerialCommand(const char *c){ Serial.print("\n"); } } - Serial.print("\n*** End Info ***\n"); + Serial.print("\n*** End Info ***\n\n"); } break; @@ -1167,6 +1167,20 @@ void Span::prettyPrint(char *buf, int nsp){ Serial.print("\n"); } // prettyPrint + +/////////////////////////// + +SpanAccessory *Span::getAccessory(uint32_t n){ + + auto it=homeSpan.Accessories.begin(); + for(;it!=homeSpan.Accessories.end() && (*it)->aid!=n; it++); + + if(it==homeSpan.Accessories.end()) + return(NULL); + + return(*it); +} + /////////////////////////////// SpanCharacteristic *Span::find(uint32_t aid, int iid){ diff --git a/src/HomeSpan.h b/src/HomeSpan.h index ac6f95d..966de42 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -219,8 +219,9 @@ struct Span{ int sprintfAttributes(char *cBuf, int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator - void prettyPrint(char *buf, int nsp=2); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces + void prettyPrint(char *buf, int nsp=2); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces SpanCharacteristic *find(uint32_t aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found) + SpanAccessory *getAccessory(uint32_t aid); // return Accessory with matching aid (else NULL if not found) int countCharacteristics(char *buf); // return number of characteristic objects referenced in PUT /characteristics JSON request int updateCharacteristics(char *buf, SpanBuf *pObj); // parses PUT /characteristics JSON request 'buf into 'pObj' and updates referenced characteristics; returns 1 on success, 0 on fail