Moved Range checking to a standalone routine checkRanges()

Ranges are now checked for all Characteristics at the end of the configuration, instead of at the end of each Accessory definition.  This is much cleaner and the output is easier to read.

To do:  Revisit use of REQ and OPT - what should constitute a fatal error and what should be a warning.

To do:  Revisit Character definitions - attempt to normalize using the methods implemented for Custom Characteristics
This commit is contained in:
Gregg 2021-10-26 22:05:44 -05:00
parent 65b15b5628
commit 61a2be533b
3 changed files with 37 additions and 15 deletions

View File

@ -157,6 +157,8 @@ void Span::poll() {
homeSpan.Accessories.back()->validate();
}
checkRanges();
if(nWarnings>0){
configLog+="\n*** CAUTION: There " + String((nWarnings>1?"are ":"is ")) + String(nWarnings) + " WARNING" + (nWarnings>1?"S":"") + " associated with this configuration that may lead to the device becoming non-responsive, or operating in an unexpected manner. ***\n";
}
@ -1347,6 +1349,37 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
return(nChars);
}
///////////////////////////////
void Span::checkRanges(){
boolean okay=true;
homeSpan.configLog+="\nRange Check:";
for(int i=0;i<Accessories.size();i++){
for(int j=0;j<Accessories[i]->Services.size();j++){
for(int k=0;k<Accessories[i]->Services[j]->Characteristics.size();k++){
SpanCharacteristic *chr=Accessories[i]->Services[j]->Characteristics[k];
if(chr->format!=STRING && (chr->uvGet<double>(chr->value) < chr->uvGet<double>(chr->minValue) || chr->uvGet<double>(chr->value) > chr->uvGet<double>(chr->maxValue))){
char c[256];
sprintf(c,"\n \u2718 Characteristic %s with AID=%d, IID=%d: Initial value of %lg is out of range [%llg,%llg]",
chr->hapName,chr->aid,chr->iid,chr->uvGet<double>(chr->value),chr->uvGet<double>(chr->minValue),chr->uvGet<double>(chr->maxValue));
if(okay)
homeSpan.configLog+="\n";
homeSpan.configLog+=c;
homeSpan.nWarnings++;
okay=false;
}
}
}
}
if(okay)
homeSpan.configLog+=" No Warnings";
homeSpan.configLog+="\n\n";
}
///////////////////////////////
// SpanAccessory //
///////////////////////////////
@ -1411,18 +1444,6 @@ void SpanAccessory::validate(){
foundProtocol=true;
else if(aid==1) // this is an Accessory with aid=1, but it has more than just AccessoryInfo and HAPProtocolInformation. So...
homeSpan.isBridge=false; // ...this is not a bridge device
for(int j=0;j<Services[i]->Characteristics.size();j++){ // check that initial values are all in range of mix/max (which may have been modified by setRange)
SpanCharacteristic *chr=Services[i]->Characteristics[j];
if(chr->format!=STRING && (chr->uvGet<double>(chr->value) < chr->uvGet<double>(chr->minValue) || chr->uvGet<double>(chr->value) > chr->uvGet<double>(chr->maxValue))){
char c[256];
sprintf(c," \u2718 Characteristic %s with IID=%d *** WARNING: Initial value of %lg is out of range [%llg,%llg]. ***\n",
chr->hapName,chr->iid,chr->uvGet<double>(chr->value),chr->uvGet<double>(chr->minValue),chr->uvGet<double>(chr->maxValue));
homeSpan.configLog+=c;
homeSpan.nWarnings++;
}
}
}
if(!foundInfo){

View File

@ -156,6 +156,7 @@ struct Span{
void checkConnect(); // check WiFi connection; connect if needed
void commandMode(); // allows user to control and reset HomeSpan settings with the control button
void processSerialCommand(const char *c); // process command 'c' (typically from readSerial, though can be called with any 'c')
void checkRanges(); // checks values of all Characteristics to ensure they are each within range
int sprintfAttributes(char *cBuf); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL
void prettyPrint(char *buf, int nsp=2); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces

View File

@ -45,8 +45,8 @@ void setup() {
new Service::LightBulb();
new Characteristic::On(0);
SpanCharacteristic *active = new Characteristic::CustomActive(2);
new Characteristic::Brightness(500);
SpanCharacteristic *active = new Characteristic::CustomActive();
new Characteristic::Brightness(50);
new Characteristic::Name("Light 1");
new Characteristic::ColorTemperature();
new Characteristic::Active();
@ -57,7 +57,7 @@ void setup() {
new SpanAccessory(); // Begin by creating a new Accessory using SpanAccessory(), which takes no arguments
active->setRange(0,10,3);
// active->setRange(0,10,3);
new Service::AccessoryInformation(); // HAP requires every Accessory to implement an AccessoryInformation Service, which has 6 required Characteristics
new Characteristic::Name("HomeSpan Test"); // Name of the Accessory, which shows up on the HomeKit "tiles", and should be unique across Accessories
new Characteristic::Manufacturer("HomeSpan"); // Manufacturer of the Accessory (arbitrary text string, and can be the same for every Accessory)