From 80a8935828f5d3a9b673d24b4e6d4b7ca3058f14 Mon Sep 17 00:00:00 2001 From: Gregg Date: Fri, 3 May 2024 06:36:25 -0500 Subject: [PATCH] Moved definitions of non-template SpanCharacteristic methods from HomeSpan.h to HomeSpan.cpp --- src/HomeSpan.cpp | 252 ++++++++++++++++++++++++++++++++++++++++++++++ src/HomeSpan.h | 257 +++++++---------------------------------------- 2 files changed, 286 insertions(+), 223 deletions(-) diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index e815af0..871ef55 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1886,6 +1886,207 @@ SpanCharacteristic::~SpanCharacteristic(){ /////////////////////////////// +String SpanCharacteristic::uvPrint(UVal &u){ + char c[64]; + switch(format){ + case FORMAT::BOOL: + return(String(u.BOOL)); + case FORMAT::INT: + return(String(u.INT)); + case FORMAT::UINT8: + return(String(u.UINT8)); + case FORMAT::UINT16: + return(String(u.UINT16)); + case FORMAT::UINT32: + return(String(u.UINT32)); + case FORMAT::UINT64: + sprintf(c,"%llu",u.UINT64); + return(String(c)); + case FORMAT::FLOAT: + sprintf(c,"%g",u.FLOAT); + return(String(c)); + case FORMAT::STRING: + case FORMAT::DATA: + case FORMAT::TLV_ENC: + return(String("\"") + String(u.STRING) + String("\"")); + } // switch + return(String()); // included to prevent compiler warnings +} + +/////////////////////////////// + +void SpanCharacteristic::uvSet(UVal &dest, UVal &src){ + if(format>=FORMAT::STRING) + uvSet(dest,(const char *)src.STRING); + else + dest=src; +} + +/////////////////////////////// + +void SpanCharacteristic::uvSet(UVal &u, const char *val){ + u.STRING = (char *)HS_REALLOC(u.STRING, strlen(val) + 1); + strcpy(u.STRING, val); +} + +/////////////////////////////// + +char *SpanCharacteristic::getStringGeneric(UVal &val){ + if(format>=FORMAT::STRING) + return val.STRING; + + return NULL; +} + +/////////////////////////////// + +void SpanCharacteristic::setString(const char *val, boolean notify){ + + setValCheck(); + uvSet(value,val); + setValFinish(notify); +} + +/////////////////////////////// + +size_t SpanCharacteristic::getDataGeneric(uint8_t *data, size_t len, UVal &val){ + if(format0){ + size_t olen; + mbedtls_base64_encode(NULL,0,&olen,NULL,len); // get length of string buffer needed (mbedtls includes the trailing null in this size) + value.STRING = (char *)HS_REALLOC(value.STRING,olen); // allocate sufficient size for storing value + mbedtls_base64_encode((uint8_t*)value.STRING,olen,&olen,data,len ); // encode data into string buf + } else { + value.STRING = (char *)HS_REALLOC(value.STRING,1); // allocate sufficient size for just trailing null character + *value.STRING ='\0'; + } + + setValFinish(notify); +} + +/////////////////////////////// + +size_t SpanCharacteristic::getTLVGeneric(TLV8 &tlv, UVal &val){ + + if(format tBuf(bufSize); // create fixed-size buffer to store decoded bytes + tlv.wipe(); // clear TLV completely + + size_t nChars=strlen(val.STRING); // total characters to decode + uint8_t *p=(uint8_t *)val.STRING; // set pointer to beginning of value + const size_t decodeSize=bufSize/3*4; // number of characters to decode in each pass + int status=0; + + while(nChars>0){ + size_t olen; + size_t n=nChars0){ + LOG0("\n*** WARNING: Can't unpack Characteristic::%s with getTLV(). TLV record is incomplete or corrupted!\n\n",hapName); + tlv.wipe(); + return(0); + } +return(tlv.pack_size()); +} + +/////////////////////////////// + +void SpanCharacteristic::setTLV(TLV8 &tlv, boolean notify){ + + setValCheck(); + + const size_t bufSize=36; // maximum size of buffer to store packed TLV bytes before encoding directly into value; must be multiple of 3 + size_t nBytes=tlv.pack_size(); // total size of packed TLV in bytes + + if(nBytes>0){ + size_t nChars; + mbedtls_base64_encode(NULL,0,&nChars,NULL,nBytes); // get length of string buffer needed (mbedtls includes the trailing null in this size) + value.STRING = (char *)HS_REALLOC(value.STRING,nChars); // allocate sufficient size for storing value + TempBuffer tBuf(bufSize); // create fixed-size buffer to store packed TLV bytes + tlv.pack_init(); // initialize TLV packing + uint8_t *p=(uint8_t *)value.STRING; // set pointer to beginning of value + while((nBytes=tlv.pack(tBuf,bufSize))>0){ // pack the next set of TLV bytes, up to a maximum of bufSize, into tBuf + size_t olen; // number of characters written (excludes null character) + mbedtls_base64_encode(p,nChars,&olen,tBuf,nBytes); // encode data directly into value + p+=olen; // advance pointer to null character + nChars-=olen; // subtract number of characters remaining + } + } else { + value.STRING = (char *)HS_REALLOC(value.STRING,1); // allocate sufficient size for just trailing null character + *value.STRING ='\0'; + } + + setValFinish(notify); +} + +/////////////////////////////// + +void SpanCharacteristic::setValCheck(){ + if(updateFlag==1) + LOG0("\n*** WARNING: Attempt to set value of Characteristic::%s within update() while it is being simultaneously updated by Home App. This may cause device to become non-responsive!\n\n",hapName); +} + +/////////////////////////////// + +void SpanCharacteristic::setValFinish(boolean notify){ + + uvSet(newValue,value); + updateTime=homeSpan.snapTime; + + if(notify){ + if((perms&EV) && (updateFlag!=2)){ // only broadcast notification if EV permission is set AND update is NOT being done in context of write-response + SpanBuf sb; // create SpanBuf object + sb.characteristic=this; // set characteristic + sb.status=StatusCode::OK; // set status + char dummy[]=""; + sb.val=dummy; // set dummy "val" so that printfNotify knows to consider this "update" + homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector + } + + if(nvsKey){ + nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store data + nvs_commit(homeSpan.charNVS); + } + } +} + +/////////////////////////////// + void SpanCharacteristic::printfAttributes(int flags){ const char permCodes[][7]={"pr","pw","ev","aa","tw","hd","wr"}; @@ -2066,6 +2267,57 @@ unsigned long SpanCharacteristic::timeVal(){ /////////////////////////////// +boolean SpanCharacteristic::updated(){ + + return(updateFlag>0); +} + +/////////////////////////////// + +uint32_t SpanCharacteristic::getIID(){ + + return(iid); +} + +/////////////////////////////// + +SpanCharacteristic *SpanCharacteristic::setPerms(uint8_t perms){ + perms&=0x7F; + if(perms>0) + this->perms=perms; + return(this); +} + +/////////////////////////////// + +SpanCharacteristic *SpanCharacteristic::addPerms(uint8_t dPerms){ + return(setPerms(perms|dPerms)); +} + +/////////////////////////////// + +SpanCharacteristic *SpanCharacteristic::removePerms(uint8_t dPerms){ + return(setPerms(perms&(~dPerms))); +} + +/////////////////////////////// + +SpanCharacteristic *SpanCharacteristic::setDescription(const char *c){ + desc = (char *)HS_REALLOC(desc, strlen(c) + 1); + strcpy(desc, c); + return(this); +} + +/////////////////////////////// + +SpanCharacteristic *SpanCharacteristic::setUnit(const char *c){ + unit = (char *)HS_REALLOC(unit, strlen(c) + 1); + strcpy(unit, c); + return(this); +} + +/////////////////////////////// + SpanCharacteristic *SpanCharacteristic::setValidValues(int n, ...){ String s="["; diff --git a/src/HomeSpan.h b/src/HomeSpan.h index d5b656b..0ce7fdb 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -549,47 +549,12 @@ class SpanCharacteristic{ void printfAttributes(int flags); // writes Characteristic JSON to hapOut stream StatusCode loadUpdate(char *val, char *ev, boolean wr); // load updated val/ev from PUT /characteristic JSON request. Return intitial HAP status code (checks to see if characteristic is found, is writable, etc.) - - String uvPrint(UVal &u){ - char c[64]; - switch(format){ - case FORMAT::BOOL: - return(String(u.BOOL)); - case FORMAT::INT: - return(String(u.INT)); - case FORMAT::UINT8: - return(String(u.UINT8)); - case FORMAT::UINT16: - return(String(u.UINT16)); - case FORMAT::UINT32: - return(String(u.UINT32)); - case FORMAT::UINT64: - sprintf(c,"%llu",u.UINT64); - return(String(c)); - case FORMAT::FLOAT: - sprintf(c,"%g",u.FLOAT); - return(String(c)); - case FORMAT::STRING: - case FORMAT::DATA: - case FORMAT::TLV_ENC: - return(String("\"") + String(u.STRING) + String("\"")); - } // switch - return(String()); // included to prevent compiler warnings - } + String uvPrint(UVal &u); // returns "printable" String for any type of Characteristic + + void uvSet(UVal &dest, UVal &src); // copies UVal src into UVal dest + void uvSet(UVal &u, const char *val); // copies string val into UVal u - void uvSet(UVal &dest, UVal &src){ - if(format>=FORMAT::STRING) - uvSet(dest,(const char *)src.STRING); - else - dest=src; - } - - void uvSet(UVal &u, const char *val){ - u.STRING = (char *)HS_REALLOC(u.STRING, strlen(val) + 1); - strcpy(u.STRING, val); - } - - template void uvSet(UVal &u, T val){ + template void uvSet(UVal &u, T val){ // copies any other type of val into UVal u switch(format){ case FORMAT::BOOL: u.BOOL=(boolean)val; @@ -619,7 +584,7 @@ class SpanCharacteristic{ } // switch } - template T uvGet(UVal &u){ + template T uvGet(UVal &u){ // returns UVal u, cast into T switch(format){ case FORMAT::BOOL: @@ -646,7 +611,7 @@ class SpanCharacteristic{ protected: - ~SpanCharacteristic(); // destructor + ~SpanCharacteristic(); // destructor template void init(T val, boolean nvsStore, A min=0, B max=1){ @@ -688,10 +653,8 @@ class SpanCharacteristic{ public: - void *operator new(size_t size){return(HS_MALLOC(size));} // override new operator to use PSRAM when available SpanCharacteristic(HapChar *hapChar, boolean isCustom=false); // constructor - - uint32_t getIID(){return(iid);} // returns IID of Characteristic + void *operator new(size_t size){return(HS_MALLOC(size));} // override new operator to use PSRAM when available template T getVal(){ return(uvGet(value)); @@ -700,155 +663,6 @@ class SpanCharacteristic{ template T getNewVal(){ return(uvGet(newValue)); } - - char *getStringGeneric(UVal &val){ - if(format>=FORMAT::STRING) - return val.STRING; - - return NULL; - } - - char *getString(){return(getStringGeneric(value));} - char *getNewString(){return(getStringGeneric(newValue));} - - void setString(const char *val, boolean notify=true){ - - setValCheck(); - uvSet(value,val); - setValFinish(notify); - } - - size_t getDataGeneric(uint8_t *data, size_t len, UVal &val){ - if(format0){ - size_t olen; - mbedtls_base64_encode(NULL,0,&olen,NULL,len); // get length of string buffer needed (mbedtls includes the trailing null in this size) - value.STRING = (char *)HS_REALLOC(value.STRING,olen); // allocate sufficient size for storing value - mbedtls_base64_encode((uint8_t*)value.STRING,olen,&olen,data,len ); // encode data into string buf - } else { - value.STRING = (char *)HS_REALLOC(value.STRING,1); // allocate sufficient size for just trailing null character - *value.STRING ='\0'; - } - - setValFinish(notify); - } - - size_t getTLVGeneric(TLV8 &tlv, UVal &val){ - - if(format tBuf(bufSize); // create fixed-size buffer to store decoded bytes - tlv.wipe(); // clear TLV completely - - size_t nChars=strlen(val.STRING); // total characters to decode - uint8_t *p=(uint8_t *)val.STRING; // set pointer to beginning of value - const size_t decodeSize=bufSize/3*4; // number of characters to decode in each pass - int status=0; - - while(nChars>0){ - size_t olen; - size_t n=nChars0){ - LOG0("\n*** WARNING: Can't unpack Characteristic::%s with getTLV(). TLV record is incomplete or corrupted!\n\n",hapName); - tlv.wipe(); - return(0); - } - return(tlv.pack_size()); - } - - size_t getTLV(TLV8 &tlv){return(getTLVGeneric(tlv,value));} - size_t getNewTLV(TLV8 &tlv){return(getTLVGeneric(tlv,newValue));} - - void setTLV(TLV8 &tlv, boolean notify=true){ - - setValCheck(); - - const size_t bufSize=36; // maximum size of buffer to store packed TLV bytes before encoding directly into value; must be multiple of 3 - size_t nBytes=tlv.pack_size(); // total size of packed TLV in bytes - - if(nBytes>0){ - size_t nChars; - mbedtls_base64_encode(NULL,0,&nChars,NULL,nBytes); // get length of string buffer needed (mbedtls includes the trailing null in this size) - value.STRING = (char *)HS_REALLOC(value.STRING,nChars); // allocate sufficient size for storing value - TempBuffer tBuf(bufSize); // create fixed-size buffer to store packed TLV bytes - tlv.pack_init(); // initialize TLV packing - uint8_t *p=(uint8_t *)value.STRING; // set pointer to beginning of value - while((nBytes=tlv.pack(tBuf,bufSize))>0){ // pack the next set of TLV bytes, up to a maximum of bufSize, into tBuf - size_t olen; // number of characters written (excludes null character) - mbedtls_base64_encode(p,nChars,&olen,tBuf,nBytes); // encode data directly into value - p+=olen; // advance pointer to null character - nChars-=olen; // subtract number of characters remaining - } - } else { - value.STRING = (char *)HS_REALLOC(value.STRING,1); // allocate sufficient size for just trailing null character - *value.STRING ='\0'; - } - - setValFinish(notify); - } - - void setValCheck(){ - if(updateFlag==1) - LOG0("\n*** WARNING: Attempt to set value of Characteristic::%s within update() while it is being simultaneously updated by Home App. This may cause device to become non-responsive!\n\n",hapName); - } - - void setValFinish(boolean notify){ - - uvSet(newValue,value); - updateTime=homeSpan.snapTime; - - if(notify){ - if((perms&EV) && (updateFlag!=2)){ // only broadcast notification if EV permission is set AND update is NOT being done in context of write-response - SpanBuf sb; // create SpanBuf object - sb.characteristic=this; // set characteristic - sb.status=StatusCode::OK; // set status - char dummy[]=""; - sb.val=dummy; // set dummy "val" so that printfNotify knows to consider this "update" - homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector - } - - if(nvsKey){ - nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store data - nvs_commit(homeSpan.charNVS); - } - } - } template void setVal(T val, boolean notify=true){ @@ -880,10 +694,29 @@ class SpanCharacteristic{ } } - } // setVal() + } // setVal() + + char *getStringGeneric(UVal &val); // return the specified UVal for string-based Characteristics + char *getString(){return(getStringGeneric(value));} // return the value for string-based Characteristics + char *getNewString(){return(getStringGeneric(newValue));} // return the newValue for string-based Characteristics + void setString(const char *val, boolean notify=true); // set the value and newValue for string-based Characteristic - boolean updated(){return(updateFlag>0);} // returns true within update() if Characteristic was updated by Home App + size_t getDataGeneric(uint8_t *data, size_t len, UVal &val); // return the specified UVal for data-based Characteristics + size_t getData(uint8_t *data, size_t len){return(getDataGeneric(data,len,value));} // return the value for data-based Characteristics + size_t getNewData(uint8_t *data, size_t len){return(getDataGeneric(data,len,newValue));} // return the newValue for data-based Characteristics + void setData(uint8_t *data, size_t len, boolean notify=true); // set the value and newValue for data-based Characteristic + + size_t getTLVGeneric(TLV8 &tlv, UVal &val); // return the specified UVal for tlv8-based Characteristics + size_t getTLV(TLV8 &tlv){return(getTLVGeneric(tlv,value));} // return the value for tlv8-based Characteristics + size_t getNewTLV(TLV8 &tlv){return(getTLVGeneric(tlv,newValue));} // return the newValue for tlv8-based Characteristics + void setTLV(TLV8 &tlv, boolean notify=true); // set the value and newValue for tlv8-based Characteristic + + void setValCheck(); // initial check before setting value of any Characteristic + void setValFinish(boolean notify); // final processing after setting value of any Characteristic + + boolean updated(); // returns true within update() if Characteristic was updated by Home App unsigned long timeVal(); // returns time elapsed (in millis) since value was last updated, either by Home App or by using setVal() + uint32_t getIID(); // returns IID of Characteristic SpanCharacteristic *setValidValues(int n, ...); // sets a list of 'n' valid values allowed for a Characteristic and returns pointer to self. Only applicable if format=INT, UINT8, UINT16, or UINT32 @@ -901,33 +734,11 @@ class SpanCharacteristic{ } // setRange() - SpanCharacteristic *setPerms(uint8_t perms){ - perms&=0x7F; - if(perms>0) - this->perms=perms; - return(this); - } - - SpanCharacteristic *addPerms(uint8_t dPerms){ - return(setPerms(perms|dPerms)); - } - - SpanCharacteristic *removePerms(uint8_t dPerms){ - return(setPerms(perms&(~dPerms))); - } - - SpanCharacteristic *setDescription(const char *c){ - desc = (char *)HS_REALLOC(desc, strlen(c) + 1); - strcpy(desc, c); - return(this); - } - - SpanCharacteristic *setUnit(const char *c){ - unit = (char *)HS_REALLOC(unit, strlen(c) + 1); - strcpy(unit, c); - return(this); - } - + SpanCharacteristic *setPerms(uint8_t perms); // sets permissions of a Characteristic + SpanCharacteristic *addPerms(uint8_t dPerms); // add permissions of a Characteristic + SpanCharacteristic *removePerms(uint8_t dPerms); // removes permissions of a Characteristic + SpanCharacteristic *setDescription(const char *c); // sets description of a Characteristic + SpanCharacteristic *setUnit(const char *c); // set unit of a Characteristic }; ///////////////////////////////