mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-02 03:37:57 +00:00
Compare commits
7 Commits
v2.6.0-RC3
...
v2.4.0-RC3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f2aaa94ba | ||
|
|
2f4ff94280 | ||
|
|
26ac5b836e | ||
|
|
e2508846b3 | ||
|
|
2d8ee9b033 | ||
|
|
bf3ba546b6 | ||
|
|
8b282a032c |
@@ -24,6 +24,9 @@ spec:
|
||||
metadata:
|
||||
annotations:
|
||||
checksum/config: {{ include "owgw.config" . | sha256sum }}
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
kubernetes.io/psp: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
|
||||
{{- end }}
|
||||
{{- with .Values.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
|
||||
28
helm/templates/psp.yaml
Normal file
28
helm/templates/psp.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
---
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "owgw.name" . }}
|
||||
helm.sh/chart: {{ include "owgw.chart" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
allowedUnsafeSysctls:
|
||||
{{- range $unsafeSysctl := .Values.securityContext.sysctls }}
|
||||
- {{ $unsafeSysctl.name }}
|
||||
{{- end }}
|
||||
privileged: false
|
||||
seLinux:
|
||||
rule: RunAsAny
|
||||
supplementalGroups:
|
||||
rule: RunAsAny
|
||||
runAsUser:
|
||||
rule: RunAsAny
|
||||
fsGroup:
|
||||
rule: RunAsAny
|
||||
volumes:
|
||||
- '*'
|
||||
{{- end }}
|
||||
16
helm/templates/role.yaml
Normal file
16
helm/templates/role.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
|
||||
rules:
|
||||
- apiGroups:
|
||||
- policy
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
verbs:
|
||||
- use
|
||||
resourceNames:
|
||||
- {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
|
||||
{{- end }}
|
||||
15
helm/templates/rolebinding.yaml
Normal file
15
helm/templates/rolebinding.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.podSecurityPolicy.enabled }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl-to-default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
@@ -8,7 +8,7 @@ fullnameOverride: ""
|
||||
images:
|
||||
owgw:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: master
|
||||
tag: v2.4.0-RC3
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
@@ -112,6 +112,17 @@ resources: {}
|
||||
|
||||
securityContext:
|
||||
fsGroup: 101
|
||||
# Usage of unsafe sysctls requires multiple things:
|
||||
# - allow these unsafe sysctls on kubelet level (by adding --allowed-unsafe-sysctls flag)
|
||||
# - enabling addition of PodSecurityContext setting podSecurityPolicy.enabled to "true" below
|
||||
# - uncommenting parameters below
|
||||
#sysctls:
|
||||
#- name: net.ipv4.tcp_keepalive_intvl
|
||||
# value: "5"
|
||||
#- name: net.ipv4.tcp_keepalive_probes
|
||||
# value: "2"
|
||||
#- name: net.ipv4.tcp_keepalive_time
|
||||
# value: "45"
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
@@ -121,6 +132,9 @@ affinity: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityPolicy:
|
||||
enabled: false
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
# storageClassName: "-"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include "DeviceRegistry.h"
|
||||
#include "WebSocketServer.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "OUIServer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
@@ -42,7 +41,6 @@ namespace OpenWifi {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if(Device != Devices_.end())
|
||||
{
|
||||
Device->second->Conn_.LastContact = time(nullptr);
|
||||
@@ -85,58 +83,47 @@ namespace OpenWifi {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if(Device != Devices_.end())
|
||||
{
|
||||
Device->second->LastHealthcheck = CheckData;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<DeviceRegistry::ConnectionEntry> DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr)
|
||||
std::shared_ptr<DeviceRegistry::ConnectionEntry> DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr, uint64_t & ConnectionId )
|
||||
{
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
if( Device == Devices_.end()) {
|
||||
auto E = Devices_[SerialNumber] = std::make_shared<ConnectionEntry>();
|
||||
|
||||
E->WSConn_ = Ptr;
|
||||
E->Conn_.SerialNumber = SerialNumber;
|
||||
E->Conn_.LastContact = std::time(nullptr);
|
||||
E->Conn_.Connected = true ;
|
||||
E->Conn_.UUID = 0 ;
|
||||
E->Conn_.MessageCount = 0 ;
|
||||
E->Conn_.Address = "";
|
||||
E->Conn_.TX = 0 ;
|
||||
E->Conn_.RX = 0;
|
||||
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
return E;
|
||||
}
|
||||
else
|
||||
{
|
||||
Device->second->WSConn_ = Ptr;
|
||||
Device->second->Conn_.Connected = true;
|
||||
Device->second->Conn_.LastContact = std::time(nullptr);
|
||||
Device->second->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
return Device->second;
|
||||
}
|
||||
const auto & E = Devices_[SerialNumber] = std::make_shared<ConnectionEntry>();
|
||||
E->WSConn_ = Ptr;
|
||||
E->Conn_.SerialNumber = SerialNumber;
|
||||
E->Conn_.LastContact = std::time(nullptr);
|
||||
E->Conn_.Connected = true ;
|
||||
E->Conn_.UUID = 0 ;
|
||||
E->Conn_.MessageCount = 0 ;
|
||||
E->Conn_.Address = "";
|
||||
E->Conn_.TX = 0 ;
|
||||
E->Conn_.RX = 0;
|
||||
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
ConnectionId = E->ConnectionId = ++Id_;
|
||||
return E;
|
||||
}
|
||||
|
||||
bool DeviceRegistry::Connected(const std::string & SerialNumber) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
auto Device = Devices_.find(SerialNumber);
|
||||
|
||||
if(Device == Devices_.end())
|
||||
return false;
|
||||
|
||||
return Device->second->Conn_.Connected;
|
||||
}
|
||||
|
||||
void DeviceRegistry::UnRegister(const std::string & SerialNumber, WSConnection *Ptr) {
|
||||
void DeviceRegistry::UnRegister(const std::string & SerialNumber, uint64_t ConnectionId) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
Devices_.erase(SerialNumber);
|
||||
}
|
||||
auto It = Devices_.find(SerialNumber);
|
||||
if(It!=Devices_.end()) {
|
||||
if(It->second->ConnectionId == ConnectionId)
|
||||
Devices_.erase(SerialNumber);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceRegistry::SendFrame(const std::string & SerialNumber, const std::string & Payload) {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
// Arilia Wireless Inc.
|
||||
//
|
||||
|
||||
#ifndef UCENTRAL_UDEVICEREGISTRY_H
|
||||
#define UCENTRAL_UDEVICEREGISTRY_H
|
||||
#pragma once
|
||||
|
||||
#include "Poco/JSON/Object.h"
|
||||
|
||||
@@ -26,6 +25,7 @@ namespace OpenWifi {
|
||||
GWObjects::ConnectionState Conn_;
|
||||
std::string LastStats;
|
||||
GWObjects::HealthCheck LastHealthcheck;
|
||||
uint64_t ConnectionId=0;
|
||||
};
|
||||
|
||||
static DeviceRegistry *instance() {
|
||||
@@ -41,17 +41,17 @@ namespace OpenWifi {
|
||||
void SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State);
|
||||
bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData);
|
||||
void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H);
|
||||
std::shared_ptr<ConnectionEntry> Register(const std::string & SerialNumber, WSConnection *);
|
||||
void UnRegister(const std::string & SerialNumber, WSConnection *);
|
||||
std::shared_ptr<ConnectionEntry> Register(const std::string & SerialNumber, WSConnection *, uint64_t & ConnectionId);
|
||||
void UnRegister(const std::string & SerialNumber, uint64_t ConnectionId);
|
||||
bool SendCommand(GWObjects::CommandDetails & Command);
|
||||
bool Connected(const std::string & SerialNumber);
|
||||
bool SendFrame(const std::string & SerialNumber, const std::string & Payload);
|
||||
void SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID);
|
||||
|
||||
bool AnalyzeRegistry(GWObjects::Dashboard &D);
|
||||
|
||||
private:
|
||||
std::map<std::string,std::shared_ptr<ConnectionEntry>> Devices_;
|
||||
inline static std::atomic_uint64_t Id_=1;
|
||||
std::map<std::string,std::shared_ptr<ConnectionEntry>> Devices_;
|
||||
|
||||
DeviceRegistry() noexcept:
|
||||
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
|
||||
@@ -62,4 +62,3 @@ namespace OpenWifi {
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //UCENTRAL_UDEVICEREGISTRY_H
|
||||
|
||||
@@ -33,6 +33,11 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::CAPABILITIES){
|
||||
return GetCapabilities();
|
||||
} else if (Command_ == RESTAPI::Protocol::LOGS) {
|
||||
@@ -55,6 +60,12 @@ namespace OpenWifi {
|
||||
if(!ValidateParameters()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::CAPABILITIES) {
|
||||
return DeleteCapabilities();
|
||||
} else if (Command_ == RESTAPI::Protocol::LOGS){
|
||||
@@ -72,6 +83,12 @@ namespace OpenWifi {
|
||||
if(!ValidateParameters()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
GWObjects::Device TheDevice;
|
||||
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (Command_ == RESTAPI::Protocol::PERFORM) {
|
||||
return ExecuteCommand();
|
||||
} else if (Command_ == RESTAPI::Protocol::CONFIGURE) {
|
||||
|
||||
@@ -21,6 +21,11 @@ namespace OpenWifi {
|
||||
void AddSerialNumber(const std::string &S);
|
||||
void DeleteSerialNumber(const std::string &S);
|
||||
void FindNumbers(const std::string &S, uint HowMany, std::vector<uint64_t> &A);
|
||||
inline bool NumberExists(const std::string &S) {
|
||||
std::lock_guard G(M_);
|
||||
uint64_t SN = std::stoull(S,0,16);
|
||||
return std::find(SNs_.begin(),SNs_.end(),SN)!=SNs_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t LastUpdate_ = 0 ;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "framework/uCentral_Protocol.h"
|
||||
#include "framework/MicroService.h"
|
||||
#include "Daemon.h"
|
||||
#include "SerialNumberCache.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
@@ -179,7 +180,8 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
WSConnection::~WSConnection() {
|
||||
DeviceRegistry()->UnRegister(SerialNumber_,this);
|
||||
if(ConnectionId_)
|
||||
DeviceRegistry()->UnRegister(SerialNumber_, ConnectionId_);
|
||||
if(Registered_ && WS_)
|
||||
{
|
||||
Reactor_.removeEventHandler(*WS_,
|
||||
@@ -339,7 +341,7 @@ namespace OpenWifi {
|
||||
auto Firmware = ParamsObj->get(uCentralProtocol::FIRMWARE).toString();
|
||||
auto Capabilities = ParamsObj->get(uCentralProtocol::CAPABILITIES).toString();
|
||||
|
||||
Conn_ = DeviceRegistry()->Register(Serial, this);
|
||||
Conn_ = DeviceRegistry()->Register(Serial, this, ConnectionId_);
|
||||
SerialNumber_ = Serial;
|
||||
Conn_->Conn_.SerialNumber = Serial;
|
||||
Conn_->Conn_.UUID = UUID;
|
||||
@@ -361,19 +363,21 @@ namespace OpenWifi {
|
||||
}
|
||||
Conn_->Conn_.VerifiedCertificate = CertValidation_;
|
||||
|
||||
if (Daemon()->AutoProvisioning() && !StorageService()->DeviceExists(SerialNumber_)) {
|
||||
auto DeviceExists = SerialNumberCache()->NumberExists(SerialNumber_);
|
||||
if (Daemon()->AutoProvisioning() && !DeviceExists) {
|
||||
StorageService()->CreateDefaultDevice(SerialNumber_, Capabilities, Firmware, Compatible_);
|
||||
} else if (StorageService()->DeviceExists(SerialNumber_)) {
|
||||
Conn_->Conn_.Compatible = Compatible_;
|
||||
} else if (DeviceExists) {
|
||||
StorageService()->UpdateDeviceCapabilities(SerialNumber_, Capabilities, Compatible_);
|
||||
Conn_->Conn_.Compatible = Compatible_;
|
||||
if(!Firmware.empty()) {
|
||||
StorageService()->SetConnectInfo(SerialNumber_, Firmware );
|
||||
}
|
||||
LookForUpgrade(UUID);
|
||||
}
|
||||
Conn_->Conn_.Compatible = Compatible_;
|
||||
|
||||
StatsProcessor_ = std::make_unique<StateProcessor>(Conn_, Logger_);
|
||||
StatsProcessor_->Initialize(Serial);
|
||||
LookForUpgrade(UUID);
|
||||
|
||||
if(KafkaManager()->Enabled()) {
|
||||
Poco::JSON::Stringifier Stringify;
|
||||
|
||||
@@ -110,6 +110,7 @@ namespace OpenWifi {
|
||||
uint64_t Errors_=0;
|
||||
std::unique_ptr<StateProcessor> StatsProcessor_;
|
||||
bool Connected_=false;
|
||||
uint64_t ConnectionId_=0;
|
||||
|
||||
void CompleteStartup();
|
||||
};
|
||||
|
||||
@@ -1900,7 +1900,7 @@ namespace OpenWifi {
|
||||
QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||
QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0);
|
||||
QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0);
|
||||
QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 1);
|
||||
QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 0);
|
||||
QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100);
|
||||
QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, "");
|
||||
QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, "");
|
||||
@@ -1912,7 +1912,7 @@ namespace OpenWifi {
|
||||
QB_.AdditionalInfo = GetBoolParameter(RESTAPI::Protocol::WITHEXTENDEDINFO,false);
|
||||
|
||||
if(QB_.Offset<1)
|
||||
QB_.Offset=1;
|
||||
QB_.Offset=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Created by stephane bourque on 2021-10-06.
|
||||
//
|
||||
|
||||
#ifndef OPENWIFI_STORAGE_H
|
||||
#define OPENWIFI_STORAGE_H
|
||||
#pragma once
|
||||
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Data/SessionPool.h"
|
||||
@@ -54,13 +53,13 @@ namespace OpenWifi {
|
||||
|
||||
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
|
||||
if(dbType_==sqlite) {
|
||||
return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " ";
|
||||
return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " ";
|
||||
} else if(dbType_==pgsql) {
|
||||
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
|
||||
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
|
||||
} else if(dbType_==mysql) {
|
||||
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
|
||||
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
|
||||
}
|
||||
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
|
||||
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
|
||||
}
|
||||
|
||||
inline std::string ConvertParams(const std::string & S) const {
|
||||
@@ -165,5 +164,3 @@ namespace OpenWifi {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENWIFI_STORAGE_H
|
||||
|
||||
@@ -360,11 +360,9 @@ typedef Poco::Tuple<
|
||||
std::string st{"SELECT " +
|
||||
DB_Command_SelectFields +
|
||||
" FROM CommandList WHERE SerialNumber=? ORDER BY Submitted DESC " + ComputeRange(0, HowMany)};
|
||||
|
||||
Select << ConvertParams(st),
|
||||
Poco::Data::Keywords::into(Records),
|
||||
Poco::Data::Keywords::use(SerialNumber),
|
||||
Poco::Data::Keywords::limit(HowMany);
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Select.execute();
|
||||
|
||||
for (auto i : Records) {
|
||||
@@ -681,7 +679,7 @@ typedef Poco::Tuple<
|
||||
while(More) {
|
||||
auto Command = RSet[0].convert<std::string>();
|
||||
if(!Command.empty())
|
||||
Types::UpdateCountedMap(R,Command);
|
||||
OpenWifi::Types::UpdateCountedMap(R,Command);
|
||||
More = RSet.moveNext();
|
||||
}
|
||||
return true;
|
||||
@@ -691,4 +689,4 @@ typedef Poco::Tuple<
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace OpenWifi {
|
||||
|
||||
std::string st{"SELECT " + DB_HealthCheckSelectFields + " FROM HealthChecks WHERE SerialNumber=? ORDER BY Recorded DESC "};
|
||||
|
||||
Select << ConvertParams(st) + ComputeRange(1,HowMany),
|
||||
Select << ConvertParams(st) + ComputeRange(0,HowMany),
|
||||
Poco::Data::Keywords::into(Records),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Select.execute();
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Statement Select(Sess);
|
||||
|
||||
|
||||
std::string st{"SELECT " + DB_LogsSelectFields + " FROM DeviceLogs WHERE SerialNumber=? AND LogType=? ORDER BY Recorded DESC " + ComputeRange(1, HowMany)};
|
||||
std::string st{"SELECT " + DB_LogsSelectFields + " FROM DeviceLogs WHERE SerialNumber=? AND LogType=? ORDER BY Recorded DESC " + ComputeRange(0, HowMany)};
|
||||
Select << ConvertParams(st),
|
||||
Poco::Data::Keywords::into(Records),
|
||||
Poco::Data::Keywords::use(SerialNumber),
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace OpenWifi {
|
||||
std::string St{"SELECT " +
|
||||
DB_StatsSelectFields +
|
||||
" FROM Statistics WHERE SerialNumber=? ORDER BY Recorded DESC "};
|
||||
Select << ConvertParams(St) + ComputeRange(1, HowMany),
|
||||
Select << ConvertParams(St) + ComputeRange(0, HowMany),
|
||||
Poco::Data::Keywords::into(Records),
|
||||
Poco::Data::Keywords::use(SerialNumber);
|
||||
Select.execute();
|
||||
|
||||
Reference in New Issue
Block a user