diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..850af89
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+owanalytics
\ No newline at end of file
diff --git a/.idea/dictionaries/stephb.xml b/.idea/dictionaries/stephb.xml
new file mode 100644
index 0000000..d141969
--- /dev/null
+++ b/.idea/dictionaries/stephb.xml
@@ -0,0 +1,7 @@
+
+
+
+ bourque
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 528bb8d..b6983ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,7 +84,7 @@ add_executable(owanalytics
src/RESTAPI/RESTAPI_routers.cpp
src/Daemon.cpp src/Daemon.h
src/Dashboard.h src/Dashboard.cpp
- src/StorageService.cpp src/StorageService.h src/RESTObjects/RESTAPI_AnalyticsObjects.cpp src/RESTObjects/RESTAPI_AnalyticsObjects.h src/StateReceiver.cpp src/StateReceiver.h src/VenueWatcher.cpp src/VenueWatcher.h src/VenueCoordinator.cpp src/VenueCoordinator.h src/sdks/SDK_prov.cpp src/sdks/SDK_prov.h src/storage/storage_boards.cpp src/storage/storage_boards.h src/RESTAPI/RESTAPI_board_list_handler.cpp src/RESTAPI/RESTAPI_board_list_handler.h src/RESTAPI/RESTAPI_board_handler.cpp src/RESTAPI/RESTAPI_board_handler.h src/RESTAPI/RESTAPI_analytics_db_helpers.h src/APStats.cpp src/APStats.h src/dict_ssid.h src/dict_ue.h src/dict_bssid.h src/DeviceStatusReceiver.cpp src/DeviceStatusReceiver.h src/RESTAPI/RESTAPI_board_devices_handler.cpp src/RESTAPI/RESTAPI_board_devices_handler.h src/HealthReceiver.cpp src/HealthReceiver.h src/StatFunc.h)
+ src/StorageService.cpp src/StorageService.h src/RESTObjects/RESTAPI_AnalyticsObjects.cpp src/RESTObjects/RESTAPI_AnalyticsObjects.h src/StateReceiver.cpp src/StateReceiver.h src/VenueWatcher.cpp src/VenueWatcher.h src/VenueCoordinator.cpp src/VenueCoordinator.h src/sdks/SDK_prov.cpp src/sdks/SDK_prov.h src/storage/storage_boards.cpp src/storage/storage_boards.h src/RESTAPI/RESTAPI_board_list_handler.cpp src/RESTAPI/RESTAPI_board_list_handler.h src/RESTAPI/RESTAPI_board_handler.cpp src/RESTAPI/RESTAPI_board_handler.h src/RESTAPI/RESTAPI_analytics_db_helpers.h src/APStats.cpp src/APStats.h src/dict_ssid.h src/dict_ue.h src/dict_bssid.h src/DeviceStatusReceiver.cpp src/DeviceStatusReceiver.h src/RESTAPI/RESTAPI_board_devices_handler.cpp src/RESTAPI/RESTAPI_board_devices_handler.h src/HealthReceiver.cpp src/HealthReceiver.h src/StatFunc.h src/RESTAPI/RESTAPI_board_timepoint_handler.cpp src/RESTAPI/RESTAPI_board_timepoint_handler.h src/storage/storage_timepoints.cpp src/storage/storage_timepoints.h)
target_link_libraries(owanalytics PUBLIC
${Poco_LIBRARIES} ${MySQL_LIBRARIES}
diff --git a/build b/build
index 3cacc0b..2edeafb 100644
--- a/build
+++ b/build
@@ -1 +1 @@
-12
\ No newline at end of file
+20
\ No newline at end of file
diff --git a/openapi/owanalytics.yaml b/openapi/owanalytics.yaml
index 8fcccfd..3d822d0 100644
--- a/openapi/owanalytics.yaml
+++ b/openapi/owanalytics.yaml
@@ -230,6 +230,213 @@ components:
items:
$ref: '#/components/schemas/DeviceInfo'
+ MSDU_entry:
+ type: object
+ properties:
+ rx_msdu:
+ type: integer
+ format: int64
+ tx_msdu:
+ type: integer
+ format: int64
+ tx_msdu_failed:
+ type: integer
+ format: int64
+ tx_msdu_retries:
+ type: integer
+ format: int64
+
+ UE_rate:
+ type: object
+ properties:
+ bitrate:
+ type: integer
+ format: int64
+ mcs:
+ type: integer
+ format: int64
+ nss:
+ type: integer
+ format: int64
+ chwidth:
+ type: integer
+ format: int64
+ ht:
+ type: boolean
+ sgi:
+ type:
+ boolean
+
+ UETimePoint:
+ type: object
+ properties:
+ association_bssid:
+ type: integer
+ format: int64
+ station:
+ type: integer
+ format: int64
+ rssi:
+ type: integer
+ format: int64
+ tx_bytes:
+ type: integer
+ format: int64
+ rx_bytes:
+ type: integer
+ format: int64
+ tx_duration:
+ type: integer
+ format: int64
+ rx_packets:
+ type: integer
+ format: int64
+ tx_packets:
+ type: integer
+ format: int64
+ tx_retries:
+ type: integer
+ format: int64
+ tx_failed:
+ type: integer
+ format: int64
+ connected:
+ type: integer
+ format: int64
+ inactive:
+ type: integer
+ format: int64
+ tx_rate:
+ $ref: '#/components/schemas/UE_rate'
+ rx_rate:
+ $ref: '#/components/schemas/UE_rate'
+ msdus:
+ type: array
+ items:
+ $ref: '#/components/schemas/MSDU_entry'
+
+ SSIDTimePoint:
+ type: object
+ properties:
+ bssid:
+ type: string
+ mode:
+ type: string
+ ssid:
+ type: string
+ associations:
+ type: array
+ items:
+ $ref: '#/components/schemas/UETimePoint'
+
+ APTimePoint:
+ type: object
+ properties:
+ collisions:
+ type: integer
+ format: int64
+ multicast:
+ type: integer
+ format: int64
+ rx_bytes:
+ type: integer
+ format: int64
+ rx_dropped:
+ type: integer
+ format: int64
+ rx_errors:
+ type: integer
+ format: int64
+ rx_packets:
+ type: integer
+ format: int64
+ tx_bytes:
+ type: integer
+ format: int64
+ tx_dropped:
+ type: integer
+ format: int64
+ tx_errors:
+ type: integer
+ format: int64
+ tx_packets:
+ type: integer
+ format: int64
+
+ RadioTimePoint:
+ type: object
+ properties:
+ band:
+ type: integer
+ format: int64
+ radio_channel:
+ type: integer
+ format: int64
+ active_ms:
+ type: integer
+ format: int64
+ busy_ms:
+ type: integer
+ format: int64
+ receive_ms:
+ type: integer
+ format: int64
+ transmit_ms:
+ type: integer
+ format: int64
+ tx_power:
+ type: integer
+ format: int64
+ channel:
+ type: integer
+ format: int64
+ temperature:
+ type: integer
+ format: int64
+ noise:
+ type: integer
+ format: int64
+
+ DeviceTimePoint:
+ type: object
+ properties:
+ timestamp:
+ type: integer
+ format: int64
+ ap_data:
+ $ref: '#/components/schemas/APTimePoint'
+ ssid_data:
+ type: array
+ items:
+ $ref: '#/components/schemas/SSIDTimePoint'
+ radio_data:
+ type: array
+ items:
+ $ref: '#/components/schemas/RadioTimePoint'
+ device_info:
+ $ref: '#/components/schemas/DeviceInfo'
+
+ DeviceTimePointList:
+ type: object
+ properties:
+ points:
+ type: array
+ items:
+ $ref: '#/components/schemas/DeviceTimePoint'
+
+ DeviceTimePointStats:
+ type: object
+ properties:
+ firstPoint:
+ type: integer
+ format: int64
+ lastPoint:
+ type: integer
+ format: int64
+ count:
+ type: integer
+ format: int64
+
#########################################################################################
##
## These are endpoints that all services in the OPenWiFI stack must provide
@@ -603,6 +810,59 @@ paths:
404:
$ref: '#/components/responses/NotFound'
+ /board/{id}/timepoint:
+ get:
+ tags:
+ - Board data
+ summary: retrieve board data for a given time period.
+ operationId: getBoardTimepoint
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: string
+ format: uuid
+ required: true
+ - in: query
+ name: fromDate
+ schema:
+ type: integer
+ required: false
+ - in: query
+ name: endDate
+ schema:
+ type: integer
+ required: false
+ - in: query
+ name: maxRecords
+ schema:
+ type: integer
+ default: 100
+ required: false
+
+ - in: query
+ name: stats
+ schema:
+ type: boolean
+ required: false
+
+ responses:
+ 200:
+ description: Successfull retrieval of timepoints
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - $ref: '#/components/schemas/DeviceTimePointList'
+ - $ref: '#/components/schemas/DeviceTimePointStats'
+ 400:
+ $ref: '#/components/responses/BadRequest'
+ 403:
+ $ref: '#/components/responses/Unauthorized'
+ 404:
+ $ref: '#/components/responses/NotFound'
+
+
/iptocountry:
get:
tags:
diff --git a/src/APStats.cpp b/src/APStats.cpp
index 4811326..d511863 100644
--- a/src/APStats.cpp
+++ b/src/APStats.cpp
@@ -4,6 +4,7 @@
#include "APStats.h"
#include "dict_ssid.h"
+#include "StorageService.h"
namespace OpenWifi {
@@ -94,16 +95,12 @@ namespace OpenWifi {
auto ref = radio["$ref"];
auto radio_parts = Poco::StringTokenizer(ref, "/");
if(radio_parts.count()==3)
- radio_location = std::atoi(radio_parts[2].c_str());
+ radio_location = std::strtol(radio_parts[2].c_str(), nullptr,10);
}
}
- std::string bssid, mode, ssid_name;
- GetJSON("bssid",ssid,bssid, std::string{""});
- SSIDTP.bssid = Utils::MACToInt(bssid);
- GetJSON("mode",ssid,mode, std::string{""} );
- SSIDTP.mode = AnalyticsObjects::SSID_Mode(mode);
- GetJSON("ssid",ssid,ssid_name, std::string{""} );
- SSIDTP.ssid = SSID_DICT()->Add(ssid_name);
+ GetJSON("bssid",ssid,SSIDTP.bssid, std::string{""});
+ GetJSON("mode",ssid,SSIDTP.mode, std::string{""} );
+ GetJSON("ssid",ssid,SSIDTP.ssid, std::string{""} );
if (ssid.contains("associations") && ssid["associations"].is_array()) {
auto associations = ssid["associations"];
auto it = radio_band.find(radio_location);
@@ -118,11 +115,7 @@ namespace OpenWifi {
}
for(const auto &association:associations) {
AnalyticsObjects::UETimePoint TP;
- std::string association_bssid,station;
- GetJSON("bssid",association,association_bssid, std::string{""} );
- GetJSON("station",association,station, std::string{} );
- TP.association_bssid = Utils::MACToInt(association_bssid);
- TP.station = Utils::MACToInt(station);
+ GetJSON("station",association,TP.station, std::string{} );
GetJSON("rssi",association,TP.rssi, (int64_t)0 );
GetJSON("tx_bytes",association,TP.tx_bytes, (uint64_t)0 );
GetJSON("rx_bytes",association,TP.rx_bytes, (uint64_t)0 );
@@ -137,7 +130,7 @@ namespace OpenWifi {
if(association.contains("msdu") && association["msdu"].is_array()) {
auto msdus = association["msdu"];
for(const auto &msdu:msdus) {
- AnalyticsObjects::msdu_entry E;
+ AnalyticsObjects::MSDU_entry E;
GetJSON("rx_msdu",msdu,E.rx_msdu, (uint64_t)0 );
GetJSON("tx_msdu",msdu,E.tx_msdu, (uint64_t)0 );
GetJSON("tx_msdu_failed",msdu,E.tx_msdu_failed, (uint64_t)0 );
@@ -146,6 +139,26 @@ namespace OpenWifi {
}
}
+ if(association.contains("tx_rate")) {
+ auto tx_rate = association["tx_rate"];
+ GetJSON("bitrate",tx_rate,TP.tx_rate.bitrate, (uint64_t)0 );
+ GetJSON("mcs",tx_rate,TP.tx_rate.mcs, (uint64_t)0 );
+ GetJSON("nss",tx_rate,TP.tx_rate.nss, (uint64_t)0 );
+ GetJSON("chwidth",tx_rate,TP.tx_rate.chwidth, (uint64_t)0 );
+ GetJSON("ht",tx_rate,TP.tx_rate.ht, false );
+ GetJSON("sgi",tx_rate,TP.tx_rate.sgi, false );
+ }
+
+ if(association.contains("rx_rate")) {
+ auto rx_rate = association["rx_rate"];
+ GetJSON("bitrate",rx_rate,TP.rx_rate.bitrate, (uint64_t)0 );
+ GetJSON("mcs",rx_rate,TP.rx_rate.mcs, (uint64_t)0 );
+ GetJSON("nss",rx_rate,TP.rx_rate.nss, (uint64_t)0 );
+ GetJSON("chwidth",rx_rate,TP.rx_rate.chwidth, (uint64_t)0 );
+ GetJSON("ht",rx_rate,TP.rx_rate.ht, false );
+ GetJSON("sgi",rx_rate,TP.rx_rate.sgi, false );
+ }
+
SSIDTP.associations.push_back(TP);
}
}
@@ -161,11 +174,17 @@ namespace OpenWifi {
std::cout << Utils::IntToSerialNumber(mac_) << ": stats failed parsing." ;
std::cout << *State << std::endl;
}
+
+ DTP.id = MicroService::instance().CreateUUID();
+ DTP.boardId = boardId_;
+ StorageService()->TimePointsDB().CreateRecord(DTP);
+
DTP_.push_back(DTP);
if(DTP_.size()>1000) {
DTP_.erase(DTP_.begin());
}
+
std::cout << "Serial: " << Utils::IntToSerialNumber(mac_) << " points: " << DTP_.size() << std::endl;
}
diff --git a/src/APStats.h b/src/APStats.h
index fc61455..1554c9d 100644
--- a/src/APStats.h
+++ b/src/APStats.h
@@ -18,7 +18,10 @@ namespace OpenWifi {
class AP {
public:
- explicit AP(uint64_t mac) : mac_(mac) {
+ explicit AP(uint64_t mac, const std::string &BoardId) :
+ mac_(mac),
+ boardId_(BoardId)
+ {
DI_.serialNumber = Utils::IntToSerialNumber(mac);
}
@@ -28,8 +31,9 @@ namespace OpenWifi {
const AnalyticsObjects::DeviceInfo & Info() const { return DI_; }
private:
- uint64_t mac_=0;
- AnalyticsObjects::DeviceInfo DI_;
- std::vector DTP_;
+ uint64_t mac_=0;
+ std::string boardId_;
+ AnalyticsObjects::DeviceInfo DI_;
+ std::vector DTP_;
};
}
diff --git a/src/RESTAPI/RESTAPI_board_timepoint_handler.cpp b/src/RESTAPI/RESTAPI_board_timepoint_handler.cpp
new file mode 100644
index 0000000..1f168cb
--- /dev/null
+++ b/src/RESTAPI/RESTAPI_board_timepoint_handler.cpp
@@ -0,0 +1,39 @@
+//
+// Created by stephane bourque on 2022-03-21.
+//
+
+#include "RESTAPI_board_timepoint_handler.h"
+#include "StorageService.h"
+
+namespace OpenWifi {
+ void RESTAPI_board_timepoint_handler::DoGet() {
+ auto id = GetBinding("id","");
+ if(id.empty()) {
+ return BadRequest(RESTAPI::Errors::MissingUUID);
+ }
+
+ AnalyticsObjects::BoardInfo B;
+ if(!StorageService()->BoardsDB().GetRecord("id",id,B)) {
+ return NotFound();
+ }
+
+ auto fromDate = GetParameter("fromDate",0);
+ auto endDate = GetParameter("endDate",0);
+ auto maxRecords = GetParameter("maxRecords",100);
+ auto stats = GetBoolParameter("stats");
+
+ if(stats) {
+ AnalyticsObjects::DeviceTimePointStats DTPS;
+ Poco::JSON::Object Answer;
+ DB_.GetStats(id,DTPS);
+ DTPS.to_json(Answer);
+ return ReturnObject(Answer);
+ }
+
+ AnalyticsObjects::DeviceTimePointList Points;
+ StorageService()->TimePointsDB().SelectRecords(fromDate, endDate, maxRecords, Points.points);
+ Poco::JSON::Object Answer;
+ Points.to_json(Answer);
+ return ReturnObject(Answer);
+ }
+}
\ No newline at end of file
diff --git a/src/RESTAPI/RESTAPI_board_timepoint_handler.h b/src/RESTAPI/RESTAPI_board_timepoint_handler.h
new file mode 100644
index 0000000..8169128
--- /dev/null
+++ b/src/RESTAPI/RESTAPI_board_timepoint_handler.h
@@ -0,0 +1,32 @@
+//
+// Created by stephane bourque on 2022-03-21.
+//
+
+#pragma once
+
+#include "framework/MicroService.h"
+#include "StorageService.h"
+
+namespace OpenWifi {
+
+ class RESTAPI_board_timepoint_handler : public RESTAPIHandler {
+ public:
+ RESTAPI_board_timepoint_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
+ : RESTAPIHandler(bindings, L,
+ std::vector{
+ Poco::Net::HTTPRequest::HTTP_GET,
+ Poco::Net::HTTPRequest::HTTP_OPTIONS},
+ Server,
+ TransactionId,
+ Internal){}
+
+ static const std::list PathName() { return std::list{"/api/v1/board/{id}/timepoint"}; };
+
+ private:
+ TimePointDB & DB_=StorageService()->TimePointsDB();
+ void DoGet() final;
+ void DoPost() final {};
+ void DoPut() final {};
+ void DoDelete() final {};
+ };
+}
diff --git a/src/RESTAPI/RESTAPI_routers.cpp b/src/RESTAPI/RESTAPI_routers.cpp
index 8863bf7..aed6dc3 100644
--- a/src/RESTAPI/RESTAPI_routers.cpp
+++ b/src/RESTAPI/RESTAPI_routers.cpp
@@ -6,26 +6,31 @@
#include "RESTAPI/RESTAPI_board_list_handler.h"
#include "RESTAPI/RESTAPI_board_handler.h"
#include "RESTAPI/RESTAPI_board_devices_handler.h"
+#include "RESTAPI/RESTAPI_board_timepoint_handler.h"
namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings,
- Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
+ Poco::Logger & L, RESTAPI_GenericServer & S,
+ uint64_t TransactionId) {
return RESTAPI_Router<
RESTAPI_system_command,
RESTAPI_board_devices_handler,
RESTAPI_board_handler,
- RESTAPI_board_list_handler
+ RESTAPI_board_list_handler,
+ RESTAPI_board_timepoint_handler
>(Path,Bindings,L, S, TransactionId);
}
Poco::Net::HTTPRequestHandler * RESTAPI_IntRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings,
- Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
+ Poco::Logger & L, RESTAPI_GenericServer & S,
+ uint64_t TransactionId) {
return RESTAPI_Router_I<
RESTAPI_system_command,
RESTAPI_board_devices_handler,
RESTAPI_board_handler,
- RESTAPI_board_list_handler
+ RESTAPI_board_list_handler,
+ RESTAPI_board_timepoint_handler
>(Path, Bindings, L, S, TransactionId);
}
diff --git a/src/RESTObjects/RESTAPI_AnalyticsObjects.cpp b/src/RESTObjects/RESTAPI_AnalyticsObjects.cpp
index afadf6f..ff7ce40 100644
--- a/src/RESTObjects/RESTAPI_AnalyticsObjects.cpp
+++ b/src/RESTObjects/RESTAPI_AnalyticsObjects.cpp
@@ -129,8 +129,31 @@ namespace OpenWifi::AnalyticsObjects {
return false;
}
+ void UE_rate::to_json(Poco::JSON::Object &Obj) const {
+ field_to_json(Obj,"bitrate",bitrate);
+ field_to_json(Obj,"mcs",mcs);
+ field_to_json(Obj,"nss",nss);
+ field_to_json(Obj,"ht",ht);
+ field_to_json(Obj,"sgi",sgi);
+ field_to_json(Obj,"chwidth",chwidth);
+ }
+
+ bool UE_rate::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"bitrate",bitrate);
+ field_from_json(Obj,"mcs",mcs);
+ field_from_json(Obj,"nss",nss);
+ field_from_json(Obj,"ht",ht);
+ field_from_json(Obj,"sgi",sgi);
+ field_from_json(Obj,"chwidth",chwidth);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
void UETimePoint::to_json(Poco::JSON::Object &Obj) const {
- field_to_json(Obj,"association_bssid",association_bssid);
field_to_json(Obj,"station",station);
field_to_json(Obj,"rssi",rssi);
field_to_json(Obj,"tx_bytes",tx_bytes);
@@ -142,6 +165,30 @@ namespace OpenWifi::AnalyticsObjects {
field_to_json(Obj,"tx_failed",tx_failed);
field_to_json(Obj,"connected",connected);
field_to_json(Obj,"inactive",inactive);
+ field_to_json(Obj,"tx_rate",tx_rate);
+ field_to_json(Obj,"rx_rate",rx_rate);
+ }
+
+ bool UETimePoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"station",station);
+ field_from_json(Obj,"rssi",rssi);
+ field_from_json(Obj,"tx_bytes",tx_bytes);
+ field_from_json(Obj,"rx_bytes",rx_bytes);
+ field_from_json(Obj,"tx_duration",tx_duration);
+ field_from_json(Obj,"rx_packets",rx_packets);
+ field_from_json(Obj,"tx_packets",tx_packets);
+ field_from_json(Obj,"tx_retries",tx_retries);
+ field_from_json(Obj,"tx_failed",tx_failed);
+ field_from_json(Obj,"connected",connected);
+ field_from_json(Obj,"inactive",inactive);
+ field_from_json(Obj,"tx_rate",tx_rate);
+ field_from_json(Obj,"rx_rate",rx_rate);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
}
void APTimePoint::to_json(Poco::JSON::Object &Obj) const {
@@ -158,13 +205,46 @@ namespace OpenWifi::AnalyticsObjects {
field_to_json(Obj,"tx_packets",tx_packets);
}
- void msdu_entry::to_json(Poco::JSON::Object &Obj) const {
+ bool APTimePoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"collisions",collisions);
+ field_from_json(Obj,"multicast",multicast);
+ field_from_json(Obj,"rx_bytes",rx_bytes);
+ field_from_json(Obj,"rx_dropped",rx_dropped);
+ field_from_json(Obj,"rx_errors",rx_errors);
+ field_from_json(Obj,"rx_packets",rx_packets);
+ field_from_json(Obj,"tx_bytes",tx_bytes);
+ field_from_json(Obj,"tx_packets",tx_packets);
+ field_from_json(Obj,"tx_dropped",tx_dropped);
+ field_from_json(Obj,"tx_errors",tx_errors);
+ field_from_json(Obj,"tx_packets",tx_packets);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
+ void MSDU_entry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"rx_msdu",rx_msdu);
field_to_json(Obj,"tx_msdu",tx_msdu);
field_to_json(Obj,"tx_msdu_failed",tx_msdu_failed);
field_to_json(Obj,"tx_msdu_retries",tx_msdu_retries);
}
+ bool MSDU_entry::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"rx_msdu",rx_msdu);
+ field_from_json(Obj,"tx_msdu",tx_msdu);
+ field_from_json(Obj,"tx_msdu_failed",tx_msdu_failed);
+ field_from_json(Obj,"tx_msdu_retries",tx_msdu_retries);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
void RadioTimePoint::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"band",band);
field_to_json(Obj,"radio_channel",radio_channel);
@@ -178,6 +258,25 @@ namespace OpenWifi::AnalyticsObjects {
field_to_json(Obj,"noise",noise);
}
+ bool RadioTimePoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"band",band);
+ field_from_json(Obj,"radio_channel",radio_channel);
+ field_from_json(Obj,"active_ms",active_ms);
+ field_from_json(Obj,"busy_ms",busy_ms);
+ field_from_json(Obj,"receive_ms",receive_ms);
+ field_from_json(Obj,"transmit_ms",transmit_ms);
+ field_from_json(Obj,"tx_power",tx_power);
+ field_from_json(Obj,"channel",channel);
+ field_from_json(Obj,"temperature",temperature);
+ field_from_json(Obj,"noise",noise);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
void SSIDTimePoint::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"bssid",bssid);
field_to_json(Obj,"mode",mode);
@@ -185,11 +284,75 @@ namespace OpenWifi::AnalyticsObjects {
field_to_json(Obj,"associations",associations);
}
+ bool SSIDTimePoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"bssid",bssid);
+ field_from_json(Obj,"mode",mode);
+ field_from_json(Obj,"ssid",ssid);
+ field_from_json(Obj,"associations",associations);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
void DeviceTimePoint::to_json(Poco::JSON::Object &Obj) const {
+ field_to_json(Obj,"id",id);
+ field_to_json(Obj,"boardId",boardId);
field_to_json(Obj,"timestamp",timestamp);
field_to_json(Obj,"ap_data",ap_data);
field_to_json(Obj,"ssid_data",ssid_data);
field_to_json(Obj,"radio_data",radio_data);
field_to_json(Obj,"device_info",device_info);
}
+
+ bool DeviceTimePoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"id",id);
+ field_from_json(Obj,"boardId",boardId);
+ field_from_json(Obj,"timestamp",timestamp);
+ field_from_json(Obj,"ap_data",ap_data);
+ field_from_json(Obj,"ssid_data",ssid_data);
+ field_from_json(Obj,"radio_data",radio_data);
+ field_from_json(Obj,"device_info",device_info);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
+ void DeviceTimePointList::to_json(Poco::JSON::Object &Obj) const {
+ field_to_json(Obj,"points",points);
+ }
+
+ bool DeviceTimePointList::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"points",points);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
+ void DeviceTimePointStats::to_json(Poco::JSON::Object &Obj) const {
+ field_to_json(Obj,"firstPoint",firstPoint);
+ field_to_json(Obj,"lastPoint",lastPoint);
+ field_to_json(Obj,"count",count);
+ }
+
+ bool DeviceTimePointStats::from_json(const Poco::JSON::Object::Ptr &Obj) {
+ try {
+ field_from_json(Obj,"firstPoint",firstPoint);
+ field_from_json(Obj,"lastPoint",lastPoint);
+ field_from_json(Obj,"count",count);
+ return true;
+ } catch(...) {
+
+ }
+ return false;
+ }
+
}
\ No newline at end of file
diff --git a/src/RESTObjects/RESTAPI_AnalyticsObjects.h b/src/RESTObjects/RESTAPI_AnalyticsObjects.h
index a066dbe..819526d 100644
--- a/src/RESTObjects/RESTAPI_AnalyticsObjects.h
+++ b/src/RESTObjects/RESTAPI_AnalyticsObjects.h
@@ -28,7 +28,6 @@ namespace OpenWifi {
bool monitorSubVenues = false;
void to_json(Poco::JSON::Object &Obj) const;
-
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
@@ -37,7 +36,6 @@ namespace OpenWifi {
std::vector venueList;
void to_json(Poco::JSON::Object &Obj) const;
-
bool from_json(const Poco::JSON::Object::Ptr &Obj);
inline bool operator<(const BoardInfo &bb) const {
@@ -75,7 +73,6 @@ namespace OpenWifi {
double memory;
void to_json(Poco::JSON::Object &Obj) const;
-
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
@@ -83,7 +80,6 @@ namespace OpenWifi {
std::vector devices;
void to_json(Poco::JSON::Object &Obj) const;
-
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
@@ -91,18 +87,30 @@ namespace OpenWifi {
band_2g = 0, band_5g = 1, band_6g = 2
};
- struct msdu_entry {
+ struct MSDU_entry {
uint64_t rx_msdu = 0,
tx_msdu = 0,
tx_msdu_failed = 0,
tx_msdu_retries = 0;
void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
+ };
+
+ struct UE_rate {
+ uint64_t bitrate=0;
+ uint64_t mcs=0;
+ uint64_t nss=0;
+ bool ht=false;
+ bool sgi=false;
+ uint64_t chwidth=0;
+
+ void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct UETimePoint {
- uint64_t association_bssid = 0,
- station = 0;
+ std::string station;
int64_t rssi = 0;
uint64_t tx_bytes = 0,
rx_bytes = 0,
@@ -113,9 +121,12 @@ namespace OpenWifi {
tx_failed = 0,
connected = 0,
inactive = 0;
- std::vector msdus;
+ UE_rate tx_rate,
+ rx_rate;
+ std::vector msdus;
void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
enum SSID_MODES {
@@ -145,12 +156,13 @@ namespace OpenWifi {
}
struct SSIDTimePoint {
- uint64_t bssid = 0,
- mode = 0,
- ssid = 0;
+ std::string bssid,
+ mode,
+ ssid;
std::vector associations;
void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
@@ -167,11 +179,12 @@ namespace OpenWifi {
tx_packets = 0;
void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioTimePoint {
- uint band = 0,
- radio_channel = 0;
+ uint64_t band = 0,
+ radio_channel = 0;
uint64_t active_ms = 0,
busy_ms = 0,
receive_ms = 0,
@@ -182,17 +195,63 @@ namespace OpenWifi {
noise = 0;
void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DeviceTimePoint {
- uint64_t timestamp = 0;
- APTimePoint ap_data;
- std::vector ssid_data;
+ std::string id;
+ std::string boardId;
+ uint64_t timestamp = 0;
+ APTimePoint ap_data;
+ std::vector ssid_data;
std::vector radio_data;
AnalyticsObjects::DeviceInfo device_info;
void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
+ };
+
+ struct DeviceTimePointList {
+ std::vector points;
+
+ void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
+ };
+
+ struct BandwidthAnalysisEntry {
+ uint64_t timestamp;
+
+ };
+
+ struct BandwidthAnalysis {
+
+ };
+
+ struct AverageValueSigned {
+ int64_t peak=0, avg=0, low=0;
+ };
+
+ struct AverageValueUnsigned {
+ uint64_t peak=0, avg=0, low=0;
+ };
+
+ struct RadioAnalysis {
+ uint64_t timestamp=0;
+ AverageValueSigned noise, temperature;
+ AverageValueUnsigned active_ms,
+ busy_ms,
+ transmit_ms,
+ receive_ms;
+ };
+
+ struct DeviceTimePointStats {
+ uint64_t firstPoint=0;
+ uint64_t lastPoint=0;
+ uint64_t count=0;
+
+ void to_json(Poco::JSON::Object &Obj) const;
+ bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
}
}
\ No newline at end of file
diff --git a/src/StatFunc.h b/src/StatFunc.h
index a3de1ac..45adcc1 100644
--- a/src/StatFunc.h
+++ b/src/StatFunc.h
@@ -68,6 +68,7 @@ namespace OpenWifi {
bool inited = false;
uint64_t LastValue=0;
};
+
std::ostream & operator<<(std::ostream &os, const RelativeCounter &rc) {
os << rc.get() ;
return os;
diff --git a/src/StorageService.cpp b/src/StorageService.cpp
index 4f900d5..79cf624 100644
--- a/src/StorageService.cpp
+++ b/src/StorageService.cpp
@@ -18,6 +18,8 @@ namespace OpenWifi {
BoardsDB_ = std::make_unique(dbType_,*Pool_, Logger());
BoardsDB_->Create();
+ TimePointsDB_ = std::make_unique(dbType_,*Pool_, Logger());
+ TimePointsDB_->Create();
Updater_.start(*this);
diff --git a/src/StorageService.h b/src/StorageService.h
index 048b3bd..aee81d1 100644
--- a/src/StorageService.h
+++ b/src/StorageService.h
@@ -11,6 +11,7 @@
#include "framework/MicroService.h"
#include "framework/StorageClass.h"
#include "storage/storage_boards.h"
+#include "storage/storage_timepoints.h"
namespace OpenWifi {
class Storage : public StorageClass, Poco::Runnable {
@@ -25,10 +26,12 @@ namespace OpenWifi {
void run() final;
OpenWifi::BoardsDB & BoardsDB() { return *BoardsDB_; };
+ OpenWifi::TimePointDB & TimePointsDB() { return *TimePointsDB_; };
void onTimer(Poco::Timer & timer);
private:
std::unique_ptr BoardsDB_;
+ std::unique_ptr TimePointsDB_;
Poco::Thread Updater_;
std::atomic_bool Running_=false;
Poco::Timer Timer_;
diff --git a/src/VenueWatcher.cpp b/src/VenueWatcher.cpp
index 3798b96..e4be5b3 100644
--- a/src/VenueWatcher.cpp
+++ b/src/VenueWatcher.cpp
@@ -11,7 +11,7 @@ namespace OpenWifi {
void VenueWatcher::Start() {
for(const auto &mac:SerialNumbers_) {
- auto ap = std::make_shared(mac);
+ auto ap = std::make_shared(mac, boardId_);
APs_[mac ] = ap;
}
diff --git a/src/VenueWatcher.h b/src/VenueWatcher.h
index 1d42218..e09c9f7 100644
--- a/src/VenueWatcher.h
+++ b/src/VenueWatcher.h
@@ -35,11 +35,10 @@ namespace OpenWifi {
class VenueWatcher : public Poco::Runnable {
public:
- explicit VenueWatcher(const std::string &id, Poco::Logger &L, const std::vector & SerialNumbers) :
- Id_(id),
- Logger_(L),
- SerialNumbers_(SerialNumbers) {
-
+ explicit VenueWatcher(const std::string &boardId, Poco::Logger &L, const std::vector & SerialNumbers) :
+ boardId_(boardId),
+ Logger_(L),
+ SerialNumbers_(SerialNumbers) {
std::sort(SerialNumbers_.begin(),SerialNumbers_.end());
auto last = std::unique(SerialNumbers_.begin(),SerialNumbers_.end());
SerialNumbers_.erase(last,SerialNumbers_.end());
@@ -68,15 +67,17 @@ namespace OpenWifi {
void ModifySerialNumbers(const std::vector &SerialNumbers);
void GetDevices(std::vector & DI);
+ void GetBandwidth(uint64_t start, uint64_t end, uint64_t interval , AnalyticsObjects::BandwidthAnalysis & BW);
+
private:
- std::recursive_mutex Mutex_;
- std::string Id_;
- Poco::NotificationQueue Queue_;
- Poco::Logger &Logger_;
- Poco::Thread Worker_;
- std::atomic_bool Running_=false;
- std::vector SerialNumbers_;
- std::map> APs_;
+ std::recursive_mutex Mutex_;
+ std::string boardId_;
+ Poco::NotificationQueue Queue_;
+ Poco::Logger &Logger_;
+ Poco::Thread Worker_;
+ std::atomic_bool Running_=false;
+ std::vector SerialNumbers_;
+ std::map> APs_;
};
}
\ No newline at end of file
diff --git a/src/framework/MicroService.h b/src/framework/MicroService.h
index 969382f..cc75328 100644
--- a/src/framework/MicroService.h
+++ b/src/framework/MicroService.h
@@ -71,6 +71,7 @@ using namespace std::chrono_literals;
#include "Poco/SimpleFileChannel.h"
#include "Poco/Util/PropertyFileConfiguration.h"
#include "Poco/SplitterChannel.h"
+#include "Poco/JWT/Signer.h"
#include "cppkafka/cppkafka.h"
@@ -379,6 +380,12 @@ namespace OpenWifi::RESTAPI_utils {
}
}
+ inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, int64_t &Value) {
+ if(Obj->isObject(Field)) {
+ Value = Obj->get(Field);
+ }
+ }
+
template void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, T &Value) {
if(Obj->isObject(Field)) {
Poco::JSON::Object::Ptr A = Obj->getObject(Field);
@@ -1350,6 +1357,22 @@ namespace OpenWifi {
}
}
+ [[nodiscard]] inline Poco::Net::ServerSocket CreateSocket(Poco::Logger &L) const {
+ Poco::Net::Context::Params P;
+
+ if (address_ == "*") {
+ Poco::Net::IPAddress Addr(Poco::Net::IPAddress::wildcard(
+ Poco::Net::Socket::supportsIPv6() ? Poco::Net::AddressFamily::IPv6
+ : Poco::Net::AddressFamily::IPv4));
+ Poco::Net::SocketAddress SockAddr(Addr, port_);
+ return Poco::Net::ServerSocket(SockAddr, backlog_);
+ } else {
+ Poco::Net::IPAddress Addr(address_);
+ Poco::Net::SocketAddress SockAddr(Addr, port_);
+ return Poco::Net::ServerSocket(SockAddr, backlog_);
+ }
+ }
+
inline void LogCertInfo(Poco::Logger &L, const Poco::Crypto::X509Certificate &C) const {
L.information("=============================================================================================");
L.information(Poco::format("> Issuer: %s", C.issuerName()));
@@ -2863,33 +2886,6 @@ namespace OpenWifi {
RESTAPI_GenericServer &Server_;
};
- inline int RESTAPI_ExtServer::Start() {
- Server_.InitLogging();
-
- for(const auto & Svr: ConfigServersList_) {
- Logger().information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
- Svr.KeyFile(),Svr.CertFile()));
-
- auto Sock{Svr.CreateSecureSocket(Logger())};
-
- Svr.LogCert(Logger());
- if(!Svr.RootCA().empty())
- Svr.LogCas(Logger());
-
- Poco::Net::HTTPServerParams::Ptr Params = new Poco::Net::HTTPServerParams;
- Params->setMaxThreads(50);
- Params->setMaxQueued(200);
- Params->setKeepAlive(true);
-
- auto NewServer = std::make_unique(new ExtRequestHandlerFactory(Server_), Pool_, Sock, Params);
- NewServer->start();
- RESTServers_.push_back(std::move(NewServer));
- }
-
- return 0;
- }
-
-
class LogMuxer : public Poco::Channel {
public:
@@ -3021,32 +3017,6 @@ namespace OpenWifi {
RESTAPI_GenericServer &Server_;
};
- inline int RESTAPI_IntServer::Start() {
- Logger().information("Starting.");
- Server_.InitLogging();
-
- for(const auto & Svr: ConfigServersList_) {
- Logger().information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
- Svr.KeyFile(),Svr.CertFile()));
-
- auto Sock{Svr.CreateSecureSocket(Logger())};
-
- Svr.LogCert(Logger());
- if(!Svr.RootCA().empty())
- Svr.LogCas(Logger());
- auto Params = new Poco::Net::HTTPServerParams;
- Params->setMaxThreads(50);
- Params->setMaxQueued(200);
- Params->setKeepAlive(true);
-
- auto NewServer = std::make_unique(new IntRequestHandlerFactory(Server_), Pool_, Sock, Params);
- NewServer->start();
- RESTServers_.push_back(std::move(NewServer));
- }
-
- return 0;
- }
-
struct MicroServiceMeta {
uint64_t Id=0;
std::string Type;
@@ -3081,7 +3051,7 @@ namespace OpenWifi {
}
[[nodiscard]] std::string Version() { return Version_; }
- [[nodiscard]] const Poco::SharedPtr & Key() { return AppKey_; }
+ // [[nodiscard]] const Poco::SharedPtr & Key() { return AppKey_; }
[[nodiscard]] inline const std::string & DataDir() { return DataDir_; }
[[nodiscard]] inline const std::string & WWWAssetsDir() { return WWWAssetsDir_; }
[[nodiscard]] bool Debug() const { return DebugMode_; }
@@ -3171,6 +3141,14 @@ namespace OpenWifi {
}
}
+ }
+ inline bool NoAPISecurity() const { return NoAPISecurity_; }
+ [[nodiscard]] inline std::string Sign(Poco::JWT::Token &T, const std::string &Algo) {
+ if(NoBuiltInCrypto_) {
+ return T.toString();
+ } else {
+ return Signer_.sign(T,Algo);
+ }
}
private:
static MicroService * instance_;
@@ -3197,12 +3175,15 @@ namespace OpenWifi {
std::recursive_mutex InfraMutex_;
std::default_random_engine RandomEngine_;
Poco::Util::PropertyFileConfiguration * PropConfigurationFile_ = nullptr;
- std::string DAEMON_PROPERTIES_FILENAME;
- std::string DAEMON_ROOT_ENV_VAR;
- std::string DAEMON_CONFIG_ENV_VAR;
- std::string DAEMON_APP_NAME;
- uint64_t DAEMON_BUS_TIMER;
- };
+ std::string DAEMON_PROPERTIES_FILENAME;
+ std::string DAEMON_ROOT_ENV_VAR;
+ std::string DAEMON_CONFIG_ENV_VAR;
+ std::string DAEMON_APP_NAME;
+ uint64_t DAEMON_BUS_TIMER;
+ bool NoAPISecurity_=false;
+ bool NoBuiltInCrypto_=false;
+ Poco::JWT::Signer Signer_;
+ };
inline void MicroService::Exit(int Reason) {
std::exit(Reason);
@@ -3325,10 +3306,19 @@ namespace OpenWifi {
}
inline void MicroService::LoadMyConfig() {
- std::string KeyFile = ConfigPath("openwifi.service.key");
- std::string KeyFilePassword = ConfigPath("openwifi.service.key.password" , "" );
- AppKey_ = Poco::SharedPtr(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
- Cipher_ = CipherFactory_.createCipher(*AppKey_);
+ NoAPISecurity_ = ConfigGetBool("openwifi.security.restapi.disable",false);
+ std::string KeyFile = ConfigPath("openwifi.service.key","");
+ if(!KeyFile.empty()) {
+ std::string KeyFilePassword = ConfigPath("openwifi.service.key.password", "");
+ AppKey_ = Poco::SharedPtr(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
+ Cipher_ = CipherFactory_.createCipher(*AppKey_);
+ Signer_.setRSAKey(AppKey_);
+ Signer_.addAllAlgorithms();
+ NoBuiltInCrypto_ = false;
+ } else {
+ NoBuiltInCrypto_ = true;
+ }
+
ID_ = Utils::GetSystemId();
if(!DebugMode_)
DebugMode_ = ConfigGetBool("openwifi.system.debug",false);
@@ -3658,10 +3648,14 @@ namespace OpenWifi {
}
inline std::string MicroService::Encrypt(const std::string &S) {
+ if(NoBuiltInCrypto_)
+ return S;
return Cipher_->encryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
inline std::string MicroService::Decrypt(const std::string &S) {
+ if(NoBuiltInCrypto_)
+ return S;
return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
@@ -3713,7 +3707,68 @@ namespace OpenWifi {
SubSystemConfigPrefix_(std::move(SubSystemConfigPrefix)) {
}
- inline int MicroService::main(const ArgVec &args) {
+ inline int RESTAPI_ExtServer::Start() {
+ Server_.InitLogging();
+
+ for(const auto & Svr: ConfigServersList_) {
+ Logger().information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
+ Svr.KeyFile(),Svr.CertFile()));
+
+ auto Sock{ MicroService::instance().NoAPISecurity() ? Svr.CreateSocket(Logger()) : Svr.CreateSecureSocket(Logger())};
+
+ if(MicroService::instance().NoAPISecurity()) {
+ Logger().information("Security has been disabled for APIs.");
+ } else {
+ Svr.LogCert(Logger());
+ if (!Svr.RootCA().empty())
+ Svr.LogCas(Logger());
+ }
+
+ Poco::Net::HTTPServerParams::Ptr Params = new Poco::Net::HTTPServerParams;
+ Params->setMaxThreads(50);
+ Params->setMaxQueued(200);
+ Params->setKeepAlive(true);
+
+ auto NewServer = std::make_unique(new ExtRequestHandlerFactory(Server_), Pool_, Sock, Params);
+ NewServer->start();
+ RESTServers_.push_back(std::move(NewServer));
+ }
+
+ return 0;
+ }
+
+ inline int RESTAPI_IntServer::Start() {
+ Logger().information("Starting.");
+ Server_.InitLogging();
+
+ for(const auto & Svr: ConfigServersList_) {
+ Logger().information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
+ Svr.KeyFile(),Svr.CertFile()));
+
+ auto Sock{ MicroService::instance().NoAPISecurity() ? Svr.CreateSocket(Logger()) : Svr.CreateSecureSocket(Logger())};
+
+ if(MicroService::instance().NoAPISecurity()) {
+ Logger().information("Security has been disabled for APIs.");
+ } else {
+ Svr.LogCert(Logger());
+ if (!Svr.RootCA().empty())
+ Svr.LogCas(Logger());
+ }
+
+ auto Params = new Poco::Net::HTTPServerParams;
+ Params->setMaxThreads(50);
+ Params->setMaxQueued(200);
+ Params->setKeepAlive(true);
+
+ auto NewServer = std::make_unique(new IntRequestHandlerFactory(Server_), Pool_, Sock, Params);
+ NewServer->start();
+ RESTServers_.push_back(std::move(NewServer));
+ }
+
+ return 0;
+ }
+
+ inline int MicroService::main(const ArgVec &args) {
MyErrorHandler ErrorHandler(*this);
Poco::ErrorHandler::set(&ErrorHandler);
diff --git a/src/storage/storage_boards.cpp b/src/storage/storage_boards.cpp
index 5173ce6..7310db2 100644
--- a/src/storage/storage_boards.cpp
+++ b/src/storage/storage_boards.cpp
@@ -61,8 +61,3 @@ template<> void ORM::DB< OpenWifi::BoardDBRecordType, OpenWifi::AnalyticsObje
Out.set<5>(In.info.modified);
Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.venueList));
}
-//
-// Created by stephane bourque on 2022-03-11.
-//
-
-#include "storage_boards.h"
diff --git a/src/storage/storage_timepoints.cpp b/src/storage/storage_timepoints.cpp
new file mode 100644
index 0000000..dc68107
--- /dev/null
+++ b/src/storage/storage_timepoints.cpp
@@ -0,0 +1,87 @@
+//
+// Created by stephane bourque on 2022-03-21.
+//
+
+#include "storage_timepoints.h"
+#include "framework/MicroService.h"
+#include "framework/OpenWifiTypes.h"
+
+namespace OpenWifi {
+
+ static ORM::FieldVec TimePoint_Fields{
+ // object info
+ ORM::Field{"id",64, true},
+ ORM::Field{"boardId",ORM::FieldType::FT_TEXT},
+ ORM::Field{"timestamp",ORM::FieldType::FT_BIGINT},
+ ORM::Field{"ap_data",ORM::FieldType::FT_TEXT},
+ ORM::Field{"ssid_data",ORM::FieldType::FT_TEXT},
+ ORM::Field{"radio_data",ORM::FieldType::FT_TEXT},
+ ORM::Field{"device_info",ORM::FieldType::FT_BIGINT}
+ };
+
+ static ORM::IndexVec TimePointDB_Indexes{
+ { std::string("timepoint_board_index"),
+ ORM::IndexEntryVec{
+ {std::string("boardId"),
+ ORM::Indextype::ASC},
+ {std::string("timestamp"),
+ ORM::Indextype::ASC}} }
+ };
+
+ TimePointDB::TimePointDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) :
+ DB(T, "timepoints", TimePoint_Fields, TimePointDB_Indexes, P, L, "tpo") {}
+
+ bool TimePointDB::Upgrade(uint32_t from, uint32_t &to) {
+ std::vector Statements{
+ };
+ RunScript(Statements);
+ to = 2;
+ return true;
+ }
+
+ bool TimePointDB::GetStats(const std::string &id, AnalyticsObjects::DeviceTimePointStats &S) {
+ S.count = S.firstPoint = S.lastPoint = 0 ;
+ auto F = [&](const DB::RecordName &R) -> bool {
+ S.count++;
+ if(S.firstPoint==0) S.firstPoint=R.timestamp;
+ S.lastPoint=R.timestamp;
+ return true;
+ };
+ Iterate(F," boardId='" + id + "'");
+ return true;
+ }
+
+ bool TimePointDB::SelectRecords(uint64_t FromDate, uint64_t LastDate, uint64_t MaxRecords, std::vector & Recs ) {
+ std::string WhereClause;
+
+ if(FromDate && LastDate) {
+ WhereClause = " (timestamp >= " + std::to_string(FromDate) + ") and ( timestamp <= " + std::to_string(LastDate) + " ) ";
+ } else if (FromDate) {
+ WhereClause = " (timestamp >= " + std::to_string(FromDate) + ") ";
+ } else if (LastDate) {
+ WhereClause = " ( timestamp <= " + std::to_string(LastDate) + " ) ";
+ }
+ GetRecords(0,MaxRecords,Recs,WhereClause," timestamp ASC ");
+ return true;
+ }
+}
+
+template<> void ORM::DB::Convert(const OpenWifi::TimePointDBRecordType &In, OpenWifi::AnalyticsObjects::DeviceTimePoint &Out) {
+ Out.id = In.get<0>();
+ Out.boardId = In.get<1>();
+ Out.timestamp = In.get<2>();
+ Out.ap_data = OpenWifi::RESTAPI_utils::to_object(In.get<3>());
+ Out.ssid_data = OpenWifi::RESTAPI_utils::to_object_array(In.get<4>());
+ Out.radio_data = OpenWifi::RESTAPI_utils::to_object_array(In.get<5>());
+ Out.device_info = OpenWifi::RESTAPI_utils::to_object(In.get<6>());
+}
+
+template<> void ORM::DB< OpenWifi::TimePointDBRecordType, OpenWifi::AnalyticsObjects::DeviceTimePoint>::Convert(const OpenWifi::AnalyticsObjects::DeviceTimePoint &In, OpenWifi::TimePointDBRecordType &Out) {
+ Out.set<0>(In.id);
+ Out.set<1>(In.boardId);
+ Out.set<2>(In.timestamp);
+ Out.set<3>(OpenWifi::RESTAPI_utils::to_string(In.ap_data));
+ Out.set<4>(OpenWifi::RESTAPI_utils::to_string(In.ssid_data));
+ Out.set<5>(OpenWifi::RESTAPI_utils::to_string(In.radio_data));
+ Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.device_info));
+}
diff --git a/src/storage/storage_timepoints.h b/src/storage/storage_timepoints.h
new file mode 100644
index 0000000..2fe5ffa
--- /dev/null
+++ b/src/storage/storage_timepoints.h
@@ -0,0 +1,29 @@
+//
+// Created by stephane bourque on 2022-03-21.
+//
+
+#pragma once
+
+#include "framework/orm.h"
+#include "RESTObjects/RESTAPI_AnalyticsObjects.h"
+
+namespace OpenWifi {
+ typedef Poco::Tuple<
+ std::string,
+ std::string,
+ uint64_t,
+ std::string,
+ std::string,
+ std::string,
+ std::string
+ > TimePointDBRecordType;
+
+ class TimePointDB : public ORM::DB {
+ public:
+ TimePointDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
+ bool GetStats(const std::string &id, AnalyticsObjects::DeviceTimePointStats &S);
+ bool SelectRecords(uint64_t FromDate, uint64_t LastDate, uint64_t MaxRecords, DB::RecordVec & Recs);
+ private:
+ bool Upgrade(uint32_t from, uint32_t &to) override;
+ };
+}