Compare commits

...

4 Commits

Author SHA1 Message Date
Kumiko18
83c4a543d8 14589 & 14652 & 14655 dev test1 2025-06-02 00:29:46 +00:00
Kumiko18
4d1d817b4c WIFI-14589, WIFI-14652 dev-complete
Signed-off-by: Kumiko18 <alex18_huang@accton.com>
2025-05-29 07:43:59 +00:00
alex18_huang
1c4c080cf7 test commit 2025-05-28 11:28:31 +08:00
alex18_huang
daa773ad73 array version
Signed-off-by: alex18_huang <alex18_huang@accton.com>
2025-05-26 14:00:08 +08:00
20 changed files with 613 additions and 71 deletions

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"chrono": "cpp"
}
}

View File

@@ -153,6 +153,7 @@ add_executable( owgw
src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
src/storage/storage_packages.cpp
src/storage/storage_scripts.cpp src/storage/storage_scripts.h
src/storage/storage_tables.cpp
src/RESTAPI/RESTAPI_routers.cpp

24
ipk-req.json Normal file
View File

@@ -0,0 +1,24 @@
[
{
"jsonrpc": "2.0",
"method": "package_list",
"id": "xxxx"
},
{
"jsonrpc": "2.0",
"method": "package_install",
"params": {
"category": "base/telephony/luci...",
"package": "package_name"
},
"id": "yyyy"
},
{
"jsonrpc": "2.0",
"method": "package_remove",
"params": {
"package": "package_name"
},
"id": "zzzz"
}
]

37
ipk-resp.json Normal file
View File

@@ -0,0 +1,37 @@
[
{
"jsonrpc": "2.0",
"result": {
"serial": "serial number",
"status": {
"error": 0,
"text": "<description of the error or success>"
},
"packages": "<installed packages>",
"lastUpdate": ""
},
"id": "xxxx"
},
{
"jsonrpc": "2.0",
"result": {
"serial": "serial number",
"status": {
"error": 0,
"text": "<description of the error or success>"
}
},
"id": "yyyy"
},
{
"jsonrpc": "2.0",
"result": {
"serial": "serial number",
"status": {
"error": 0,
"text": "<description of the error or success>"
}
},
"id": "zzzz"
}
]

View File

@@ -145,6 +145,7 @@ namespace OpenWifi {
std::uint64_t uuid_=0;
bool Simulated_=false;
std::atomic_uint64_t LastContact_=0;
GWObjects::PackagesOnDevice DevicePackages_;
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
@@ -168,6 +169,9 @@ namespace OpenWifi {
void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
void Process_packagelist(Poco::JSON::Object::Ptr ParamsObj);
void Process_packageinstall(Poco::JSON::Object::Ptr ParamsObj);
void Process_packageremove(Poco::JSON::Object::Ptr ParamsObj);
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
RawLastHealthcheck_ = H;

View File

@@ -105,10 +105,15 @@ namespace OpenWifi {
Restrictions_.developer = Capabilities->getValue<bool>("developer");
}
if(Capabilities->has("secure-rtty")) {
if (Capabilities->has("secure-rtty")) {
RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
}
if (ParamsObj->has("packages")) {
auto Packages = ParamsObj->getArray("packages");
DevicePackages_.from_json(Packages);
}
State_.locale = FindCountryFromIP()->Get(IP);
GWObjects::Device DeviceInfo;
std::lock_guard DbSessionLock(DbSession_->Mutex());
@@ -149,6 +154,8 @@ namespace OpenWifi {
StorageService()->CreateDefaultDevice( DbSession_->Session(),
SerialNumber_, Caps, Firmware, PeerAddress_,
State_.VerifiedCertificate == GWObjects::SIMULATED);
StorageService()->CreateDeviceInstalledPackages(SerialNumber_,
DevicePackages_);
}
} else if (!Daemon()->AutoProvisioning() && !DeviceExists) {
SendKafkaDeviceNotProvisioned(SerialNumber_, Firmware, Compatible_, CId_);
@@ -156,6 +163,7 @@ namespace OpenWifi {
return EndConnection();
} else if (DeviceExists) {
StorageService()->UpdateDeviceCapabilities(DbSession_->Session(), SerialNumber_, Caps);
StorageService()->CreateDeviceInstalledPackages(SerialNumber_, DevicePackages_);
int Updated{0};
if (!Firmware.empty()) {
if (Firmware != DeviceInfo.Firmware) {

View File

@@ -0,0 +1,61 @@
//
// Created by euphokumiko on 2025-05-19.
//
#include "AP_WS_Connection.h"
#include "StorageService.h"
#include "fmt/format.h"
#include "framework/ow_constants.h"
#include <GWKafkaEvents.h>
namespace OpenWifi {
void AP_WS_Connection::Process_packagelist(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) {
poco_warning(Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++;
return;
}
poco_trace(Logger_, fmt::format("PACKAGE_LIST({}): new entry.", CId_));
return;
}
void AP_WS_Connection::Process_packageinstall(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) {
poco_warning(Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++;
return;
}
if (ParamsObj->has(uCentralProtocol::PACKAGE) && ParamsObj->has(uCentralProtocol::CATEGORY)) {
poco_trace(Logger_, fmt::format("PACKAGE_INSTALL({}): new entry.", CId_));
} else {
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
return;
}
}
void AP_WS_Connection::Process_packageremove(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) {
poco_warning(Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++;
return;
}
if (ParamsObj->has(uCentralProtocol::PACKAGE)) {
poco_trace(Logger_, fmt::format("PACKAGE_REMOVE({}): new entry.", CId_));
} else {
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
return;
}
}
} // namespace OpenWifi

12
src/ParsePackageList.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "nlohmann/json.hpp"
namespace OpenWiFi {
}

View File

@@ -155,7 +155,13 @@ namespace OpenWifi::RESTAPI_RPC {
auto ScanObj = rpc_answer->get(uCentralProtocol::RESULT)
.extract<Poco::JSON::Object::Ptr>();
ParseWifiScan(ScanObj, ResultText, Logger);
} else {
}
// else if (Cmd.Command == uCentralProtocol::PACKAGE) {
// auto PkgObj = rpc_answer->get(uCentralProtocol::RESULT)
// .extract<Poco::JSON::Object::Ptr>();
// ParsePackageList(PkgObj, ResultText, Logger);
// }
else {
Poco::JSON::Stringifier::stringify(rpc_answer->get(uCentralProtocol::RESULT),
ResultText);
}

View File

@@ -91,6 +91,8 @@ namespace OpenWifi {
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
return Rtty(UUID, RPC, 60000ms, Restrictions);
};
case APCommands::Commands::package:
return GetPackages();
default:
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
@@ -128,6 +130,28 @@ namespace OpenWifi {
return DeleteChecks();
case APCommands::Commands::statistics:
return DeleteStatistics();
// case APCommands::Commands::package:
// GWObjects::DeviceRestrictions Restrictions;
// if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
// CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
// return BadRequest(RESTAPI::Errors::DeviceNotConnected);
// }
// std::string Command_UUID;
// APCommands::Commands CommandName;
// if (CommandManager()->CommandRunningForDevice(SerialNumberInt_, Command_UUID,
// CommandName)) {
// auto Extra = fmt::format("UUID={} Command={}", Command_UUID,
// APCommands::to_string(CommandName));
// CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
// return BadRequest(RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
// }
// auto UUID = MicroServiceCreateUUID();
// auto RPC = CommandManager()->Next_RPC_ID();
// poco_debug(Logger_, fmt::format("Command {} TID={} can proceed. Identified as {} "
// "and RPCID as {}. thr_id={}",
// Command_, TransactionId_, UUID, RPC,
// Poco::Thread::current()->id()));
// return DeletePackages(UUID, RPC, 12000, Restrictions);
default:
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
@@ -170,7 +194,7 @@ namespace OpenWifi {
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms},
{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
// {APCommands::Commands::package, false, true, &RESTAPI_device_commandHandler::PackageInstall, 120000ms},
};
void RESTAPI_device_commandHandler::DoPost() {
@@ -408,6 +432,52 @@ namespace OpenWifi {
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::GetPackages() {
poco_debug(Logger_, fmt::format("GET-PACKAGES({},{}): TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if(IsDeviceSimulated(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
GWObjects::PackagesOnDevice Pkgs;
StorageService()->GetDeviceInstalledPackages(SerialNumber_, Pkgs);
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
for (const auto &i : Pkgs.packageArray) {
Poco::JSON::Object::Ptr Obj =
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
i.to_json(*Obj);
ArrayObj->add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::PACKAGES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
return ReturnObject(RetObj);
}
// void RESTAPI_device_commandHandler::DeletePackages() {
// poco_debug(Logger_, fmt::format("DELETE-PACKAGES({},{}): TID={} user={} serial={}. thr_id={}",
// TransactionId_, Requester(), SerialNumber_,
// Poco::Thread::current()->id()));
// if(IsDeviceSimulated(SerialNumber_)) {
// CallCanceled("PACKAGEDELETE", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
// return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
// }
// GWObjects::PackageList Pkgs;
// if (StorageService()->GetDeviceInstalledPackages(SerialNumber_, Pkgs)) {
// Poco::JSON::Object RetObj;
// Pkgs.to_json(RetObj);
// RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
// return ReturnObject(RetObj);
// }
// NotFound();
// }
void RESTAPI_device_commandHandler::Ping(
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
@@ -1651,4 +1721,27 @@ namespace OpenWifi {
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
// void RESTAPI_device_commandHandler::InstallPackage(
// const std::string &CMD_UUID, uint64_t CMD_RPC,
// [[maybe_unused]] std::chrono::milliseconds timeout,
// [[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
// poco_debug(Logger_, fmt::format("INSTALLPACKAGE({},{}): TID={} user={} serial={}", CMD_UUID,
// CMD_RPC, TransactionId_, Requester(), SerialNumber_));
// if(IsDeviceSimulated(SerialNumber_)) {
// CallCanceled("INSTALLPACKAGE", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
// return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
// }
// GWObjects::PackageList Pkgs;
// if (StorageService()->GetDeviceInstalledPackages(SerialNumber_, Pkgs)) {
// Poco::JSON::Object RetObj;
// Pkgs.to_json(RetObj);
// RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
// return ReturnObject(RetObj);
// }
// NotFound();
// }
} // namespace OpenWifi

View File

@@ -33,6 +33,8 @@ namespace OpenWifi {
void GetStatus();
void GetChecks();
void DeleteChecks();
void GetPackages();
void DeletePackages();
bool IsDeviceSimulated(std::string &Serial);
@@ -74,6 +76,8 @@ namespace OpenWifi {
const GWObjects::DeviceRestrictions &R);
void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void PackageInstall(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
static auto PathName() {
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};

View File

@@ -0,0 +1,14 @@
//
// Created by Euphokumiko on 2025-05-22.
// Accton Corp.
//
#include "RESTAPI_packages_handler.h"
#include "StorageService.h"
#include "framework/ow_constants.h"
namespace OpenWifi {
void RESTAPI_packages_handler::DoGet() {
}
} // namespace OpenWifi

View File

@@ -0,0 +1,25 @@
//
// Created by Euphokumiko on 2025-05-22.
//
#pragma once
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_packages_handler : public RESTAPIHandler {
public:
RESTAPI_packages_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server,
uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/packages"}; }
void DoGet() final;
void DoDelete() final{};
void DoPost() final{};
void DoPut() final{};
};
} // namespace OpenWifi

View File

@@ -12,9 +12,9 @@
#include "Daemon.h"
#ifdef TIP_GATEWAY_SERVICE
#include "AP_WS_Server.h"
#include "StorageService.h"
#include "CapabilitiesCache.h"
#include "RADIUSSessionTracker.h"
#include "StorageService.h"
#endif
#include "RESTAPI_GWobjects.h"
@@ -31,7 +31,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "serialNumber", SerialNumber);
#ifdef TIP_GATEWAY_SERVICE
field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
field_to_json(Obj, "blackListed",
StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
#endif
field_to_json(Obj, "macAddress", MACAddress);
field_to_json(Obj, "manufacturer", Manufacturer);
@@ -70,12 +71,12 @@ namespace OpenWifi::GWObjects {
#ifdef TIP_GATEWAY_SERVICE
ConnectionState ConState;
#ifdef USE_MEDUSA_CLIENT
auto Res = GS()->GetState(SerialNumber);
if (Res.has_value()) {
Res.value().to_json(SerialNumber,Obj);
auto Res = GS()->GetState(SerialNumber);
if (Res.has_value()) {
Res.value().to_json(SerialNumber, Obj);
#else
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(SerialNumber,Obj);
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(SerialNumber, Obj);
#endif
} else {
field_to_json(Obj, "ipAddress", "");
@@ -172,17 +173,16 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "recorded", Recorded);
}
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "sanity", Sanity);
field_from_json(Obj, "recorded", Recorded);
return true;
} catch(...) {
}
return false;
}
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "sanity", Sanity);
field_from_json(Obj, "recorded", Recorded);
return true;
} catch (...) {
}
return false;
}
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "deviceType", deviceType);
@@ -275,7 +275,8 @@ namespace OpenWifi::GWObjects {
return false;
}
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber, Poco::JSON::Object &Obj) {
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber,
Poco::JSON::Object &Obj) {
field_to_json(Obj, "ipAddress", Address);
field_to_json(Obj, "txBytes", TX);
field_to_json(Obj, "rxBytes", RX);
@@ -299,12 +300,12 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_to_json(Obj, "connectReason", connectReason);
field_to_json(Obj, "uptime", uptime);
field_to_json(Obj, "compatible", Compatible);
field_to_json(Obj, "compatible", Compatible);
#ifdef TIP_GATEWAY_SERVICE
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
#endif
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
field_to_json(Obj, "hasGPS", hasGPS);
field_to_json(Obj, "sanity", sanity);
field_to_json(Obj, "memoryUsed", memoryUsed);
@@ -334,44 +335,44 @@ namespace OpenWifi::GWObjects {
}
}
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "compatible", Compatible);
field_from_json(Obj, "ipAddress", Address);
field_from_json(Obj, "txBytes", TX);
field_from_json(Obj, "rxBytes", RX);
field_from_json(Obj, "messageCount", MessageCount);
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "connected", Connected);
field_from_json(Obj, "firmware", Firmware);
field_from_json(Obj, "lastContact", LastContact);
field_from_json(Obj, "associations_2G", Associations_2G);
field_from_json(Obj, "associations_5G", Associations_5G);
field_from_json(Obj, "associations_6G", Associations_6G);
field_from_json(Obj, "webSocketClients", webSocketClients);
field_from_json(Obj, "websocketPackets", websocketPackets);
field_from_json(Obj, "kafkaClients", kafkaClients);
field_from_json(Obj, "kafkaPackets", kafkaPackets);
field_from_json(Obj, "locale", locale);
field_from_json(Obj, "started", started);
field_from_json(Obj, "sessionId", sessionId);
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_from_json(Obj, "connectReason", connectReason);
field_from_json(Obj, "uptime", uptime);
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
field_from_json(Obj, "hasGPS", hasGPS);
field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "memoryUsed", memoryUsed);
field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "load", load);
field_from_json(Obj, "temperature", temperature);
return true;
} catch(const Poco::Exception &E) {
}
return false;
}
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "compatible", Compatible);
field_from_json(Obj, "ipAddress", Address);
field_from_json(Obj, "txBytes", TX);
field_from_json(Obj, "rxBytes", RX);
field_from_json(Obj, "messageCount", MessageCount);
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "connected", Connected);
field_from_json(Obj, "firmware", Firmware);
field_from_json(Obj, "lastContact", LastContact);
field_from_json(Obj, "associations_2G", Associations_2G);
field_from_json(Obj, "associations_5G", Associations_5G);
field_from_json(Obj, "associations_6G", Associations_6G);
field_from_json(Obj, "webSocketClients", webSocketClients);
field_from_json(Obj, "websocketPackets", websocketPackets);
field_from_json(Obj, "kafkaClients", kafkaClients);
field_from_json(Obj, "kafkaPackets", kafkaPackets);
field_from_json(Obj, "locale", locale);
field_from_json(Obj, "started", started);
field_from_json(Obj, "sessionId", sessionId);
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_from_json(Obj, "connectReason", connectReason);
field_from_json(Obj, "uptime", uptime);
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
field_from_json(Obj, "hasGPS", hasGPS);
field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "memoryUsed", memoryUsed);
field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "load", load);
field_from_json(Obj, "temperature", temperature);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
@@ -819,4 +820,46 @@ namespace OpenWifi::GWObjects {
}
return false;
}
bool PackageInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "version", version);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void PackageInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "version", version);
}
bool PackagesOnDevice::from_json(const Poco::JSON::Array::Ptr &Obj) {
try {
std::ostringstream oss;
Poco::JSON::Stringifier::stringify(Obj, oss);
packageStringArray = oss.str();
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void PackagesOnDevice::to_json(Poco::JSON::Object &Obj) const {
Obj.set("serialNumber", serialNumber);
Poco::JSON::Array packageJsonArray;
for (const auto &pkg : packageArray) {
Poco::JSON::Object pkgObj;
pkg.to_json(pkgObj);
packageJsonArray.add(pkgObj);
}
Obj.set("packageArray", packageJsonArray);
Obj.set("FirstUpdate", Poco::UInt64(FirstUpdate));
Obj.set("LastUpdate", Poco::UInt64(LastUpdate));
}
} // namespace OpenWifi::GWObjects

View File

@@ -545,6 +545,36 @@ namespace OpenWifi::GWObjects {
std::uint64_t when;
std::vector<std::string> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PackageInfo {
std::string name;
std::string version;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackagesOnDevice {
std::string serialNumber;
std::vector<PackageInfo> packageArray;
uint64_t FirstUpdate = 0;
uint64_t LastUpdate = 0;
std::string packageStringArray;
bool from_json(const Poco::JSON::Array::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackageInstall {
std::string serialNumber;
std::uint64_t when;
std::string pkgURL;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PackageRemove {
std::string serialNumber;
std::uint64_t when;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
} // namespace OpenWifi::GWObjects

View File

@@ -282,6 +282,11 @@ namespace OpenWifi {
bool SetDeviceLastRecordedContact(std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool SetDeviceLastRecordedContact(Poco::Data::Session & Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool GetDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs);
bool CreateDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs);
bool UpdateDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs);
bool DeleteDeviceInstalledPackages(std::string &SerialNumber);
int Create_Tables();
int Create_Statistics();
int Create_Devices();
@@ -293,6 +298,7 @@ namespace OpenWifi {
int Create_BlackList();
int Create_FileUploads();
int Create_DefaultFirmwares();
int Create_Packages();
bool AnalyzeCommands(Types::CountedMap &R);
bool AnalyzeDevices(GWObjects::Dashboard &D);

View File

@@ -550,6 +550,8 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *DEBUG = "debug";
static const char *SCRIPT = "script";
static const char *TIMEOUT = "timeout";
static const char *PACKAGE = "package";
static const char *PACKAGES = "packages";
static const char *NEWPASSWORD = "newPassword";
static const char *USERS = "users";
@@ -668,6 +670,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *SIGNATURE = "signature";
static const char *INFO = "info";
static const char *DATE = "date";
static const char *PACKAGE = "package";
static const char *PACKAGES = "packages";
static const char *CATEGORY = "category";
static const char *SERIALNUMBER = "serialNumber";
static const char *COMPATIBLE = "compatible";
@@ -733,7 +738,8 @@ namespace OpenWifi::uCentralProtocol::Events {
ET_EVENT,
ET_WIFISCAN,
ET_ALARM,
ET_REBOOTLOG
ET_REBOOTLOG,
ET_PACKAGE
};
inline EVENT_MSG EventFromString(const std::string &Method) {
@@ -767,6 +773,8 @@ namespace OpenWifi::uCentralProtocol::Events {
return ET_ALARM;
else if (strcmp(REBOOTLOG, Method.c_str()) == 0)
return ET_REBOOTLOG;
else if (strcmp(PACKAGE, Method.c_str()) == 0)
return ET_PACKAGE;
return ET_UNKNOWN;
};
} // namespace OpenWifi::uCentralProtocol::Events
@@ -797,6 +805,7 @@ namespace OpenWifi::APCommands {
powercycle,
fixedconfig,
cablediagnostics,
package,
unknown
};
@@ -812,7 +821,8 @@ namespace OpenWifi::APCommands {
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS,
RESTAPI::Protocol::PACKAGE
};
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }

View File

@@ -0,0 +1,124 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Euphokumiko on 2025-05-20.
// Accton Corp.
//
#include "CentralConfig.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "StorageService.h"
#include "framework/utils.h"
#include "fmt/format.h"
namespace OpenWifi {
const static std::string DB_PackageSelectField{"SerialNumber, Packages, FirstUpdate, LastUpdate"};
// serial pkgs f_update l_update
typedef Poco::Tuple<std::string, std::string, uint64_t, uint64_t> PackageTuple;
bool Storage::CreateDeviceInstalledPackages(std::string &SerialNumber,
GWObjects::PackagesOnDevice &Pkgs) {
try {
Poco::Data::Session Sess(Pool_->get());
Poco::Data::Statement UpSert(Sess);
uint64_t Now = Utils::Now();
std::string St{
"INSERT INTO Packages (SerialNumber, Packages, FirstUpdate, LastUpdate) "
"VALUES (?,?,?,?) "
"ON CONFLICT (SerialNumber) DO "
"UPDATE SET Packages = ?, LastUpdate = ?"};
UpSert << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
Poco::Data::Keywords::use(Pkgs.packageStringArray),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Pkgs.packageStringArray),
Poco::Data::Keywords::use(Now);
UpSert.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
E.displayText()));
}
return false;
}
bool Storage::UpdateDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs) {
return CreateDeviceInstalledPackages(SerialNumber, Pkgs);
}
bool Storage::GetDeviceInstalledPackages(std::string &SerialNumber,
GWObjects::PackagesOnDevice &DevicePackages) {
try {
Poco::Data::Session Sess(Pool_->get());
Poco::Data::Statement Select(Sess);
PackageTuple packageTuple;
std::string TmpSerialNumber;
std::string packageStringArray;
std::string St{"SELECT " + DB_PackageSelectField +
" FROM Packages WHERE SerialNumber=?"};
Select << ConvertParams(St), Poco::Data::Keywords::into(TmpSerialNumber),
Poco::Data::Keywords::into(packageStringArray),
Poco::Data::Keywords::into(DevicePackages.FirstUpdate),
Poco::Data::Keywords::into(DevicePackages.LastUpdate),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
if (!TmpSerialNumber.empty()) {
Poco::JSON::Parser parser;
Poco::Dynamic::Var result = parser.parse(packageStringArray);
Poco::JSON::Array::Ptr jsonArray = result.extract<Poco::JSON::Array::Ptr>();
DevicePackages.serialNumber = TmpSerialNumber;
DevicePackages.packageArray.clear();
for (const auto &item : *jsonArray) {
Poco::JSON::Object::Ptr obj = item.extract<Poco::JSON::Object::Ptr>();
GWObjects::PackageInfo pkg;
pkg.name = obj->getValue<std::string>("name");
pkg.version = obj->getValue<std::string>("version");
DevicePackages.packageArray.emplace_back(pkg);
}
} else {
DevicePackages.packageArray.clear();
}
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
E.displayText()));
}
return false;
}
bool Storage::DeleteDeviceInstalledPackages(std::string &SerialNumber) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM Packages WHERE SerialNumber=?"};
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
E.displayText()));
}
return false;
}
} // namespace OpenWifi

View File

@@ -22,6 +22,7 @@ namespace OpenWifi {
Create_BlackList();
Create_FileUploads();
Create_DefaultFirmwares();
Create_Packages();
return 0;
}
@@ -49,8 +50,7 @@ namespace OpenWifi {
"Data TEXT, "
"Recorded BIGINT, "
"INDEX StatSerial0 (SerialNumber)), ",
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))",
Poco::Data::Keywords::now;
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))", Poco::Data::Keywords::now;
}
return 0;
} catch (const Poco::Exception &E) {
@@ -154,8 +154,7 @@ namespace OpenWifi {
"alter table devices add column lastRecordedContact bigint",
"alter table devices add column simulated boolean",
"alter table devices add column certificateExpiryDate bigint",
"alter table devices add column connectReason TEXT"
};
"alter table devices add column connectReason TEXT"};
for (const auto &i : Script) {
try {
@@ -279,9 +278,7 @@ namespace OpenWifi {
Poco::Data::Keywords::now;
}
std::vector<std::string> Script{
"alter table DefaultConfigs add column Platform text"
};
std::vector<std::string> Script{"alter table DefaultConfigs add column Platform text"};
for (const auto &i : Script) {
try {
@@ -454,4 +451,23 @@ namespace OpenWifi {
return -1;
}
int Storage::Create_Packages() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS Packages ("
"SerialNumber VARCHAR(30) PRIMARY KEY, "
"Packages JSON, "
"FirstUpdate BIGINT, "
"LastUpdate BIGINT"
")",
Poco::Data::Keywords::now;
return 0;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return -1;
}
} // namespace OpenWifi

19
verbosity.json Normal file
View File

@@ -0,0 +1,19 @@
[
{
"serialNumber": "xxxxx",
"packages": "akiho - 98-10-16-71a3b533e-1 \n erichi - 98-12-06-98e79a27f-1 \n ucrun - 2022-02-19-05be6abeb-1 \n vxlan - 7 ..."
},
{
"serialNumber": "xxxxx",
"packages": [
{
"packageName": "akiho",
"version": "98-10-16-71a3b533e-1"
},
{
"packageName": "erichi",
"version": "98-12-06-98e79a27f-1"
}
]
}
]