Converted all remaining sprintfAttributes to printfAttributes

This removes last of large-sized JSON buffers - everything has now been converted to using hapOut.

Next up: Must add prettyPrint to hapOut to support 'd' command
This commit is contained in:
Gregg 2024-01-01 08:49:33 -06:00
parent 6c3df551eb
commit bef151cdb1
3 changed files with 59 additions and 164 deletions

View File

@ -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<len;i++)
if(urlBuf[i]==',')
numIDs++;
TempBuffer<char *> ids(numIDs); // reserve space for number of IDs found
TempBuffer<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)
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<char> 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";
hapOut.setLogLevel(2).setHapClient(this);
hapOut << "HTTP/1.1 204 No Content\r\n\r\n";
hapOut.flush();
LOG2("\n>>>>>>>>>> ");
LOG2(client.remoteIP());
LOG2(" >>>>>>>>>>\n");
LOG2(body);
} else { // multicast respose is required
sendEncrypted(body,NULL,0);
} 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<char> 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

View File

@ -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;i<nObj;i++){
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?128:0,"{\"aid\":%u,\"iid\":%d,\"status\":%d}",pObj[i].aid,pObj[i].iid,(int)pObj[i].status);
if(i+1<nObj)
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,",");
hapOut << "{\"aid\":" << pObj[i].aid << ",\"iid\":" << pObj[i].iid << ",\"status\":" << (int)pObj[i].status << "}";
if(i+1<nObj)
hapOut << ",";
}
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,"]}");
return(nChars);
hapOut << "]}";
}
///////////////////////////////
int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
boolean Span::printfAttributes(char **ids, int numIDs, int flags){
int nChars=0;
uint32_t aid;
int iid;
SpanCharacteristic *Characteristics[numIDs];
StatusCode status[numIDs];
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
sscanf(ids[i],"%u.%d",&aid,&iid); // parse aid and iid
Characteristics[i]=find(aid,iid); // find matching chararacteristic
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)
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;i<numIDs;i++){ // PASS 2: loop over all ids requested and create JSON for each (with or without status code base on sFlag set above)
for(int i=0;i<numIDs;i++){ // PASS 2: loop over all ids requested and create JSON for each (either all with, or all without, a status attribute based on final flags setting)
if(Characteristics[i]) // if found
nChars+=Characteristics[i]->sprintfAttributes(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(sFlag){ // status flag is needed - overlay at end
nChars--;
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,",\"status\":%d}",(int)status[i]);
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(i+1<numIDs)
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,",");
hapOut << ",";
}
nChars+=snprintf(cBuf?(cBuf+nChars):NULL,cBuf?64:0,"]}");
hapOut << "]}";
return(nChars);
return(flags&GET_STATUS);
}
///////////////////////////////
@ -1909,81 +1897,14 @@ void SpanCharacteristic::printfAttributes(int flags){
if(flags&GET_EV)
hapOut << ",\"ev\":" << (ev[HAPClient::conNum]?"true":"false");
if(flags&GET_STATUS)
hapOut << ",\"status\":0";
hapOut << "}";
}
///////////////////////////////
int SpanCharacteristic::sprintfAttributes(char *cBuf, int flags){
int nBytes=0;
const char permCodes[][7]={"pr","pw","ev","aa","tw","hd","wr"};
const char formatCodes[][9]={"bool","uint8","uint16","uint32","uint64","int","float","string","data"};
nBytes+=snprintf(cBuf,cBuf?64:0,"{\"iid\":%d",iid);
if(flags&GET_TYPE)
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"type\":\"%s\"",type);
if((perms&PR) && (flags&GET_VALUE)){
if(perms&NV && !(flags&GET_NV))
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"value\":null");
else
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"value\":%s",uvPrint(value).c_str());
}
if(flags&GET_META){
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,",\"format\":\"%s\"",formatCodes[format]);
if(customRange && (flags&GET_META)){
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?128:0,",\"minValue\":%s,\"maxValue\":%s",uvPrint(minValue).c_str(),uvPrint(maxValue).c_str());
if(uvGet<float>(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<<i)){
nBytes+=snprintf(cBuf?(cBuf+nBytes):NULL,cBuf?64:0,"\"%s\"",permCodes[i]);
if(perms>=(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

View File

@ -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.)