diff --git a/src/HAP.cpp b/src/HAP.cpp index 5a2c703..b002c82 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -898,7 +898,7 @@ int HAPClient::getAccessoriesURL(){ return(0); } - LOG1("In Get Accessories #%d (%s)...",conNum,client.remoteIP().toString().c_str()); + LOG1("In Get Accessories #%d (%s)...\n",conNum,client.remoteIP().toString().c_str()); homeSpan.printfAttributes(); size_t nBytes=hapOut.getSize(); @@ -926,19 +926,15 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){ return(0); } - LOG1("In Get Characteristics #"); - LOG1(conNum); - LOG1(" ("); - LOG1(client.remoteIP()); - LOG1(")...\n"); + LOG1("In Get Characteristics #%d (%s)...\n",conNum,client.remoteIP().toString().c_str()); - int len=strlen(urlBuf); // determine number of IDs specificed by counting commas in URL + int len=strlen(urlBuf); // determine number of IDs specified by counting commas in URL int numIDs=1; for(int i=0;i ids(numIDs); // reserve space for number of IDs found + TempBuffer 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 @@ -975,24 +971,16 @@ 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) - TempBuffer jsonBuf(nBytes+1); - homeSpan.sprintfAttributes(ids,numIDs,flags,jsonBuf); + boolean statusFlag=homeSpan.printfAttributes(ids,numIDs,flags); // get statusFlag returned to use below + size_t nBytes=hapOut.getSize(); + hapOut.flush(); - boolean sFlag=strstr(jsonBuf,"status"); // status attribute found? + hapOut.setLogLevel(2).setHapClient(this); + hapOut << "HTTP/1.1 " << (!statusFlag?"200 OK":"207 Multi-Status") << "\r\nContent-Type: application/hap+json\r\nContent-Length: " << nBytes << "\r\n\r\n"; + homeSpan.printfAttributes(ids,numIDs,flags); + hapOut.flush(); - 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); - - LOG2("\n>>>>>>>>>> "); - LOG2(client.remoteIP()); - LOG2(" >>>>>>>>>>\n"); - LOG2(body); - LOG2(jsonBuf.get()); - LOG2("\n"); - - sendEncrypted(body,(uint8_t *)jsonBuf.get(),nBytes); // note recasting of jsonBuf into uint8_t* - free(body); + LOG2("\n-------- SENT ENCRYPTED! --------\n"); return(1); } @@ -1006,11 +994,7 @@ int HAPClient::putCharacteristicsURL(char *json){ return(0); } - LOG1("In Put Characteristics #"); - LOG1(conNum); - LOG1(" ("); - LOG1(client.remoteIP()); - LOG1(")...\n"); + LOG1("In Put Characteristics #%d (%s)...\n",conNum,client.remoteIP().toString().c_str()); int n=homeSpan.countCharacteristics(json); // count number of objects in JSON request if(n==0) // if no objects found, return @@ -1025,38 +1009,28 @@ int HAPClient::putCharacteristicsURL(char *json){ if(pObj[i].status!=StatusCode::OK) multiCast=1; + LOG2("\n>>>>>>>>>> %s >>>>>>>>>>\n",client.remoteIP().toString().c_str()); + if(!multiCast){ // JSON object has no content - - char body[]="HTTP/1.1 204 No Content\r\n\r\n"; - - LOG2("\n>>>>>>>>>> "); - LOG2(client.remoteIP()); - LOG2(" >>>>>>>>>>\n"); - LOG2(body); - sendEncrypted(body,NULL,0); + hapOut.setLogLevel(2).setHapClient(this); + hapOut << "HTTP/1.1 204 No Content\r\n\r\n"; + hapOut.flush(); - } else { // multicast respose is required + } else { // multicast respose is required - int nBytes=homeSpan.sprintfAttributes(pObj,n,NULL); // get JSON response - includes terminating null (will be recast to uint8_t* below) - TempBuffer jsonBuf(nBytes+1); - homeSpan.sprintfAttributes(pObj,n,jsonBuf); - - char *body; - asprintf(&body,"HTTP/1.1 207 Multi-Status\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes); - - LOG2("\n>>>>>>>>>> "); - LOG2(client.remoteIP()); - LOG2(" >>>>>>>>>>\n"); - LOG2(body); - LOG2(jsonBuf.get()); - LOG2("\n"); - - sendEncrypted(body,(uint8_t *)jsonBuf.get(),nBytes); // note recasting of jsonBuf into uint8_t* - free(body); + homeSpan.printfAttributes(pObj,n); + size_t nBytes=hapOut.getSize(); + hapOut.flush(); + hapOut.setLogLevel(2).setHapClient(this); + hapOut << "HTTP/1.1 207 Multi-Status\r\nContent-Type: application/hap+json\r\nContent-Length: " << nBytes << "\r\n\r\n"; + homeSpan.printfAttributes(pObj,n); + hapOut.flush(); } + LOG2("\n-------- SENT ENCRYPTED! --------\n"); + // Create and send Event Notifications if needed eventNotify(pObj,n,HAPClient::conNum); // transmit EVENT Notification for "n" pObj objects, except DO NOT notify client making request diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 44e4ef5..f514d40 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -1516,77 +1516,65 @@ void Span::printfNotify(SpanBuf *pObj, int nObj, int conNum){ /////////////////////////////// -int Span::sprintfAttributes(SpanBuf *pObj, int nObj, char *cBuf){ +void Span::printfAttributes(SpanBuf *pObj, int nObj){ - int nChars=0; - - nChars+=snprintf(cBuf,cBuf?64:0,"{\"characteristics\":["); + hapOut << "{\"characteristics\":["; for(int i=0;iperms&PERMS::PR){ // if permissions allow reading - status[i]=StatusCode::OK; // always set status to OK (since no actual reading of device is needed) + if(Characteristics[i]){ // if found + if(Characteristics[i]->perms&PERMS::PR){ // if permissions allow reading + status[i]=StatusCode::OK; // always set status to OK (since no actual reading of device is needed) } else { - Characteristics[i]=NULL; + Characteristics[i]=NULL; // set to NULL to trigger not-found in Pass 2 below status[i]=StatusCode::WriteOnly; - sFlag=true; // set flag indicating there was an error + flags|=GET_STATUS; // update flags to require status attribute for all characteristics } } else { status[i]=StatusCode::UnknownResource; - sFlag=true; // set flag indicating there was an error + flags|=GET_STATUS; // update flags to require status attribute for all characteristics } } - nChars+=snprintf(cBuf,cBuf?64:0,"{\"characteristics\":["); + hapOut << "{\"characteristics\":["; - for(int i=0;isprintfAttributes(cBuf?(cBuf+nChars):NULL,flags); // get JSON attributes for characteristic - else{ - sscanf(ids[i],"%u.%d",&aid,&iid); // parse aid and 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(Characteristics[i]) // if found + Characteristics[i]->printfAttributes(flags); // get JSON attributes for characteristic (may or may not include status=0 attribute) + else{ // else create JSON status attribute based on requested aid/iid + sscanf(ids[i],"%u.%d",&aid,&iid); + hapOut << "{\"iid\":" << iid << ",\"aid\":" << aid << ",\"status\":" << (int)status[i] << "}"; } - - if(sFlag){ // status flag is needed - overlay at end - nChars--; - nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,",\"status\":%d}",(int)status[i]); - } - + if(i+1(stepValue)>0) - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"minStep\":%s",uvPrint(stepValue).c_str()); - } - - if(unit){ - if(strlen(unit)>0) - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"unit\":\"%s\"",unit); - else - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"unit\":null"); - } - - if(validValues){ - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"valid-values\":%s",validValues); - } - } - - if(desc && (flags&GET_DESC)){ - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"description\":\"%s\"",desc); - } - - if(flags&GET_PERMS){ - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"perms\":["); - for(int i=0;i<7;i++){ - if(perms&(1<=(1<<(i+1))) - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,","); - } - } - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,"]"); - } - - if(flags&GET_AID) - nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"aid\":%u",aid); - - 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,"}"); - - return(nBytes); -} - -/////////////////////////////// - StatusCode SpanCharacteristic::loadUpdate(char *val, char *ev){ if(ev){ // request for notification diff --git a/src/HomeSpan.h b/src/HomeSpan.h index 387db50..f1327d2 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -64,7 +64,8 @@ enum { GET_EV=16, GET_DESC=32, GET_NV=64, - GET_VALUE=128 + GET_VALUE=128, + GET_STATUS=256 }; /////////////////////////////// @@ -291,8 +292,8 @@ class Span{ 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 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 sprintfAttributes(SpanBuf *pObj, int nObj, char *cBuf); // prints SpanBuf object into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL - int sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf); // prints accessory.characteristic ids into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL + void printfAttributes(SpanBuf *pObj, int nObj); // writes SpanBuf objects to hapOut stream + boolean printfAttributes(char **ids, int numIDs, int flags); // writes accessory requested characteristic ids to hapOut stream - returns true if all characteristics are found and readable, else returns false void clearNotify(int slotNum); // set ev notification flags for connection 'slotNum' to false across all characteristics void printfNotify(SpanBuf *pObj, int nObj, int conNum); // writes notification JSON to hapOut stream based on SpanBuf objects and specified connection number @@ -506,7 +507,6 @@ class SpanCharacteristic{ UVal newValue; // the updated value requested by PUT /characteristic SpanService *service=NULL; // pointer to Service containing this Characteristic - int sprintfAttributes(char *val, int flags); // prints Characteristic JSON records into buf; return number of characters printed, excluding null terminator void printfAttributes(int flags); // writes Characteristic JSON to hapOut stream StatusCode loadUpdate(char *val, char *ev); // load updated val/ev from PUT /characteristic JSON request. Return intitial HAP status code (checks to see if characteristic is found, is writable, etc.)