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
|
|
@ -905,8 +905,21 @@ void Span::processSerialCommand(const char *c){
|
|||
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)
|
||||
LOG0(" (nvs)");
|
||||
|
||||
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())
|
||||
|
|
@ -1420,10 +1433,10 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
|
|||
} else {
|
||||
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
|
||||
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)
|
||||
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,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
|
||||
pObj[i].status=StatusCode::UnknownResource; // if not found, set HAP error
|
||||
pObj[i].status=StatusCode::UnknownResource; // if not found, set HAP error
|
||||
}
|
||||
|
||||
} // 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
|
||||
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
|
||||
boolean evFlag;
|
||||
|
|
@ -2000,7 +2013,7 @@ StatusCode SpanCharacteristic::loadUpdate(char *val, char *ev){
|
|||
|
||||
} // 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;
|
||||
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
|
||||
|
||||
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()
|
||||
UVal newValue; // the updated value requested by PUT /characteristic
|
||||
SpanService *service=NULL; // pointer to Service containing this Characteristic
|
||||
|
||||
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.)
|
||||
void printfAttributes(int flags); // writes Characteristic JSON to hapOut stream
|
||||
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){
|
||||
char c[67]; // space for 64 characters + surrounding quotes + terminating null
|
||||
|
|
@ -669,28 +669,35 @@ class SpanCharacteristic{
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void setString(const char *val){
|
||||
void setString(const char *val, boolean notify=true){
|
||||
|
||||
if((perms & EV) == 0){
|
||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setString() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
||||
if(!((perms&EV) || (updateFlag==2))){
|
||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No EVENT NOTIFICATION (EV) permission on this characteristic\n\n",hapName);
|
||||
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(newValue,value);
|
||||
|
||||
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(notify){
|
||||
if(updateFlag!=2){ // do not broadcast EV if update is being done in context of write-response
|
||||
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);
|
||||
if(nvsKey){
|
||||
nvs_set_str(homeSpan.charNVS,nvsKey,value.STRING); // store data
|
||||
nvs_commit(homeSpan.charNVS);
|
||||
}
|
||||
}
|
||||
|
||||
} // setString()
|
||||
|
|
@ -731,10 +738,10 @@ class SpanCharacteristic{
|
|||
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){
|
||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
||||
if(!((perms&EV) || (updateFlag==2))){
|
||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No EVENT NOTIFICATION (EV) permission on this characteristic\n\n",hapName);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -744,19 +751,22 @@ class SpanCharacteristic{
|
|||
}
|
||||
|
||||
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)
|
||||
TempBuffer<char> tBuf(olen); // create temporary string buffer, with room for trailing null
|
||||
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
|
||||
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){
|
||||
|
||||
if((perms & EV) == 0){
|
||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setVal() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
||||
if(!((perms&EV) || (updateFlag==2))){
|
||||
LOG0("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No EVENT NOTIFICATION (EV) permission on this characteristic\n\n",hapName);
|
||||
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)))){
|
||||
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",
|
||||
hapName,(double)val,uvGet<double>(minValue),uvGet<double>(maxValue));
|
||||
|
|
@ -768,12 +778,14 @@ class SpanCharacteristic{
|
|||
updateTime=homeSpan.snapTime;
|
||||
|
||||
if(notify){
|
||||
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(updateFlag!=2){ // do not broadcast EV if update is being done in context of write-response
|
||||
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_u64(homeSpan.charNVS,nvsKey,value.UINT64); // store data as uint64_t regardless of actual type (it will be read correctly when access through uvGet())
|
||||
|
|
@ -783,8 +795,8 @@ class SpanCharacteristic{
|
|||
|
||||
} // setVal()
|
||||
|
||||
boolean updated(){return(isUpdated);} // returns isUpdated
|
||||
unsigned long timeVal(); // returns time elapsed (in millis) since value was last updated
|
||||
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, 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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue