Completed error-checking/validation
Added validation to ensure all Accessories have a AccessoryInformation Service and all Accessories have a HAPProtocolInformation Service, unless the device is configured as a bridge, in which case only the first Accessory requires a HAPProtocolInformation Service.
This commit is contained in:
parent
254406c802
commit
c7f762da5f
|
|
@ -71,11 +71,19 @@ void Span::poll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isInitialized){
|
if(!isInitialized){
|
||||||
|
|
||||||
if(logLevel>0 || nFatalErrors>0){
|
if(!homeSpan.Accessories.empty()){
|
||||||
Serial.print(configLog);
|
|
||||||
Serial.print("\n*** End Config Log ***\n");
|
if(!homeSpan.Accessories.back()->Services.empty())
|
||||||
|
homeSpan.Accessories.back()->Services.back()->validate();
|
||||||
|
|
||||||
|
homeSpan.Accessories.back()->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.print(configLog);
|
||||||
|
Serial.print("\nConfigured as Bridge: ");
|
||||||
|
Serial.print(homeSpan.isBridge?"YES":"NO");
|
||||||
|
Serial.print("\n\n*** End Config Log ***\n");
|
||||||
|
|
||||||
if(nFatalErrors>0){
|
if(nFatalErrors>0){
|
||||||
Serial.print("\n*** PROGRAM HALTED DUE TO ");
|
Serial.print("\n*** PROGRAM HALTED DUE TO ");
|
||||||
|
|
@ -1006,6 +1014,14 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
SpanAccessory::SpanAccessory(){
|
SpanAccessory::SpanAccessory(){
|
||||||
|
|
||||||
|
if(!homeSpan.Accessories.empty()){
|
||||||
|
|
||||||
|
if(!homeSpan.Accessories.back()->Services.empty())
|
||||||
|
homeSpan.Accessories.back()->Services.back()->validate();
|
||||||
|
|
||||||
|
homeSpan.Accessories.back()->validate();
|
||||||
|
}
|
||||||
|
|
||||||
homeSpan.Accessories.push_back(this);
|
homeSpan.Accessories.push_back(this);
|
||||||
aid=homeSpan.Accessories.size();
|
aid=homeSpan.Accessories.size();
|
||||||
|
|
@ -1015,6 +1031,35 @@ SpanAccessory::SpanAccessory(){
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
|
void SpanAccessory::validate(){
|
||||||
|
|
||||||
|
boolean foundInfo=false;
|
||||||
|
boolean foundProtocol=false;
|
||||||
|
|
||||||
|
for(int i=0;i<Services.size();i++){
|
||||||
|
if(!strcmp(Services[i]->type,"3E"))
|
||||||
|
foundInfo=true;
|
||||||
|
else if(!strcmp(Services[i]->type,"A2"))
|
||||||
|
foundProtocol=true;
|
||||||
|
else if(aid==1) // this is the first Accessory and it has more than just AccessoryInfo and HAPProtocolInformation
|
||||||
|
homeSpan.isBridge=false; // this is not a bridge device
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!foundInfo){
|
||||||
|
homeSpan.configLog+=" !Service AccessoryInformation";
|
||||||
|
homeSpan.configLog+=" *** ERROR! Required Service for this Accessory not found. ***\n";
|
||||||
|
homeSpan.nFatalErrors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!foundProtocol && (aid==1 || !homeSpan.isBridge)){ // HAPProtocolInformation must always be present in first Accessory, and any other Accessory is the device is not a bridge)
|
||||||
|
homeSpan.configLog+=" !Service HAPProtocolInformation";
|
||||||
|
homeSpan.configLog+=" *** ERROR! Required Service for this Accessory not found. ***\n";
|
||||||
|
homeSpan.nFatalErrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
int SpanAccessory::sprintfAttributes(char *cBuf){
|
int SpanAccessory::sprintfAttributes(char *cBuf){
|
||||||
int nBytes=0;
|
int nBytes=0;
|
||||||
|
|
||||||
|
|
@ -1037,6 +1082,9 @@ int SpanAccessory::sprintfAttributes(char *cBuf){
|
||||||
|
|
||||||
SpanService::SpanService(const char *type, const char *hapName){
|
SpanService::SpanService(const char *type, const char *hapName){
|
||||||
|
|
||||||
|
if(!homeSpan.Accessories.back()->Services.empty()) // this is not the first Service to be defined for this Accessory
|
||||||
|
homeSpan.Accessories.back()->Services.back()->validate();
|
||||||
|
|
||||||
this->type=type;
|
this->type=type;
|
||||||
this->hapName=hapName;
|
this->hapName=hapName;
|
||||||
|
|
||||||
|
|
@ -1093,6 +1141,23 @@ int SpanService::sprintfAttributes(char *cBuf){
|
||||||
return(nBytes);
|
return(nBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
void SpanService::validate(){
|
||||||
|
|
||||||
|
for(int i=0;i<req.size();i++){
|
||||||
|
boolean valid=false;
|
||||||
|
for(int j=0;!valid && j<Characteristics.size();j++)
|
||||||
|
valid=!strcmp(req[i]->id,Characteristics[j]->type);
|
||||||
|
|
||||||
|
if(!valid){
|
||||||
|
homeSpan.configLog+=" !Characteristic " + String(req[i]->name);
|
||||||
|
homeSpan.configLog+=" *** ERROR! Required Characteristic for this Service not found. ***\n";
|
||||||
|
homeSpan.nFatalErrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// SpanCharacteristic //
|
// SpanCharacteristic //
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
@ -1110,7 +1175,7 @@ SpanCharacteristic::SpanCharacteristic(char *type, uint8_t perms, char *hapName)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char valid=false;
|
boolean valid=false;
|
||||||
|
|
||||||
for(int i=0; !valid && i<homeSpan.Accessories.back()->Services.back()->req.size(); i++)
|
for(int i=0; !valid && i<homeSpan.Accessories.back()->Services.back()->req.size(); i++)
|
||||||
valid=!strcmp(type,homeSpan.Accessories.back()->Services.back()->req[i]->id);
|
valid=!strcmp(type,homeSpan.Accessories.back()->Services.back()->req[i]->id);
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ struct Span{
|
||||||
boolean isInitialized=false; // flag indicating HomeSpan has been initialized
|
boolean isInitialized=false; // flag indicating HomeSpan has been initialized
|
||||||
int nFatalErrors=0; // number of fatal errors in user-defined configuration
|
int nFatalErrors=0; // number of fatal errors in user-defined configuration
|
||||||
String configLog="\n*** Config Log ***\n\n"; // log of configuration process, including any errors
|
String configLog="\n*** Config Log ***\n\n"; // log of configuration process, including any errors
|
||||||
|
boolean isBridge=true; // flag indicating whether device is configured as a bridge (i.e. first Accessory contains nothing but AccessoryInformation and HAPProtocolInformation)
|
||||||
|
|
||||||
char *defaultSetupCode=DEFAULT_SETUP_CODE; // Setup Code used for pairing
|
char *defaultSetupCode=DEFAULT_SETUP_CODE; // Setup Code used for pairing
|
||||||
uint8_t statusPin=DEFAULT_STATUS_PIN; // pin for status LED
|
uint8_t statusPin=DEFAULT_STATUS_PIN; // pin for status LED
|
||||||
|
|
@ -121,6 +122,7 @@ struct SpanAccessory{
|
||||||
SpanAccessory();
|
SpanAccessory();
|
||||||
|
|
||||||
int sprintfAttributes(char *cBuf); // prints Accessory JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL
|
int sprintfAttributes(char *cBuf); // prints Accessory JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL
|
||||||
|
void validate(); // error-checks Accessory
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
@ -142,6 +144,8 @@ struct SpanService{
|
||||||
SpanService *setHidden(); // sets the Service Type to be hidden and returns pointer to self
|
SpanService *setHidden(); // sets the Service Type to be hidden and returns pointer to self
|
||||||
|
|
||||||
int sprintfAttributes(char *cBuf); // prints Service JSON records into buf; return number of characters printed, excluding null terminator
|
int sprintfAttributes(char *cBuf); // prints Service JSON records into buf; return number of characters printed, excluding null terminator
|
||||||
|
void validate(); // error-checks Service
|
||||||
|
|
||||||
virtual boolean update() {return(true);} // placeholder for code that is called when a Service is updated via a Controller. Must return true/false depending on success of update
|
virtual boolean update() {return(true);} // placeholder for code that is called when a Service is updated via a Controller. Must return true/false depending on success of update
|
||||||
virtual void loop(){} // loops for each Service - called every cycle and can be over-ridden with user-defined code
|
virtual void loop(){} // loops for each Service - called every cycle and can be over-ridden with user-defined code
|
||||||
virtual void button(int pin, boolean isLong){} // method called for a Service when a button attached to "pin" has a Short-Press or Long-Press, according to "isLong"
|
virtual void button(int pin, boolean isLong){} // method called for a Service when a button attached to "pin" has a Short-Press or Long-Press, according to "isLong"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue