Added "C" CLI command and updated/fixed config number logic

The "C" command computes a hash of the current database config and updates the config number if needed.  If config number has changed, the MDNS "c#" record is updated and the new config number is rebroadcast.  This triggers HomeKit to immediately request an update of the HAP database so that the changes can be shortly reflected in the Home App without the need to close any Client connections or reboot the device.

The config number logic has also been updated/fixed.  Previously it would create a hash from the full HAP database, which includes the value of each characteristic.  Thus, initial value changes of Characteristics, as a result of stored values in NVS, would cause an update to the config number upon reboot.
 This is not problematic, but also not intended, as a change in value is not really a change in the database config.  The new logic computes a hash of the database that EXCLUDES all Characteristic values.
This commit is contained in:
Gregg 2022-05-06 17:04:15 -05:00
parent 628c29c6b6
commit 7546350775
3 changed files with 43 additions and 30 deletions

View File

@ -142,34 +142,14 @@ void HAPClient::init(){
nvs_get_blob(hapNVS,"HAPHASH",&homeSpan.hapConfig,&len); // retrieve data
} else {
Serial.print("Resetting Accessory Configuration number...\n");
nvs_set_blob(hapNVS,"HAPHASH",&homeSpan.hapConfig,sizeof(homeSpan.hapConfig)); // update data
nvs_set_blob(hapNVS,"HAPHASH",&homeSpan.hapConfig,sizeof(homeSpan.hapConfig)); // save data (will default to all zero values, which will then be updated below)
nvs_commit(hapNVS); // commit to NVS
}
Serial.print("\n");
uint8_t tHash[48];
TempBuffer <char> tBuf(homeSpan.sprintfAttributes(NULL,GET_META|GET_PERMS|GET_TYPE|GET_DESC)+1);
homeSpan.sprintfAttributes(tBuf.buf,GET_META|GET_PERMS|GET_TYPE|GET_DESC);
mbedtls_sha512_ret((uint8_t *)tBuf.buf,tBuf.len(),tHash,1); // create SHA-384 hash of JSON (can be any hash - just looking for a unique key)
if(memcmp(tHash,homeSpan.hapConfig.hashCode,48)){ // if hash code of current HAP database does not match stored hash code
memcpy(homeSpan.hapConfig.hashCode,tHash,48); // update stored hash code
homeSpan.hapConfig.configNumber++; // increment configuration number
if(homeSpan.hapConfig.configNumber==65536) // reached max value
homeSpan.hapConfig.configNumber=1; // reset to 1
Serial.print("Accessory configuration has changed. Updating configuration number to ");
Serial.print(homeSpan.hapConfig.configNumber);
Serial.print("\n\n");
nvs_set_blob(hapNVS,"HAPHASH",&homeSpan.hapConfig,sizeof(homeSpan.hapConfig)); // update data
nvs_commit(hapNVS); // commit to NVS
} else {
Serial.print("Accessory configuration number: ");
Serial.print(homeSpan.hapConfig.configNumber);
Serial.print("\n\n");
}
homeSpan.updateConfigNum();
for(int i=0;i<homeSpan.Accessories.size();i++){ // identify all services with over-ridden loop() methods
for(int j=0;j<homeSpan.Accessories[i]->Services.size();j++){
SpanService *s=homeSpan.Accessories[i]->Services[j];

View File

@ -899,14 +899,13 @@ void Span::processSerialCommand(const char *c){
}
break;
case 'C': {
char cNum[16];
sprintf(cNum,"%d",++hapConfig.configNumber);
mdns_service_txt_item_set("_hap","_tcp","c#",cNum); // Accessory Current Configuration Number (updated whenever config of HAP Accessory Attribute Database is updated)
Serial.printf("\n*** Configuration number updated to: %d\n\n",hapConfig.configNumber);
if(updateConfigNum()){ // if config number changed, update MDNS record
char cNum[16];
sprintf(cNum,"%d",hapConfig.configNumber);
mdns_service_txt_item_set("_hap","_tcp","c#",cNum);
}
}
break;
@ -1055,7 +1054,8 @@ void Span::processSerialCommand(const char *c){
Serial.print(" S <code> - change the HomeKit Pairing Setup Code to <code>\n");
Serial.print(" Q <id> - change the HomeKit Setup ID for QR Codes to <id>\n");
Serial.print(" O - change the OTA password\n");
Serial.print(" A - start the HomeSpan Setup Access Point\n");
Serial.print(" A - start the HomeSpan Setup Access Point\n");
Serial.print(" C - update database configuration number\n");
Serial.print("\n");
Serial.print(" V - delete value settings for all saved Characteristics\n");
Serial.print(" U - unpair device by deleting all Controller data\n");
@ -1459,6 +1459,38 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
return(nChars);
}
///////////////////////////////
boolean Span::updateConfigNum(){
uint8_t tHash[48];
TempBuffer <char> tBuf(sprintfAttributes(NULL,GET_META|GET_PERMS|GET_TYPE|GET_DESC)+1);
sprintfAttributes(tBuf.buf,GET_META|GET_PERMS|GET_TYPE|GET_DESC);
mbedtls_sha512_ret((uint8_t *)tBuf.buf,tBuf.len(),tHash,1); // create SHA-384 hash of JSON (can be any hash - just looking for a unique key)
boolean changed=false;
if(memcmp(tHash,hapConfig.hashCode,48)){ // if hash code of current HAP database does not match stored hash code
memcpy(hapConfig.hashCode,tHash,48); // update stored hash code
hapConfig.configNumber++; // increment configuration number
if(hapConfig.configNumber==65536) // reached max value
hapConfig.configNumber=1; // reset to 1
Serial.print("Accessory configuration has changed. Updating configuration number to ");
Serial.print(hapConfig.configNumber);
Serial.print("\n\n");
nvs_set_blob(HAPClient::hapNVS,"HAPHASH",&hapConfig,sizeof(hapConfig)); // update data
nvs_commit(HAPClient::hapNVS); // commit to NVS
changed=true;
} else {
Serial.print("Accessory configuration number: ");
Serial.print(hapConfig.configNumber);
Serial.print("\n\n");
}
return(changed);
}
///////////////////////////////
// SpanAccessory //
///////////////////////////////

View File

@ -214,6 +214,7 @@ struct Span{
void checkConnect(); // check WiFi connection; connect if needed
void commandMode(); // allows user to control and reset HomeSpan settings with the control button
void processSerialCommand(const char *c); // process command 'c' (typically from readSerial, though can be called with any 'c')
boolean updateConfigNum(); // updates HAP configuration number (MDNS 'c#' record) if hash of current config database is different from previously-stored hash; returns true if config number changed
int sprintfAttributes(char *cBuf, int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator