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
TempBuffer <Controller> tBuf(len/sizeof(Controller));
TempBuffer<Controller> tBuf(len/sizeof(Controller));
nvs_get_blob(hapNVS,"CONTROLLERS",tBuf.get(),&len); // retrieve data
for(int i=0;i<tBuf.size();i++){
if(tBuf.get()[i].allocated)
@ -157,7 +157,7 @@ void HAPClient::processRequest(){
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
LOG2("<<<< #### ");
@ -859,7 +859,7 @@ int HAPClient::getAccessoriesURL(){
LOG1(")...\n");
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)
char *body;
@ -958,7 +958,7 @@ int HAPClient::postPairingsURL(){
case 5: {
LOG1("List...\n");
TempBuffer <uint8_t> tBuf(listControllers(NULL));
TempBuffer<uint8_t> tBuf(listControllers(NULL));
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
@ -1006,9 +1006,10 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
if(urlBuf[i]==',')
numIDs++;
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)
numIDs=0; // reset 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)
numIDs=0; // reset number of IDs found
char *lastSpace=strchr(urlBuf,' ');
if(lastSpace)
@ -1035,7 +1036,7 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
char *p2;
while(char *t2=strtok_r(t1,",",&p2)){ // parse IDs
t1=NULL;
ids[numIDs++]=t2;
ids.get()[numIDs++]=t2;
}
}
} // parse URL
@ -1043,11 +1044,12 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
if(!numIDs) // could not find any IDs
return(0);
int nBytes=homeSpan.sprintfAttributes(ids,numIDs,flags,NULL); // get JSON response - includes terminating null (will be recast to uint8_t* below)
char jsonBuf[nBytes+1];
homeSpan.sprintfAttributes(ids,numIDs,flags,jsonBuf);
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];
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;
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(" >>>>>>>>>>\n");
LOG2(body);
LOG2(jsonBuf);
LOG2(jsonBuf.get());
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);
return(1);
@ -1401,7 +1403,7 @@ void HAPClient::eventNotify(SpanBuf *pObj, int nObj, int ignoreClient){
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
char *body;
@ -1441,7 +1443,7 @@ int HAPClient::receiveEncrypted(uint8_t *httpBuf, int messageSize){
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()){
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)
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()[1]=bodyLen/256;
@ -1704,7 +1706,7 @@ void HAPClient::saveControllers(){
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
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': {
HAPClient::saveControllers();
break;
TempBuffer <uint8_t> tBuf(HAPClient::listControllers(NULL));
TempBuffer<uint8_t> tBuf(HAPClient::listControllers(NULL));
HAPClient::listControllers(tBuf.get());
Serial.printf("SIZE = %d\n",tBuf.len());
HAPClient::hexPrintRow(tBuf.get(),tBuf.len());
@ -629,7 +629,7 @@ void Span::processSerialCommand(const char *c){
case 'd': {
TempBuffer <char> qBuf(sprintfAttributes(NULL)+1);
TempBuffer<char> qBuf(sprintfAttributes(NULL)+1);
sprintfAttributes(qBuf.get());
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
if(pObj[j].characteristic->nvsKey){ // if storage key found
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
nvs_set_str(charNVS,pObj[j].characteristic->nvsKey,pObj[j].characteristic->value.STRING); // store data
nvs_commit(charNVS);
@ -1595,7 +1595,7 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
boolean Span::updateDatabase(boolean updateMDNS){
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);
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,12 +627,9 @@ class SpanCharacteristic{
size_t len;
if(format!=FORMAT::STRING && format!=FORMAT::DATA){
if(!nvs_get_blob(homeSpan.charNVS,nvsKey,NULL,&len)){
nvs_get_blob(homeSpan.charNVS,nvsKey,&value,&len);
}
else {
nvs_set_blob(homeSpan.charNVS,nvsKey,&value,sizeof(UVal)); // store data
nvs_commit(homeSpan.charNVS); // commit to NVS
if(nvs_get_u64(homeSpan.charNVS,nvsKey,&(value.UINT64))!=ESP_OK) {
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); // commit to NVS
}
} else {
if(!nvs_get_str(homeSpan.charNVS,nvsKey,NULL,&len)){
@ -641,7 +638,7 @@ class SpanCharacteristic{
uvSet(value,(const char *)c);
}
else {
nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store string data
nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store string data
nvs_commit(homeSpan.charNVS); // commit to NVS
}
}
@ -790,7 +787,7 @@ class SpanCharacteristic{
homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector
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);
}
}

View File

@ -184,7 +184,7 @@ void Network::apConfigure(){
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

View File

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