Initial commit

This commit is contained in:
stephb9959
2022-03-10 22:51:41 -08:00
parent 970db6fe81
commit 1286e90511
13 changed files with 1811 additions and 8 deletions

View File

@@ -83,7 +83,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/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)
target_link_libraries(owanalytics PUBLIC
${Poco_LIBRARIES} ${MySQL_LIBRARIES}

2
build
View File

@@ -1 +1 @@
3
6

586
openapi/owanalytics.yaml Normal file
View File

@@ -0,0 +1,586 @@
openapi: 3.0.1
info:
title: OpenWiFi Analytics Service
description: Definitions and APIs to analyze OpenWiFi network.
version: 2.6.0
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
servers:
- url: 'https://localhost:16009/api/v1'
security:
- bearerAuth: []
- ApiKeyAuth: []
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-KEY
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
NotFound:
description: The specified resource was not found.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
Unauthorized:
description: The requested does not have sufficient rights to perform the operation.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
enum:
- 0 # Success
- 1 # PASSWORD_CHANGE_REQUIRED,
- 2 # INVALID_CREDENTIALS,
- 3 # PASSWORD_ALREADY_USED,
- 4 # USERNAME_PENDING_VERIFICATION,
- 5 # PASSWORD_INVALID,
- 6 # INTERNAL_ERROR,
- 7 # ACCESS_DENIED,
- 8 # INVALID_TOKEN
- 9 # EXPIRED_TOKEN
- 10 # RATE_LIMIT_EXCEEDED
- 11 # BAD_MFA_TRANSACTION
- 12 # MFA_FAILURE
- 13 # SECURITY_SERVICE_UNREACHABLE
ErrorDetails:
type: string
ErrorDescription:
type: string
Success:
description: The requested operation was performed.
content:
application/json:
schema:
properties:
Operation:
type: string
Details:
type: string
Code:
type: integer
BadRequest:
description: The requested operation failed.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: integer
schemas:
ObjectInfo:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
description:
type: string
notes:
type: array
items:
$ref: '#/components/schemas/NoteInfo'
created:
type: integer
format: int64
modified:
type: integer
format: int64
tags:
type: array
items:
type: integer
format: int64
VenueInfo:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
description:
type: string
retention:
type: integer
interval:
type: integer
monitorSubVenues:
type: boolean
BoardInfo:
type: object
properties:
allOf:
$ref: '#/components/schemas/ObjectInfo'
venueList:
type: array
items:
$ref: '#/components/schemas/VenueInfo'
BoardInfoList:
type: object
properties:
boards:
type: array
items:
$ref: '#/components/schemas/BoardInfo'
#########################################################################################
##
## These are endpoints that all services in the OPenWiFI stack must provide
##
#########################################################################################
AnyPayload:
type: object
properties:
Document:
type: string
StringList:
type: object
properties:
list:
type: array
items:
type: string
TagValuePair:
type: object
properties:
tag:
type: string
value:
type: string
TagValuePairList:
type: object
properties:
tagList:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
TagIntPair:
type: object
properties:
tag:
type: string
value:
type: integer
format: int64
TagIntPairList:
type: object
properties:
tagList:
type: array
items:
$ref: '#/components/schemas/TagIntPair'
SystemCommandDetails:
type: object
properties:
command:
type: string
enum:
- setloglevels
- getloglevels
- getSubSystemNames
- getLogLevelNames
- stats
parameters:
oneOf:
- $ref: '#/components/schemas/StringList'
- $ref: '#/components/schemas/TagValuePairList'
SystemCommandResults:
type: object
oneOf:
- $ref: '#/components/schemas/StringList'
- $ref: '#/components/schemas/TagValuePairList'
NoteInfo:
type: object
properties:
created:
type: integer
format: int64
createdBy:
type: string
note:
type: string
SystemInfoResults:
type: object
properties:
version:
type: string
uptime:
type: integer
format: integer64
start:
type: integer
format: integer64
os:
type: string
processors:
type: integer
hostname:
type: string
certificates:
type: array
items:
type: object
properties:
filename:
type: string
expires:
type: integer
format: int64
Dashboard:
type: object
properties:
snapshot:
type: integer
format: int64
tenants:
$ref: '#/components/schemas/TagIntPairList'
SystemCommandSetLogLevel:
type: object
properties:
command:
type: string
enum:
- setloglevel
subsystems:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandReload:
type: object
properties:
command:
type: string
enum:
- reload
subsystems:
type: array
items:
type: string
example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult.
SystemCommandGetLogLevels:
type: object
properties:
command:
type: string
enum:
- getloglevels
SystemGetLogLevelsResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandGetLogLevelNames:
type: object
properties:
command:
type: string
enum:
- getloglevelnames
SystemCommandGetSubsystemNames:
type: object
properties:
command:
type: string
enum:
- getsubsystemnames
SystemCommandGetLogLevelNamesResult:
type: object
properties:
list:
type: array
items:
type: string
SystemGetSubSystemNamesResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
paths:
/boards:
get:
tags:
- Boards
operationId: getBoards
summary: Retrieve a list of boards.
parameters:
- in: query
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: offset
schema:
type: integer
required: false
- in: query
description: Maximum number of entries to return (if absent, no limit is assumed)
name: limit
schema:
type: integer
required: false
- in: query
description: Filter the results
name: filter
schema:
type: string
required: false
- in: query
description: return the number of boards
name: countOnly
schema:
type: boolean
required: false
responses:
200:
description: Return a list of boards
content:
application/json:
schema:
$ref: '#/components/schemas/BoardInfoList'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/board/{id}:
get:
tags:
- Boards
operationId: getBoard
summary: Retrieve a board
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
responses:
200:
description: Return a list of boards
content:
application/json:
schema:
$ref: '#/components/schemas/BoardInfo'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- Boards
operationId: deleteBoard
summary: Remove a board
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
responses:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- Boards
operationId: createBoard
summary: Create a board
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
example: value should be 0 for a post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/BoardInfo'
responses:
200:
$ref: '#/components/schemas/BoardInfo'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- Boards
operationId: modifyBoard
summary: Modify a board
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/BoardInfo'
responses:
200:
$ref: '#/components/schemas/BoardInfo'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/iptocountry:
get:
tags:
- Utility
summary: Get the country code for an IP address
operationId: getIpToCountry
parameters:
- in: query
name: iplist
schema:
type: string
example:
10.2.2.2,10.3.4.3
required: true
responses:
200:
description: List of country codes.
content:
application/json:
schema:
type: object
properties:
enabled:
type: boolean
countryCodes:
type: array
items:
type: string
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
#########################################################################################
##
## These are endpoints that all services in the OpenWiFi stack must provide
##
#########################################################################################
/system:
post:
tags:
- System Commands
summary: Perform some system wide commands.
operationId: systemCommand
requestBody:
description: Command details
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemCommandSetLogLevel'
- $ref: '#/components/schemas/SystemCommandReload'
- $ref: '#/components/schemas/SystemCommandGetLogLevels'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNames'
- $ref: '#/components/schemas/SystemCommandGetSubsystemNames'
responses:
200:
description: Successful command execution
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemGetLogLevelsResult'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult'
- $ref: '#/components/schemas/SystemGetSubSystemNamesResult'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
get:
tags:
- System Commands
summary: Retrieve different values from the running service.
operationId: getSystemCommand
parameters:
- in: query
description: Get a value
name: command
schema:
type: string
enum:
- info
required: true
responses:
200:
description: Successful command execution
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemInfoResults'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -13,6 +13,7 @@
#include "Daemon.h"
#include "StorageService.h"
#include "VenueCoordinator.h"
namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr;
@@ -25,7 +26,8 @@ namespace OpenWifi {
vDAEMON_APP_NAME,
vDAEMON_BUS_TIMER,
SubSystemVec{
OpenWifi::StorageService()
OpenWifi::StorageService(),
VenueCoordinator()
});
}
return instance_;

View File

@@ -0,0 +1,565 @@
//
// Created by stephane bourque on 2021-10-27.
//
#include "RESTAPI_SubObjects.h"
#include "framework/MicroService.h"
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
namespace OpenWifi::SubObjects {
void HomeDeviceMode::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "enableLEDS", enableLEDS);
field_to_json(Obj, "type", type);
field_to_json(Obj, "subnet", subnet);
field_to_json(Obj, "subnetMask", subnetMask);
field_to_json(Obj, "startIP", startIP);
field_to_json(Obj, "endIP", endIP);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
field_to_json(Obj, "subnetV6", subnetV6);
field_to_json(Obj, "subnetMaskV6", subnetMaskV6);
field_to_json(Obj, "startIPV6", startIPV6);
field_to_json(Obj, "endIPV6", endIPV6);
}
bool HomeDeviceMode::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "enableLEDS", enableLEDS);
field_from_json(Obj, "type", type);
field_from_json(Obj, "subnet", subnet);
field_from_json(Obj, "subnetMask", subnetMask);
field_from_json(Obj, "startIP", startIP);
field_from_json(Obj, "endIP", endIP);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
field_from_json(Obj, "subnetV6", subnetV6);
field_from_json(Obj, "subnetMaskV6", subnetMaskV6);
field_from_json(Obj, "startIPV6", startIPV6);
field_from_json(Obj, "endIPV6", endIPV6);
return true;
} catch (...) {
}
return false;
}
void IPReservation::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "nickname", nickname);
field_to_json(Obj, "ipAddress", ipAddress);
field_to_json(Obj, "macAddress", macAddress);
}
bool IPReservation::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "nickname", nickname);
field_from_json(Obj, "ipAddress", ipAddress);
field_from_json(Obj, "macAddress", macAddress);
return true;
} catch (...) {
}
return false;
}
void IPReservationList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "reservations", reservations);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool IPReservationList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "id", id);
field_from_json(Obj, "reservations", reservations);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void DnsConfiguration::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "ISP", ISP);
field_to_json(Obj, "custom", custom);
field_to_json(Obj, "primary", primary);
field_to_json(Obj, "secondary", secondary);
field_to_json(Obj, "primaryV6", primaryV6);
field_to_json(Obj, "secondaryV6", secondaryV6);
}
bool DnsConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "ISP", ISP);
field_from_json(Obj, "custom", custom);
field_from_json(Obj, "primary", primary);
field_from_json(Obj, "secondary", secondary);
field_from_json(Obj, "primaryV6", primaryV6);
field_from_json(Obj, "secondaryV6", secondaryV6);
return true;
} catch (...) {
}
return false;
}
void InternetConnection::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "type", type);
field_to_json(Obj, "username", username);
field_to_json(Obj, "password", password);
field_to_json(Obj, "ipAddress", ipAddress);
field_to_json(Obj, "subnetMask", subnetMask);
field_to_json(Obj, "defaultGateway", defaultGateway);
field_to_json(Obj, "sendHostname", sendHostname);
field_to_json(Obj, "primaryDns", primaryDns);
field_to_json(Obj, "secondaryDns", secondaryDns);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
field_to_json(Obj, "ipV6Support", ipV6Support);
field_to_json(Obj, "ipAddressV6", ipAddressV6);
field_to_json(Obj, "subnetMaskV6", subnetMaskV6);
field_to_json(Obj, "defaultGatewayV6", defaultGatewayV6);
field_to_json(Obj, "primaryDnsV6", primaryDnsV6);
field_to_json(Obj, "secondaryDnsV6", secondaryDnsV6);
}
bool InternetConnection::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "type", type);
field_from_json(Obj, "username", username);
field_from_json(Obj, "password", password);
field_from_json(Obj, "ipAddress", ipAddress);
field_from_json(Obj, "subnetMask", subnetMask);
field_from_json(Obj, "defaultGateway", defaultGateway);
field_from_json(Obj, "sendHostname", sendHostname);
field_from_json(Obj, "primaryDns", primaryDns);
field_from_json(Obj, "secondaryDns", secondaryDns);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
field_from_json(Obj, "ipV6Support", ipV6Support);
field_from_json(Obj, "ipAddressV6", ipAddressV6);
field_from_json(Obj, "subnetMaskV6", subnetMaskV6);
field_from_json(Obj, "defaultGatewayV6", defaultGatewayV6);
field_from_json(Obj, "primaryDnsV6", primaryDnsV6);
field_from_json(Obj, "secondaryDnsV6", secondaryDnsV6);
return true;
} catch (...) {
}
return false;
}
void WifiNetwork::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "type", type);
field_to_json(Obj, "name", name);
field_to_json(Obj, "password", password);
field_to_json(Obj, "encryption", encryption);
field_to_json(Obj, "bands", bands);
}
bool WifiNetwork::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "type", type);
field_from_json(Obj, "name", name);
field_from_json(Obj, "password", password);
field_from_json(Obj, "encryption", encryption);
field_from_json(Obj, "bands", bands);
return true;
} catch (...) {
}
return false;
}
void WifiNetworkList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "wifiNetworks", wifiNetworks);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool WifiNetworkList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "wifiNetworks", wifiNetworks);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void AccessTime::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "day", day);
field_to_json(Obj, "rangeList", rangeList);
}
bool AccessTime::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "day", day);
field_from_json(Obj, "rangeList", rangeList);
return true;
} catch (...) {
}
return false;
}
void AccessTimes::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "schedule", schedule);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool AccessTimes::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "schedule", schedule);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void SubscriberDevice::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "description", description);
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "manufacturer", manufacturer);
field_to_json(Obj, "firstContact", firstContact);
field_to_json(Obj, "lastContact", lastContact);
field_to_json(Obj, "group", group);
field_to_json(Obj, "icon", icon);
field_to_json(Obj, "suspended", suspended);
field_to_json(Obj, "ip", ip);
field_to_json(Obj, "schedule", schedule);
}
bool SubscriberDevice::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "description", description);
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "manufacturer", manufacturer);
field_from_json(Obj, "firstContact", firstContact);
field_from_json(Obj, "lastContact", lastContact);
field_from_json(Obj, "group", group);
field_from_json(Obj, "icon", icon);
field_from_json(Obj, "suspended", suspended);
field_from_json(Obj, "ip", ip);
field_from_json(Obj, "schedule", schedule);
return true;
} catch (...) {
}
return false;
}
void SubscriberDeviceList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "devices", devices);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool SubscriberDeviceList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "devices", devices);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void Association::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "ssid", ssid);
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "rssi", rssi);
field_to_json(Obj, "power", power);
field_to_json(Obj, "ipv4", ipv4);
field_to_json(Obj, "ipv6", ipv6);
field_to_json(Obj, "tx", tx);
field_to_json(Obj, "rx", rx);
}
bool Association::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "ssid", ssid);
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "rssi", rssi);
field_from_json(Obj, "power", power);
field_from_json(Obj, "ipv4", ipv4);
field_from_json(Obj, "ipv6", ipv6);
field_from_json(Obj, "tx", tx);
field_from_json(Obj, "rx", rx);
return true;
} catch (...) {
}
return false;
}
void AssociationList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "associations", associations);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool AssociationList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "associations", associations);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void Client::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "speed", speed);
field_to_json(Obj, "mode", mode);
field_to_json(Obj, "ipv4", ipv4);
field_to_json(Obj, "ipv6", ipv6);
field_to_json(Obj, "tx", tx);
field_to_json(Obj, "rx", rx);
}
bool Client::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "speed", speed);
field_from_json(Obj, "mode", mode);
field_from_json(Obj, "ipv4", ipv4);
field_from_json(Obj, "ipv6", ipv6);
field_from_json(Obj, "tx", tx);
field_from_json(Obj, "rx", rx);
return true;
} catch (...) {
}
return false;
}
void ClientList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "clients", clients);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool ClientList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "clients", clients);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void Location::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "buildingName", buildingName);
field_to_json(Obj, "addressLines", addressLines);
field_to_json(Obj, "city", city);
field_to_json(Obj, "state", state);
field_to_json(Obj, "postal", postal);
field_to_json(Obj, "country", country);
field_to_json(Obj, "phones", phones);
field_to_json(Obj, "mobiles", mobiles);
}
bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "buildingName", buildingName);
field_from_json(Obj, "addressLines", addressLines);
field_from_json(Obj, "city", city);
field_from_json(Obj, "state", state);
field_from_json(Obj, "postal", postal);
field_from_json(Obj, "country", country);
field_from_json(Obj, "phones", phones);
field_from_json(Obj, "mobiles", mobiles);
return true;
} catch (...) {
}
return false;
}
void RadioHE::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "multipleBSSID", multipleBSSID);
field_to_json(Obj, "ema", ema);
field_to_json(Obj, "bssColor", bssColor);
}
bool RadioHE::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "multipleBSSID", multipleBSSID);
field_from_json(Obj, "ema", ema);
field_from_json(Obj, "bssColor", bssColor);
return true;
} catch (...) {
}
return false;
}
void RadioRates::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "beacon", beacon);
field_to_json(Obj, "multicast", multicast);
}
bool RadioRates::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "beacon", beacon);
field_from_json(Obj, "multicast", multicast);
return true;
} catch (...) {
}
return false;
}
void RadioInformation::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "band", band);
field_to_json(Obj, "bandwidth", bandwidth);
field_to_json(Obj, "channel", channel);
field_to_json(Obj, "country", country);
field_to_json(Obj, "channelMode", channelMode);
field_to_json(Obj, "channelWidth", channelWidth);
field_to_json(Obj, "requireMode", requireMode);
field_to_json(Obj, "txpower", txpower);
field_to_json(Obj, "legacyRates", legacyRates);
field_to_json(Obj, "beaconInterval", beaconInterval);
field_to_json(Obj, "dtimPeriod", dtimPeriod);
field_to_json(Obj, "maximumClients", maximumClients);
field_to_json(Obj, "rates", rates);
field_to_json(Obj, "he", he);
field_to_json(Obj, "rawInfo", rawInfo);
field_to_json(Obj, "allowDFS", allowDFS);
field_to_json(Obj, "mimo", mimo);
}
bool RadioInformation::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "band", band);
field_from_json(Obj, "bandwidth", bandwidth);
field_from_json(Obj, "channel", channel);
field_from_json(Obj, "country", country);
field_from_json(Obj, "channelMode", channelMode);
field_from_json(Obj, "channelWidth", channelWidth);
field_from_json(Obj, "requireMode", requireMode);
field_from_json(Obj, "txpower", txpower);
field_from_json(Obj, "legacyRates", legacyRates);
field_from_json(Obj, "beaconInterval", beaconInterval);
field_from_json(Obj, "dtimPeriod", dtimPeriod);
field_from_json(Obj, "maximumClients", maximumClients);
field_from_json(Obj, "rates", rates);
field_from_json(Obj, "he", he);
field_from_json(Obj, "rawInfo", rawInfo);
field_from_json(Obj, "allowDFS", allowDFS);
field_from_json(Obj, "mimo", mimo);
return true;
} catch (...) {
}
return false;
}
void AccessPoint::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "serialNumber", serialNumber);
field_to_json(Obj, "name", name);
field_to_json(Obj, "deviceType", deviceType);
field_to_json(Obj, "subscriberDevices", subscriberDevices);
field_to_json(Obj, "ipReservations", ipReservations);
field_to_json(Obj, "address", address);
field_to_json(Obj, "wifiNetworks", wifiNetworks);
field_to_json(Obj, "internetConnection", internetConnection);
field_to_json(Obj, "deviceMode", deviceMode);
field_to_json(Obj, "dnsConfiguration", dnsConfiguration);
field_to_json(Obj, "radios", radios);
field_to_json(Obj, "automaticUpgrade", automaticUpgrade);
field_to_json(Obj, "configurationUUID", configurationUUID);
field_to_json(Obj, "currentFirmware", currentFirmware);
field_to_json(Obj, "currentFirmwareDate", currentFirmwareDate);
field_to_json(Obj, "latestFirmware", latestFirmware);
field_to_json(Obj, "latestFirmwareDate", latestFirmwareDate);
field_to_json(Obj, "newFirmwareAvailable", newFirmwareAvailable);
field_to_json(Obj, "latestFirmwareURI", latestFirmwareURI);
}
bool AccessPoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "id", id);
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "serialNumber", serialNumber);
field_from_json(Obj, "name", name);
field_from_json(Obj, "deviceType", deviceType);
field_from_json(Obj, "subscriberDevices", subscriberDevices);
field_from_json(Obj, "ipReservations", ipReservations);
field_from_json(Obj, "address", address);
field_from_json(Obj, "wifiNetworks", wifiNetworks);
field_from_json(Obj, "internetConnection", internetConnection);
field_from_json(Obj, "deviceMode", deviceMode);
field_from_json(Obj, "dnsConfiguration", dnsConfiguration);
field_from_json(Obj, "radios", radios);
field_from_json(Obj, "automaticUpgrade", automaticUpgrade);
field_from_json(Obj, "configurationUUID", configurationUUID);
field_from_json(Obj, "currentFirmware", currentFirmware);
field_from_json(Obj, "currentFirmwareDate", currentFirmwareDate);
field_from_json(Obj, "latestFirmware", latestFirmware);
field_from_json(Obj, "latestFirmwareDate", latestFirmwareDate);
field_from_json(Obj, "newFirmwareAvailable", newFirmwareAvailable);
field_from_json(Obj, "latestFirmwareURI", latestFirmwareURI);
return true;
} catch (...) {
}
return false;
}
void AccessPointList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "list", list);
}
bool AccessPointList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "list", list);
return true;
} catch (...) {
}
return false;
}
void SubscriberInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "userId", userId);
field_to_json(Obj, "firstName", firstName);
field_to_json(Obj, "initials", initials);
field_to_json(Obj, "lastName", lastName);
field_to_json(Obj, "phoneNumber", phoneNumber);
field_to_json(Obj, "secondaryEmail", secondaryEmail);
field_to_json(Obj, "accessPoints", accessPoints);
field_to_json(Obj, "serviceAddress", serviceAddress);
field_to_json(Obj, "billingAddress", billingAddress);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool SubscriberInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "id", id);
field_from_json(Obj, "userId", userId);
field_from_json(Obj, "firstName", firstName);
field_from_json(Obj, "initials", initials);
field_from_json(Obj, "lastName", lastName);
field_from_json(Obj, "phoneNumber", phoneNumber);
field_from_json(Obj, "secondaryEmail", secondaryEmail);
field_from_json(Obj, "accessPoints", accessPoints);
field_from_json(Obj, "serviceAddress", serviceAddress);
field_from_json(Obj, "billingAddress", billingAddress);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
}

View File

@@ -0,0 +1,303 @@
//
// Created by stephane bourque on 2021-10-27.
//
#ifndef OWSUB_RESTAPI_SUBOBJECTS_H
#define OWSUB_RESTAPI_SUBOBJECTS_H
#include <string>
#include "Poco/JSON/Object.h"
namespace OpenWifi::SubObjects {
struct HomeDeviceMode {
bool enableLEDS = true;
std::string type; // bridge, manual, automatic
std::string subnet;
std::string subnetMask;
std::string startIP;
std::string endIP;
uint64_t created = 0 ;
uint64_t modified = 0 ;
std::string subnetV6;
int subnetMaskV6=0;
std::string startIPV6;
std::string endIPV6;
std::string leaseTime;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct IPReservation {
std::string nickname;
std::string ipAddress;
std::string macAddress;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct IPReservationList {
std::string id;
std::vector<IPReservation> reservations;
uint64_t created = 0 ;
uint64_t modified = 0 ;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DnsConfiguration {
bool ISP=false;
bool custom=false;
std::string primary;
std::string secondary;
std::string primaryV6;
std::string secondaryV6;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct InternetConnection {
std::string type; // automatic, pppoe, manual
std::string username;
std::string password;
std::string ipAddress;
std::string subnetMask;
std::string defaultGateway;
bool sendHostname = true;
std::string primaryDns;
std::string secondaryDns;
uint64_t created=0;
uint64_t modified=0;
bool ipV6Support=false;
std::string ipAddressV6;
int subnetMaskV6=0;
std::string defaultGatewayV6;
std::string primaryDnsV6;
std::string secondaryDnsV6;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct WifiNetwork {
std::string type; // main, guest
std::string name;
std::string password;
std::string encryption;
std::vector<std::string> bands;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct WifiNetworkList {
std::vector<WifiNetwork> wifiNetworks;
uint64_t created=0;
uint64_t modified=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessTime {
std::string day;
std::vector<std::string> rangeList;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessTimes {
std::vector<AccessTime> schedule;
uint64_t created=0;
uint64_t modified=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SubscriberDevice {
std::string name;
std::string description;
std::string macAddress;
std::string manufacturer;
uint64_t firstContact=0;
uint64_t lastContact=0;
std::string group;
std::string icon;
bool suspended=false;
std::string ip;
std::vector<AccessTimes> schedule;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SubscriberDeviceList {
std::vector<SubscriberDevice> devices;
uint64_t created=0;
uint64_t modified=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Association {
std::string name;
std::string ssid;
std::string macAddress;
int rssi=0;
int power=0;
std::string ipv4;
std::string ipv6;
uint64_t tx=0;
uint64_t rx=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AssociationList {
std::vector<Association> associations;
uint64_t created=0;
uint64_t modified=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Client {
std::string macAddress;
std::string speed;
std::string mode;
std::string ipv4;
std::string ipv6;
uint64_t tx=0;
uint64_t rx=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct ClientList {
std::vector<Client> clients;
uint64_t created=0;
uint64_t modified=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Location {
std::string buildingName;
std::vector<std::string> addressLines;
std::string city;
std::string state;
std::string postal;
std::string country;
std::vector<std::string> phones;
std::vector<std::string> mobiles;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioHE {
bool multipleBSSID = false;
bool ema = false;
uint64_t bssColor = 64;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioRates {
uint64_t beacon = 6000;
uint64_t multicast = 24000;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioInformation {
std::string band;
uint64_t bandwidth;
uint64_t channel = 0 ;
std::string country;
std::string channelMode{"HE"};
uint64_t channelWidth = 80;
std::string requireMode;
uint64_t txpower=0;
bool legacyRates = false;
uint64_t beaconInterval = 100;
uint64_t dtimPeriod = 2;
uint64_t maximumClients = 64;
RadioRates rates;
RadioHE he;
bool allowDFS=false;
std::string mimo;
std::vector<std::string> rawInfo;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessPoint {
std::string id;
std::string macAddress;
std::string serialNumber;
std::string name;
std::string deviceType;
SubscriberDeviceList subscriberDevices;
IPReservationList ipReservations;
Location address;
WifiNetworkList wifiNetworks;
InternetConnection internetConnection;
HomeDeviceMode deviceMode;
DnsConfiguration dnsConfiguration;
std::vector<RadioInformation> radios;
bool automaticUpgrade = true;
std::string configurationUUID;
std::string currentFirmware;
uint64_t currentFirmwareDate;
std::string latestFirmware;
uint64_t latestFirmwareDate;
bool newFirmwareAvailable;
std::string latestFirmwareURI;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessPointList {
std::vector<AccessPoint> list;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SubscriberInfo {
std::string id;
std::string userId;
std::string firstName;
std::string initials;
std::string lastName;
std::string phoneNumber;
std::string secondaryEmail;
AccessPointList accessPoints;
Location serviceAddress;
Location billingAddress;
uint64_t created = 0;
uint64_t modified = 0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
}
#endif //OWSUB_RESTAPI_SUBOBJECTS_H

90
src/StateReceiver.cpp Normal file
View File

@@ -0,0 +1,90 @@
//
// Created by stephane bourque on 2022-03-10.
//
#include "StateReceiver.h"
#include "VenueWatcher.h"
namespace OpenWifi {
int StateReceiver::Start() {
Running_ = true;
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) { this->StateReceived(Key,Payload); };
StateWatcherId_ = KafkaManager()->RegisterTopicWatcher(KafkaTopics::STATE, F);
Worker_.start(*this);
return 0;
};
void StateReceiver::Stop() {
Running_ = false;
KafkaManager()->UnregisterTopicWatcher(KafkaTopics::STATE, StateWatcherId_);
Queue_.wakeUpAll();
Worker_.join();
};
void StateReceiver::run() {
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
while(Note && Running_) {
auto Msg = dynamic_cast<StateMessage *>(Note.get());
if(Msg!= nullptr) {
try {
nlohmann::json msg = nlohmann::json::parse(Msg->Payload());
if (msg.contains(uCentralProtocol::PAYLOAD)) {
auto payload = msg[uCentralProtocol::PAYLOAD];
if (payload.contains("state") && payload.contains("serial")) {
auto serialNumber = payload["serial"].get<std::string>();
auto state = std::make_shared<nlohmann::json>(payload["state"]);
auto it = Notifiers_.find(Utils::SerialNumberToInt(serialNumber));
if(it!=Notifiers_.end()) {
for(const auto &i:it->second) {
i->Post(Utils::SerialNumberToInt(serialNumber), state);
}
}
}
}
} catch (const Poco::Exception &E) {
Logger().log(E);
} catch (...) {
}
} else {
}
Note = Queue_.waitDequeueNotification();
}
}
void StateReceiver::StateReceived( const std::string & Key, const std::string & Payload) {
std::lock_guard G(Mutex_);
Logger().information(Poco::format("Device(%s): State message.", Key));
Queue_.enqueueNotification( new StateMessage(Key,Payload));
}
void StateReceiver::Register(uint64_t SerialNumber, VenueWatcher *VW) {
std::lock_guard G(Mutex_);
auto it = Notifiers_.find(SerialNumber);
if(it == Notifiers_.end()) {
std::list<VenueWatcher *> L;
L.push_back(VW);
Notifiers_[SerialNumber] = L;
} else {
it->second.push_back(VW);
}
}
void StateReceiver::DeRegister(uint64_t SerialNumber, VenueWatcher *VW) {
std::lock_guard G(Mutex_);
auto it = Notifiers_.find(SerialNumber);
if(it==Notifiers_.end())
return;
for(auto i=it->second.begin();i!=it->second.end();i++) {
if(*i==VW) {
it->second.erase(i);
break;
}
}
}
}

54
src/StateReceiver.h Normal file
View File

@@ -0,0 +1,54 @@
//
// Created by stephane bourque on 2022-03-10.
//
#pragma once
#include "framework/MicroService.h"
namespace OpenWifi {
class StateMessage : public Poco::Notification {
public:
explicit StateMessage(const std::string &Key, const std::string &Payload ) :
Key_(Key),
Payload_(Payload) {}
const std::string & Key() { return Key_; }
const std::string & Payload() { return Payload_; }
private:
std::string Key_;
std::string Payload_;
};
class VenueWatcher;
class StateReceiver : public SubSystemServer, Poco::Runnable {
public:
static auto instance() {
static auto instance_ = new StateReceiver;
return instance_;
}
int Start() override;
void Stop() override;
void StateReceived( const std::string & Key, const std::string & Payload);
void run() override;
void Register(uint64_t SerialNumber, VenueWatcher *VW);
void DeRegister(uint64_t SerialNumber, VenueWatcher *VW);
private:
// map of mac(as int), list of (id,func)
std::map<uint64_t , std::list< VenueWatcher * >> Notifiers_;
uint64_t StateWatcherId_=0;
Poco::NotificationQueue Queue_;
Poco::Thread Worker_;
std::atomic_bool Running_=false;
StateReceiver() noexcept:
SubSystemServer("StatsReceiver", "STATS-RECEIVER", "stats.receiver")
{
}
};
inline auto StateReceiver() { return StateReceiver::instance(); }
}

47
src/VenueCoordinator.cpp Normal file
View File

@@ -0,0 +1,47 @@
//
// Created by stephane bourque on 2022-03-10.
//
#include "VenueCoordinator.h"
#include "VenueWatcher.h"
namespace OpenWifi {
int VenueCoordinator::Start() {
std::vector<std::string> S{
"903cb3bb1ef4",
"04f8f8fc3772",
"04f8f8fc3b02",
"24f5a207a130",
"68215f0427da"
};
std::vector<uint64_t> Numbers;
for(const auto &i:S)
Numbers.push_back(Utils::SerialNumberToInt(i));
std::sort(Numbers.begin(),Numbers.end());
Watchers_.push_back(std::make_shared<VenueWatcher>(std::string{"id-1"},Logger(),Numbers));
Worker_.start(*this);
return 0;
}
void VenueCoordinator::Stop() {
Running_=false;
Worker_.wakeUp();
Worker_.join();
}
void VenueCoordinator::run() {
Running_=true;
while(Running_) {
Poco::Thread::trySleep(2000);
}
}
}

35
src/VenueCoordinator.h Normal file
View File

@@ -0,0 +1,35 @@
//
// Created by stephane bourque on 2022-03-10.
//
#pragma once
#include "framework/MicroService.h"
#include "VenueWatcher.h"
namespace OpenWifi {
class VenueCoordinator : public SubSystemServer, Poco::Runnable {
public:
static auto instance() {
static auto instance_ = new VenueCoordinator;
return instance_;
}
int Start() override;
void Stop() override;
void run() override;
private:
Poco::Thread Worker_;
std::atomic_bool Running_=false;
std::vector<std::shared_ptr<VenueWatcher>> Watchers_;
VenueCoordinator() noexcept:
SubSystemServer("VenueCoordinator", "VENUE-COORD", "venue.coordinator")
{
}
};
inline auto VenueCoordinator() { return VenueCoordinator::instance(); }
}

66
src/VenueWatcher.cpp Normal file
View File

@@ -0,0 +1,66 @@
//
// Created by stephane bourque on 2022-03-10.
//
#include "VenueWatcher.h"
#include "StateReceiver.h"
namespace OpenWifi {
void VenueWatcher::Start() {
for(const auto &i:SerialNumbers_)
StateReceiver()->Register(i,this);
Worker_.start(*this);
}
void VenueWatcher::Stop() {
Running_ = false;
Queue_.wakeUpAll();
Worker_.join();
}
void VenueWatcher::run() {
Running_ = true;
Poco::AutoPtr<Poco::Notification> Msg(Queue_.waitDequeueNotification());
while(Msg && Running_) {
auto MsgContent = dynamic_cast<VenueMessage *>(Msg.get());
if(MsgContent!= nullptr) {
try {
auto State = MsgContent->Payload();
std::cout << "SerialNumber: " << Utils::IntToSerialNumber(MsgContent->SerialNumber()) << std::endl;
} catch (const Poco::Exception &E) {
Logger().log(E);
} catch (...) {
}
} else {
}
Msg = Queue_.waitDequeueNotification();
}
}
void VenueWatcher::SetSerialNumbers(const std::vector<uint64_t> &SerialNumbers) {
std::lock_guard G(Mutex_);
std::vector<uint64_t> Diff;
std::set_symmetric_difference(SerialNumbers_.begin(),SerialNumbers_.end(),SerialNumbers.begin(),
SerialNumbers.end(),std::inserter(Diff,Diff.begin()));
std::vector<uint64_t> ToRemove;
std::set_intersection(SerialNumbers_.begin(),SerialNumbers_.end(),Diff.begin(),
Diff.end(),std::inserter(ToRemove,ToRemove.begin()));
std::vector<uint64_t> ToAdd;
std::set_intersection(SerialNumbers.begin(),SerialNumbers.end(),Diff.begin(),
Diff.end(),std::inserter(ToAdd,ToAdd.begin()));
for(const auto &i:ToRemove)
StateReceiver()->DeRegister(i,this);
for(const auto &i:ToAdd)
StateReceiver()->Register(i,this);
SerialNumbers_ = SerialNumbers;
}
}

57
src/VenueWatcher.h Normal file
View File

@@ -0,0 +1,57 @@
//
// Created by stephane bourque on 2022-03-10.
//
#pragma once
#include "framework/MicroService.h"
namespace OpenWifi {
class VenueMessage : public Poco::Notification {
public:
explicit VenueMessage(uint64_t SerialNumber, std::shared_ptr<nlohmann::json> &M ) :
Payload_(M),
SerialNumber_(SerialNumber) {
}
inline std::shared_ptr<nlohmann::json> & Payload() { return Payload_; }
inline auto SerialNumber() { return SerialNumber_; }
private:
std::shared_ptr<nlohmann::json> &Payload_;
uint64_t SerialNumber_=0;
};
class VenueWatcher : public Poco::Runnable {
public:
explicit VenueWatcher(const std::string &id, Poco::Logger &L, const std::vector<uint64_t> & SerialNumbers) :
Id_(id),
Logger_(L),
SerialNumbers_(SerialNumbers) {
std::sort(SerialNumbers_.begin(),SerialNumbers_.end());
auto last = std::unique(SerialNumbers_.begin(),SerialNumbers_.end());
SerialNumbers_.erase(last,SerialNumbers_.end());
}
void Post(uint64_t SerialNumber, std::shared_ptr<nlohmann::json> &Msg) {
std::lock_guard G(Mutex_);
Queue_.enqueueNotification(new VenueMessage(SerialNumber, Msg));
}
void Start();
void Stop();
void run() final;
inline Poco::Logger & Logger() { return Logger_; }
void SetSerialNumbers(const std::vector<uint64_t> &SerialNumbers);
private:
std::recursive_mutex Mutex_;
std::string Id_;
Poco::NotificationQueue Queue_;
Poco::Logger &Logger_;
Poco::Thread Worker_;
std::atomic_bool Running_=false;
std::vector<uint64_t> SerialNumbers_;
};
}

View File

@@ -915,13 +915,11 @@ namespace OpenWifi::Utils {
[[nodiscard]] inline bool ValidEMailAddress(const std::string &email) {
// define a regular expression
static const std::regex pattern
(("(\\w+)(\\.|_\\+)?(\\w*)@(\\w+)(\\.(\\w+))+"));
(("(\\w+)(\\.|_|\\++)?(\\w*)@(\\w+)(\\.(\\w+))+"));
// try to match the string with the regular expression
return std::regex_match(email, pattern);
}
[[nodiscard]] inline std::string LoadFile( const Poco::File & F) {
std::string Result;
try {
@@ -1809,14 +1807,14 @@ namespace OpenWifi {
return std::stoull(Hint->second);
}
[[nodiscard]] inline bool GetBoolParameter(const std::string &Name, bool Default) {
[[nodiscard]] inline bool GetBoolParameter(const std::string &Name, bool Default=false) {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==end(Parameters_) || !is_bool(Hint->second))
return Default;
return Hint->second=="true";
}
[[nodiscard]] inline std::string GetParameter(const std::string &Name, const std::string &Default) {
[[nodiscard]] inline std::string GetParameter(const std::string &Name, const std::string &Default="") {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; });
if(Hint==end(Parameters_))
return Default;