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(!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
|
processSerialCommand("i"); // print homeSpan configuration info
|
||||||
|
|
||||||
if(nFatalErrors>0){
|
if(nFatalErrors>0){
|
||||||
|
|
@ -926,7 +915,7 @@ void Span::processSerialCommand(const char *c){
|
||||||
|
|
||||||
Serial.print("\n*** HomeSpan Info ***\n\n");
|
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++){
|
for(auto acc=Accessories.begin(); acc!=Accessories.end(); acc++){
|
||||||
Serial.printf("\u27a4 Accessory: AID=%d\n",(*acc)->aid);
|
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...
|
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
|
isBridge=false; // ...this is not a bridge device
|
||||||
|
|
||||||
|
unordered_set<HapChar *> hapChar;
|
||||||
|
|
||||||
for(auto chr=(*svc)->Characteristics.begin(); chr!=(*svc)->Characteristics.end(); chr++){
|
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);
|
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(" (nvs)");
|
||||||
Serial.printf("\n");
|
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");
|
Serial.printf(" *** WARNING! Service does not support this Characteristic ***\n");
|
||||||
else
|
else
|
||||||
if(invalidUUID((*chr)->type,(*chr)->isCustom))
|
if(invalidUUID((*chr)->type,(*chr)->isCustom))
|
||||||
Serial.printf(" *** ERROR! Format of UUID is invalid ***\n");
|
Serial.printf(" *** ERROR! Format of UUID is invalid ***\n");
|
||||||
else
|
else
|
||||||
if((*chr)->isRepeated)
|
if(hapChar.find((*chr)->hapChar)!=hapChar.end())
|
||||||
Serial.printf(" *** ERROR! Characteristic already defined for this Service ***\n");
|
Serial.printf(" *** ERROR! Characteristic already defined for this Service ***\n");
|
||||||
|
|
||||||
if((*chr)->setRangeError)
|
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)))
|
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));
|
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
|
hapChar.insert((*chr)->hapChar);
|
||||||
// 3. AID CHECK
|
|
||||||
|
|
||||||
} // Characteristics
|
} // 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
|
} // Services
|
||||||
|
|
||||||
if(!foundInfo)
|
if(!foundInfo)
|
||||||
Serial.printf(" *** ERROR! Required Accessory Information Service not found ***\n");
|
Serial.printf(" *** ERROR! Required 'AccessoryInformation' Service not found ***\n");
|
||||||
|
|
||||||
} // Accessories
|
} // Accessories
|
||||||
|
|
||||||
|
|
@ -1458,10 +1453,7 @@ SpanAccessory::SpanAccessory(uint32_t aid){
|
||||||
}
|
}
|
||||||
|
|
||||||
this->aid=homeSpan.Accessories.back()->aid+1;
|
this->aid=homeSpan.Accessories.back()->aid+1;
|
||||||
|
|
||||||
if(!homeSpan.Accessories.back()->Services.empty())
|
|
||||||
homeSpan.Accessories.back()->Services.back()->validate();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this->aid=1;
|
this->aid=1;
|
||||||
}
|
}
|
||||||
|
|
@ -1498,22 +1490,18 @@ int SpanAccessory::sprintfAttributes(char *cBuf){
|
||||||
|
|
||||||
SpanService::SpanService(const char *type, const char *hapName, boolean isCustom){
|
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
|
if(homeSpan.Accessories.empty()){
|
||||||
// homeSpan.Accessories.back()->Services.back()->validate();
|
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->type=type;
|
||||||
this->hapName=hapName;
|
this->hapName=hapName;
|
||||||
this->isCustom=isCustom;
|
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);
|
homeSpan.Accessories.back()->Services.push_back(this);
|
||||||
iid=++(homeSpan.Accessories.back()->iidCount);
|
iid=++(homeSpan.Accessories.back()->iidCount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
@ -1573,26 +1561,6 @@ 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]->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 //
|
// SpanCharacteristic //
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
@ -1604,13 +1572,12 @@ SpanCharacteristic::SpanCharacteristic(HapChar *hapChar, boolean isCustom){
|
||||||
format=hapChar->format;
|
format=hapChar->format;
|
||||||
staticRange=hapChar->staticRange;
|
staticRange=hapChar->staticRange;
|
||||||
this->isCustom=isCustom;
|
this->isCustom=isCustom;
|
||||||
|
this->hapChar=hapChar;
|
||||||
homeSpan.configLog+=" \u21e8 Characteristic " + String(hapName);
|
|
||||||
|
|
||||||
if(homeSpan.Accessories.empty() || homeSpan.Accessories.back()->Services.empty()){
|
if(homeSpan.Accessories.empty() || homeSpan.Accessories.back()->Services.empty()){
|
||||||
homeSpan.configLog+=" *** ERROR! Can't create new Characteristic without a defined Service! ***\n";
|
Serial.printf("\nFATAL ERROR! Can't create new Characteristic '%s' without a defined Service ***\n",hapName);
|
||||||
homeSpan.nFatalErrors++;
|
Serial.printf("\n=== PROGRAM HALTED ===");
|
||||||
return;
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
iid=++(homeSpan.Accessories.back()->iidCount);
|
iid=++(homeSpan.Accessories.back()->iidCount);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
#include <nvs.h>
|
#include <nvs.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::unordered_map;
|
using std::unordered_map;
|
||||||
|
using std::unordered_set;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GET_AID=1,
|
GET_AID=1,
|
||||||
|
|
@ -297,8 +298,8 @@ struct SpanService{
|
||||||
boolean hidden=false; // optional property indicating service is hidden
|
boolean hidden=false; // optional property indicating service is hidden
|
||||||
boolean primary=false; // optional property indicating service is primary
|
boolean primary=false; // optional property indicating service is primary
|
||||||
vector<SpanCharacteristic *> Characteristics; // vector of pointers to all Characteristics in this Service
|
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
|
unordered_set<HapChar *> req; // unordered set 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 *> 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
|
vector<SpanService *> linkedServices; // vector of pointers to any optional linked Services
|
||||||
boolean isCustom; // flag to indicate this is a Custom Service
|
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
|
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
|
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
|
||||||
|
|
@ -333,6 +333,7 @@ struct SpanCharacteristic{
|
||||||
};
|
};
|
||||||
|
|
||||||
int iid=0; // Instance ID (HAP Table 6-3)
|
int iid=0; // Instance ID (HAP Table 6-3)
|
||||||
|
HapChar *hapChar; // pointer to HAP Characteristic structure
|
||||||
const char *type; // Characteristic Type
|
const char *type; // Characteristic Type
|
||||||
const char *hapName; // HAP Name
|
const char *hapName; // HAP Name
|
||||||
UVal value; // Characteristic Value
|
UVal value; // Characteristic Value
|
||||||
|
|
@ -349,8 +350,6 @@ struct SpanCharacteristic{
|
||||||
boolean *ev; // Characteristic Event Notify Enable (per-connection)
|
boolean *ev; // Characteristic Event Notify Enable (per-connection)
|
||||||
char *nvsKey=NULL; // key for NVS storage of Characteristic value
|
char *nvsKey=NULL; // key for NVS storage of Characteristic value
|
||||||
boolean isCustom; // flag to indicate this is a Custom Characteristic
|
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
|
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
|
uint32_t aid=0; // Accessory ID - passed through from Service containing this Characteristic
|
||||||
|
|
@ -512,18 +511,7 @@ struct SpanCharacteristic{
|
||||||
uvSet(maxValue,max);
|
uvSet(maxValue,max);
|
||||||
uvSet(stepValue,0);
|
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);
|
homeSpan.Accessories.back()->Services.back()->Characteristics.push_back(this);
|
||||||
|
|
||||||
} // init()
|
} // init()
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@
|
||||||
|
|
||||||
// Macros to define vectors of required and optional characteristics for each Span Service structure
|
// Macros to define vectors of required and optional characteristics for each Span Service structure
|
||||||
|
|
||||||
#define REQ(HAPCHAR) req.push_back(&hapChars.HAPCHAR)
|
#define REQ(HAPCHAR) req.insert(&hapChars.HAPCHAR)
|
||||||
#define OPT(HAPCHAR) opt.push_back(&hapChars.HAPCHAR)
|
#define OPT(HAPCHAR) opt.insert(&hapChars.HAPCHAR)
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue