mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov.git
synced 2026-03-20 03:40:31 +00:00
297 lines
12 KiB
C++
297 lines
12 KiB
C++
//
|
|
// Created by stephane bourque on 2021-09-07.
|
|
//
|
|
|
|
#include "APConfig.h"
|
|
#include "StorageService.h"
|
|
|
|
namespace OpenWifi {
|
|
|
|
APConfig::APConfig(const std::string &SerialNumber, const std::string &DeviceType, Poco::Logger &L, bool Explain)
|
|
: SerialNumber_(SerialNumber),
|
|
DeviceType_(DeviceType),
|
|
Logger_(L),
|
|
Explain_(Explain)
|
|
{
|
|
}
|
|
|
|
APConfig::APConfig(const std::string & SerialNumber, Poco::Logger & L)
|
|
: SerialNumber_(SerialNumber),
|
|
Logger_(L)
|
|
{
|
|
Explain_ = false;
|
|
Sub_ = true;
|
|
}
|
|
|
|
bool APConfig::FindRadio(const std::string &Band, const Poco::JSON::Array::Ptr &Arr, Poco::JSON::Object::Ptr & Radio) {
|
|
for(const auto &i:*Arr) {
|
|
auto R = i.extract<Poco::JSON::Object::Ptr>();
|
|
if(R->has("band") && R->get("band").toString()==Band) {
|
|
Radio = R;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool APConfig::RemoveBand(const std::string &Band, const Poco::JSON::Array::Ptr &A_in,Poco::JSON::Array::Ptr &A_Out) {
|
|
for(const auto &i:*A_in) {
|
|
auto R = i.extract<Poco::JSON::Object::Ptr>();
|
|
if(R->has("band") && R->get("band").toString()==Band) {
|
|
} else {
|
|
A_Out->add(i);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
[[maybe_unused ]] static void ShowJSON([[maybe_unused]] const char *S, [[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) {
|
|
/*
|
|
std::stringstream O;
|
|
Poco::JSON::Stringifier::stringify(Obj,O);
|
|
std::cout << S << ":" << std::endl;
|
|
std::cout << ">>>" << std::endl << O.str() << std::endl << "<<<" << std::endl;
|
|
*/
|
|
}
|
|
|
|
bool APConfig::ReplaceVariablesInObject( const Poco::JSON::Object::Ptr & Original, Poco::JSON::Object::Ptr & Result) {
|
|
// get all the names and expand
|
|
auto Names = Original->getNames();
|
|
for(const auto &i:Names) {
|
|
if(i=="__variableBlock") {
|
|
if(Original->isArray(i)) {
|
|
auto UUIDs = Original->getArray(i);
|
|
for(const auto &uuid:*UUIDs) {
|
|
ProvObjects::VariableBlock VB;
|
|
if(StorageService()->VariablesDB().GetRecord("id", uuid, VB)) {
|
|
for(const auto &var:VB.variables) {
|
|
Poco::JSON::Parser P;
|
|
auto VariableBlockInfo = P.parse(var.value).extract<Poco::JSON::Object::Ptr>();
|
|
auto VarNames = VariableBlockInfo->getNames();
|
|
for(const auto &j:VarNames) {
|
|
Result->set(j,VariableBlockInfo->get(j));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if(Original->isArray(i)) {
|
|
auto Arr = Poco::makeShared<Poco::JSON::Array>();
|
|
auto Obj = Original->getArray(i);
|
|
ReplaceVariablesInArray(Obj,Arr);
|
|
Result->set(i,Arr);
|
|
} else if (Original->isObject(i)) {
|
|
auto Expanded = Poco::makeShared<Poco::JSON::Object>();
|
|
auto Obj = Original->getObject(i);
|
|
ReplaceVariablesInObject(Obj,Expanded);
|
|
Result->set(i,Expanded);
|
|
} else {
|
|
Result->set(i,Original->get(i));
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool APConfig::ReplaceVariablesInArray( const Poco::JSON::Array::Ptr & Original, Poco::JSON::Array::Ptr & ResultArray) {
|
|
|
|
for(const auto &element:*Original) {
|
|
|
|
if(element.isArray()) {
|
|
auto Expanded = Poco::makeShared<Poco::JSON::Array>();
|
|
const auto & Object = element.extract<Poco::JSON::Array::Ptr>();
|
|
ReplaceVariablesInArray(Object,Expanded);
|
|
ResultArray->add(Expanded);
|
|
} else if(element.isStruct()) {
|
|
auto Expanded = Poco::makeShared<Poco::JSON::Object>();
|
|
const auto & Object = element.extract<Poco::JSON::Object::Ptr>();
|
|
ReplaceVariablesInObject(Object,Expanded);
|
|
ResultArray->add(Expanded);
|
|
} else if( element.isString() ||
|
|
element.isNumeric() ||
|
|
element.isBoolean() ||
|
|
element.isInteger() ||
|
|
element.isSigned() ) {
|
|
ResultArray->add(element);
|
|
} else {
|
|
auto Expanded = Poco::makeShared<Poco::JSON::Object>();
|
|
const auto & Object = element.extract<Poco::JSON::Object::Ptr>();
|
|
ReplaceVariablesInObject(Object,Expanded);
|
|
ResultArray->add(Expanded);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool APConfig::Get(Poco::JSON::Object::Ptr & Configuration) {
|
|
if(Config_.empty()) {
|
|
Explanation_.clear();
|
|
try {
|
|
if(!Sub_) {
|
|
ProvObjects::InventoryTag D;
|
|
if (StorageService()->InventoryDB().GetRecord("serialNumber", SerialNumber_, D)) {
|
|
if (!D.deviceConfiguration.empty()) {
|
|
AddConfiguration(D.deviceConfiguration);
|
|
}
|
|
if (!D.entity.empty()) {
|
|
AddEntityConfig(D.entity);
|
|
} else if (!D.venue.empty()) {
|
|
AddVenueConfig(D.venue);
|
|
}
|
|
}
|
|
} else {
|
|
ProvObjects::SubscriberDevice D;
|
|
if (StorageService()->SubscriberDeviceDB().GetRecord("serialNumber", SerialNumber_, D)) {
|
|
if (!D.configuration.empty()) {
|
|
AddConfiguration(D.configuration);
|
|
}
|
|
}
|
|
}
|
|
// Now we have all the config we need.
|
|
} catch (const Poco::Exception &E ) {
|
|
Logger_.log(E);
|
|
}
|
|
}
|
|
|
|
std::set<std::string> Sections;
|
|
for(const auto &i:Config_) {
|
|
Poco::JSON::Parser P;
|
|
auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>();
|
|
auto Names = O->getNames();
|
|
for(const auto &SectionName:Names) {
|
|
auto InsertInfo = Sections.insert(SectionName);
|
|
if (InsertInfo.second) {
|
|
if (O->isArray(SectionName)) {
|
|
auto OriginalArray = O->getArray(SectionName);
|
|
if (Explain_) {
|
|
Poco::JSON::Object ExObj;
|
|
ExObj.set("from-uuid", i.info.id);
|
|
ExObj.set("from-name", i.info.name);
|
|
ExObj.set("action", "added");
|
|
ExObj.set("element", OriginalArray);
|
|
Explanation_.add(ExObj);
|
|
}
|
|
auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>();
|
|
ReplaceVariablesInArray(OriginalArray, ExpandedArray);
|
|
Configuration->set(SectionName, ExpandedArray);
|
|
} else if (O->isObject(SectionName)) {
|
|
auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>();
|
|
if (Explain_) {
|
|
Poco::JSON::Object ExObj;
|
|
ExObj.set("from-uuid", i.info.id);
|
|
ExObj.set("from-name", i.info.name);
|
|
ExObj.set("action", "added");
|
|
ExObj.set("element", OriginalSection);
|
|
Explanation_.add(ExObj);
|
|
}
|
|
auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>();
|
|
ReplaceVariablesInObject(OriginalSection, ExpandedSection);
|
|
Configuration->set(SectionName, ExpandedSection);
|
|
} else {
|
|
std::cout << " --- unknown element type --- " << O->get(SectionName).toString() << std::endl;
|
|
}
|
|
} else {
|
|
if (Explain_) {
|
|
Poco::JSON::Object ExObj;
|
|
ExObj.set("from-uuid", i.info.id);
|
|
ExObj.set("from-name", i.info.name);
|
|
ExObj.set("action", "ignored");
|
|
ExObj.set("reason", "weight insufficient");
|
|
ExObj.set("element", O->get(SectionName));
|
|
Explanation_.add(ExObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(Config_.empty())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) {
|
|
for(const auto &i:Types) {
|
|
if(i=="*" || Poco::icompare(DeviceType,i)==0)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void APConfig::AddConfiguration(const ProvObjects::DeviceConfigurationElementVec &Elements) {
|
|
for(const auto &i:Elements) {
|
|
if(i.weight==0) {
|
|
VerboseElement VE{ .element = i, .info = ProvObjects::ObjectInfo{} };
|
|
Config_.push_back(VE);
|
|
} else {
|
|
// we need to insert after everything bigger or equal
|
|
auto Hint = std::lower_bound(Config_.cbegin(),Config_.cend(),i.weight,
|
|
[](const VerboseElement &Elem, uint64_t Value) {
|
|
return Elem.element.weight>=Value; });
|
|
VerboseElement VE{ .element = i, .info = ProvObjects::ObjectInfo{}};
|
|
Config_.insert(Hint,VE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void APConfig::AddConfiguration(const Types::UUIDvec_t &UUIDs) {
|
|
for(const auto &i:UUIDs)
|
|
AddConfiguration(i);
|
|
}
|
|
|
|
void APConfig::AddConfiguration(const std::string &UUID) {
|
|
if(UUID.empty())
|
|
return;
|
|
|
|
ProvObjects::DeviceConfiguration Config;
|
|
if(StorageService()->ConfigurationDB().GetRecord("id", UUID, Config)) {
|
|
if(!Config.configuration.empty()) {
|
|
if(DeviceTypeMatch(DeviceType_,Config.deviceTypes)) {
|
|
for(const auto &i:Config.configuration) {
|
|
if(i.weight==0) {
|
|
VerboseElement VE{ .element = i, .info = Config.info};
|
|
Config_.push_back(VE);
|
|
} else {
|
|
// we need to insert after everything bigger or equal
|
|
auto Hint = std::lower_bound(Config_.cbegin(),Config_.cend(),i.weight,
|
|
[](const VerboseElement &Elem, uint64_t Value) {
|
|
return Elem.element.weight>=Value; });
|
|
VerboseElement VE{ .element = i, .info = Config.info};
|
|
Config_.insert(Hint,VE);
|
|
}
|
|
}
|
|
} else {
|
|
Poco::JSON::Object ExObj;
|
|
ExObj.set("from-uuid", Config.info.id);
|
|
ExObj.set("from-name",Config.info.name );
|
|
ExObj.set("action", "ignored");
|
|
ExObj.set("reason", "deviceType mismatch");
|
|
Explanation_.add(ExObj);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void APConfig::AddEntityConfig(const std::string &UUID) {
|
|
ProvObjects::Entity E;
|
|
if(StorageService()->EntityDB().GetRecord("id",UUID,E)) {
|
|
AddConfiguration(E.configurations);
|
|
if(!E.parent.empty()) {
|
|
AddEntityConfig(E.parent);
|
|
}
|
|
} else {
|
|
}
|
|
}
|
|
|
|
void APConfig::AddVenueConfig(const std::string &UUID) {
|
|
ProvObjects::Venue V;
|
|
if(StorageService()->VenueDB().GetRecord("id",UUID,V)) {
|
|
AddConfiguration(V.configurations);
|
|
if(!V.entity.empty()) {
|
|
AddEntityConfig(V.entity);
|
|
} else if(!V.parent.empty()) {
|
|
AddVenueConfig(V.parent);
|
|
}
|
|
} else {
|
|
}
|
|
}
|
|
} |