Added ability to specify "aid" for Accessories

If not specified, "aid" defaults to an index number representing the order in which the Accessories were created.   Values are stored as uint32_t  (which is more limited than HAP requirements of uint64_t, but makes the code easier).

TO DO:  Must add validation to ensure duplicate aid values are not used.
This commit is contained in:
Gregg 2020-12-05 12:41:33 -06:00
parent da489b4d94
commit 1847478252
2 changed files with 42 additions and 31 deletions

View File

@ -649,14 +649,14 @@ void Span::processSerialCommand(char *c){
char d[]="------------------------------"; char d[]="------------------------------";
char cBuf[256]; char cBuf[256];
sprintf(cBuf,"%-30s %s %s %s %s %s %s\n","Service","Type","AID","IID","Update","Loop","Button"); sprintf(cBuf,"%-30s %s %10s %s %s %s %s\n","Service","Type","AID","IID","Update","Loop","Button");
Serial.print(cBuf); Serial.print(cBuf);
sprintf(cBuf,"%.30s %.4s %.3s %.3s %.6s %.4s %.6s\n",d,d,d,d,d,d,d); sprintf(cBuf,"%.30s %.4s %.10s %.3s %.6s %.4s %.6s\n",d,d,d,d,d,d,d);
Serial.print(cBuf); Serial.print(cBuf);
for(int i=0;i<Accessories.size();i++){ // identify all services with over-ridden loop() methods for(int i=0;i<Accessories.size();i++){ // identify all services with over-ridden loop() methods
for(int j=0;j<Accessories[i]->Services.size();j++){ for(int j=0;j<Accessories[i]->Services.size();j++){
SpanService *s=Accessories[i]->Services[j]; SpanService *s=Accessories[i]->Services[j];
sprintf(cBuf,"%-30s %4s %3d %3d %6s %4s %6s\n",s->hapName,s->type,Accessories[i]->aid,s->iid, sprintf(cBuf,"%-30s %4s %10u %3d %6s %4s %6s\n",s->hapName,s->type,Accessories[i]->aid,s->iid,
(void(*)())(s->*(&SpanService::update))!=(void(*)())(&SpanService::update)?"YES":"NO", (void(*)())(s->*(&SpanService::update))!=(void(*)())(&SpanService::update)?"YES":"NO",
(void(*)())(s->*(&SpanService::loop))!=(void(*)())(&SpanService::loop)?"YES":"NO", (void(*)())(s->*(&SpanService::loop))!=(void(*)())(&SpanService::loop)?"YES":"NO",
(void(*)(int,boolean))(s->*(&SpanService::button))!=(void(*)(int,boolean))(&SpanService::button)?"YES":"NO" (void(*)(int,boolean))(s->*(&SpanService::button))!=(void(*)(int,boolean))(&SpanService::button)?"YES":"NO"
@ -767,22 +767,28 @@ void Span::prettyPrint(char *buf, int nsp){
/////////////////////////////// ///////////////////////////////
SpanCharacteristic *Span::find(int aid, int iid){ SpanCharacteristic *Span::find(uint32_t aid, int iid){
if(aid<1 || aid>Accessories.size()) // aid out of range int index=-1;
return(NULL); for(int i=0;i<Accessories.size();i++){ // loop over all Accessories to find aid
if(Accessories[i]->aid==aid){ // if match, save index into Accessories array
aid--; // convert from aid to array index number index=i;
break;
for(int i=0;i<Accessories[aid]->Services.size();i++){ // loop over all Services in this Accessory
for(int j=0;j<Accessories[aid]->Services[i]->Characteristics.size();j++){ // loop over all Characteristics in this Service
if(iid == Accessories[aid]->Services[i]->Characteristics[j]->iid) // if matching iid
return(Accessories[aid]->Services[i]->Characteristics[j]); // return pointer to Characteristic
} }
} }
return(NULL); if(index<0) // fail if no match on aid
return(NULL);
for(int i=0;i<Accessories[index]->Services.size();i++){ // loop over all Services in this Accessory
for(int j=0;j<Accessories[index]->Services[i]->Characteristics.size();j++){ // loop over all Characteristics in this Service
if(iid == Accessories[index]->Services[i]->Characteristics[j]->iid) // if matching iid
return(Accessories[index]->Services[i]->Characteristics[j]); // return pointer to Characteristic
}
}
return(NULL); // fail if no match on iid
} }
/////////////////////////////// ///////////////////////////////
@ -828,7 +834,7 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
t1=NULL; t1=NULL;
char *t3; char *t3;
if(!strcmp(t2,"aid") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){ if(!strcmp(t2,"aid") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){
pObj[nObj].aid=atoi(t3); sscanf(t3,"%u",&pObj[nObj].aid);
okay|=1; okay|=1;
} else } else
if(!strcmp(t2,"iid") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){ if(!strcmp(t2,"iid") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){
@ -974,7 +980,7 @@ int Span::sprintfAttributes(SpanBuf *pObj, int nObj, char *cBuf){
nChars+=snprintf(cBuf,cBuf?64:0,"{\"characteristics\":["); nChars+=snprintf(cBuf,cBuf?64:0,"{\"characteristics\":[");
for(int i=0;i<nObj;i++){ for(int i=0;i<nObj;i++){
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?128:0,"{\"aid\":%d,\"iid\":%d,\"status\":%d}",pObj[i].aid,pObj[i].iid,pObj[i].status); nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?128:0,"{\"aid\":%u,\"iid\":%d,\"status\":%d}",pObj[i].aid,pObj[i].iid,pObj[i].status);
if(i+1<nObj) if(i+1<nObj)
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,","); nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,",");
} }
@ -989,14 +995,15 @@ int Span::sprintfAttributes(SpanBuf *pObj, int nObj, char *cBuf){
int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
int nChars=0; int nChars=0;
int aid, iid; uint32_t aid;
int iid;
SpanCharacteristic *Characteristics[numIDs]; SpanCharacteristic *Characteristics[numIDs];
StatusCode status[numIDs]; StatusCode status[numIDs];
boolean sFlag=false; boolean sFlag=false;
for(int i=0;i<numIDs;i++){ // PASS 1: loop over all ids requested to check status codes - only errors are if characteristic not found, or not readable for(int i=0;i<numIDs;i++){ // PASS 1: loop over all ids requested to check status codes - only errors are if characteristic not found, or not readable
sscanf(ids[i],"%d.%d",&aid,&iid); // parse aid and iid sscanf(ids[i],"%u.%d",&aid,&iid); // parse aid and iid
Characteristics[i]=find(aid,iid); // find matching chararacteristic Characteristics[i]=find(aid,iid); // find matching chararacteristic
if(Characteristics[i]){ // if found if(Characteristics[i]){ // if found
@ -1020,8 +1027,8 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
if(Characteristics[i]) // if found if(Characteristics[i]) // if found
nChars+=Characteristics[i]->sprintfAttributes(cBuf?(cBuf+nChars):NULL,flags); // get JSON attributes for characteristic nChars+=Characteristics[i]->sprintfAttributes(cBuf?(cBuf+nChars):NULL,flags); // get JSON attributes for characteristic
else{ else{
sscanf(ids[i],"%d.%d",&aid,&iid); // parse aid and iid sscanf(ids[i],"%u.%d",&aid,&iid); // parse aid and iid
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,"{\"iid\":%d,\"aid\":%d}",iid,aid); // else create JSON attributes based on requested aid/iid nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,"{\"iid\":%d,\"aid\":%u}",iid,aid); // else create JSON attributes based on requested aid/iid
} }
if(sFlag){ // status flag is needed - overlay at end if(sFlag){ // status flag is needed - overlay at end
@ -1043,7 +1050,7 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
// SpanAccessory // // SpanAccessory //
/////////////////////////////// ///////////////////////////////
SpanAccessory::SpanAccessory(){ SpanAccessory::SpanAccessory(uint32_t aid){
if(!homeSpan.Accessories.empty()){ if(!homeSpan.Accessories.empty()){
@ -1054,9 +1061,13 @@ SpanAccessory::SpanAccessory(){
} }
homeSpan.Accessories.push_back(this); homeSpan.Accessories.push_back(this);
aid=homeSpan.Accessories.size();
if(aid==0)
this->aid=homeSpan.Accessories.size();
else
this->aid=aid;
homeSpan.configLog+="+Accessory-" + String(aid) + "\n"; homeSpan.configLog+="+Accessory-" + String(this->aid) + "\n";
} }
/////////////////////////////// ///////////////////////////////
@ -1093,7 +1104,7 @@ void SpanAccessory::validate(){
int SpanAccessory::sprintfAttributes(char *cBuf){ int SpanAccessory::sprintfAttributes(char *cBuf){
int nBytes=0; int nBytes=0;
nBytes+=snprintf(cBuf,cBuf?64:0,"{\"aid\":%d,\"services\":[",aid); nBytes+=snprintf(cBuf,cBuf?64:0,"{\"aid\":%u,\"services\":[",aid);
for(int i=0;i<Services.size();i++){ for(int i=0;i<Services.size();i++){
nBytes+=Services[i]->sprintfAttributes(cBuf?(cBuf+nBytes):NULL); nBytes+=Services[i]->sprintfAttributes(cBuf?(cBuf+nBytes):NULL);
@ -1380,7 +1391,7 @@ int SpanCharacteristic::sprintfAttributes(char *cBuf, int flags){
} }
if(flags&GET_AID) if(flags&GET_AID)
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"aid\":%d",aid); nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"aid\":%u",aid);
if(flags&GET_EV) if(flags&GET_EV)
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"ev\":%s",ev[HAPClient::conNum]?"true":"false"); nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"ev\":%s",ev[HAPClient::conNum]?"true":"false");

View File

@ -118,7 +118,7 @@ struct Span{
int sprintfAttributes(char *cBuf); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL int sprintfAttributes(char *cBuf); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL
void prettyPrint(char *buf, int nsp=2); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces void prettyPrint(char *buf, int nsp=2); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces
SpanCharacteristic *find(int aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found) SpanCharacteristic *find(uint32_t aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found)
int countCharacteristics(char *buf); // return number of characteristic objects referenced in PUT /characteristics JSON request int countCharacteristics(char *buf); // return number of characteristic objects referenced in PUT /characteristics JSON request
int updateCharacteristics(char *buf, SpanBuf *pObj); // parses PUT /characteristics JSON request 'buf into 'pObj' and updates referenced characteristics; returns 1 on success, 0 on fail int updateCharacteristics(char *buf, SpanBuf *pObj); // parses PUT /characteristics JSON request 'buf into 'pObj' and updates referenced characteristics; returns 1 on success, 0 on fail
@ -142,11 +142,11 @@ struct Span{
struct SpanAccessory{ struct SpanAccessory{
int aid=0; // Accessory Instance ID (HAP Table 6-1) uint32_t aid=0; // Accessory Instance ID (HAP Table 6-1)
int iidCount=0; // running count of iid to use for Services and Characteristics associated with this Accessory int iidCount=0; // running count of iid to use for Services and Characteristics associated with this Accessory
vector<SpanService *> Services; // vector of pointers to all Services in this Accessory vector<SpanService *> Services; // vector of pointers to all Services in this Accessory
SpanAccessory(); SpanAccessory(uint32_t aid=0);
int sprintfAttributes(char *cBuf); // prints Accessory JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL int sprintfAttributes(char *cBuf); // prints Accessory JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL
void validate(); // error-checks Accessory void validate(); // error-checks Accessory
@ -225,7 +225,7 @@ struct SpanCharacteristic{
SpanRange *range=NULL; // Characteristic min/max/step; NULL = default values (optional) SpanRange *range=NULL; // Characteristic min/max/step; NULL = default values (optional)
boolean *ev; // Characteristic Event Notify Enable (per-connection) boolean *ev; // Characteristic Event Notify Enable (per-connection)
int aid=0; // Accessory ID - passed through from Service containing this Characteristic uint32_t aid=0; // Accessory ID - passed through from Service containing this Characteristic
boolean isUpdated=false; // set to true when new value has been requested by PUT /characteristic boolean isUpdated=false; // set to true when new value has been requested by PUT /characteristic
unsigned long updateTime; // last time value was updated (in millis) either by PUT /characteristic OR by setVal() unsigned long updateTime; // last time value was updated (in millis) either by PUT /characteristic OR by setVal()
UVal newValue; // the updated value requested by PUT /characteristic UVal newValue; // the updated value requested by PUT /characteristic
@ -295,7 +295,7 @@ struct SpanRange{
/////////////////////////////// ///////////////////////////////
struct SpanBuf{ // temporary storage buffer for use with putCharacteristicsURL() and checkTimedResets() struct SpanBuf{ // temporary storage buffer for use with putCharacteristicsURL() and checkTimedResets()
int aid=0; // updated aid uint32_t aid=0; // updated aid
int iid=0; // updated iid int iid=0; // updated iid
char *val=NULL; // updated value (optional, though either at least 'val' or 'ev' must be specified) char *val=NULL; // updated value (optional, though either at least 'val' or 'ev' must be specified)
char *ev=NULL; // updated event notification flag (optional, though either at least 'val' or 'ev' must be specified) char *ev=NULL; // updated event notification flag (optional, though either at least 'val' or 'ev' must be specified)