mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov.git
synced 2025-10-29 17:52:28 +00:00
Fixing Subscriber Device Config Change Update.
This commit is contained in:
127
src/APConfig.cpp
127
src/APConfig.cpp
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user