Added checks for use of setVal()
Throws warning, but still performs change, if setVal() is used within update() to change the value of a Characteristic that is being updated by the Home App, UNLESS the Characteristics has requested a write-response (in which case setVal() is expected). Throw warning, and DOES NOT perform change, if setVal() is used on a Characteristic without EV permission, UNLESS it has been used in update() in response to a write-response request. Also added diagnostic to 'i' CLI command that indicates which connections have currently asked to EV Notifications for each Characteristic. Only applies if EV permission is set for a Characteristic.
This commit is contained in:
parent
8ce80157b3
commit
faa99e0fbb
|
|
@ -904,9 +904,22 @@ void Span::processSerialCommand(const char *c){
|
||||||
else
|
else
|
||||||
LOG0(", %sRange=[%s,%s]",(*chr)->customRange?"Custom-":"",(*chr)->uvPrint((*chr)->minValue).c_str(),(*chr)->uvPrint((*chr)->maxValue).c_str());
|
LOG0(", %sRange=[%s,%s]",(*chr)->customRange?"Custom-":"",(*chr)->uvPrint((*chr)->minValue).c_str(),(*chr)->uvPrint((*chr)->maxValue).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(((*chr)->perms)&EV){
|
||||||
|
LOG0(", EV=(");
|
||||||
|
boolean addComma=false;
|
||||||
|
for(int i=0;i<homeSpan.maxConnections;i++){
|
||||||
|
if((*chr)->ev[i] && hap[i]->client){
|
||||||
|
LOG0("%s%d",addComma?",":"",i);
|
||||||
|
addComma=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG0(")");
|
||||||
|
}
|
||||||
|
|
||||||
if((*chr)->nvsKey)
|
if((*chr)->nvsKey)
|
||||||
LOG0(" (nvs)");
|
LOG0(" (nvs)");
|
||||||
|
|
||||||
LOG0("\n");
|
LOG0("\n");
|
||||||
|
|
||||||
if(!(*chr)->isCustom && !(*svc)->isCustom && std::find((*svc)->req.begin(),(*svc)->req.end(),(*chr)->hapChar)==(*svc)->req.end() && std::find((*svc)->opt.begin(),(*svc)->opt.end(),(*chr)->hapChar)==(*svc)->opt.end())
|
if(!(*chr)->isCustom && !(*svc)->isCustom && std::find((*svc)->req.begin(),(*svc)->req.end(),(*chr)->hapChar)==(*svc)->req.end() && std::find((*svc)->opt.begin(),(*svc)->opt.end(),(*chr)->hapChar)==(*svc)->opt.end())
|
||||||
|
|
@ -1420,10 +1433,10 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
|
||||||
} else {
|
} else {
|
||||||
pObj[i].characteristic = find(pObj[i].aid,pObj[i].iid); // find characteristic with matching aid/iid and store pointer
|
pObj[i].characteristic = find(pObj[i].aid,pObj[i].iid); // find characteristic with matching aid/iid and store pointer
|
||||||
|
|
||||||
if(pObj[i].characteristic) // if found, initialize characterstic update with new val/ev
|
if(pObj[i].characteristic) // if found, initialize characterstic update with new val/ev
|
||||||
pObj[i].status=pObj[i].characteristic->loadUpdate(pObj[i].val,pObj[i].ev); // save status code, which is either an error, or TBD (in which case isUpdated for the characteristic has been set to true)
|
pObj[i].status=pObj[i].characteristic->loadUpdate(pObj[i].val,pObj[i].ev,pObj[i].wr); // save status code, which is either an error, or TBD (in which case updateFlag for the characteristic has been set to either 1 or 2)
|
||||||
else
|
else
|
||||||
pObj[i].status=StatusCode::UnknownResource; // if not found, set HAP error
|
pObj[i].status=StatusCode::UnknownResource; // if not found, set HAP error
|
||||||
}
|
}
|
||||||
|
|
||||||
} // first pass
|
} // first pass
|
||||||
|
|
@ -1455,7 +1468,7 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
|
||||||
pObj[j].characteristic->uvSet(pObj[j].characteristic->newValue,pObj[j].characteristic->value); // replace characteristic new value with original value
|
pObj[j].characteristic->uvSet(pObj[j].characteristic->newValue,pObj[j].characteristic->value); // replace characteristic new value with original value
|
||||||
LOG1(" (failed)\n");
|
LOG1(" (failed)\n");
|
||||||
}
|
}
|
||||||
pObj[j].characteristic->isUpdated=false; // reset isUpdated flag for characteristic
|
pObj[j].characteristic->updateFlag=0; // reset updateFlag for characteristic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1899,7 +1912,7 @@ void SpanCharacteristic::printfAttributes(int flags){
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
StatusCode SpanCharacteristic::loadUpdate(char *val, char *ev){
|
StatusCode SpanCharacteristic::loadUpdate(char *val, char *ev, boolean wr){
|
||||||
|
|
||||||
if(ev){ // request for notification
|
if(ev){ // request for notification
|
||||||
boolean evFlag;
|
boolean evFlag;
|
||||||
|
|
@ -2000,7 +2013,7 @@ StatusCode SpanCharacteristic::loadUpdate(char *val, char *ev){
|
||||||
|
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
isUpdated=true;
|
updateFlag=1+wr; // set flag to 1 if successful update or 2 if successful AND write-response flag is set
|
||||||
updateTime=homeSpan.snapTime;
|
updateTime=homeSpan.snapTime;
|
||||||
return(StatusCode::TBD);
|
return(StatusCode::TBD);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -500,13 +500,13 @@ class SpanCharacteristic{
|
||||||
boolean setValidValuesError=false; // flag to indicate attempt to set Valid Values on Characteristic that does not support changes to Valid Values
|
boolean setValidValuesError=false; // flag to indicate attempt to set Valid Values on Characteristic that does not support changes to Valid Values
|
||||||
|
|
||||||
uint32_t 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
|
uint8_t updateFlag=0; // set to either 1 (for normal write) or 2 (for write-response) inside update() when Characteristic is successfully updated via Home App
|
||||||
unsigned long updateTime=0; // last time value was updated (in millis) either by PUT /characteristic OR by setVal()
|
unsigned long updateTime=0; // 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
|
||||||
SpanService *service=NULL; // pointer to Service containing this Characteristic
|
SpanService *service=NULL; // pointer to Service containing this Characteristic
|
||||||
|
|
||||||
void printfAttributes(int flags); // writes Characteristic JSON to hapOut stream
|
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.)
|
StatusCode loadUpdate(char *val, char *ev, boolean wr); // load updated val/ev from PUT /characteristic JSON request. Return intitial HAP status code (checks to see if characteristic is found, is writable, etc.)
|
||||||
|
|
||||||
String uvPrint(UVal &u){
|
String uvPrint(UVal &u){
|
||||||
char c[67]; // space for 64 characters + surrounding quotes + terminating null
|
char c[67]; // space for 64 characters + surrounding quotes + terminating null
|
||||||
|
|
@ -669,28 +669,35 @@ class SpanCharacteristic{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setString(const char *val){
|
void setString(const char *val, boolean notify=true){
|
||||||
|
|
||||||
if((perms & EV) == 0){
|
if(!((perms&EV) || (updateFlag==2))){
|
||||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setString() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No EVENT NOTIFICATION (EV) permission on this characteristic\n\n",hapName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(updateFlag==1)
|
||||||
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setVal() within update() while it is being updated by Home App. This may cause device to become non-responsive!\n\n",hapName);
|
||||||
|
|
||||||
uvSet(value,val);
|
uvSet(value,val);
|
||||||
uvSet(newValue,value);
|
uvSet(newValue,value);
|
||||||
|
|
||||||
updateTime=homeSpan.snapTime;
|
updateTime=homeSpan.snapTime;
|
||||||
|
|
||||||
SpanBuf sb; // create SpanBuf object
|
|
||||||
sb.characteristic=this; // set characteristic
|
|
||||||
sb.status=StatusCode::OK; // set status
|
|
||||||
char dummy[]="";
|
|
||||||
sb.val=dummy; // set dummy "val" so that printfNotify knows to consider this "update"
|
|
||||||
homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector
|
|
||||||
|
|
||||||
if(nvsKey){
|
if(notify){
|
||||||
nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store data
|
if(updateFlag!=2){ // do not broadcast EV if update is being done in context of write-response
|
||||||
nvs_commit(homeSpan.charNVS);
|
SpanBuf sb; // create SpanBuf object
|
||||||
|
sb.characteristic=this; // set characteristic
|
||||||
|
sb.status=StatusCode::OK; // set status
|
||||||
|
char dummy[]="";
|
||||||
|
sb.val=dummy; // set dummy "val" so that printfNotify knows to consider this "update"
|
||||||
|
homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nvsKey){
|
||||||
|
nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store data
|
||||||
|
nvs_commit(homeSpan.charNVS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // setString()
|
} // setString()
|
||||||
|
|
@ -731,12 +738,12 @@ class SpanCharacteristic{
|
||||||
return(olen);
|
return(olen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setData(uint8_t *data, size_t len){
|
void setData(uint8_t *data, size_t len, boolean notify=true){
|
||||||
|
|
||||||
if((perms & EV) == 0){
|
if(!((perms&EV) || (updateFlag==2))){
|
||||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No EVENT NOTIFICATION (EV) permission on this characteristic\n\n",hapName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(len<1){
|
if(len<1){
|
||||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. Size of data buffer must be greater than zero\n\n",hapName);
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. Size of data buffer must be greater than zero\n\n",hapName);
|
||||||
|
|
@ -744,18 +751,21 @@ class SpanCharacteristic{
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olen;
|
size_t olen;
|
||||||
mbedtls_base64_encode(NULL,0,&olen,data,len); // get length of string buffer needed (mbedtls includes the trailing null in this size)
|
mbedtls_base64_encode(NULL,0,&olen,data,len); // get length of string buffer needed (mbedtls includes the trailing null in this size)
|
||||||
TempBuffer<char> tBuf(olen); // create temporary string buffer, with room for trailing null
|
TempBuffer<char> tBuf(olen); // create temporary string buffer, with room for trailing null
|
||||||
mbedtls_base64_encode((uint8_t*)tBuf.get(),olen,&olen,data,len ); // encode data into string buf
|
mbedtls_base64_encode((uint8_t*)tBuf.get(),olen,&olen,data,len ); // encode data into string buf
|
||||||
setString(tBuf); // call setString to continue processing as if characteristic was a string
|
setString(tBuf,notify); // call setString to continue processing as if characteristic was a string
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void setVal(T val, boolean notify=true){
|
template <typename T> void setVal(T val, boolean notify=true){
|
||||||
|
|
||||||
if((perms & EV) == 0){
|
if(!((perms&EV) || (updateFlag==2))){
|
||||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setVal() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No EVENT NOTIFICATION (EV) permission on this characteristic\n\n",hapName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(updateFlag==1)
|
||||||
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setVal() within update() while it is being updated by Home App. This may cause device to become non-responsive!\n\n",hapName);
|
||||||
|
|
||||||
if(!((val >= uvGet<T>(minValue)) && (val <= uvGet<T>(maxValue)))){
|
if(!((val >= uvGet<T>(minValue)) && (val <= uvGet<T>(maxValue)))){
|
||||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setVal(%g) is out of range [%g,%g]. This may cause device to become non-responsive!\n\n",
|
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setVal(%g) is out of range [%g,%g]. This may cause device to become non-responsive!\n\n",
|
||||||
|
|
@ -768,13 +778,15 @@ class SpanCharacteristic{
|
||||||
updateTime=homeSpan.snapTime;
|
updateTime=homeSpan.snapTime;
|
||||||
|
|
||||||
if(notify){
|
if(notify){
|
||||||
SpanBuf sb; // create SpanBuf object
|
if(updateFlag!=2){ // do not broadcast EV if update is being done in context of write-response
|
||||||
sb.characteristic=this; // set characteristic
|
SpanBuf sb; // create SpanBuf object
|
||||||
sb.status=StatusCode::OK; // set status
|
sb.characteristic=this; // set characteristic
|
||||||
char dummy[]="";
|
sb.status=StatusCode::OK; // set status
|
||||||
sb.val=dummy; // set dummy "val" so that printfNotify knows to consider this "update"
|
char dummy[]="";
|
||||||
homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector
|
sb.val=dummy; // set dummy "val" so that printfNotify knows to consider this "update"
|
||||||
|
homeSpan.Notifications.push_back(sb); // store SpanBuf in Notifications vector
|
||||||
|
}
|
||||||
|
|
||||||
if(nvsKey){
|
if(nvsKey){
|
||||||
nvs_set_u64(homeSpan.charNVS,nvsKey,value.UINT64); // store data as uint64_t regardless of actual type (it will be read correctly when access through uvGet())
|
nvs_set_u64(homeSpan.charNVS,nvsKey,value.UINT64); // store data as uint64_t regardless of actual type (it will be read correctly when access through uvGet())
|
||||||
nvs_commit(homeSpan.charNVS);
|
nvs_commit(homeSpan.charNVS);
|
||||||
|
|
@ -783,8 +795,8 @@ class SpanCharacteristic{
|
||||||
|
|
||||||
} // setVal()
|
} // setVal()
|
||||||
|
|
||||||
boolean updated(){return(isUpdated);} // returns isUpdated
|
boolean updated(){return(updateFlag>0);} // returns true within update() if Characteristic was updated by Home App
|
||||||
unsigned long timeVal(); // returns time elapsed (in millis) since value was last updated
|
unsigned long timeVal(); // returns time elapsed (in millis) since value was last updated, either by Home App or by using setVal()
|
||||||
|
|
||||||
SpanCharacteristic *setValidValues(int n, ...); // sets a list of 'n' valid values allowed for a Characteristic and returns pointer to self. Only applicable if format=INT, UINT8, UINT16, or UINT32
|
SpanCharacteristic *setValidValues(int n, ...); // sets a list of 'n' valid values allowed for a Characteristic and returns pointer to self. Only applicable if format=INT, UINT8, UINT16, or UINT32
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue