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:
parent
9e0512e48b
commit
b7c294d210
38
src/HAP.cpp
38
src/HAP.cpp
|
|
@ -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,9 +1006,10 @@ 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
|
||||||
int flags=GET_VALUE|GET_AID; // flags indicating which characteristic fields to include in response (HAP Table 6-13)
|
TempBuffer<char *> ids(numIDs); // reserve space for number of IDs found
|
||||||
numIDs=0; // reset 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,' ');
|
char *lastSpace=strchr(urlBuf,' ');
|
||||||
if(lastSpace)
|
if(lastSpace)
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -627,12 +627,9 @@ 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())
|
||||||
}
|
nvs_commit(homeSpan.charNVS); // commit to NVS
|
||||||
else {
|
|
||||||
nvs_set_blob(homeSpan.charNVS,nvsKey,&value,sizeof(UVal)); // store data
|
|
||||||
nvs_commit(homeSpan.charNVS); // commit to NVS
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!nvs_get_str(homeSpan.charNVS,nvsKey,NULL,&len)){
|
if(!nvs_get_str(homeSpan.charNVS,nvsKey,NULL,&len)){
|
||||||
|
|
@ -641,7 +638,7 @@ class SpanCharacteristic{
|
||||||
uvSet(value,(const char *)c);
|
uvSet(value,(const char *)c);
|
||||||
}
|
}
|
||||||
else {
|
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
|
nvs_commit(homeSpan.charNVS); // commit to NVS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
15
src/src.ino
15
src/src.ino
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue