Change NVS storage for Characteristics to always use nvs_set_u64()

Reduces NVS consumption by from 3 to only 1 records when storing numerical values.

Also:  Fixed memory problem in getCharacteristics by replacing dynamically-sized stack buffers with TempBuffer (must do this everywhere), which was causing stack probllem when combination number of Accessories and number of Characteristics got very large.
This commit is contained in:
Gregg 2023-11-24 09:53:12 -06:00
parent 9e0512e48b
commit b7c294d210
5 changed files with 38 additions and 38 deletions

View File

@ -96,7 +96,7 @@ void HAPClient::init(){
} }
if(!nvs_get_blob(hapNVS,"CONTROLLERS",NULL,&len)){ // if found long-term Controller Pairings data from NVS if(!nvs_get_blob(hapNVS,"CONTROLLERS",NULL,&len)){ // if found long-term Controller Pairings data from NVS
TempBuffer <Controller> tBuf(len/sizeof(Controller)); TempBuffer<Controller> tBuf(len/sizeof(Controller));
nvs_get_blob(hapNVS,"CONTROLLERS",tBuf.get(),&len); // retrieve data nvs_get_blob(hapNVS,"CONTROLLERS",tBuf.get(),&len); // retrieve data
for(int i=0;i<tBuf.size();i++){ for(int i=0;i<tBuf.size();i++){
if(tBuf.get()[i].allocated) if(tBuf.get()[i].allocated)
@ -157,7 +157,7 @@ void HAPClient::processRequest(){
return; return;
} }
TempBuffer <uint8_t> httpBuf(messageSize+1); // leave room for null character added below TempBuffer<uint8_t> httpBuf(messageSize+1); // leave room for null character added below
if(cPair){ // expecting encrypted message if(cPair){ // expecting encrypted message
LOG2("<<<< #### "); LOG2("<<<< #### ");
@ -859,7 +859,7 @@ int HAPClient::getAccessoriesURL(){
LOG1(")...\n"); LOG1(")...\n");
int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON
TempBuffer <char> jBuf(nBytes+1); TempBuffer<char> jBuf(nBytes+1);
homeSpan.sprintfAttributes(jBuf.get()); // create JSON database (will need to re-cast to uint8_t* below) homeSpan.sprintfAttributes(jBuf.get()); // create JSON database (will need to re-cast to uint8_t* below)
char *body; char *body;
@ -958,7 +958,7 @@ int HAPClient::postPairingsURL(){
case 5: { case 5: {
LOG1("List...\n"); LOG1("List...\n");
TempBuffer <uint8_t> tBuf(listControllers(NULL)); TempBuffer<uint8_t> tBuf(listControllers(NULL));
char *body; char *body;
asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/pairing+tlv8\r\nContent-Length: %d\r\n\r\n",tBuf.len()); // create Body with Content Length = size of TLV data asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/pairing+tlv8\r\nContent-Length: %d\r\n\r\n",tBuf.len()); // create Body with Content Length = size of TLV data
@ -1006,7 +1006,8 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
if(urlBuf[i]==',') if(urlBuf[i]==',')
numIDs++; numIDs++;
char *ids[numIDs]; // reserve space for number of IDs found // char *ids[numIDs]; // reserve space for number of IDs found
TempBuffer<char *> ids(numIDs); // reserve space for number of IDs found
int flags=GET_VALUE|GET_AID; // flags indicating which characteristic fields to include in response (HAP Table 6-13) int flags=GET_VALUE|GET_AID; // flags indicating which characteristic fields to include in response (HAP Table 6-13)
numIDs=0; // reset number of IDs found numIDs=0; // reset number of IDs found
@ -1035,7 +1036,7 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
char *p2; char *p2;
while(char *t2=strtok_r(t1,",",&p2)){ // parse IDs while(char *t2=strtok_r(t1,",",&p2)){ // parse IDs
t1=NULL; t1=NULL;
ids[numIDs++]=t2; ids.get()[numIDs++]=t2;
} }
} }
} // parse URL } // parse URL
@ -1043,11 +1044,12 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
if(!numIDs) // could not find any IDs if(!numIDs) // could not find any IDs
return(0); return(0);
int nBytes=homeSpan.sprintfAttributes(ids,numIDs,flags,NULL); // get JSON response - includes terminating null (will be recast to uint8_t* below) int nBytes=homeSpan.sprintfAttributes(ids.get(),numIDs,flags,NULL); // get JSON response - includes terminating null (will be recast to uint8_t* below)
char jsonBuf[nBytes+1]; // char jsonBuf[nBytes+1];
homeSpan.sprintfAttributes(ids,numIDs,flags,jsonBuf); TempBuffer<char> jsonBuf(nBytes+1);
homeSpan.sprintfAttributes(ids.get(),numIDs,flags,jsonBuf.get());
boolean sFlag=strstr(jsonBuf,"status"); // status attribute found? boolean sFlag=strstr(jsonBuf.get(),"status"); // status attribute found?
char *body; char *body;
asprintf(&body,"HTTP/1.1 %s\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",!sFlag?"200 OK":"207 Multi-Status",nBytes); asprintf(&body,"HTTP/1.1 %s\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",!sFlag?"200 OK":"207 Multi-Status",nBytes);
@ -1056,10 +1058,10 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
LOG2(client.remoteIP()); LOG2(client.remoteIP());
LOG2(" >>>>>>>>>>\n"); LOG2(" >>>>>>>>>>\n");
LOG2(body); LOG2(body);
LOG2(jsonBuf); LOG2(jsonBuf.get());
LOG2("\n"); LOG2("\n");
sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t* sendEncrypted(body,(uint8_t *)jsonBuf.get(),nBytes); // note recasting of jsonBuf into uint8_t*
free(body); free(body);
return(1); return(1);
@ -1401,7 +1403,7 @@ void HAPClient::eventNotify(SpanBuf *pObj, int nObj, int ignoreClient){
void HAPClient::tlvRespond(){ void HAPClient::tlvRespond(){
TempBuffer <uint8_t> tBuf(tlv8.pack(NULL)); // create buffer to hold TLV data TempBuffer<uint8_t> tBuf(tlv8.pack(NULL)); // create buffer to hold TLV data
tlv8.pack(tBuf.get()); // pack TLV records into buffer tlv8.pack(tBuf.get()); // pack TLV records into buffer
char *body; char *body;
@ -1441,7 +1443,7 @@ int HAPClient::receiveEncrypted(uint8_t *httpBuf, int messageSize){
return(0); return(0);
} }
TempBuffer <uint8_t> tBuf(n+16); // expected number of total bytes = n bytes in encoded message + 16 bytes for appended authentication tag TempBuffer<uint8_t> tBuf(n+16); // expected number of total bytes = n bytes in encoded message + 16 bytes for appended authentication tag
if(client.read(tBuf.get(),tBuf.len())!=tBuf.len()){ if(client.read(tBuf.get(),tBuf.len())!=tBuf.len()){
LOG0("\n\n*** ERROR: Malformed encrypted message frame\n\n"); LOG0("\n\n*** ERROR: Malformed encrypted message frame\n\n");
@ -1477,7 +1479,7 @@ void HAPClient::sendEncrypted(char *body, uint8_t *dataBuf, int dataLen){
if(maxFrameSize>FRAME_SIZE) // cap maxFrameSize by FRAME_SIZE (HAP restriction) if(maxFrameSize>FRAME_SIZE) // cap maxFrameSize by FRAME_SIZE (HAP restriction)
maxFrameSize=FRAME_SIZE; maxFrameSize=FRAME_SIZE;
TempBuffer <uint8_t> tBuf(2+maxFrameSize+16); // 2-byte AAD + encrytped data + 16-byte authentication tag TempBuffer<uint8_t> tBuf(2+maxFrameSize+16); // 2-byte AAD + encrytped data + 16-byte authentication tag
tBuf.get()[0]=bodyLen%256; // store number of bytes in first frame that encrypts the Body (AAD bytes) tBuf.get()[0]=bodyLen%256; // store number of bytes in first frame that encrypts the Body (AAD bytes)
tBuf.get()[1]=bodyLen/256; tBuf.get()[1]=bodyLen/256;
@ -1704,7 +1706,7 @@ void HAPClient::saveControllers(){
return; return;
} }
TempBuffer <Controller> tBuf(controllerList.size()); // create temporary buffer to hold Controller data TempBuffer<Controller> tBuf(controllerList.size()); // create temporary buffer to hold Controller data
std::copy(controllerList.begin(),controllerList.end(),tBuf.get()); // copy data from linked list to buffer std::copy(controllerList.begin(),controllerList.end(),tBuf.get()); // copy data from linked list to buffer
nvs_set_blob(hapNVS,"CONTROLLERS",tBuf.get(),tBuf.len()); // update data nvs_set_blob(hapNVS,"CONTROLLERS",tBuf.get(),tBuf.len()); // update data

View File

@ -581,7 +581,7 @@ void Span::processSerialCommand(const char *c){
case 'Z': { case 'Z': {
HAPClient::saveControllers(); HAPClient::saveControllers();
break; break;
TempBuffer <uint8_t> tBuf(HAPClient::listControllers(NULL)); TempBuffer<uint8_t> tBuf(HAPClient::listControllers(NULL));
HAPClient::listControllers(tBuf.get()); HAPClient::listControllers(tBuf.get());
Serial.printf("SIZE = %d\n",tBuf.len()); Serial.printf("SIZE = %d\n",tBuf.len());
HAPClient::hexPrintRow(tBuf.get(),tBuf.len()); HAPClient::hexPrintRow(tBuf.get(),tBuf.len());
@ -629,7 +629,7 @@ void Span::processSerialCommand(const char *c){
case 'd': { case 'd': {
TempBuffer <char> qBuf(sprintfAttributes(NULL)+1); TempBuffer<char> qBuf(sprintfAttributes(NULL)+1);
sprintfAttributes(qBuf.get()); sprintfAttributes(qBuf.get());
LOG0("\n*** Attributes Database: size=%d configuration=%d ***\n\n",qBuf.len()-1,hapConfig.configNumber); LOG0("\n*** Attributes Database: size=%d configuration=%d ***\n\n",qBuf.len()-1,hapConfig.configNumber);
@ -1452,7 +1452,7 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
pObj[j].characteristic->uvSet(pObj[j].characteristic->value,pObj[j].characteristic->newValue); // update characteristic value with new value pObj[j].characteristic->uvSet(pObj[j].characteristic->value,pObj[j].characteristic->newValue); // update characteristic value with new value
if(pObj[j].characteristic->nvsKey){ // if storage key found if(pObj[j].characteristic->nvsKey){ // if storage key found
if(pObj[j].characteristic->format!=FORMAT::STRING && pObj[j].characteristic->format!=FORMAT::DATA) if(pObj[j].characteristic->format!=FORMAT::STRING && pObj[j].characteristic->format!=FORMAT::DATA)
nvs_set_blob(charNVS,pObj[j].characteristic->nvsKey,&(pObj[j].characteristic->value),sizeof(pObj[j].characteristic->value)); // store data nvs_set_u64(charNVS,pObj[j].characteristic->nvsKey,pObj[j].characteristic->value.UINT64); // store data as uint64_t regardless of actual type (it will be read correctly when access through uvGet())
else else
nvs_set_str(charNVS,pObj[j].characteristic->nvsKey,pObj[j].characteristic->value.STRING); // store data nvs_set_str(charNVS,pObj[j].characteristic->nvsKey,pObj[j].characteristic->value.STRING); // store data
nvs_commit(charNVS); nvs_commit(charNVS);
@ -1595,7 +1595,7 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
boolean Span::updateDatabase(boolean updateMDNS){ boolean Span::updateDatabase(boolean updateMDNS){
uint8_t tHash[48]; uint8_t tHash[48];
TempBuffer <char> tBuf(sprintfAttributes(NULL,GET_META|GET_PERMS|GET_TYPE|GET_DESC)+1); TempBuffer<char> tBuf(sprintfAttributes(NULL,GET_META|GET_PERMS|GET_TYPE|GET_DESC)+1);
sprintfAttributes(tBuf.get(),GET_META|GET_PERMS|GET_TYPE|GET_DESC); sprintfAttributes(tBuf.get(),GET_META|GET_PERMS|GET_TYPE|GET_DESC);
mbedtls_sha512_ret((uint8_t *)tBuf.get(),tBuf.len(),tHash,1); // create SHA-384 hash of JSON (can be any hash - just looking for a unique key) mbedtls_sha512_ret((uint8_t *)tBuf.get(),tBuf.len(),tHash,1); // create SHA-384 hash of JSON (can be any hash - just looking for a unique key)

View File

@ -627,11 +627,8 @@ class SpanCharacteristic{
size_t len; size_t len;
if(format!=FORMAT::STRING && format!=FORMAT::DATA){ if(format!=FORMAT::STRING && format!=FORMAT::DATA){
if(!nvs_get_blob(homeSpan.charNVS,nvsKey,NULL,&len)){ if(nvs_get_u64(homeSpan.charNVS,nvsKey,&(value.UINT64))!=ESP_OK) {
nvs_get_blob(homeSpan.charNVS,nvsKey,&value,&len); nvs_set_u64(homeSpan.charNVS,nvsKey,value.UINT64); // store data as uint64_t regardless of actual type (it will be read correctly when access through uvGet())
}
else {
nvs_set_blob(homeSpan.charNVS,nvsKey,&value,sizeof(UVal)); // store data
nvs_commit(homeSpan.charNVS); // commit to NVS nvs_commit(homeSpan.charNVS); // commit to NVS
} }
} else { } else {
@ -790,7 +787,7 @@ class SpanCharacteristic{
homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector
if(nvsKey){ if(nvsKey){
nvs_set_blob(homeSpan.charNVS,nvsKey,&value,sizeof(UVal)); // store data nvs_set_u64(homeSpan.charNVS,nvsKey,value.UINT64); // store data as uint64_t regardless of actual type (it will be read correctly when access through uvGet())
nvs_commit(homeSpan.charNVS); nvs_commit(homeSpan.charNVS);
} }
} }

View File

@ -184,7 +184,7 @@ void Network::apConfigure(){
continue; continue;
} }
TempBuffer <uint8_t> httpBuf(messageSize+1); // leave room for null character added below TempBuffer<uint8_t> httpBuf(messageSize+1); // leave room for null character added below
int nBytes=client.read(httpBuf.get(),messageSize); // read all available bytes up to maximum allowed+1 int nBytes=client.read(httpBuf.get(),messageSize); // read all available bytes up to maximum allowed+1

View File

@ -32,10 +32,9 @@ void setup() {
Serial.begin(115200); Serial.begin(115200);
homeSpan.setLogLevel(2) homeSpan.setLogLevel(2);
.enableWebLog(500,"pool.ntp.org","UTC") // homeSpan.enableWebLog(500,"pool.ntp.org","UTC");
.setWifiCallback(wifiEstablished) // homeSpan.setWifiCallback(wifiEstablished);
;
homeSpan.begin(Category::Lighting,"HomeSpan Max"); homeSpan.begin(Category::Lighting,"HomeSpan Max");
@ -43,7 +42,7 @@ void setup() {
ps_new(Service::AccessoryInformation)(); ps_new(Service::AccessoryInformation)();
ps_new(Characteristic::Identify)(); ps_new(Characteristic::Identify)();
for(int i=0;i<100;i++){ for(int i=0;i<149;i++){
ps_new(SpanAccessory)(); ps_new(SpanAccessory)();
ps_new(Service::AccessoryInformation)(); ps_new(Service::AccessoryInformation)();
ps_new(Characteristic::Identify)(); ps_new(Characteristic::Identify)();
@ -51,8 +50,10 @@ void setup() {
sprintf(c,"Light-%d",i); sprintf(c,"Light-%d",i);
ps_new(Characteristic::Name)(c); ps_new(Characteristic::Name)(c);
ps_new(Service::LightBulb)(); ps_new(Service::LightBulb)();
ps_new(Characteristic::On)(); ps_new(Characteristic::On)(0,true);
ps_new(Characteristic::Brightness)(50,false); ps_new(Characteristic::Brightness)(50,true);
ps_new(Characteristic::Hue)(120,true);
ps_new(Characteristic::Saturation)(100,true);
} }
} }