Added native support for WR (write-response)
HAPClient::putCharacteristics() now parses for "r":true in JSON, which is the HAP request for a write-response. When found, HomeSpan will return with a full write-response for all Characteristics updated using "207 Multi-Status", where "value" will be included only if "r":true was specified for a Characteristic. HomeSpan processes "r":true for any Characteristic regardless if permissions includes WR. To change the value of the Characteristic from within an update() method, use setVal() WITH OPTIONAL SECOND ARGUMENT AS FALSE to supress an EV broadcast (in the unlikely event that there was a notification subscriber). To do: Consider generally disallowing the changing of any Characteristic value from within update() using setVal() unless the Characteristic has WR permission. And if so, automatically surpress EV notification.
This commit is contained in:
parent
181c5e99b2
commit
8ce80157b3
|
|
@ -998,10 +998,10 @@ int HAPClient::putCharacteristicsURL(char *json){
|
||||||
if(!homeSpan.updateCharacteristics(json, pObj)) // perform update
|
if(!homeSpan.updateCharacteristics(json, pObj)) // perform update
|
||||||
return(0); // return if failed to update (error message will have been printed in update)
|
return(0); // return if failed to update (error message will have been printed in update)
|
||||||
|
|
||||||
int multiCast=0; // check if all status is OK, or if multicast response is request
|
boolean multiCast=false;
|
||||||
for(int i=0;i<n;i++)
|
for(int i=0;i<n && !multiCast;i++) // for each characterstic, check if any status is either NOT OKAY, or if WRITE-RESPONSE is requested
|
||||||
if(pObj[i].status!=StatusCode::OK)
|
if(pObj[i].status!=StatusCode::OK || pObj[i].wr) // if so, to use multicast response
|
||||||
multiCast=1;
|
multiCast=true;
|
||||||
|
|
||||||
LOG2("\n>>>>>>>>>> %s >>>>>>>>>>\n",client.remoteIP().toString().c_str());
|
LOG2("\n>>>>>>>>>> %s >>>>>>>>>>\n",client.remoteIP().toString().c_str());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1378,6 +1378,9 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
|
||||||
pObj[nObj].ev=t3;
|
pObj[nObj].ev=t3;
|
||||||
okay|=8;
|
okay|=8;
|
||||||
} else
|
} else
|
||||||
|
if(!strcmp(t2,"r") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){
|
||||||
|
pObj[nObj].wr=(t3 && (!strcmp(t3,"1") || !strcmp(t3,"true")));
|
||||||
|
} else
|
||||||
if(!strcmp(t2,"pid") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){
|
if(!strcmp(t2,"pid") && (t3=strtok_r(t1,"}[]:, \"\t\n\r",&p2))){
|
||||||
uint64_t pid=strtoull(t3,NULL,0);
|
uint64_t pid=strtoull(t3,NULL,0);
|
||||||
if(!TimedWrites.count(pid)){
|
if(!TimedWrites.count(pid)){
|
||||||
|
|
@ -1395,7 +1398,9 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
|
||||||
} // parse property tokens
|
} // parse property tokens
|
||||||
|
|
||||||
if(!t1){ // at least one token was found that was not initial "characteristics"
|
if(!t1){ // at least one token was found that was not initial "characteristics"
|
||||||
if(okay==7 || okay==11 || okay==15){ // all required properties found
|
if(okay==7 || okay==11 || okay==15){ // all required properties found
|
||||||
|
if(!pObj[nObj].val) // if value is NOT being updated
|
||||||
|
pObj[nObj].wr=false; // ignore any request for write-response
|
||||||
nObj++; // increment number of characteristic objects found
|
nObj++; // increment number of characteristic objects found
|
||||||
} else {
|
} else {
|
||||||
LOG0("\n*** ERROR: Problems parsing JSON characteristics object - missing required properties\n\n");
|
LOG0("\n*** ERROR: Problems parsing JSON characteristics object - missing required properties\n\n");
|
||||||
|
|
@ -1507,7 +1512,10 @@ void Span::printfAttributes(SpanBuf *pObj, int nObj){
|
||||||
hapOut << "{\"characteristics\":[";
|
hapOut << "{\"characteristics\":[";
|
||||||
|
|
||||||
for(int i=0;i<nObj;i++){
|
for(int i=0;i<nObj;i++){
|
||||||
hapOut << "{\"aid\":" << pObj[i].aid << ",\"iid\":" << pObj[i].iid << ",\"status\":" << (int)pObj[i].status << "}";
|
hapOut << "{\"aid\":" << pObj[i].aid << ",\"iid\":" << pObj[i].iid << ",\"status\":" << (int)pObj[i].status;
|
||||||
|
if(pObj[i].status==StatusCode::OK && pObj[i].wr && pObj[i].characteristic)
|
||||||
|
hapOut << ",\"value\":" << pObj[i].characteristic->uvPrint(pObj[i].characteristic->value).c_str();
|
||||||
|
hapOut << "}";
|
||||||
if(i+1<nObj)
|
if(i+1<nObj)
|
||||||
hapOut << ",";
|
hapOut << ",";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ struct SpanConfig{
|
||||||
struct SpanBuf{ // temporary storage buffer for use with putCharacteristicsURL() and checkTimedResets()
|
struct SpanBuf{ // temporary storage buffer for use with putCharacteristicsURL() and checkTimedResets()
|
||||||
uint32_t aid=0; // updated aid
|
uint32_t aid=0; // updated aid
|
||||||
int iid=0; // updated iid
|
int iid=0; // updated iid
|
||||||
|
boolean wr=false; // flag to indicate write-response has been requested
|
||||||
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)
|
||||||
StatusCode status; // return status (HAP Table 6-11)
|
StatusCode status; // return status (HAP Table 6-11)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue