From 3ed18b3f797ba972027ad828aed753203f28e743 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 29 Jun 2024 10:03:07 -0500 Subject: [PATCH] Added constructors for TLV8 and DATA Characteristics Conformed all CUSTOM_CHAR macros to allow for these constructors --- src/Characteristics.h | 11 ----------- src/HomeSpan.cpp | 31 ++++++++++++++++++------------- src/HomeSpan.h | 35 +++++++++++++++++++++++++---------- src/Span.h | 37 ++++++++----------------------------- src/TLV8.cpp | 10 ++++------ src/TLV8.h | 17 +++++++---------- src/src.ino | 30 ++++++++++++++++++++++++++++++ 7 files changed, 92 insertions(+), 79 deletions(-) diff --git a/src/Characteristics.h b/src/Characteristics.h index 52d43aa..8500728 100644 --- a/src/Characteristics.h +++ b/src/Characteristics.h @@ -55,17 +55,6 @@ enum FORMAT { // HAP Table 6-5 /////////////////////////////// -typedef boolean BOOL_t; -typedef uint8_t UINT8_t; -typedef uint16_t UINT16_t; -typedef uint32_t UINT32_t; -typedef uint64_t UINT64_t; -typedef int32_t INT_t; -typedef double FLOAT_t; -typedef char * STRING_t; - -/////////////////////////////// - struct HapChar { const char *type; const char *hapName; diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index e7a2475..a0241be 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1867,14 +1867,29 @@ void SpanCharacteristic::uvSet(UVal &dest, UVal &src){ /////////////////////////////// -void SpanCharacteristic::uvSet(UVal &u, const char *val){ +void SpanCharacteristic::uvSet(UVal &u, STRING_t val){ u.STRING = (char *)HS_REALLOC(u.STRING, strlen(val) + 1); strcpy(u.STRING, val); } /////////////////////////////// -void SpanCharacteristic::uvSet(UVal &u, const TLV8 &tlv){ +void SpanCharacteristic::uvSet(UVal &u, DATA_t data){ + + if(data.second>0){ + size_t olen; + mbedtls_base64_encode(NULL,0,&olen,NULL,data.second); // 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.first,data.second ); // 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'; + } +} + +/////////////////////////////// + +void SpanCharacteristic::uvSet(UVal &u, TLV_ENC_t tlv){ 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 @@ -1941,17 +1956,7 @@ size_t SpanCharacteristic::getDataGeneric(uint8_t *data, size_t len, UVal &val){ void SpanCharacteristic::setData(uint8_t *data, size_t len, boolean notify){ setValCheck(); - - if(len>0){ - 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'; - } - + uvSet(value,{data,len}); setValFinish(notify); } diff --git a/src/HomeSpan.h b/src/HomeSpan.h index 9297f50..d173ea7 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -71,6 +71,20 @@ enum { GET_STATUS=256 }; +typedef boolean BOOL_t; +typedef uint8_t UINT8_t; +typedef uint16_t UINT16_t; +typedef uint32_t UINT32_t; +typedef uint64_t UINT64_t; +typedef int32_t INT_t; +typedef double FLOAT_t; +typedef const char * STRING_t; +typedef const TLV8 & TLV_ENC_t; +typedef std::pair DATA_t; + +static DATA_t NULL_DATA={NULL,0}; +static TLV8 NULL_TLV{}; + /////////////////////////////// #define STATUS_UPDATE(LED_UPDATE,MESSAGE_UPDATE) {homeSpan.statusLED->LED_UPDATE;if(homeSpan.statusCallback)homeSpan.statusCallback(MESSAGE_UPDATE);} @@ -485,14 +499,14 @@ class SpanCharacteristic{ friend class SpanService; union UVal { - BOOL_t BOOL; - UINT8_t UINT8; - UINT16_t UINT16; - UINT32_t UINT32; - UINT64_t UINT64; - INT_t INT; - FLOAT_t FLOAT; - STRING_t STRING = NULL; + boolean BOOL; + uint8_t UINT8; + uint16_t UINT16; + uint32_t UINT32; + uint64_t UINT64; + int32_t INT; + double FLOAT; + char * STRING = NULL; }; class EVLIST : public vector>{ // vector of current connections that have subscribed to EV notifications for this Characteristic @@ -534,8 +548,9 @@ class SpanCharacteristic{ 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 &u, const TLV8 &tlv); // copies TLV8 val into UVal u (after transforming to a char *) + void uvSet(UVal &u, STRING_t val); // copies string val into UVal u + void uvSet(UVal &u, DATA_t data); // copies DATA data into UVal u (after transforming to a char *) + void uvSet(UVal &u, TLV_ENC_t tlv); // copies TLV8 tlv into UVal u (after transforming to a char *) template void uvSet(UVal &u, T val){ // copies numeric val into UVal u switch(format){ diff --git a/src/Span.h b/src/Span.h index e43a88a..d255d48 100644 --- a/src/Span.h +++ b/src/Span.h @@ -513,7 +513,7 @@ namespace Characteristic { CREATE_CHAR(double,CurrentRelativeHumidity,0,0,100); // current humidity measured as a percentage CREATE_CHAR(double,CurrentTemperature,0,0,100); // current temperature measured in Celsius CREATE_CHAR(int,CurrentTiltAngle,0,-90,90); // current angle (in degrees) of slats from fully up or left (-90) to fully open (0) to fully down or right (90) - CREATE_CHAR(const TLV8 &,DisplayOrder,TLV8::NULL_TLV,TLV8::NULL_TLV,TLV8::NULL_TLV); // specifies the order in which the TV inputs are displayed for selection in the Home App + CREATE_CHAR(const TLV8 &,DisplayOrder,NULL_TLV,NULL_TLV,NULL_TLV); // specifies the order in which the TV inputs are displayed for selection in the Home App CREATE_CHAR(double,FilterLifeLevel,100,0,100); // measured as a percentage of remaining life CREATE_CHAR(uint8_t,FilterChangeIndication,0,0,1,NO_CHANGE_NEEDED,CHANGE_NEEDED); // indicates state of filter CREATE_CHAR(const char *,FirmwareRevision,"1.0.0",NULL,NULL); // must be in form x[.y[.z]] - informational only @@ -607,46 +607,25 @@ namespace Characteristic { #define CUSTOM_CHAR(NAME,UUID,PERMISISONS,FORMAT,DEFVAL,MINVAL,MAXVAL,STATIC_RANGE) \ HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),FORMAT,STATIC_RANGE}; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore,(FORMAT##_t)MINVAL,(FORMAT##_t)MAXVAL); } }; } - -#define CUSTOM_CHAR_STRING(NAME,UUID,PERMISISONS,DEFVAL) \ - HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),STRING,true}; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } - -#define CUSTOM_CHAR_DATA(NAME,UUID,PERMISISONS) \ - HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),DATA,true}; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val="", boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } - -#define CUSTOM_CHAR_TLV8(NAME,UUID,PERMISISONS) \ - HapChar _CUSTOM_##NAME {#UUID,#NAME,(PERMS)(PERMISISONS),TLV_ENC,true}; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val="", boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } + namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore,MINVAL,MAXVAL); } }; } #else #define CUSTOM_CHAR(NAME,UUID,PERMISISONS,FORMAT,DEFVAL,MINVAL,MAXVAL,STATIC_RANGE) \ extern HapChar _CUSTOM_##NAME; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore,(FORMAT##_t)MINVAL,(FORMAT##_t)MAXVAL); } }; } + namespace Characteristic { struct NAME : SpanCharacteristic { NAME(FORMAT##_t val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore,MINVAL,MAXVAL); } }; } -#define CUSTOM_CHAR_STRING(NAME,UUID,PERMISISONS,DEFVAL) \ - extern HapChar _CUSTOM_##NAME; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val=DEFVAL, boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } +#endif -#define CUSTOM_CHAR_DATA(NAME,UUID,PERMISISONS) \ - extern HapChar _CUSTOM_##NAME; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val="", boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } - -#define CUSTOM_CHAR_TLV8(NAME,UUID,PERMISISONS) \ - extern HapChar _CUSTOM_##NAME; \ - namespace Characteristic { struct NAME : SpanCharacteristic { NAME(const char * val="", boolean nvsStore=false) : SpanCharacteristic {&_CUSTOM_##NAME,true} { init(val,nvsStore); } }; } - -#endif +#define CUSTOM_CHAR_STRING(NAME,UUID,PERMISISONS,DEFVAL) CUSTOM_CHAR(NAME,UUID,PERMISISONS,STRING,DEFVAL,NULL,NULL,true); +#define CUSTOM_CHAR_TLV8(NAME,UUID,PERMISISONS) CUSTOM_CHAR(NAME,UUID,PERMISISONS,TLV_ENC,NULL_TLV,NULL_TLV,NULL_TLV,true); +#define CUSTOM_CHAR_DATA(NAME,UUID,PERMISISONS) CUSTOM_CHAR(NAME,UUID,PERMISISONS,DATA,NULL_DATA,NULL_DATA,NULL_DATA,true); #define CUSTOM_SERV(NAME,UUID) \ namespace Service { struct NAME : SpanService { NAME() : SpanService{#UUID,#NAME,true}{} }; } - //////////////////////////////////////////////////////// -// MACROS TO ADD A NEW ACCESSORT WITH OPTIONAL NAME // +// MACROS TO ADD A NEW ACCESSORY WITH OPTIONAL NAME // //////////////////////////////////////////////////////// #define SPAN_ACCESSORY(...) new SpanAccessory(); new Service::AccessoryInformation(); new Characteristic::Identify(); __VA_OPT__(new Characteristic::Name(__VA_ARGS__)); diff --git a/src/TLV8.cpp b/src/TLV8.cpp index 4b161da..e700946 100644 --- a/src/TLV8.cpp +++ b/src/TLV8.cpp @@ -68,7 +68,7 @@ void tlv8_t::osprint(std::ostream& os) const { ///////////////////////////////////// -TLV8_it TLV8::add(uint8_t tag, size_t len, const uint8_t* val){ +TLV8_itc TLV8::add(uint8_t tag, size_t len, const uint8_t* val) { if(!empty() && back().getTag()==tag) back().update(len,val); @@ -80,7 +80,7 @@ TLV8_it TLV8::add(uint8_t tag, size_t len, const uint8_t* val){ ///////////////////////////////////// -TLV8_it TLV8::add(uint8_t tag, TLV8 &subTLV){ +TLV8_itc TLV8::add(uint8_t tag, TLV8 &subTLV){ auto it=add(tag,subTLV.pack_size(),NULL); // create space for inserting sub TLV and store iterator to new element subTLV.pack(*it); // pack subTLV into new element @@ -89,7 +89,7 @@ TLV8_it TLV8::add(uint8_t tag, TLV8 &subTLV){ ///////////////////////////////////// -TLV8_it TLV8::add(uint8_t tag, uint64_t val){ +TLV8_itc TLV8::add(uint8_t tag, uint64_t val){ uint8_t *p=reinterpret_cast(&val); size_t nBytes=sizeof(uint64_t); @@ -227,7 +227,7 @@ int TLV8::unpack(uint8_t *buf, size_t bufSize){ ///////////////////////////////////// -int TLV8::unpack(TLV8_it it){ +int TLV8::unpack(TLV8_itc it){ if(it==end()) return(0); @@ -297,5 +297,3 @@ void TLV8::osprint(std::ostream& os, TLV8_itc it1, TLV8_itc it2) const { } ////////////////////////////////////// - -TLV8 TLV8::NULL_TLV; diff --git a/src/TLV8.h b/src/TLV8.h index a31f5ad..e51dc62 100644 --- a/src/TLV8.h +++ b/src/TLV8.h @@ -79,7 +79,6 @@ class tlv8_t { ///////////////////////////////////// -typedef std::list>::iterator TLV8_it; typedef std::list>::const_iterator TLV8_itc; typedef struct { const uint8_t tag; const char *name; } TLV8_names; @@ -108,11 +107,11 @@ class TLV8 : public std::list> { TLV8(){}; TLV8(const TLV8_names *names, int nNames) : names{names}, nNames{nNames} {}; - TLV8_it add(uint8_t tag, size_t len, const uint8_t *val); - TLV8_it add(uint8_t tag, uint64_t val); - TLV8_it add(uint8_t tag, TLV8 &subTLV); - TLV8_it add(uint8_t tag){return(add(tag, 0, NULL));} - TLV8_it add(uint8_t tag, const char *val){return(add(tag, strlen(val), reinterpret_cast(val)));} + TLV8_itc add(uint8_t tag, size_t len, const uint8_t *val); + TLV8_itc add(uint8_t tag, uint64_t val); + TLV8_itc add(uint8_t tag, TLV8 &subTLV); + TLV8_itc add(uint8_t tag){return(add(tag, 0, NULL));} + TLV8_itc add(uint8_t tag, const char *val){return(add(tag, strlen(val), reinterpret_cast(val)));} TLV8_itc find(uint8_t tag, TLV8_itc it1, TLV8_itc it2) const; TLV8_itc find(uint8_t tag, TLV8_itc it1) const {return(find(tag, it1, end()));} @@ -142,9 +141,7 @@ class TLV8 : public std::list> { void osprint(std::ostream& os) const {osprint(os, begin(), end());} int unpack(uint8_t *buf, size_t bufSize); - int unpack(TLV8_it it); + int unpack(TLV8_itc it); - void wipe(){std::list>().swap(*this);} - - static TLV8 NULL_TLV; + void wipe() {std::list>().swap(*this);} }; diff --git a/src/src.ino b/src/src.ino index 98d9733..16da73d 100644 --- a/src/src.ino +++ b/src/src.ino @@ -27,6 +27,12 @@ #include "HomeSpan.h" + +CUSTOM_CHAR(TestChar,3F4F,PR+PW,UINT8,20,0,100,false) +CUSTOM_CHAR_STRING(TestString,3F45,PR+EV,"Hello"); +CUSTOM_CHAR_TLV8(TestTLV,4F45,PW+PR); +CUSTOM_CHAR_DATA(TestData,303,PW+PW); + void setup() { Serial.begin(115200); @@ -43,7 +49,31 @@ void setup() { new Characteristic::Identify(); new Service::LightBulb(); new Characteristic::On(); + new Characteristic::TestChar(30); + new Characteristic::TestString(); + new Characteristic::TestString("MyName"); + new Characteristic::TestTLV(); + Characteristic::TestData *testData = new Characteristic::TestData(); + TLV8 myTLV; + + myTLV.add(5,0x20); + myTLV.add(5,0x30); + myTLV.add(1); + myTLV.add(5,255); + + Characteristic::TestTLV *testTLV = new Characteristic::TestTLV(myTLV); + + size_t n=testTLV->getData(NULL,0); + uint8_t buf[n]; + testTLV->getData(buf,n); + + Serial.printf("\n"); + for(int i=0;isetData(buf,0); }