Updated logic for required/optional Characteristics
Logic now embedded in 'i' CLI command.
This commit is contained in:
parent
0e6f7d27f9
commit
9f71c67f14
|
|
@ -179,17 +179,6 @@ void Span::pollTask() {
|
|||
|
||||
if(!isInitialized){
|
||||
|
||||
if(!homeSpan.Accessories.empty()){
|
||||
|
||||
if(!homeSpan.Accessories.back()->Services.empty())
|
||||
homeSpan.Accessories.back()->Services.back()->validate();
|
||||
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
processSerialCommand("i"); // print homeSpan configuration info
|
||||
|
||||
if(nFatalErrors>0){
|
||||
|
|
@ -926,7 +915,7 @@ void Span::processSerialCommand(const char *c){
|
|||
|
||||
Serial.print("\n*** HomeSpan Info ***\n\n");
|
||||
|
||||
std::set<uint32_t> aidValues;
|
||||
unordered_set<uint32_t> aidValues;
|
||||
|
||||
for(auto acc=Accessories.begin(); acc!=Accessories.end(); acc++){
|
||||
Serial.printf("\u27a4 Accessory: AID=%d\n",(*acc)->aid);
|
||||
|
|
@ -951,7 +940,9 @@ void Span::processSerialCommand(const char *c){
|
|||
}
|
||||
else if((*acc)->aid==1) // this is an Accessory with aid=1, but it has more than just AccessoryInfo. So...
|
||||
isBridge=false; // ...this is not a bridge device
|
||||
|
||||
|
||||
unordered_set<HapChar *> hapChar;
|
||||
|
||||
for(auto chr=(*svc)->Characteristics.begin(); chr!=(*svc)->Characteristics.end(); chr++){
|
||||
Serial.printf(" \u21e8 Characteristic %s(%s): IID=%d, %sUUID=\"%s\"",(*chr)->hapName,(*chr)->uvPrint((*chr)->value).c_str(),(*chr)->iid,(*chr)->isCustom?"Custom-":"",(*chr)->type);
|
||||
|
||||
|
|
@ -966,13 +957,13 @@ void Span::processSerialCommand(const char *c){
|
|||
Serial.printf(" (nvs)");
|
||||
Serial.printf("\n");
|
||||
|
||||
if(!(*chr)->isSupported)
|
||||
if(!(*chr)->isCustom && !(*svc)->isCustom && (*svc)->req.find((*chr)->hapChar)==(*svc)->req.end() && (*svc)->opt.find((*chr)->hapChar)==(*svc)->opt.end())
|
||||
Serial.printf(" *** WARNING! Service does not support this Characteristic ***\n");
|
||||
else
|
||||
if(invalidUUID((*chr)->type,(*chr)->isCustom))
|
||||
Serial.printf(" *** ERROR! Format of UUID is invalid ***\n");
|
||||
else
|
||||
if((*chr)->isRepeated)
|
||||
if(hapChar.find((*chr)->hapChar)!=hapChar.end())
|
||||
Serial.printf(" *** ERROR! Characteristic already defined for this Service ***\n");
|
||||
|
||||
if((*chr)->setRangeError)
|
||||
|
|
@ -981,15 +972,19 @@ void Span::processSerialCommand(const char *c){
|
|||
if((*chr)->format!=STRING && ((*chr)->uvGet<double>((*chr)->value) < (*chr)->uvGet<double>((*chr)->minValue) || (*chr)->uvGet<double>((*chr)->value) > (*chr)->uvGet<double>((*chr)->maxValue)))
|
||||
Serial.printf(" *** WARNING! Value of %llg is out of range [%llg,%llg] ***\n",(*chr)->uvGet<double>((*chr)->value),(*chr)->uvGet<double>((*chr)->minValue),(*chr)->uvGet<double>((*chr)->maxValue));
|
||||
|
||||
// 2. MISSING REQUIRED CHARACTERISTICS
|
||||
// 3. AID CHECK
|
||||
|
||||
hapChar.insert((*chr)->hapChar);
|
||||
|
||||
} // Characteristics
|
||||
|
||||
for(auto req=(*svc)->req.begin(); req!=(*svc)->req.end(); req++){
|
||||
if(hapChar.find(*req)==hapChar.end())
|
||||
Serial.printf(" *** WARNING! Required '%s' Characteristic for this Service not found ***\n",(*req)->hapName);
|
||||
}
|
||||
|
||||
} // Services
|
||||
|
||||
if(!foundInfo)
|
||||
Serial.printf(" *** ERROR! Required Accessory Information Service not found ***\n");
|
||||
Serial.printf(" *** ERROR! Required 'AccessoryInformation' Service not found ***\n");
|
||||
|
||||
} // Accessories
|
||||
|
||||
|
|
@ -1458,10 +1453,7 @@ SpanAccessory::SpanAccessory(uint32_t aid){
|
|||
}
|
||||
|
||||
this->aid=homeSpan.Accessories.back()->aid+1;
|
||||
|
||||
if(!homeSpan.Accessories.back()->Services.empty())
|
||||
homeSpan.Accessories.back()->Services.back()->validate();
|
||||
|
||||
|
||||
} else {
|
||||
this->aid=1;
|
||||
}
|
||||
|
|
@ -1498,22 +1490,18 @@ int SpanAccessory::sprintfAttributes(char *cBuf){
|
|||
|
||||
SpanService::SpanService(const char *type, const char *hapName, boolean isCustom){
|
||||
|
||||
// if(!homeSpan.Accessories.empty() && !homeSpan.Accessories.back()->Services.empty()) // this is not the first Service to be defined for this Accessory
|
||||
// homeSpan.Accessories.back()->Services.back()->validate();
|
||||
if(homeSpan.Accessories.empty()){
|
||||
Serial.printf("\nFATAL ERROR! Can't create new Service '%s' without a defined Accessory ***\n",hapName);
|
||||
Serial.printf("\n=== PROGRAM HALTED ===");
|
||||
while(1);
|
||||
}
|
||||
|
||||
this->type=type;
|
||||
this->hapName=hapName;
|
||||
this->isCustom=isCustom;
|
||||
|
||||
if(homeSpan.Accessories.empty()){
|
||||
homeSpan.configLog+=" *** ERROR! Can't create new Service without a defined Accessory! ***\n";
|
||||
homeSpan.nFatalErrors++;
|
||||
return;
|
||||
}
|
||||
|
||||
homeSpan.Accessories.back()->Services.push_back(this);
|
||||
iid=++(homeSpan.Accessories.back()->iidCount);
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
|
@ -1573,26 +1561,6 @@ int SpanService::sprintfAttributes(char *cBuf){
|
|||
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]->type,Characteristics[j]->type);
|
||||
|
||||
if(!valid){
|
||||
homeSpan.configLog+=" \u2718 Characteristic " + String(req[i]->hapName);
|
||||
homeSpan.configLog+=" *** WARNING! Required Characteristic for this Service not found. ***\n";
|
||||
homeSpan.nWarnings++;
|
||||
}
|
||||
}
|
||||
|
||||
vector<HapChar *>().swap(opt);
|
||||
vector<HapChar *>().swap(req);
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// SpanCharacteristic //
|
||||
///////////////////////////////
|
||||
|
|
@ -1604,13 +1572,12 @@ SpanCharacteristic::SpanCharacteristic(HapChar *hapChar, boolean isCustom){
|
|||
format=hapChar->format;
|
||||
staticRange=hapChar->staticRange;
|
||||
this->isCustom=isCustom;
|
||||
|
||||
homeSpan.configLog+=" \u21e8 Characteristic " + String(hapName);
|
||||
this->hapChar=hapChar;
|
||||
|
||||
if(homeSpan.Accessories.empty() || homeSpan.Accessories.back()->Services.empty()){
|
||||
homeSpan.configLog+=" *** ERROR! Can't create new Characteristic without a defined Service! ***\n";
|
||||
homeSpan.nFatalErrors++;
|
||||
return;
|
||||
Serial.printf("\nFATAL ERROR! Can't create new Characteristic '%s' without a defined Service ***\n",hapName);
|
||||
Serial.printf("\n=== PROGRAM HALTED ===");
|
||||
while(1);
|
||||
}
|
||||
|
||||
iid=++(homeSpan.Accessories.back()->iidCount);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include <Arduino.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <nvs.h>
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
using std::vector;
|
||||
using std::unordered_map;
|
||||
using std::unordered_set;
|
||||
|
||||
enum {
|
||||
GET_AID=1,
|
||||
|
|
@ -297,8 +298,8 @@ struct SpanService{
|
|||
boolean hidden=false; // optional property indicating service is hidden
|
||||
boolean primary=false; // optional property indicating service is primary
|
||||
vector<SpanCharacteristic *> Characteristics; // vector of pointers to all Characteristics in this Service
|
||||
vector<HapChar *> req; // vector of pointers to all required HAP Characteristic Types for this Service
|
||||
vector<HapChar *> opt; // vector of pointers to all optional HAP Characteristic Types for this Service
|
||||
unordered_set<HapChar *> req; // unordered set of pointers to all required HAP Characteristic Types for this Service
|
||||
unordered_set<HapChar *> opt; // unordered set of pointers to all optional HAP Characteristic Types for this Service
|
||||
vector<SpanService *> linkedServices; // vector of pointers to any optional linked Services
|
||||
boolean isCustom; // flag to indicate this is a Custom Service
|
||||
|
||||
|
|
@ -310,7 +311,6 @@ struct SpanService{
|
|||
vector<SpanService *> getLinks(){return(linkedServices);} // returns linkedServices vector for use as range in "for-each" loops
|
||||
|
||||
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 void loop(){} // loops for each Service - called every cycle and can be over-ridden with user-defined code
|
||||
|
|
@ -333,6 +333,7 @@ struct SpanCharacteristic{
|
|||
};
|
||||
|
||||
int iid=0; // Instance ID (HAP Table 6-3)
|
||||
HapChar *hapChar; // pointer to HAP Characteristic structure
|
||||
const char *type; // Characteristic Type
|
||||
const char *hapName; // HAP Name
|
||||
UVal value; // Characteristic Value
|
||||
|
|
@ -349,8 +350,6 @@ struct SpanCharacteristic{
|
|||
boolean *ev; // Characteristic Event Notify Enable (per-connection)
|
||||
char *nvsKey=NULL; // key for NVS storage of Characteristic value
|
||||
boolean isCustom; // flag to indicate this is a Custom Characteristic
|
||||
boolean isSupported; // flag to indicate this Characteristic is supported by the containing Service (it's either required or optional)
|
||||
boolean isRepeated=false; // flag to indicate this Characteristic is defined repeated times within the same Service (reports an error)
|
||||
boolean setRangeError=false; // flag to indicate attempt to set range on Characteristic that does not support changes to range
|
||||
|
||||
uint32_t aid=0; // Accessory ID - passed through from Service containing this Characteristic
|
||||
|
|
@ -512,18 +511,7 @@ struct SpanCharacteristic{
|
|||
uvSet(maxValue,max);
|
||||
uvSet(stepValue,0);
|
||||
}
|
||||
|
||||
isSupported=isCustom|service->isCustom; // automatically set valid if either Characteristic or containing Service is Custom
|
||||
|
||||
for(int i=0; !isSupported && i<homeSpan.Accessories.back()->Services.back()->req.size(); i++)
|
||||
isSupported=!strcmp(type,homeSpan.Accessories.back()->Services.back()->req[i]->type);
|
||||
|
||||
for(int i=0; !isSupported && i<homeSpan.Accessories.back()->Services.back()->opt.size(); i++)
|
||||
isSupported=!strcmp(type,homeSpan.Accessories.back()->Services.back()->opt[i]->type);
|
||||
|
||||
for(int i=0; !isRepeated && i<homeSpan.Accessories.back()->Services.back()->Characteristics.size(); i++)
|
||||
isRepeated=!strcmp(type,homeSpan.Accessories.back()->Services.back()->Characteristics[i]->type);
|
||||
|
||||
|
||||
homeSpan.Accessories.back()->Services.back()->Characteristics.push_back(this);
|
||||
|
||||
} // init()
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
// Macros to define vectors of required and optional characteristics for each Span Service structure
|
||||
|
||||
#define REQ(HAPCHAR) req.push_back(&hapChars.HAPCHAR)
|
||||
#define OPT(HAPCHAR) opt.push_back(&hapChars.HAPCHAR)
|
||||
#define REQ(HAPCHAR) req.insert(&hapChars.HAPCHAR)
|
||||
#define OPT(HAPCHAR) opt.insert(&hapChars.HAPCHAR)
|
||||
|
||||
namespace Service {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue