Fixing Subscriber Device Config Change Update.

This commit is contained in:
stephb9959
2022-05-19 00:24:57 -07:00
parent 74aa7f7f41
commit ce366dc18c
7 changed files with 117 additions and 111 deletions

View File

@@ -15,6 +15,14 @@ namespace OpenWifi {
{
}
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>();
@@ -46,84 +54,6 @@ namespace OpenWifi {
*/
}
bool APConfig::mergeArray(const std::string &K, const Poco::JSON::Array::Ptr &A , const Poco::JSON::Array::Ptr &B, Poco::JSON::Array &Arr) {
if(K=="radios") {
auto BB=Poco::makeShared<Poco::JSON::Array>();
BB = B;
for(const auto &i:*A) {
auto A_Radio = i.extract<Poco::JSON::Object::Ptr>();
// std::cout << "Radio A:" << std::endl;
// ShowJSON(A_Radio);
if(A_Radio->has("band")) {
std::string Band = A_Radio->get("band").toString();
// std::cout << "Looking for band: " << Band << std::endl;
auto B_Radio=Poco::makeShared<Poco::JSON::Object>();
if(FindRadio(Band,B,B_Radio)) {
ShowJSON("Data to be merged", B_Radio);
auto RR = Poco::makeShared<Poco::JSON::Object>();
merge(A_Radio, B_Radio,RR);
ShowJSON("Merged data", RR);
auto CC = Poco::makeShared<Poco::JSON::Array>();
RemoveBand(Band, BB, CC );
BB = CC;
Arr.add(RR);
} else {
Arr.add(A_Radio);
}
}
}
for(const auto &i:*BB)
Arr.add(i);
} else {
Arr = *A;
}
return true;
}
bool APConfig::merge(const Poco::JSON::Object::Ptr & A, const Poco::JSON::Object::Ptr & B, Poco::JSON::Object::Ptr &C) {
for(const auto &i:*A) {
const std::string & K = i.first;
// std::cout << "KEY: " << K << std::endl;
if(B->has(K)) {
if(A->isArray(K)) {
// std::cout << "ISARRAY" << std::endl;
if(B->isArray(K)) {
Poco::JSON::Array Arr;
auto AR1=A->getArray(K);
auto AR2=B->getArray(K);
mergeArray(K,AR1,AR2,Arr);
C->set(K,Arr);
} else {
C->set(K,A->getArray(K));
}
}
else if(A->isObject(K) && B->isObject(K)) {
// std::cout << "ISOBJECT" << std::endl;
auto R=Poco::makeShared<Poco::JSON::Object>();
merge(A->getObject(K),B->getObject(K),R);
C->set(K,R);
}
else {
C->set(K,i.second);
}
} else {
C->set(K,i.second);
}
}
for(const auto &i:*B) {
const std::string & K = i.first;
if(!A->has(K)) {
// std::cout << "Before leave" << std::endl;
// ShowJSON(C);
C->set(K, i.second);
// std::cout << "After leave" << std::endl;
// ShowJSON(C);
}
}
return true;
}
bool APConfig::ReplaceVariablesInObject( const Poco::JSON::Object::Ptr & Original, Poco::JSON::Object::Ptr & Result) {
// get all the names and expand
auto Names = Original->getNames();
@@ -196,15 +126,24 @@ namespace OpenWifi {
if(Config_.empty()) {
Explanation_.clear();
try {
ProvObjects::InventoryTag D;
if(StorageService()->InventoryDB().GetRecord("serialNumber", SerialNumber_, D)) {
if(!D.deviceConfiguration.empty()) {
AddConfiguration(D.deviceConfiguration);
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);
}
}
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.
@@ -277,6 +216,22 @@ namespace OpenWifi {
return false;
}
void APConfig::AddConfiguration(const ProvObjects::DeviceConfigurationElementVec &Elements) {
for(const auto &i:Elements) {
if(i.weight==0) {
VerboseElement VE{ .element = i};
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};
Config_.insert(Hint,VE);
}
}
}
void APConfig::AddConfiguration(const Types::UUIDvec_t &UUIDs) {
for(const auto &i:UUIDs)
AddConfiguration(i);

View File

@@ -19,12 +19,14 @@ namespace OpenWifi {
class APConfig {
public:
explicit APConfig(const std::string & SerialNumber, const std::string & DeviceType, Poco::Logger & L, bool Explain=false);
explicit APConfig(const std::string & SerialNumber, Poco::Logger & L);
[[nodiscard]] bool Get(Poco::JSON::Object::Ptr &Configuration);
void AddConfiguration(const std::string &UUID);
void AddConfiguration(const Types::UUIDvec_t &UUID);
void AddConfiguration(const ProvObjects::DeviceConfigurationElementVec &Elements);
void AddVenueConfig(const std::string &UUID);
void AddEntityConfig(const std::string &UUID);
const Poco::JSON::Array & Explanation() { return Explanation_; };
@@ -37,7 +39,8 @@ namespace OpenWifi {
Types::StringPairVec Errors;
bool Explain_=false;
Poco::JSON::Array Explanation_;
Poco::Logger & Logger() { return Logger_;}
bool Sub_=false;
Poco::Logger & Logger() { return Logger_;}
bool ReplaceVariablesInArray( const Poco::JSON::Array::Ptr & O, Poco::JSON::Array::Ptr & Result);
bool ReplaceVariablesInObject( const Poco::JSON::Object::Ptr & Original, Poco::JSON::Object::Ptr & Result);

View File

@@ -5,6 +5,8 @@
#include "RESTAPI_sub_devices_handler.h"
#include "RESTAPI/RESTAPI_db_helpers.h"
#include "sdks/SDK_sec.h"
#include "sdks/SDK_gw.h"
#include "APConfig.h"
namespace OpenWifi {
@@ -111,7 +113,32 @@ namespace OpenWifi {
if(RawObject->has("configuration")) {
Existing.configuration = UpdateObj.configuration;
}
StorageService()->SubscriberDeviceDB().UpdateRecord("id",uuid,Existing);
ApplyConfiguration(Existing.serialNumber);
return ReturnUpdatedObject(DB_,Existing,*this);
}
bool RESTAPI_sub_devices_handler::ApplyConfiguration(const std::string &SerialNumber) {
auto Device = std::make_shared<APConfig>(SerialNumber, Logger());
auto Configuration = Poco::makeShared<Poco::JSON::Object>();
Poco::JSON::Object ErrorsObj, WarningsObj;
Logger().debug(Poco::format("%s: Computing configuration.",SerialNumber));
if (Device->Get(Configuration)) {
std::ostringstream OS;
Configuration->stringify(OS);
auto Response=Poco::makeShared<Poco::JSON::Object>();
Logger().debug(Poco::format("%s: Sending configuration push.",SerialNumber));
if (SDK::GW::Device::Configure(this, SerialNumber, Configuration, Response)) {
Logger().debug(Poco::format("%s: Sending configuration pushed.",SerialNumber));
return true;
} else {
Logger().debug(Poco::format("%s: Sending configuration failed.",SerialNumber));
return false;
}
} else {
Logger().debug(Poco::format("%s: Configuration is bad.",SerialNumber));
return false;
}
}
}

View File

@@ -20,6 +20,8 @@ namespace OpenWifi {
TransactionId,
Internal){}
static auto PathName() { return std::list<std::string>{"/api/v1/subscriberDevice/{uuid}"}; };
bool ApplyConfiguration(const std::string &SerialNumber);
private:
SubscriberDeviceDB &DB_=StorageService()->SubscriberDeviceDB();
void DoGet() final ;

View File

@@ -4148,10 +4148,10 @@ namespace OpenWifi {
Producer.produce(
cppkafka::MessageBuilder(Msg->Topic()).key(Msg->Key()).payload(Msg->Payload()));
}
} catch (const cppkafka::HandleException &E) {
KafkaManager()->Logger().warning(fmt::format("Caught a Kafka exception (producer): {}", E.what()));
} catch( const Poco::Exception &E) {
KafkaManager()->Logger().log(E);
} catch (const cppkafka::HandleException &E) {
KafkaManager()->Logger().error(fmt::format("{}: Exception --> {}", E.get_error().to_string(), E.what()));
} catch (...) {
KafkaManager()->Logger().error("std::exception");
}
@@ -4212,7 +4212,8 @@ namespace OpenWifi {
if (Msg.get_error()) {
if (!Msg.is_eof()) {
KafkaManager()->Logger().error(fmt::format("Error: {}", Msg.get_error().to_string()));
}if(!AutoCommit)
}
if(!AutoCommit)
Consumer.async_commit(Msg);
continue;
}

View File

@@ -208,7 +208,8 @@ namespace ORM {
int Place=0;
for(const auto &i:Fields) {
FieldNames_[i.Name] = Place;
std::string FieldName = Poco::toLower(i.Name);
FieldNames_[FieldName] = Place;
if(!first) {
CreateFields_ += ", ";
SelectFields_ += ", ";
@@ -218,9 +219,9 @@ namespace ORM {
SelectList_ += "(";
}
CreateFields_ += i.Name + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : "");
SelectFields_ += i.Name ;
UpdateFields_ += i.Name + "=?";
CreateFields_ += FieldName + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : "");
SelectFields_ += FieldName ;
UpdateFields_ += FieldName + "=?";
SelectList_ += "?";
first = false;
Place++;
@@ -235,12 +236,13 @@ namespace ORM {
IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + TableName_+ " (";
bool first_entry=true;
for(const auto &k:j.Entries) {
assert(FieldNames_.find(k.FieldName) != FieldNames_.end());
auto IndexFieldName = Poco::toLower(k.FieldName);
assert(ValidFieldName(IndexFieldName));
if(!first_entry) {
IndexLine += " , ";
}
first_entry = false;
IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ;
IndexLine += IndexFieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ;
}
IndexLine += " )";
IndexCreation_.template emplace_back(IndexLine);
@@ -255,12 +257,13 @@ namespace ORM {
IndexLine += " INDEX " + j.Name + " ( " ;
bool first_entry=true;
for(const auto &k:j.Entries) {
assert(FieldNames_.find(k.FieldName) != FieldNames_.end());
auto IndexFieldName = Poco::toLower(k.FieldName);
assert(FieldNames_.find(IndexFieldName) != FieldNames_.end());
if(!first_entry) {
IndexLine += " ,";
}
first_entry = false;
IndexLine += k.FieldName + std::string(k.Type == Indextype::ASC ? " ASC" : " DESC");
IndexLine += IndexFieldName + std::string(k.Type == Indextype::ASC ? " ASC" : " DESC");
}
IndexLine += " ) ";
}
@@ -275,27 +278,27 @@ namespace ORM {
[[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; };
inline std::string OP(field_name_t F, SqlComparison O , bool V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
assert(ValidFieldName(F));
return std::string{"("} + F + SQLCOMPS[O] + (V ? "true" : "false") + ")" ;
}
inline std::string OP(field_name_t F, SqlComparison O , int V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
assert(ValidFieldName(F));
return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
}
inline std::string OP(field_name_t F, SqlComparison O , uint64_t V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
assert(ValidFieldName(F));
return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
}
std::string OP(field_name_t F, SqlComparison O , const std::string & V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
assert(ValidFieldName(F));
return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
}
std::string OP(field_name_t F, SqlComparison O , const char * V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
assert(ValidFieldName(F));
return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
}
@@ -417,7 +420,7 @@ namespace ORM {
template<typename T> bool GetRecord(field_name_t FieldName, const T & Value, RecordType & R) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert(ValidFieldName(FieldName));
if(Cache_) {
if(Cache_->GetFromCache(FieldName, Value, R))
@@ -455,7 +458,7 @@ namespace ORM {
typename T0, typename T1> bool GR(field_name_t FieldName, T & R,T0 &V0, T1 &V1) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert( ValidFieldName(FieldName) );
Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session);
@@ -513,7 +516,7 @@ namespace ORM {
template <typename T> bool UpdateRecord(field_name_t FieldName, const T & Value, const RecordType & R) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert( ValidFieldName(FieldName) );
Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Update(Session);
@@ -567,7 +570,7 @@ namespace ORM {
template <typename T> bool GetNameAndDescription(field_name_t FieldName, const T & Value, std::string & Name, std::string & Description ) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert( ValidFieldName(FieldName) );
Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session);
RecordTuple RT;
@@ -594,7 +597,7 @@ namespace ORM {
template <typename T> bool DeleteRecord(field_name_t FieldName, const T & Value) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert( ValidFieldName(FieldName) );
Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Delete(Session);
@@ -632,7 +635,7 @@ namespace ORM {
bool Exists(field_name_t FieldName, const std::string & Value) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert( ValidFieldName(FieldName) );
RecordType R;
if(GetRecord(FieldName,Value,R))
@@ -721,7 +724,7 @@ namespace ORM {
template <typename X> bool ManipulateVectorMember( X T, field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID, bool Add) {
try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() );
assert( ValidFieldName(FieldName) );
RecordType R;
if(GetRecord(FieldName, ParentUUID, R)) {
@@ -870,6 +873,15 @@ namespace ORM {
return false;
}
inline bool ValidFieldName(const std::string &FieldName) {
return FieldNames_.find(Poco::toLower(FieldName)) != FieldNames_.end();
}
inline bool ValidFieldName(const char *FieldName) {
std::string Field{FieldName};
return ValidFieldName(Field);
}
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(From<1) From=0;
switch(Type_) {

View File

@@ -415,7 +415,13 @@ namespace OpenWifi::uCentralProtocol {
static const char *SCRIPT = "script";
static const char *TYPE = "type";
}
static const char *RADIUS = "radius";
static const char *RADIUSDATA = "data";
static const char *RADIUSACCT = "acct";
static const char *RADIUSAUTH = "auth";
static const char *RADIUSDST = "dst";
}
namespace OpenWifi::uCentralProtocol::Events {