mirror of
https://github.com/Telecominfraproject/wlan-cloud-analytics.git
synced 2026-03-20 03:39:59 +00:00
Compare commits
104 Commits
v2.6.0-RC1
...
v2.7.0-RC4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7997f28f4 | ||
|
|
ef7deb3515 | ||
|
|
70444bb7ab | ||
|
|
105bf2912b | ||
|
|
87dfb313d5 | ||
|
|
5658db43eb | ||
|
|
bff4db6a3a | ||
|
|
8ecc461749 | ||
|
|
97377fef7b | ||
|
|
877f7985cd | ||
|
|
9b916621a2 | ||
|
|
5e57c9a7c5 | ||
|
|
e9bb037ef2 | ||
|
|
054c40c7ed | ||
|
|
99c59313ea | ||
|
|
ff843f093c | ||
|
|
eec96dff52 | ||
|
|
9c9f2cbf4f | ||
|
|
98342bb626 | ||
|
|
93890a1e99 | ||
|
|
f9111bab7b | ||
|
|
8f9e954f20 | ||
|
|
a568fce901 | ||
|
|
6e2a21c831 | ||
|
|
da8a9e14cf | ||
|
|
075b83a7d5 | ||
|
|
3c35ec1523 | ||
|
|
b65f33c975 | ||
|
|
cbd5b09cdf | ||
|
|
0a145c8501 | ||
|
|
2ed88569d0 | ||
|
|
58c2269893 | ||
|
|
a708cc2be0 | ||
|
|
9c8f7ed6f9 | ||
|
|
b79a3b6c12 | ||
|
|
2c3b7711b3 | ||
|
|
831e144869 | ||
|
|
67910c982a | ||
|
|
9be196ce40 | ||
|
|
222afe2858 | ||
|
|
40a02c4752 | ||
|
|
7f1577503f | ||
|
|
7ab2e6c96e | ||
|
|
639db8631e | ||
|
|
9fe9b74dea | ||
|
|
20c025f994 | ||
|
|
ee78155b68 | ||
|
|
9f9a866ad3 | ||
|
|
adbd852ccd | ||
|
|
4bb5ee0b86 | ||
|
|
06bb8cebbe | ||
|
|
dde46ce6b2 | ||
|
|
515f8a4fea | ||
|
|
8dcfe04310 | ||
|
|
5db6fc3027 | ||
|
|
8049291138 | ||
|
|
613fa2e2bb | ||
|
|
eb9a748836 | ||
|
|
6ee3cae1db | ||
|
|
33e4f8abd8 | ||
|
|
d5b4d15307 | ||
|
|
e01f985974 | ||
|
|
8dc3e53fc0 | ||
|
|
52e1bf8817 | ||
|
|
a8b0028af6 | ||
|
|
7976602d17 | ||
|
|
55b0075c0c | ||
|
|
1da468e52c | ||
|
|
fa434f79c3 | ||
|
|
d396a104ff | ||
|
|
61837a8975 | ||
|
|
c1f06ec784 | ||
|
|
10ffba95b5 | ||
|
|
fd3a6be11a | ||
|
|
ec2874748f | ||
|
|
432d0ed52b | ||
|
|
fe247c6093 | ||
|
|
4c1daf84cf | ||
|
|
1d4aa80205 | ||
|
|
d0c4030289 | ||
|
|
34100b5fb0 | ||
|
|
0856e256e9 | ||
|
|
228b2162bc | ||
|
|
d4602f0db1 | ||
|
|
d4148e6f01 | ||
|
|
d18d567166 | ||
|
|
c8186b30b7 | ||
|
|
d83c841455 | ||
|
|
c180e60d0a | ||
|
|
dff48d6561 | ||
|
|
052c685938 | ||
|
|
ee916d5db6 | ||
|
|
64799106ae | ||
|
|
643e748a95 | ||
|
|
c36f222416 | ||
|
|
9e9b7cc4e8 | ||
|
|
6c81f0585c | ||
|
|
76d6abc994 | ||
|
|
e905fbe155 | ||
|
|
5c778c0de5 | ||
|
|
d1a01e9d31 | ||
|
|
0ceb204a83 | ||
|
|
df7c860246 | ||
|
|
1ab0e7f291 |
9
.github/workflows/cleanup.yml
vendored
9
.github/workflows/cleanup.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- 'release/*'
|
||||
types: [ closed ]
|
||||
|
||||
defaults:
|
||||
@@ -16,4 +17,10 @@ jobs:
|
||||
steps:
|
||||
- run: |
|
||||
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
|
||||
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owanalytics/$PR_BRANCH_TAG"
|
||||
|
||||
if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then
|
||||
echo "PR branch is $PR_BRANCH_TAG, deleting Docker image"
|
||||
curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owanalytics/$PR_BRANCH_TAG"
|
||||
else
|
||||
echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
|
||||
fi
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,6 +32,7 @@
|
||||
*.app
|
||||
|
||||
test_scripts/curl/token.json
|
||||
test_scripts/curl/result.json
|
||||
.vscode/c_cpp_properties.json
|
||||
test_scripts/curl/result.json
|
||||
*.swp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(owanalytics VERSION 2.6.0)
|
||||
project(owanalytics VERSION 2.7.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_GENERATOR "Unix Makefiles")
|
||||
@@ -63,6 +63,8 @@ include_directories(/usr/local/include /usr/local/opt/openssl/include src inclu
|
||||
|
||||
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
|
||||
|
||||
add_definitions(-DPOCO_LOG_DEBUG="1")
|
||||
|
||||
add_executable(owanalytics
|
||||
build
|
||||
src/ow_version.h.in
|
||||
@@ -75,6 +77,7 @@ add_executable(owanalytics
|
||||
src/framework/ConfigurationValidator.cpp
|
||||
src/framework/ConfigurationValidator.h
|
||||
src/framework/ow_constants.h
|
||||
src/framework/MicroServiceErrorHandler.h
|
||||
src/framework/WebSocketClientNotifications.h
|
||||
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
|
||||
src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
|
||||
|
||||
54
Dockerfile
54
Dockerfile
@@ -1,4 +1,10 @@
|
||||
FROM alpine:3.15 AS build-base
|
||||
ARG ALPINE_VERSION=3.16.2
|
||||
ARG POCO_VERSION=poco-tip-v1
|
||||
ARG FMTLIB_VERSION=9.0.0
|
||||
ARG CPPKAFKA_VERSION=tip-v1
|
||||
ARG JSON_VALIDATOR_VERSION=2.1.0
|
||||
|
||||
FROM alpine:$ALPINE_VERSION AS build-base
|
||||
|
||||
RUN apk add --update --no-cache \
|
||||
make cmake g++ git \
|
||||
@@ -9,8 +15,10 @@ RUN apk add --update --no-cache \
|
||||
|
||||
FROM build-base AS poco-build
|
||||
|
||||
ADD https://api.github.com/repos/stephb9959/poco/git/refs/heads/master version.json
|
||||
RUN git clone https://github.com/stephb9959/poco /poco
|
||||
ARG POCO_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
|
||||
|
||||
WORKDIR /poco
|
||||
RUN mkdir cmake-build
|
||||
@@ -19,10 +27,26 @@ RUN cmake ..
|
||||
RUN cmake --build . --config Release -j8
|
||||
RUN cmake --build . --target install
|
||||
|
||||
FROM build-base AS fmtlib-build
|
||||
|
||||
ARG FMTLIB_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/tags/${FMTLIB_VERSION} version.json
|
||||
RUN git clone https://github.com/fmtlib/fmt --branch ${FMTLIB_VERSION} /fmtlib
|
||||
|
||||
WORKDIR /fmtlib
|
||||
RUN mkdir cmake-build
|
||||
WORKDIR cmake-build
|
||||
RUN cmake ..
|
||||
RUN make
|
||||
RUN make install
|
||||
|
||||
FROM build-base AS cppkafka-build
|
||||
|
||||
ADD https://api.github.com/repos/stephb9959/cppkafka/git/refs/heads/master version.json
|
||||
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
|
||||
ARG CPPKAFKA_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
|
||||
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
|
||||
|
||||
WORKDIR /cppkafka
|
||||
RUN mkdir cmake-build
|
||||
@@ -33,8 +57,10 @@ RUN cmake --build . --target install
|
||||
|
||||
FROM build-base AS json-schema-validator-build
|
||||
|
||||
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/heads/master version.json
|
||||
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
|
||||
ARG JSON_VALIDATOR_VERSION
|
||||
|
||||
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/tags/${JSON_VALIDATOR_VERSION} version.json
|
||||
RUN git clone https://github.com/pboettch/json-schema-validator --branch ${JSON_VALIDATOR_VERSION} /json-schema-validator
|
||||
|
||||
WORKDIR /json-schema-validator
|
||||
RUN mkdir cmake-build
|
||||
@@ -43,18 +69,6 @@ RUN cmake ..
|
||||
RUN make
|
||||
RUN make install
|
||||
|
||||
FROM build-base AS fmtlib-build
|
||||
|
||||
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/heads/master version.json
|
||||
RUN git clone https://github.com/fmtlib/fmt /fmtlib
|
||||
|
||||
WORKDIR /fmtlib
|
||||
RUN mkdir cmake-build
|
||||
WORKDIR cmake-build
|
||||
RUN cmake ..
|
||||
RUN make
|
||||
RUN make install
|
||||
|
||||
FROM build-base AS owanalytics-build
|
||||
|
||||
ADD CMakeLists.txt build /owanalytics/
|
||||
@@ -77,7 +91,7 @@ WORKDIR /owanalytics/cmake-build
|
||||
RUN cmake ..
|
||||
RUN cmake --build . --config Release -j8
|
||||
|
||||
FROM alpine:3.15
|
||||
FROM alpine:$ALPINE_VERSION
|
||||
|
||||
ENV OWANALYTICS_USER=owanalytics \
|
||||
OWANALYTICS_ROOT=/owanalytics-data \
|
||||
|
||||
@@ -5,7 +5,7 @@ if [ "$SELFSIGNED_CERTS" = 'true' ]; then
|
||||
update-ca-certificates
|
||||
fi
|
||||
|
||||
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWANALYTICS_CONFIG"/owanalytics.properties ]]; then
|
||||
if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWANALYTICS_ROOT/certs/restapi-ca.pem"} \
|
||||
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16009"} \
|
||||
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWANALYTICS_ROOT/certs/restapi-cert.pem"} \
|
||||
@@ -24,6 +24,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWANALYTICS_CONFIG"/owanalytics.prop
|
||||
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17009"} \
|
||||
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16009"} \
|
||||
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
|
||||
SECURITY_RESTAPI_DISABLE=${SECURITY_RESTAPI_DISABLE:-"false"} \
|
||||
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
|
||||
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
|
||||
KAFKA_SSL_CA_LOCATION=${KAFKA_SSL_CA_LOCATION:-""} \
|
||||
|
||||
2
helm/.gitignore
vendored
2
helm/.gitignore
vendored
@@ -1 +1,3 @@
|
||||
*.swp
|
||||
Chart.lock
|
||||
charts/
|
||||
|
||||
@@ -5,14 +5,14 @@ name: owanalytics
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 10.9.2
|
||||
condition: postgresql.enabled
|
||||
- name: mysql
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 8.8.3
|
||||
condition: mysql.enabled
|
||||
- name: mariadb
|
||||
repository: https://charts.bitnami.com/bitnami
|
||||
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||
version: 9.4.2
|
||||
condition: mariadb.enabled
|
||||
|
||||
@@ -70,8 +70,8 @@ The following table lists the configurable parameters of the chart and their def
|
||||
| persistence.size | string | Defines PV size | `'10Gi'` |
|
||||
| public_env_variables | hash | Defines list of environment variables to be passed to the Analytics | |
|
||||
| configProperties | hash | Configuration properties that should be passed to the application in `owanalytics.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
|
||||
| certs | hash | Defines files (keys and certificates) that should be passed to the Analytics (PEM format is adviced to be used) (see `volumes.owanalytics` on where it is mounted) | |
|
||||
|
||||
| existingCertsSecret | string | Existing Kubernetes secret containing all required certificates and private keys for microservice operation. If set, certificates from `certs` key are ignored | `""` |
|
||||
| certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owanalytics` on where it is mounted). If `existingCertsSecret` is set, certificates passed this way will not be used. | |
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{{- $root := . -}}
|
||||
{{- $storageType := index .Values.configProperties "storage.type" -}}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
@@ -46,6 +47,39 @@ spec:
|
||||
- -timeout
|
||||
- 600s
|
||||
|
||||
{{- if eq $storageType "postgresql" }}
|
||||
- name: wait-postgres
|
||||
image: "{{ .Values.images.owanalytics.repository }}:{{ .Values.images.owanalytics.tag }}"
|
||||
imagePullPolicy: {{ .Values.images.owanalytics.pullPolicy }}
|
||||
command:
|
||||
- /wait-for-postgres.sh
|
||||
- {{ index .Values.configProperties "storage.type.postgresql.host" }}
|
||||
- echo
|
||||
- "PostgreSQL is ready"
|
||||
env:
|
||||
- name: KUBERNETES_DEPLOYED
|
||||
value: "{{ now }}"
|
||||
{{- range $key, $value := .Values.public_env_variables }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.secret_env_variables }}
|
||||
- name: {{ $key }}
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "owanalytics.fullname" $root }}-env
|
||||
key: {{ $key }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- range .Values.volumes.owanalytics }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
{{- if .subPath }}
|
||||
subPath: {{ .subPath }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
containers:
|
||||
|
||||
- name: owanalytics
|
||||
|
||||
@@ -9,7 +9,7 @@ fullnameOverride: ""
|
||||
images:
|
||||
owanalytics:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owanalytics
|
||||
tag: main
|
||||
tag: v2.7.0-RC4
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
@@ -71,7 +71,7 @@ volumes:
|
||||
mountPath: /owanalytics-data/certs
|
||||
volumeDefinition: |
|
||||
secret:
|
||||
secretName: {{ include "owanalytics.fullname" . }}-certs
|
||||
secretName: {{ if .Values.existingCertsSecret }}{{ .Values.existingCertsSecret }}{{ else }}{{ include "owanalytics.fullname" . }}-certs{{ end }}
|
||||
# Change this if you want to use another volume type
|
||||
- name: persist
|
||||
mountPath: /owanalytics-data/persist
|
||||
@@ -198,6 +198,9 @@ configProperties:
|
||||
storage.type.mysql.username: stephb
|
||||
storage.type.mysql.password: snoopy99
|
||||
|
||||
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
|
||||
existingCertsSecret: ""
|
||||
|
||||
certs:
|
||||
# restapi-ca.pem: ""
|
||||
# restapi-cert.pem: ""
|
||||
|
||||
@@ -27,71 +27,13 @@ components:
|
||||
|
||||
responses:
|
||||
NotFound:
|
||||
description: The specified resource was not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
ErrorCode:
|
||||
type: integer
|
||||
ErrorDetails:
|
||||
type: string
|
||||
ErrorDescription:
|
||||
type: string
|
||||
|
||||
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound'
|
||||
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
|
||||
|
||||
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized'
|
||||
Success:
|
||||
description: The requested operation was performed.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
Operation:
|
||||
type: string
|
||||
Details:
|
||||
type: string
|
||||
Code:
|
||||
type: integer
|
||||
|
||||
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success'
|
||||
BadRequest:
|
||||
description: The requested operation failed.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
ErrorCode:
|
||||
type: integer
|
||||
ErrorDetails:
|
||||
type: string
|
||||
ErrorDescription:
|
||||
type: integer
|
||||
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest'
|
||||
|
||||
schemas:
|
||||
ObjectInfo:
|
||||
@@ -1134,42 +1076,6 @@ paths:
|
||||
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
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
404:
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
/wifiClientHistory:
|
||||
get:
|
||||
tags:
|
||||
|
||||
@@ -34,6 +34,7 @@ openwifi.system.uri.private = https://localhost:17009
|
||||
openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16009
|
||||
openwifi.system.commandchannel = /tmp/app.owanalytics
|
||||
openwifi.system.uri.ui = owprov-ui.arilia.com
|
||||
openwifi.security.restapi.disable = false
|
||||
|
||||
#############################
|
||||
# Generic information for all micro services
|
||||
@@ -101,4 +102,4 @@ storage.type.mysql.connectiontimeout = 60
|
||||
########################################################################
|
||||
logging.type = file
|
||||
logging.path = $OWANALYTICS_ROOT/logs
|
||||
logging.level = debug
|
||||
logging.level = debug
|
||||
|
||||
@@ -39,6 +39,7 @@ openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
|
||||
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
|
||||
openwifi.system.commandchannel = /tmp/app.owanalytics
|
||||
openwifi.system.uri.ui = ${SYSTEM_URI_UI}
|
||||
openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE}
|
||||
|
||||
#############################
|
||||
# Generic information for all micro services
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace OpenWifi {
|
||||
DI_.connected =true;
|
||||
|
||||
AnalyticsObjects::DeviceTimePoint DTP;
|
||||
Logger().information(fmt::format("{}: stats message.", DI_.serialNumber));
|
||||
poco_information(Logger(),fmt::format("{}: stats message.", DI_.serialNumber));
|
||||
|
||||
// find radios first to get associations.
|
||||
try {
|
||||
@@ -158,6 +158,7 @@ namespace OpenWifi {
|
||||
auto interfaces = (*State)["interfaces"];
|
||||
DI_.associations_2g = DI_.associations_5g = DI_.associations_6g = 0;
|
||||
for(const auto &interface:interfaces) {
|
||||
std::string InterfaceName = fmt::format("{}: {}", DI_.serialNumber, interface.contains("name") ? to_string(interface["name"]) : "unknown");
|
||||
if(interface.contains("counters")) {
|
||||
auto counters = interface["counters"];
|
||||
GetJSON("collisions", counters, DTP.ap_data.collisions, (uint64_t) 0);
|
||||
@@ -172,6 +173,34 @@ namespace OpenWifi {
|
||||
GetJSON("tx_packets", counters, DTP.ap_data.tx_packets, (uint64_t) 0);
|
||||
}
|
||||
|
||||
InterfaceClientEntryMap_t ICEM;
|
||||
if(interface.contains("clients") && interface["clients"].is_array()) {
|
||||
try {
|
||||
auto Clients = interface["clients"];
|
||||
for(const auto & client: Clients) {
|
||||
if(client.contains("mac") && client["mac"].is_string()) {
|
||||
InterfaceClientEntry E;
|
||||
if(client.contains("ipv4_addresses") && client["ipv4_addresses"].is_array()) {
|
||||
for(const auto &ip:client["ipv4_addresses"]) {
|
||||
E.ipv4_addresses.push_back(ip);
|
||||
}
|
||||
}
|
||||
if(client.contains("ipv6_addresses") && client["ipv6_addresses"].is_array()) {
|
||||
for(const auto &ip:client["ipv6_addresses"]) {
|
||||
E.ipv6_addresses.push_back(ip);
|
||||
}
|
||||
}
|
||||
auto M = mac_filter(client["mac"]);
|
||||
ICEM[M] = E;
|
||||
}
|
||||
}
|
||||
} catch(...) {
|
||||
std::cout << "Exception will parsing clients: " << InterfaceName << std::endl;
|
||||
}
|
||||
} else {
|
||||
// std::cout <<"Interface: No clients: " << InterfaceName << std::endl;
|
||||
}
|
||||
|
||||
if(interface.contains("ssids")) {
|
||||
auto ssids = interface["ssids"];
|
||||
for (const auto &ssid: ssids) {
|
||||
@@ -243,8 +272,19 @@ namespace OpenWifi {
|
||||
GetJSON("rx_packets",association,WFH.rx_packets,(uint64_t)0);
|
||||
GetJSON("tx_packets",association,WFH.tx_packets,(uint64_t)0);
|
||||
|
||||
WFH.ipv4 = "---";
|
||||
WFH.ipv6 = "----";
|
||||
// try to locate the IP addresses
|
||||
auto ClientInfo = ICEM.find(WFH.station_id);
|
||||
if(ClientInfo!=end(ICEM)) {
|
||||
if(!ClientInfo->second.ipv4_addresses.empty()) {
|
||||
WFH.ipv4 = ClientInfo->second.ipv4_addresses[0];
|
||||
}
|
||||
if(!ClientInfo->second.ipv6_addresses.empty()) {
|
||||
WFH.ipv6 = ClientInfo->second.ipv6_addresses[0];
|
||||
}
|
||||
std::cout << __LINE__ << ": " << InterfaceName << " Mac Found: " << ICEM.size() << " entries. " << WFH.station_id << std::endl;
|
||||
} else {
|
||||
std::cout << __LINE__ << ": " << InterfaceName << " Mac NOT found: " << ICEM.size() << " entries. " << WFH.station_id << std::endl;
|
||||
}
|
||||
|
||||
for(const auto &rd:DTP.radio_data) {
|
||||
if(rd.band == SSIDTP.band) {
|
||||
@@ -311,7 +351,7 @@ namespace OpenWifi {
|
||||
}
|
||||
DTP.device_info = DI_;
|
||||
} catch (...) {
|
||||
Logger().information(fmt::format("{}: stats failed parsing.", DI_.serialNumber));
|
||||
poco_information(Logger(),fmt::format("{}: stats failed parsing.", DI_.serialNumber));
|
||||
}
|
||||
|
||||
if(got_base) {
|
||||
@@ -439,7 +479,7 @@ namespace OpenWifi {
|
||||
try {
|
||||
if (Connection->contains("ping")) {
|
||||
got_connection = true;
|
||||
Logger().information(fmt::format("{}: ping message.", DI_.serialNumber));
|
||||
poco_debug(Logger(),fmt::format("{}: ping message.", DI_.serialNumber));
|
||||
DI_.connected = true;
|
||||
DI_.lastPing = OpenWifi::Now();
|
||||
auto ping = (*Connection)["ping"];
|
||||
@@ -455,13 +495,13 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
} else if (Connection->contains("disconnection")) {
|
||||
Logger().information(fmt::format("{}: disconnection message.", DI_.serialNumber));
|
||||
poco_debug(Logger(),fmt::format("{}: disconnection message.", DI_.serialNumber));
|
||||
auto Disconnection = (*Connection)["disconnection"];
|
||||
GetJSON("timestamp", Disconnection, DI_.lastDisconnection, (uint64_t)0 );
|
||||
got_base = got_health = got_connection = false;
|
||||
DI_.connected = false;
|
||||
} else if (Connection->contains("capabilities")) {
|
||||
Logger().information(fmt::format("{}: connection message.", DI_.serialNumber));
|
||||
poco_debug(Logger(),fmt::format("{}: connection message.", DI_.serialNumber));
|
||||
got_connection = true;
|
||||
DI_.connected = true;
|
||||
DI_.lastConnection = OpenWifi::Now();
|
||||
@@ -477,7 +517,7 @@ namespace OpenWifi {
|
||||
GetJSON("locale", ConnectionData, DI_.locale, std::string{} );
|
||||
}
|
||||
} catch (...) {
|
||||
Logger().information(fmt::format("{}: error parsing connection message.", DI_.serialNumber));
|
||||
poco_information(Logger(),fmt::format("{}: error parsing connection message.", DI_.serialNumber));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,9 +526,9 @@ namespace OpenWifi {
|
||||
got_health = true;
|
||||
GetJSON("timestamp", *Health, DI_.lastHealth, (uint64_t)0 );
|
||||
GetJSON("sanity", *Health, DI_.health, (uint64_t)0 );
|
||||
Logger().information(fmt::format("{}: health message.", DI_.serialNumber));
|
||||
poco_debug(Logger(),fmt::format("{}: health message.", DI_.serialNumber));
|
||||
} catch(...) {
|
||||
Logger().information(fmt::format("{}: error parsing health message.", DI_.serialNumber));
|
||||
poco_information(Logger(),fmt::format("{}: error parsing health message.", DI_.serialNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,13 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
struct InterfaceClientEntry {
|
||||
std::vector<std::string> ipv4_addresses;
|
||||
std::vector<std::string> ipv6_addresses;
|
||||
};
|
||||
|
||||
using InterfaceClientEntryMap_t = std::map<std::string,InterfaceClientEntry>;
|
||||
|
||||
class AP {
|
||||
public:
|
||||
explicit AP(uint64_t mac, const std::string &venue_id, const std::string &BoardId, Poco::Logger &L) :
|
||||
|
||||
@@ -45,17 +45,25 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
try {
|
||||
auto App = OpenWifi::Daemon::instance();
|
||||
auto ExitCode = App->run(argc, argv);
|
||||
delete App;
|
||||
int ExitCode;
|
||||
try {
|
||||
Poco::Net::SSLManager::instance().initializeServer(nullptr, nullptr, nullptr);
|
||||
auto App = OpenWifi::Daemon::instance();
|
||||
ExitCode = App->run(argc, argv);
|
||||
Poco::Net::SSLManager::instance().shutdown();
|
||||
} catch (Poco::Exception &exc) {
|
||||
ExitCode = Poco::Util::Application::EXIT_SOFTWARE;
|
||||
std::cout << exc.displayText() << std::endl;
|
||||
} catch (std::exception &exc) {
|
||||
ExitCode = Poco::Util::Application::EXIT_TEMPFAIL;
|
||||
std::cout << exc.what() << std::endl;
|
||||
} catch (...) {
|
||||
ExitCode = Poco::Util::Application::EXIT_TEMPFAIL;
|
||||
std::cout << "Exception on closure" << std::endl;
|
||||
}
|
||||
|
||||
return ExitCode;
|
||||
|
||||
} catch (Poco::Exception &exc) {
|
||||
std::cerr << exc.displayText() << std::endl;
|
||||
return Poco::Util::Application::EXIT_SOFTWARE;
|
||||
}
|
||||
std::cout << "Exitcode: " << ExitCode << std::endl;
|
||||
return ExitCode;
|
||||
}
|
||||
|
||||
// end of namespace
|
||||
@@ -23,6 +23,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void DeviceStatusReceiver::run() {
|
||||
Utils::SetThreadName("dev-status");
|
||||
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
|
||||
while(Note && Running_) {
|
||||
auto Msg = dynamic_cast<DeviceStatusMessage *>(Note.get());
|
||||
@@ -74,7 +75,7 @@ namespace OpenWifi {
|
||||
|
||||
void DeviceStatusReceiver::DeviceStatusReceived(const std::string &Key, const std::string &Payload) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Logger().information(fmt::format("Device({}): Connection/Ping message.", Key));
|
||||
poco_debug(Logger(),fmt::format("Device({}): Connection/Ping message.", Key));
|
||||
Queue_.enqueueNotification( new DeviceStatusMessage(Key,Payload));
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void HealthReceiver::run() {
|
||||
Utils::SetThreadName("dev-health");
|
||||
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
|
||||
while(Note && Running_) {
|
||||
auto Msg = dynamic_cast<HealthMessage *>(Note.get());
|
||||
@@ -74,7 +75,7 @@ namespace OpenWifi {
|
||||
|
||||
void HealthReceiver::HealthReceived(const std::string &Key, const std::string &Payload) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Logger().information(fmt::format("Device({}): Health message.", Key));
|
||||
poco_debug(Logger(),fmt::format("Device({}): Health message.", Key));
|
||||
Queue_.enqueueNotification( new HealthMessage(Key,Payload));
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,13 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
void RESTAPI_board_devices_handler::DoGet() {
|
||||
|
||||
auto id = GetBinding("id","");
|
||||
|
||||
if(id.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingUUID);
|
||||
}
|
||||
|
||||
AnalyticsObjects::BoardInfo BI;
|
||||
if(!StorageService()->BoardsDB().GetRecord("id",id,BI)) {
|
||||
return NotFound();
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace OpenWifi {
|
||||
NewBoard.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
return InternalError(RESTAPI::Errors::RecordNotCreated);
|
||||
}
|
||||
|
||||
void RESTAPI_board_handler::DoPut() {
|
||||
@@ -89,7 +90,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if(StorageService()->BoardsDB().UpdateRecord("id",Existing.info.id,Existing)) {
|
||||
VenueCoordinator()->ModifyBoard(Existing.info.id);
|
||||
VenueCoordinator()->UpdateBoard(Existing.info.id);
|
||||
AnalyticsObjects::BoardInfo NewBoard;
|
||||
StorageService()->BoardsDB().GetRecord("id",Existing.info.id,NewBoard);
|
||||
Poco::JSON::Object Answer;
|
||||
|
||||
@@ -5,54 +5,11 @@
|
||||
#include "RESTAPI_board_timepoint_handler.h"
|
||||
#include "StorageService.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace OpenWifi {
|
||||
static auto find_number_of_buckets(std::vector<AnalyticsObjects::DeviceTimePoint> &p) {
|
||||
uint32_t buckets=0,cur_buckets=0;
|
||||
std::string current_serialNumber;
|
||||
for(const auto &i:p) {
|
||||
if(current_serialNumber.empty()) {
|
||||
current_serialNumber = i.device_info.serialNumber;
|
||||
cur_buckets=0;
|
||||
}
|
||||
if(current_serialNumber==i.device_info.serialNumber) {
|
||||
cur_buckets++;
|
||||
} else {
|
||||
buckets = std::max(buckets,cur_buckets);
|
||||
current_serialNumber=i.device_info.serialNumber;
|
||||
cur_buckets=1;
|
||||
}
|
||||
}
|
||||
return std::max(buckets,cur_buckets);
|
||||
}
|
||||
|
||||
typedef std::vector< std::vector<AnalyticsObjects::DeviceTimePoint>> split_points;
|
||||
|
||||
static void split_in_buckets([[maybe_unused]] uint32_t buckets,std::vector<AnalyticsObjects::DeviceTimePoint> &p,split_points &sp) {
|
||||
std::string cur_sn;
|
||||
uint32_t cur_bucket=0;
|
||||
for(const auto &i:p) {
|
||||
if(cur_sn.empty()) {
|
||||
cur_bucket=1;
|
||||
cur_sn=i.device_info.serialNumber;
|
||||
}
|
||||
if(cur_sn==i.device_info.serialNumber) {
|
||||
if (cur_bucket>sp.size()) {
|
||||
std::vector<AnalyticsObjects::DeviceTimePoint> tmp_p;
|
||||
tmp_p.push_back(i);
|
||||
sp.push_back(tmp_p);
|
||||
cur_bucket++;
|
||||
} else {
|
||||
sp[cur_bucket-1].push_back(i);
|
||||
cur_bucket++;
|
||||
}
|
||||
} else {
|
||||
cur_bucket=1;
|
||||
sp[cur_bucket-1].push_back(i);
|
||||
cur_bucket++;
|
||||
cur_sn=i.device_info.serialNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
typedef std::vector<std::pair<std::uint64_t , std::uint64_t >> bucket_timespans;
|
||||
typedef std::vector< std::vector<AnalyticsObjects::DeviceTimePoint>> split_points;
|
||||
|
||||
template <typename X, typename M> void AverageAPData( X T, const std::vector<M> &Values, AnalyticsObjects::AveragePoint &P) {
|
||||
if(Values.empty())
|
||||
@@ -89,6 +46,81 @@ namespace OpenWifi {
|
||||
P.avg = 0.0;
|
||||
}
|
||||
|
||||
static void NewSort(const AnalyticsObjects::DeviceTimePointList &l,split_points &sp) {
|
||||
|
||||
struct {
|
||||
bool operator()(const AnalyticsObjects::DeviceTimePoint &lhs, const AnalyticsObjects::DeviceTimePoint &rhs) const {
|
||||
if (lhs.device_info.serialNumber < rhs.device_info.serialNumber) return true;
|
||||
if (lhs.device_info.serialNumber > rhs.device_info.serialNumber) return false;
|
||||
return lhs.timestamp < rhs.timestamp;
|
||||
}
|
||||
} sort_serial_ts;
|
||||
|
||||
// attempt at finding an interval
|
||||
AnalyticsObjects::DeviceTimePointList tmp{l};
|
||||
std::sort(tmp.points.begin(),tmp.points.end(),sort_serial_ts);
|
||||
|
||||
std::string cur_ser;
|
||||
std::uint64_t cur_int=0,start_val, last_val, first_val = 0;
|
||||
for(const auto &point:tmp.points) {
|
||||
if(cur_ser.empty()) {
|
||||
start_val = point.timestamp;
|
||||
cur_ser = point.serialNumber;
|
||||
first_val = point.timestamp;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(cur_ser==point.serialNumber) {
|
||||
auto this_int = point.timestamp - start_val;
|
||||
if(cur_int) {
|
||||
if(this_int<cur_int) {
|
||||
cur_int = this_int;
|
||||
}
|
||||
} else {
|
||||
cur_int = this_int;
|
||||
}
|
||||
start_val = point.timestamp;
|
||||
} else {
|
||||
cur_ser = point.serialNumber;
|
||||
start_val = point.timestamp;
|
||||
}
|
||||
last_val = point.timestamp;
|
||||
}
|
||||
|
||||
// std::cout << "Intervals: " << cur_int << std::endl;
|
||||
|
||||
std::vector<std::pair<std::uint64_t,std::uint64_t>> time_slots; // timeslot 0 has <t1,t2>
|
||||
std::vector<std::set<std::string>> serial_numbers; // serial number already in a timeslot.
|
||||
|
||||
|
||||
std::uint64_t cur_first=first_val,cur_end=0;
|
||||
sp.clear();
|
||||
while(cur_end<last_val) {
|
||||
std::pair<std::uint64_t,std::uint64_t> e;
|
||||
e.first = cur_first;
|
||||
e.second = e.first + cur_int-1;
|
||||
cur_first = e.second+1;
|
||||
cur_end = e.second;
|
||||
time_slots.emplace_back(e);
|
||||
std::set<std::string> q;
|
||||
serial_numbers.emplace_back(q);
|
||||
std::vector<AnalyticsObjects::DeviceTimePoint> qq;
|
||||
sp.emplace_back(qq);
|
||||
}
|
||||
|
||||
for(const auto &point:tmp.points) {
|
||||
std::uint64_t slot_index=0;
|
||||
for(const auto &slot:time_slots) {
|
||||
if(point.timestamp >= slot.first && point.timestamp <= slot.second) {
|
||||
serial_numbers[slot_index].insert(point.serialNumber);
|
||||
sp[slot_index].emplace_back(point);
|
||||
}
|
||||
slot_index++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RESTAPI_board_timepoint_handler::DoGet() {
|
||||
auto id = GetBinding("id","");
|
||||
if(id.empty() || !Utils::ValidUUID(id)) {
|
||||
@@ -102,7 +134,12 @@ namespace OpenWifi {
|
||||
|
||||
auto fromDate = GetParameter("fromDate",0);
|
||||
auto endDate = GetParameter("endDate",0);
|
||||
auto maxRecords = GetParameter("maxRecords",1000);
|
||||
std::uint64_t maxRecords;
|
||||
if(Request->has("limit"))
|
||||
maxRecords = QB_.Limit;
|
||||
else
|
||||
maxRecords = GetParameter("maxRecords",1000);
|
||||
|
||||
auto statsOnly = GetBoolParameter("statsOnly");
|
||||
auto pointsOnly = GetBoolParameter("pointsOnly");
|
||||
auto pointsStatsOnly = GetBoolParameter("pointsStatsOnly");
|
||||
@@ -115,71 +152,39 @@ namespace OpenWifi {
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
|
||||
auto Points = std::make_unique<AnalyticsObjects::DeviceTimePointList>();
|
||||
StorageService()->TimePointsDB().SelectRecords(id,fromDate, endDate, maxRecords, Points->points);
|
||||
AnalyticsObjects::DeviceTimePointList Points;
|
||||
StorageService()->TimePointsDB().SelectRecords(id,fromDate, endDate, maxRecords, Points.points);
|
||||
std::cout << "1 MaxRecords=" << maxRecords << " retrieved=" << Points.points.size() << std::endl;
|
||||
|
||||
// sort by timestamp & serial number.
|
||||
struct {
|
||||
bool operator()(const AnalyticsObjects::DeviceTimePoint &lhs, const AnalyticsObjects::DeviceTimePoint &rhs) const {
|
||||
if(lhs.device_info.serialNumber < rhs.device_info.serialNumber) return true;
|
||||
if(lhs.device_info.serialNumber > rhs.device_info.serialNumber) return false;
|
||||
return lhs.timestamp < rhs.timestamp;
|
||||
}
|
||||
} DeviceTimePoint_sort;
|
||||
split_points sp;
|
||||
|
||||
struct {
|
||||
bool operator()(const AnalyticsObjects::SSIDTimePoint &lhs, const AnalyticsObjects::SSIDTimePoint &rhs) const {
|
||||
if(lhs.ssid < rhs.ssid) return true;
|
||||
if(lhs.ssid > rhs.ssid) return false;
|
||||
return lhs.bssid < rhs.bssid;
|
||||
}
|
||||
} SSID_sort;
|
||||
NewSort(Points,sp);
|
||||
std::cout << __LINE__ << std::endl;
|
||||
|
||||
struct {
|
||||
bool operator()(const AnalyticsObjects::UETimePoint &lhs, const AnalyticsObjects::UETimePoint &rhs) const {
|
||||
if(lhs.station < rhs.station) return true;
|
||||
return false;
|
||||
}
|
||||
} Association_sort;
|
||||
|
||||
std::sort( Points->points.begin(), Points->points.end(), DeviceTimePoint_sort);
|
||||
auto BucketsNeeded = find_number_of_buckets(Points->points);
|
||||
|
||||
auto sp = std::make_unique<split_points>();
|
||||
split_in_buckets(BucketsNeeded,Points->points, *sp);
|
||||
// must sort each bucket according to serial number.
|
||||
for(auto &i: *sp) {
|
||||
std::sort(i.begin(),i.end(),DeviceTimePoint_sort);
|
||||
// now sort according to UEs within a block
|
||||
for(auto &j:i) {
|
||||
std::sort(j.ssid_data.begin(),j.ssid_data.end(),SSID_sort);
|
||||
for(auto &k:j.ssid_data) {
|
||||
std::sort(k.associations.begin(),k.associations.end(),Association_sort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Answer = std::make_unique<Poco::JSON::Object>();
|
||||
Poco::JSON::Object Answer;
|
||||
if(!pointsStatsOnly) {
|
||||
auto Points_OuterArray = std::make_unique<Poco::JSON::Array>();
|
||||
for (const auto &point_list:*sp) {
|
||||
Poco::JSON::Array Points_OuterArray;
|
||||
for (const auto &point_list:sp) {
|
||||
Poco::JSON::Array Points_InnerArray;
|
||||
for (const auto &point: point_list) {
|
||||
Poco::JSON::Object O;
|
||||
point.to_json(O);
|
||||
Points_InnerArray.add(O);
|
||||
}
|
||||
Points_OuterArray->add(Points_InnerArray);
|
||||
Points_OuterArray.add(Points_InnerArray);
|
||||
}
|
||||
Answer->set("points",*Points_OuterArray);
|
||||
Answer.set("points",Points_OuterArray);
|
||||
}
|
||||
|
||||
// calculate the stats for each time slot
|
||||
if(!pointsOnly) {
|
||||
auto Stats_Array = std::make_unique<Poco::JSON::Array>();
|
||||
for (const auto &point_list:*sp) {
|
||||
Poco::JSON::Array Stats_Array;
|
||||
for (const auto &point_list:sp) {
|
||||
AnalyticsObjects::DeviceTimePointAnalysis DTPA;
|
||||
|
||||
if(point_list.empty())
|
||||
continue;
|
||||
|
||||
DTPA.timestamp = point_list[0].timestamp;
|
||||
AverageAPData(&AnalyticsObjects::APTimePoint::tx_bytes_bw, point_list, DTPA.tx_bytes_bw);
|
||||
AverageAPData(&AnalyticsObjects::APTimePoint::rx_bytes_bw, point_list, DTPA.rx_bytes_bw);
|
||||
@@ -200,12 +205,12 @@ namespace OpenWifi {
|
||||
|
||||
Poco::JSON::Object Stats_point;
|
||||
DTPA.to_json(Stats_point);
|
||||
Stats_Array->add(Stats_point);
|
||||
Stats_Array.add(Stats_point);
|
||||
}
|
||||
Answer->set("stats", *Stats_Array);
|
||||
Answer.set("stats", Stats_Array);
|
||||
}
|
||||
|
||||
return ReturnObject(*Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
|
||||
void RESTAPI_board_timepoint_handler::DoDelete() {
|
||||
|
||||
@@ -20,10 +20,9 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if(GetBoolParameter("macsOnly")) {
|
||||
|
||||
auto macFilter = GetParameter("macFilter","");
|
||||
std::vector<uint64_t> Macs;
|
||||
WifiClientCache()->FindNumbers(venue,macFilter,500,Macs);
|
||||
WifiClientCache()->FindNumbers(venue,macFilter,QB_.Offset, QB_.Limit, Macs);
|
||||
Poco::JSON::Array Arr;
|
||||
for(const auto &mac: Macs)
|
||||
Arr.add(Utils::IntToSerialNumber(mac));
|
||||
@@ -63,11 +62,8 @@ namespace OpenWifi {
|
||||
return ReturnCountOnly(Count);
|
||||
}
|
||||
|
||||
if(StorageService()->WifiClientHistoryDB().GetRecords(QB_.Offset,QB_.Limit, Results, Where, OrderBy)) {
|
||||
return ReturnObject("entries",Results);
|
||||
}
|
||||
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
StorageService()->WifiClientHistoryDB().GetRecords(QB_.Offset,QB_.Limit, Results, Where, OrderBy);
|
||||
return ReturnObject("entries",Results);
|
||||
}
|
||||
|
||||
void RESTAPI_wificlienthistory_handler::DoDelete() {
|
||||
|
||||
@@ -3,176 +3,206 @@
|
||||
//
|
||||
|
||||
#include "RESTAPI_CertObjects.h"
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||
|
||||
namespace OpenWifi {
|
||||
namespace CertObjects {
|
||||
void CertificateEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"entity", entity);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"type", type);
|
||||
field_to_json(Obj,"status", status);
|
||||
field_to_json(Obj,"certificate", certificate);
|
||||
field_to_json(Obj,"key", key);
|
||||
field_to_json(Obj,"devid", devid);
|
||||
field_to_json(Obj,"cas", cas);
|
||||
field_to_json(Obj,"manufacturer", manufacturer);
|
||||
field_to_json(Obj,"model", model);
|
||||
field_to_json(Obj,"redirector", redirector);
|
||||
field_to_json(Obj,"commonName", commonName);
|
||||
field_to_json(Obj,"certificateId", certificateId);
|
||||
field_to_json(Obj,"batch", batch);
|
||||
field_to_json(Obj,"created", created);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
field_to_json(Obj,"revoked", revoked);
|
||||
field_to_json(Obj,"revokeCount", revokeCount);
|
||||
}
|
||||
namespace OpenWifi::CertObjects {
|
||||
void CertificateEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"entity", entity);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"type", type);
|
||||
field_to_json(Obj,"status", status);
|
||||
field_to_json(Obj,"certificate", certificate);
|
||||
field_to_json(Obj,"key", key);
|
||||
field_to_json(Obj,"devid", devid);
|
||||
field_to_json(Obj,"cas", cas);
|
||||
field_to_json(Obj,"manufacturer", manufacturer);
|
||||
field_to_json(Obj,"model", model);
|
||||
field_to_json(Obj,"redirector", redirector);
|
||||
field_to_json(Obj,"commonName", commonName);
|
||||
field_to_json(Obj,"certificateId", certificateId);
|
||||
field_to_json(Obj,"batch", batch);
|
||||
field_to_json(Obj,"created", created);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
field_to_json(Obj,"revoked", revoked);
|
||||
field_to_json(Obj,"revokeCount", revokeCount);
|
||||
field_to_json(Obj,"synched", synched);
|
||||
}
|
||||
|
||||
bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"type", type);
|
||||
field_from_json(Obj,"status", status);
|
||||
field_from_json(Obj,"certificate", certificate);
|
||||
field_from_json(Obj,"key", key);
|
||||
field_from_json(Obj,"devid", devid);
|
||||
field_from_json(Obj,"cas", cas);
|
||||
field_from_json(Obj,"manufacturer", manufacturer);
|
||||
field_from_json(Obj,"model", model);
|
||||
field_from_json(Obj,"redirector", redirector);
|
||||
field_from_json(Obj,"commonName", commonName);
|
||||
field_from_json(Obj,"certificateId", certificateId);
|
||||
field_from_json(Obj,"batch", batch);
|
||||
field_from_json(Obj,"created", created);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
field_from_json(Obj,"revoked", revoked);
|
||||
field_from_json(Obj,"revokeCount", revokeCount);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"type", type);
|
||||
field_from_json(Obj,"status", status);
|
||||
field_from_json(Obj,"certificate", certificate);
|
||||
field_from_json(Obj,"key", key);
|
||||
field_from_json(Obj,"devid", devid);
|
||||
field_from_json(Obj,"cas", cas);
|
||||
field_from_json(Obj,"manufacturer", manufacturer);
|
||||
field_from_json(Obj,"model", model);
|
||||
field_from_json(Obj,"redirector", redirector);
|
||||
field_from_json(Obj,"commonName", commonName);
|
||||
field_from_json(Obj,"certificateId", certificateId);
|
||||
field_from_json(Obj,"batch", batch);
|
||||
field_from_json(Obj,"created", created);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
field_from_json(Obj,"revoked", revoked);
|
||||
field_from_json(Obj,"revokeCount", revokeCount);
|
||||
field_from_json(Obj,"synched", synched);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"name", name);
|
||||
field_to_json(Obj,"description", description);
|
||||
field_to_json(Obj,"defaultRedirector", defaultRedirector);
|
||||
field_to_json(Obj,"apiKey", apiKey);
|
||||
field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
|
||||
field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
|
||||
field_to_json(Obj,"organization", organization);
|
||||
field_to_json(Obj,"created", created);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
field_to_json(Obj,"suspended", suspended);
|
||||
field_to_json(Obj,"deleted", deleted);
|
||||
field_to_json(Obj,"notes", notes);
|
||||
}
|
||||
void EntityEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"name", name);
|
||||
field_to_json(Obj,"description", description);
|
||||
field_to_json(Obj,"defaultRedirector", defaultRedirector);
|
||||
field_to_json(Obj,"apiKey", apiKey);
|
||||
field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
|
||||
field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
|
||||
field_to_json(Obj,"organization", organization);
|
||||
field_to_json(Obj,"created", created);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
field_to_json(Obj,"suspended", suspended);
|
||||
field_to_json(Obj,"deleted", deleted);
|
||||
field_to_json(Obj,"notes", notes);
|
||||
}
|
||||
|
||||
bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"name", name);
|
||||
field_from_json(Obj,"description", description);
|
||||
field_from_json(Obj,"defaultRedirector", defaultRedirector);
|
||||
field_from_json(Obj,"apiKey", apiKey);
|
||||
field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
|
||||
field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
|
||||
field_from_json(Obj,"organization", organization);
|
||||
field_from_json(Obj,"created", created);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
field_from_json(Obj,"suspended", suspended);
|
||||
field_from_json(Obj,"deleted", deleted);
|
||||
field_from_json(Obj,"notes", notes);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"name", name);
|
||||
field_from_json(Obj,"description", description);
|
||||
field_from_json(Obj,"defaultRedirector", defaultRedirector);
|
||||
field_from_json(Obj,"apiKey", apiKey);
|
||||
field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
|
||||
field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
|
||||
field_from_json(Obj,"organization", organization);
|
||||
field_from_json(Obj,"created", created);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
field_from_json(Obj,"suspended", suspended);
|
||||
field_from_json(Obj,"deleted", deleted);
|
||||
field_from_json(Obj,"notes", notes);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BatchEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"entity", entity);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"name", name);
|
||||
field_to_json(Obj,"description", description);
|
||||
field_to_json(Obj,"manufacturer", manufacturer);
|
||||
field_to_json(Obj,"model", model);
|
||||
field_to_json(Obj,"redirector", redirector);
|
||||
field_to_json(Obj,"commonNames", commonNames);
|
||||
field_to_json(Obj,"jobHistory", jobHistory);
|
||||
field_to_json(Obj,"notes", notes);
|
||||
field_to_json(Obj,"submitted", submitted);
|
||||
field_to_json(Obj,"started", started);
|
||||
field_to_json(Obj,"completed", completed);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
}
|
||||
void BatchEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"entity", entity);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"name", name);
|
||||
field_to_json(Obj,"description", description);
|
||||
field_to_json(Obj,"manufacturer", manufacturer);
|
||||
field_to_json(Obj,"model", model);
|
||||
field_to_json(Obj,"redirector", redirector);
|
||||
field_to_json(Obj,"commonNames", commonNames);
|
||||
field_to_json(Obj,"jobHistory", jobHistory);
|
||||
field_to_json(Obj,"notes", notes);
|
||||
field_to_json(Obj,"submitted", submitted);
|
||||
field_to_json(Obj,"started", started);
|
||||
field_to_json(Obj,"completed", completed);
|
||||
field_to_json(Obj,"modified", modified);
|
||||
}
|
||||
|
||||
bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"name", name);
|
||||
field_from_json(Obj,"description", description);
|
||||
field_from_json(Obj,"manufacturer", manufacturer);
|
||||
field_from_json(Obj,"model", model);
|
||||
field_from_json(Obj,"redirector", redirector);
|
||||
field_from_json(Obj,"commonNames", commonNames);
|
||||
field_from_json(Obj,"jobHistory", jobHistory);
|
||||
field_from_json(Obj,"notes", notes);
|
||||
field_from_json(Obj,"submitted", submitted);
|
||||
field_from_json(Obj,"started", started);
|
||||
field_from_json(Obj,"completed", completed);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"name", name);
|
||||
field_from_json(Obj,"description", description);
|
||||
field_from_json(Obj,"manufacturer", manufacturer);
|
||||
field_from_json(Obj,"model", model);
|
||||
field_from_json(Obj,"redirector", redirector);
|
||||
field_from_json(Obj,"commonNames", commonNames);
|
||||
field_from_json(Obj,"jobHistory", jobHistory);
|
||||
field_from_json(Obj,"notes", notes);
|
||||
field_from_json(Obj,"submitted", submitted);
|
||||
field_from_json(Obj,"started", started);
|
||||
field_from_json(Obj,"completed", completed);
|
||||
field_from_json(Obj,"modified", modified);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void JobEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"entity", entity);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"batch", batch);
|
||||
field_to_json(Obj,"commonNames", commonNames);
|
||||
field_to_json(Obj,"completedNames", completedNames);
|
||||
field_to_json(Obj,"errorNames", errorNames);
|
||||
field_to_json(Obj,"status", status);
|
||||
field_to_json(Obj,"command", command);
|
||||
field_to_json(Obj,"parameters", parameters);
|
||||
field_to_json(Obj,"submitted", submitted);
|
||||
field_to_json(Obj,"started", started);
|
||||
field_to_json(Obj,"completed", completed);
|
||||
}
|
||||
void JobEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"id", id);
|
||||
field_to_json(Obj,"entity", entity);
|
||||
field_to_json(Obj,"creator", creator);
|
||||
field_to_json(Obj,"batch", batch);
|
||||
field_to_json(Obj,"commonNames", commonNames);
|
||||
field_to_json(Obj,"completedNames", completedNames);
|
||||
field_to_json(Obj,"errorNames", errorNames);
|
||||
field_to_json(Obj,"status", status);
|
||||
field_to_json(Obj,"command", command);
|
||||
field_to_json(Obj,"parameters", parameters);
|
||||
field_to_json(Obj,"submitted", submitted);
|
||||
field_to_json(Obj,"started", started);
|
||||
field_to_json(Obj,"completed", completed);
|
||||
}
|
||||
|
||||
bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"batch", batch);
|
||||
field_from_json(Obj,"commonNames", commonNames);
|
||||
field_from_json(Obj,"completedNames", completedNames);
|
||||
field_from_json(Obj,"errorNames", errorNames);
|
||||
field_from_json(Obj,"status", status);
|
||||
field_from_json(Obj,"command", command);
|
||||
field_from_json(Obj,"parameters", parameters);
|
||||
field_from_json(Obj,"submitted", submitted);
|
||||
field_from_json(Obj,"started", started);
|
||||
field_from_json(Obj,"completed", completed);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"id", id);
|
||||
field_from_json(Obj,"entity", entity);
|
||||
field_from_json(Obj,"creator", creator);
|
||||
field_from_json(Obj,"batch", batch);
|
||||
field_from_json(Obj,"commonNames", commonNames);
|
||||
field_from_json(Obj,"completedNames", completedNames);
|
||||
field_from_json(Obj,"errorNames", errorNames);
|
||||
field_from_json(Obj,"status", status);
|
||||
field_from_json(Obj,"command", command);
|
||||
field_from_json(Obj,"parameters", parameters);
|
||||
field_from_json(Obj,"submitted", submitted);
|
||||
field_from_json(Obj,"started", started);
|
||||
field_from_json(Obj,"completed", completed);
|
||||
return true;
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DashBoardYearlyStats::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj, "year", year);
|
||||
field_to_json(Obj, "activeCerts", activeCerts);
|
||||
field_to_json(Obj, "revokedCerts", revokedCerts);
|
||||
}
|
||||
|
||||
void Dashboard::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"snapshot", snapshot);
|
||||
field_to_json(Obj,"numberOfIssuedCerts", numberOfIssuedCerts);
|
||||
field_to_json(Obj,"numberOfRevokedCerts", numberOfRevokedCerts);
|
||||
field_to_json(Obj,"activeCertsPerOrganization", activeCertsPerOrganization);
|
||||
field_to_json(Obj,"revokedCertsPerOrganization", revokedCertsPerOrganization);
|
||||
field_to_json(Obj,"numberOfRedirectors", numberOfRedirectors);
|
||||
field_to_json(Obj,"deviceTypes", deviceTypes);
|
||||
field_to_json(Obj,"monthlyNumberOfCerts", monthlyNumberOfCerts);
|
||||
field_to_json(Obj,"monthlyNumberOfCertsPerOrgPerYear", monthlyNumberOfCertsPerOrgPerYear);
|
||||
}
|
||||
|
||||
void Dashboard::reset() {
|
||||
snapshot=0;
|
||||
numberOfRevokedCerts = numberOfIssuedCerts = 0;
|
||||
activeCertsPerOrganization.clear();
|
||||
revokedCertsPerOrganization.clear();
|
||||
numberOfRedirectors.clear();
|
||||
deviceTypes.clear();
|
||||
monthlyNumberOfCerts.clear();
|
||||
monthlyNumberOfCertsPerOrgPerYear.clear();
|
||||
}
|
||||
}
|
||||
@@ -5,97 +5,118 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "framework/MicroService.h"
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
namespace OpenWifi::CertObjects {
|
||||
|
||||
namespace CertObjects {
|
||||
struct CertificateEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t entity;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
std::string type;
|
||||
std::string status;
|
||||
std::string certificate;
|
||||
std::string key;
|
||||
std::string devid;
|
||||
std::string cas;
|
||||
std::string manufacturer;
|
||||
std::string model;
|
||||
std::string redirector;
|
||||
std::string commonName;
|
||||
std::string certificateId;
|
||||
OpenWifi::Types::UUID_t batch;
|
||||
uint64_t created = 0;
|
||||
uint64_t modified = 0;
|
||||
uint64_t revoked = 0;
|
||||
uint64_t revokeCount = 0;
|
||||
uint64_t synched = 0;
|
||||
|
||||
struct CertificateEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t entity;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
std::string type;
|
||||
std::string status;
|
||||
std::string certificate;
|
||||
std::string key;
|
||||
std::string devid;
|
||||
std::string cas;
|
||||
std::string manufacturer;
|
||||
std::string model;
|
||||
std::string redirector;
|
||||
std::string commonName;
|
||||
std::string certificateId;
|
||||
OpenWifi::Types::UUID_t batch;
|
||||
uint64_t created = 0;
|
||||
uint64_t modified = 0;
|
||||
uint64_t revoked = 0;
|
||||
uint64_t revokeCount = 0;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
struct EntityEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string defaultRedirector;
|
||||
std::string apiKey;
|
||||
std::string serverEnrollmentProfile;
|
||||
std::string clientEnrollmentProfile;
|
||||
std::string organization;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
bool suspended=false;
|
||||
bool deleted=false;
|
||||
uint64_t created = 0 ;
|
||||
uint64_t modified = 0 ;
|
||||
|
||||
struct EntityEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string defaultRedirector;
|
||||
std::string apiKey;
|
||||
std::string serverEnrollmentProfile;
|
||||
std::string clientEnrollmentProfile;
|
||||
std::string organization;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
bool suspended=false;
|
||||
bool deleted=false;
|
||||
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);
|
||||
};
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
struct BatchEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t entity;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string manufacturer;
|
||||
std::string model;
|
||||
std::string redirector;
|
||||
std::vector<std::string> commonNames;
|
||||
std::vector<std::string> jobHistory;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
uint64_t submitted = 0 ;
|
||||
uint64_t started = 0 ;
|
||||
uint64_t completed = 0 ;
|
||||
uint64_t modified = 0 ;
|
||||
|
||||
struct BatchEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t entity;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string manufacturer;
|
||||
std::string model;
|
||||
std::string redirector;
|
||||
std::vector<std::string> commonNames;
|
||||
std::vector<std::string> jobHistory;
|
||||
SecurityObjects::NoteInfoVec notes;
|
||||
uint64_t submitted = 0 ;
|
||||
uint64_t started = 0 ;
|
||||
uint64_t completed = 0 ;
|
||||
uint64_t modified = 0 ;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
struct JobEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t entity;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
OpenWifi::Types::UUID_t batch;
|
||||
std::string command;
|
||||
OpenWifi::Types::StringVec commonNames;
|
||||
OpenWifi::Types::StringVec completedNames;
|
||||
OpenWifi::Types::StringVec errorNames;
|
||||
Types::StringPairVec parameters;
|
||||
std::string status;
|
||||
uint64_t submitted=0;
|
||||
uint64_t started=0;
|
||||
uint64_t completed=0;
|
||||
|
||||
struct JobEntry {
|
||||
OpenWifi::Types::UUID_t id;
|
||||
OpenWifi::Types::UUID_t entity;
|
||||
OpenWifi::Types::UUID_t creator;
|
||||
OpenWifi::Types::UUID_t batch;
|
||||
std::string command;
|
||||
OpenWifi::Types::StringVec commonNames;
|
||||
OpenWifi::Types::StringVec completedNames;
|
||||
OpenWifi::Types::StringVec errorNames;
|
||||
Types::StringPairVec parameters;
|
||||
std::string status;
|
||||
uint64_t submitted=0;
|
||||
uint64_t started=0;
|
||||
uint64_t completed=0;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct DashBoardYearlyStats {
|
||||
uint64_t year=0;
|
||||
OpenWifi::Types::Counted3DMapSII activeCerts;
|
||||
OpenWifi::Types::Counted3DMapSII revokedCerts;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
struct Dashboard {
|
||||
uint64_t snapshot=0;
|
||||
uint64_t numberOfIssuedCerts=0;
|
||||
uint64_t numberOfRevokedCerts=0;
|
||||
OpenWifi::Types::CountedMap activeCertsPerOrganization;
|
||||
OpenWifi::Types::CountedMap revokedCertsPerOrganization;
|
||||
OpenWifi::Types::CountedMap numberOfRedirectors;
|
||||
OpenWifi::Types::CountedMap deviceTypes;
|
||||
OpenWifi::Types::CountedMap monthlyNumberOfCerts;
|
||||
std::vector<DashBoardYearlyStats> monthlyNumberOfCertsPerOrgPerYear;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
void reset();
|
||||
};
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -203,6 +203,10 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"kafkaClients", kafkaClients);
|
||||
field_to_json(Obj,"kafkaPackets", kafkaPackets);
|
||||
field_to_json(Obj,"locale", locale);
|
||||
field_to_json(Obj,"started", started);
|
||||
field_to_json(Obj,"sessionId", sessionId);
|
||||
field_to_json(Obj,"connectionCompletionTime", connectionCompletionTime);
|
||||
field_to_json(Obj,"totalConnectionTime", OpenWifi::Now() - started);
|
||||
|
||||
switch(VerifiedCertificate) {
|
||||
case NO_CERTIFICATE:
|
||||
@@ -218,6 +222,21 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"averageConnectionTime", averageConnectionTime);
|
||||
field_to_json(Obj,"connectedDevices", connectedDevices );
|
||||
}
|
||||
|
||||
bool DeviceConnectionStatistics::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"averageConnectionTime", averageConnectionTime);
|
||||
field_from_json(Obj,"connectedDevices", connectedDevices );
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"serialNumber", SerialNumber);
|
||||
field_to_json(Obj,"server", Server);
|
||||
@@ -293,7 +312,6 @@ namespace OpenWifi::GWObjects {
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void RadiusProxyPoolList::to_json(Poco::JSON::Object &Obj) const {
|
||||
@@ -314,6 +332,8 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"description",description);
|
||||
field_to_json(Obj,"authConfig",authConfig);
|
||||
field_to_json(Obj,"acctConfig",acctConfig);
|
||||
field_to_json(Obj,"coaConfig",coaConfig);
|
||||
field_to_json(Obj,"useByDefault",useByDefault);
|
||||
}
|
||||
|
||||
bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -322,6 +342,8 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj,"description",description);
|
||||
field_from_json(Obj,"authConfig",authConfig);
|
||||
field_from_json(Obj,"acctConfig",acctConfig);
|
||||
field_from_json(Obj,"coaConfig",coaConfig);
|
||||
field_from_json(Obj,"useByDefault",useByDefault);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
@@ -329,7 +351,7 @@ namespace OpenWifi::GWObjects {
|
||||
}
|
||||
|
||||
void RadiusProxyServerConfig::to_json(Poco::JSON::Object &Obj) const {
|
||||
field_to_json(Obj,"policy",strategy);
|
||||
field_to_json(Obj,"strategy",strategy);
|
||||
field_to_json(Obj,"monitor",monitor);
|
||||
field_to_json(Obj,"monitorMethod",monitorMethod);
|
||||
field_to_json(Obj,"methodParameters",methodParameters);
|
||||
@@ -338,7 +360,7 @@ namespace OpenWifi::GWObjects {
|
||||
|
||||
bool RadiusProxyServerConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
field_from_json(Obj,"policy",strategy);
|
||||
field_from_json(Obj,"strategy",strategy);
|
||||
field_from_json(Obj,"monitor",monitor);
|
||||
field_from_json(Obj,"monitorMethod",monitorMethod);
|
||||
field_from_json(Obj,"methodParameters",methodParameters);
|
||||
@@ -354,6 +376,16 @@ namespace OpenWifi::GWObjects {
|
||||
field_to_json(Obj,"ip",ip);
|
||||
field_to_json(Obj,"port",port);
|
||||
field_to_json(Obj,"weight",weight);
|
||||
field_to_json(Obj,"secret",secret);
|
||||
field_to_json(Obj,"certificate",certificate);
|
||||
field_to_json(Obj,"radsec",radsec);
|
||||
field_to_json(Obj,"radsecPort",radsecPort);
|
||||
field_to_json(Obj,"radsecSecret",radsecSecret);
|
||||
field_to_json(Obj,"radsecCacerts",radsecCacerts);
|
||||
field_to_json(Obj,"radsecCert",radsecCert);
|
||||
field_to_json(Obj,"radsecKey",radsecKey);
|
||||
field_to_json(Obj,"radsecRealms",radsecRealms);
|
||||
field_to_json(Obj,"ignore",ignore);
|
||||
}
|
||||
|
||||
bool RadiusProxyServerEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -362,6 +394,16 @@ namespace OpenWifi::GWObjects {
|
||||
field_from_json(Obj,"ip",ip);
|
||||
field_from_json(Obj,"port",port);
|
||||
field_from_json(Obj,"weight",weight);
|
||||
field_from_json(Obj,"secret",secret);
|
||||
field_from_json(Obj,"certificate",certificate);
|
||||
field_from_json(Obj,"radsec",radsec);
|
||||
field_from_json(Obj,"radsecSecret",radsecSecret);
|
||||
field_from_json(Obj,"radsecPort",radsecPort);
|
||||
field_from_json(Obj,"radsecCacerts",radsecCacerts);
|
||||
field_from_json(Obj,"radsecCert",radsecCert);
|
||||
field_from_json(Obj,"radsecKey",radsecKey);
|
||||
field_from_json(Obj,"radsecRealms",radsecRealms);
|
||||
field_from_json(Obj,"ignore",ignore);
|
||||
return true;
|
||||
} catch (const Poco::Exception &E) {
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ namespace OpenWifi::GWObjects {
|
||||
uint64_t kafkaPackets=0;
|
||||
uint64_t websocketPackets=0;
|
||||
std::string locale;
|
||||
uint64_t started=0;
|
||||
uint64_t sessionId=0;
|
||||
double connectionCompletionTime=0.0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
};
|
||||
|
||||
@@ -71,6 +75,13 @@ namespace OpenWifi::GWObjects {
|
||||
void Print() const;
|
||||
};
|
||||
|
||||
struct DeviceConnectionStatistics {
|
||||
std::uint64_t connectedDevices = 0;
|
||||
std::uint64_t averageConnectionTime = 0;
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
struct Statistics {
|
||||
std::string SerialNumber;
|
||||
uint64_t UUID = 0 ;
|
||||
@@ -216,6 +227,16 @@ namespace OpenWifi::GWObjects {
|
||||
std::string ip;
|
||||
uint16_t port=0;
|
||||
uint64_t weight=0;
|
||||
std::string secret;
|
||||
std::string certificate;
|
||||
bool radsec=false;
|
||||
uint16_t radsecPort=2083;
|
||||
std::string radsecSecret;
|
||||
std::string radsecKey;
|
||||
std::string radsecCert;
|
||||
std::vector<std::string> radsecCacerts;
|
||||
std::vector<std::string> radsecRealms;
|
||||
bool ignore=false;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
@@ -237,6 +258,8 @@ namespace OpenWifi::GWObjects {
|
||||
std::string description;
|
||||
RadiusProxyServerConfig authConfig;
|
||||
RadiusProxyServerConfig acctConfig;
|
||||
RadiusProxyServerConfig coaConfig;
|
||||
bool useByDefault=false;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include "framework/OpenWifiTypes.h"
|
||||
#include "Poco/JSON/Object.h"
|
||||
#include "Poco/Data/LOB.h"
|
||||
@@ -27,8 +28,13 @@ namespace OpenWifi {
|
||||
bool Delete_ = true;
|
||||
bool PortalLogin_ = true;
|
||||
|
||||
AclTemplate() noexcept = default;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj); };
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
static_assert( std::is_nothrow_move_constructible_v<AclTemplate> );
|
||||
|
||||
struct WebToken {
|
||||
std::string access_token_;
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace OpenWifi {
|
||||
|
||||
void StateReceiver::run() {
|
||||
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
|
||||
Utils::SetThreadName("dev-state");
|
||||
while(Note && Running_) {
|
||||
auto Msg = dynamic_cast<StateMessage *>(Note.get());
|
||||
if(Msg!= nullptr) {
|
||||
@@ -58,7 +59,7 @@ namespace OpenWifi {
|
||||
|
||||
void StateReceiver::StateReceived( const std::string & Key, const std::string & Payload) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Logger().information(fmt::format("Device({}): State message.", Key));
|
||||
poco_debug(Logger(),fmt::format("Device({}): State message.", Key));
|
||||
Queue_.enqueueNotification( new StateMessage(Key,Payload));
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace OpenWifi {
|
||||
|
||||
int Storage::Start() {
|
||||
poco_notice(Logger(),"Starting...");
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
StorageClass::Start();
|
||||
@@ -43,14 +44,14 @@ namespace OpenWifi {
|
||||
uint64_t start = 0 ;
|
||||
bool done = false;
|
||||
const uint64_t batch=100;
|
||||
Logger().information("Starting cleanup of TimePoint Database");
|
||||
poco_information(Logger(),"Starting cleanup of TimePoint Database");
|
||||
while(!done) {
|
||||
if(!BoardsDB().GetRecords(start,batch,BoardList)) {
|
||||
for(const auto &board:BoardList) {
|
||||
for(const auto &venue:board.venueList) {
|
||||
auto now = OpenWifi::Now();
|
||||
auto lower_bound = now - venue.retention;
|
||||
Logger().information(fmt::format("Removing old records for board '{}'",board.info.name));
|
||||
poco_information(Logger(),fmt::format("Removing old records for board '{}'",board.info.name));
|
||||
BoardsDB().DeleteRecords(fmt::format(" boardId='{}' and timestamp<{}", board.info.id, lower_bound));
|
||||
}
|
||||
}
|
||||
@@ -60,12 +61,13 @@ namespace OpenWifi {
|
||||
|
||||
auto MaxDays = MicroService::instance().ConfigGetInt("wificlient.age.limit",14);
|
||||
auto LowerDate = OpenWifi::Now() - (MaxDays*60*60*24);
|
||||
Logger().information(fmt::format("Removing WiFi Clients history older than {} days.", MaxDays));
|
||||
poco_information(Logger(),fmt::format("Removing WiFi Clients history older than {} days.", MaxDays));
|
||||
StorageService()->WifiClientHistoryDB().DeleteRecords(fmt::format(" timestamp<{} ", LowerDate));
|
||||
Logger().information(fmt::format("Done cleanup of databases. Next run in {} seconds.", PeriodicCleanup_));
|
||||
poco_information(Logger(),fmt::format("Done cleanup of databases. Next run in {} seconds.", PeriodicCleanup_));
|
||||
}
|
||||
|
||||
void Storage::run() {
|
||||
Utils::SetThreadName("strg-updtr");
|
||||
Running_ = true ;
|
||||
bool FirstRun=true;
|
||||
long Retry = 2000;
|
||||
@@ -80,11 +82,12 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void Storage::Stop() {
|
||||
poco_notice(Logger(),"Stopping...");
|
||||
Running_=false;
|
||||
Timer_.stop();
|
||||
Updater_.wakeUp();
|
||||
Updater_.join();
|
||||
Logger().notice("Stopping.");
|
||||
poco_notice(Logger(),"Stopped...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,37 +11,58 @@
|
||||
namespace OpenWifi {
|
||||
|
||||
int VenueCoordinator::Start() {
|
||||
poco_notice(Logger(),"Starting...");
|
||||
GetBoardList();
|
||||
Worker_.start(*this);
|
||||
|
||||
ReconcileTimerCallback_ = std::make_unique<Poco::TimerCallback<VenueCoordinator>>(*this,&VenueCoordinator::onReconcileTimer);
|
||||
ReconcileTimerTimer_.setStartInterval( 3 * 60 * 1000 );
|
||||
ReconcileTimerTimer_.setPeriodicInterval(3 * 60 * 1000); // 1 hours
|
||||
ReconcileTimerTimer_.start(*ReconcileTimerCallback_, MicroService::instance().TimerPool());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VenueCoordinator::onReconcileTimer([[maybe_unused]] Poco::Timer &timer) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Utils::SetThreadName("brd-refresh");
|
||||
|
||||
poco_information(Logger(),"Starting to reconcile board information.");
|
||||
for(const auto &[board_id, watcher]:Watchers_) {
|
||||
poco_information(Logger(),fmt::format("Updating: {}", board_id));
|
||||
UpdateBoard(board_id);
|
||||
}
|
||||
poco_information(Logger(),"Finished reconciling board information.");
|
||||
}
|
||||
|
||||
void VenueCoordinator::GetBoardList() {
|
||||
BoardsToWatch_.clear();
|
||||
auto F = [&](const AnalyticsObjects::BoardInfo &B) ->bool {
|
||||
BoardsToWatch_.insert(B);
|
||||
// Logger().information(fmt::format("Starting watch for {}.", B.info.name));
|
||||
// poco_information(Logger(),fmt::format("Starting watch for {}.", B.info.name));
|
||||
return true;
|
||||
};
|
||||
StorageService()->BoardsDB().Iterate(F);
|
||||
}
|
||||
|
||||
void VenueCoordinator::Stop() {
|
||||
poco_notice(Logger(),"Stopping...");
|
||||
Running_=false;
|
||||
Worker_.wakeUp();
|
||||
Worker_.wakeUp();
|
||||
Worker_.join();
|
||||
poco_notice(Logger(),"Stopped...");
|
||||
}
|
||||
|
||||
void VenueCoordinator::run() {
|
||||
Utils::SetThreadName("venue-coord");
|
||||
Running_=true;
|
||||
while(Running_) {
|
||||
Poco::Thread::trySleep(2000);
|
||||
|
||||
Poco::Thread::trySleep(20000);
|
||||
if(!Running_)
|
||||
break;
|
||||
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
GetBoardList();
|
||||
|
||||
if(!BoardsToWatch_.empty()) {
|
||||
@@ -59,9 +80,11 @@ namespace OpenWifi {
|
||||
|
||||
void VenueCoordinator::RetireBoard(const AnalyticsObjects::BoardInfo &B) {
|
||||
Logger().error(fmt::format("Venue board '{}' is no longer in the system. Retiring its associated board.", B.venueList[0].name));
|
||||
/*
|
||||
StopBoard(B.info.id);
|
||||
StorageService()->BoardsDB().DeleteRecord("id",B.info.id);
|
||||
StorageService()->TimePointsDB().DeleteRecords(fmt::format(" boardId='{}' ", B.info.id));
|
||||
*/
|
||||
}
|
||||
|
||||
bool VenueCoordinator::GetDevicesForBoard(const AnalyticsObjects::BoardInfo &B, std::vector<uint64_t> & Devices, bool & VenueExists) {
|
||||
@@ -96,7 +119,7 @@ namespace OpenWifi {
|
||||
ExistingBoards_[B.info.id] = Devices;
|
||||
Watchers_[B.info.id] = std::make_shared<VenueWatcher>(B.info.id, B.venueList[0].id, Logger(), Devices);
|
||||
Watchers_[B.info.id]->Start();
|
||||
Logger().information(fmt::format("Started board {} for venue {}", B.info.name,B.venueList[0].id ));
|
||||
poco_information(Logger(),fmt::format("Started board {} for venue {}", B.info.name,B.venueList[0].id ));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -105,7 +128,7 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger().information(fmt::format("Could not start board {}",B.info.name));
|
||||
poco_information(Logger(),fmt::format("Could not start board {}",B.info.name));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,7 +142,7 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
void VenueCoordinator::ModifyBoard(const std::string &id) {
|
||||
void VenueCoordinator::UpdateBoard(const std::string &id) {
|
||||
AnalyticsObjects::BoardInfo B;
|
||||
if(StorageService()->BoardsDB().GetRecord("id",id,B)) {
|
||||
std::vector<uint64_t> Devices;
|
||||
@@ -130,15 +153,15 @@ namespace OpenWifi {
|
||||
if(it!=ExistingBoards_.end()) {
|
||||
if(it->second!=Devices) {
|
||||
auto it2 = Watchers_.find(id);
|
||||
if(it2!=Watchers_.end())
|
||||
if(it2!=Watchers_.end()) {
|
||||
it2->second->ModifySerialNumbers(Devices);
|
||||
}
|
||||
ExistingBoards_[id] = Devices;
|
||||
Logger().information(fmt::format("Modified board {}",B.info.name));
|
||||
poco_information(Logger(),fmt::format("Modified board {}",B.info.name));
|
||||
} else {
|
||||
Logger().information(fmt::format("No device changes in board {}",B.info.name));
|
||||
poco_information(Logger(),fmt::format("No device changes in board {}",B.info.name));
|
||||
}
|
||||
}
|
||||
Logger().information(fmt::format("Modified board {}",B.info.name));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,7 +170,7 @@ namespace OpenWifi {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger().information(fmt::format("Could not modify board {}",B.info.name));
|
||||
poco_information(Logger(),fmt::format("Could not modify board {}",B.info.name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +186,7 @@ namespace OpenWifi {
|
||||
if(StorageService()->BoardsDB().GetRecord("id",id,B))
|
||||
BoardsToWatch_.insert(B);
|
||||
else
|
||||
Logger().information(fmt::format("Board {} does not seem to exist",id));
|
||||
poco_information(Logger(),fmt::format("Board {} does not seem to exist",id));
|
||||
}
|
||||
|
||||
void VenueCoordinator::GetDevices(std::string &id, AnalyticsObjects::DeviceInfoList &DIL) {
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
#include "VenueWatcher.h"
|
||||
|
||||
#include "Poco/Timer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class VenueCoordinator : public SubSystemServer, Poco::Runnable {
|
||||
@@ -21,7 +24,7 @@ namespace OpenWifi {
|
||||
void run() override;
|
||||
|
||||
void StopBoard(const std::string &id);
|
||||
void ModifyBoard(const std::string &id);
|
||||
void UpdateBoard(const std::string &id);
|
||||
void AddBoard(const std::string &id);
|
||||
|
||||
bool GetDevicesForBoard(const AnalyticsObjects::BoardInfo &B, std::vector<uint64_t> & Devices, bool & VenueExists);
|
||||
@@ -30,13 +33,17 @@ namespace OpenWifi {
|
||||
bool Watching(const std::string &id);
|
||||
void RetireBoard(const AnalyticsObjects::BoardInfo &B);
|
||||
|
||||
private:
|
||||
Poco::Thread Worker_;
|
||||
std::atomic_bool Running_=false;
|
||||
std::set<AnalyticsObjects::BoardInfo> BoardsToWatch_;
|
||||
std::map<std::string,std::shared_ptr<VenueWatcher>> Watchers_;
|
||||
void onReconcileTimer(Poco::Timer & timer);
|
||||
|
||||
std::map<std::string,std::vector<uint64_t>> ExistingBoards_;
|
||||
private:
|
||||
Poco::Thread Worker_;
|
||||
std::atomic_bool Running_=false;
|
||||
std::set<AnalyticsObjects::BoardInfo> BoardsToWatch_;
|
||||
std::map<std::string,std::shared_ptr<VenueWatcher>> Watchers_;
|
||||
std::unique_ptr<Poco::TimerCallback<VenueCoordinator>> ReconcileTimerCallback_;
|
||||
Poco::Timer ReconcileTimerTimer_;
|
||||
|
||||
std::map<std::string,std::vector<uint64_t>> ExistingBoards_;
|
||||
|
||||
VenueCoordinator() noexcept:
|
||||
SubSystemServer("VenueCoordinator", "VENUE-COORD", "venue.coordinator")
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace OpenWifi {
|
||||
|
||||
void VenueWatcher::Start() {
|
||||
poco_notice(Logger(),"Starting...");
|
||||
for(const auto &mac:SerialNumbers_) {
|
||||
auto ap = std::make_shared<AP>(mac, venue_id_, boardId_, Logger());
|
||||
APs_[mac ] = ap;
|
||||
@@ -24,6 +25,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void VenueWatcher::Stop() {
|
||||
poco_notice(Logger(),"Stopping...");
|
||||
Running_ = false;
|
||||
Queue_.wakeUpAll();
|
||||
Worker_.join();
|
||||
@@ -31,9 +33,11 @@ namespace OpenWifi {
|
||||
StateReceiver()->DeRegister(i,this);
|
||||
DeviceStatusReceiver()->DeRegister(this);
|
||||
HealthReceiver()->DeRegister(this);
|
||||
poco_notice(Logger(),"Stopped...");
|
||||
}
|
||||
|
||||
void VenueWatcher::run() {
|
||||
Utils::SetThreadName("venue-watch");
|
||||
Running_ = true;
|
||||
Poco::AutoPtr<Poco::Notification> Msg(Queue_.waitDequeueNotification());
|
||||
while(Msg && Running_) {
|
||||
|
||||
@@ -69,9 +69,11 @@ namespace OpenWifi {
|
||||
void GetDevices(std::vector<AnalyticsObjects::DeviceInfo> & DI);
|
||||
|
||||
void GetBandwidth(uint64_t start, uint64_t end, uint64_t interval , AnalyticsObjects::BandwidthAnalysis & BW);
|
||||
|
||||
inline std::string Venue() const {
|
||||
return venue_id_;
|
||||
}
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
std::mutex Mutex_;
|
||||
std::string boardId_;
|
||||
std::string venue_id_;
|
||||
Poco::NotificationQueue Queue_;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace OpenWifi {
|
||||
|
||||
int WifiClientCache::Start() {
|
||||
poco_notice(Logger(),"Starting...");
|
||||
TimerCallback_ = std::make_unique<Poco::TimerCallback<WifiClientCache>>(*this,&WifiClientCache::onTimer);
|
||||
Timer_.setStartInterval( 30 * 1000); // first run in 20 seconds
|
||||
Timer_.setPeriodicInterval( 60 * 60 * 1000); // 1 hours
|
||||
@@ -18,7 +19,9 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void WifiClientCache::Stop() {
|
||||
poco_notice(Logger(),"Stopping...");
|
||||
Timer_.stop();
|
||||
poco_notice(Logger(),"Stopped...");
|
||||
}
|
||||
|
||||
void WifiClientCache::onTimer([[maybe_unused]] Poco::Timer & timer) {
|
||||
@@ -124,32 +127,36 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
void WifiClientCache::FindNumbers(const std::string &venue_id, const std::string &S, uint HowMany, std::vector<uint64_t> &A) {
|
||||
void WifiClientCache::FindNumbers(const std::string &venueId, const std::string &SerialNumber, std::uint64_t StartingOffset, std::uint64_t HowMany, std::vector<uint64_t> &A) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
A.clear();
|
||||
auto VenueIt = Cache_.find(venue_id);
|
||||
auto VenueIt = Cache_.find(venueId);
|
||||
if(VenueIt==Cache_.end())
|
||||
return;
|
||||
|
||||
if(S.empty()) {
|
||||
if(SerialNumber.empty()) {
|
||||
auto Start = VenueIt->second.SNs_.begin();
|
||||
std::uint64_t Offset=0;
|
||||
while(HowMany && Start!=VenueIt->second.SNs_.end()) {
|
||||
A.push_back(*Start);
|
||||
if(Offset>=StartingOffset) {
|
||||
A.push_back(*Start);
|
||||
HowMany--;
|
||||
}
|
||||
Start++;
|
||||
HowMany--;
|
||||
Offset++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (S[0] == '*') {
|
||||
if (SerialNumber[0] == '*') {
|
||||
std::string Reversed;
|
||||
std::copy(rbegin(S), rend(S)-1, std::back_inserter(Reversed));
|
||||
std::copy(rbegin(SerialNumber), rend(SerialNumber)-1, std::back_inserter(Reversed));
|
||||
if(Reversed.empty())
|
||||
return;
|
||||
return ReturnNumbers(Reversed, HowMany, VenueIt->second.Reverse_SNs_, A, true);
|
||||
} else {
|
||||
return ReturnNumbers(S, HowMany, VenueIt->second.SNs_, A, false);
|
||||
return ReturnNumbers(SerialNumber, HowMany, VenueIt->second.SNs_, A, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace OpenWifi {
|
||||
void Stop() override;
|
||||
void AddSerialNumber(const std::string &venueId, const std::string &SerialNumber);
|
||||
void DeleteSerialNumber(const std::string &venueId, const std::string &SerialNumber);
|
||||
void FindNumbers(const std::string &venueId, const std::string &SerialNumber, uint HowMany, std::vector<uint64_t> &A);
|
||||
void FindNumbers(const std::string &venueId, const std::string &SerialNumber, std::uint64_t start, std::uint64_t HowMany, std::vector<uint64_t> &A);
|
||||
inline bool NumberExists(const std::string &venueId, uint64_t SerialNumber) {
|
||||
std::lock_guard G(Mutex_);
|
||||
auto It = Cache_.find(venueId);
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
static const std::string GitUCentralJSONSchemaFile{"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"};
|
||||
static const std::string GitUCentralJSONSchemaFile{
|
||||
"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"};
|
||||
|
||||
static json DefaultUCentralSchema = R"(
|
||||
static json DefaultUCentralSchema = R"(
|
||||
|
||||
{
|
||||
"$id": "https://openwrt.org/ucentral.schema.json",
|
||||
@@ -43,7 +44,7 @@ namespace OpenWifi {
|
||||
"switch": {
|
||||
"$ref": "#/$defs/switch"
|
||||
},
|
||||
"radios": {
|
||||
"radiosgrep": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/radio"
|
||||
@@ -518,7 +519,7 @@ namespace OpenWifi {
|
||||
"maximum": 4050
|
||||
},
|
||||
"proto": {
|
||||
"decription": "The L2 vlan tag that shall be added (1q,1ad) ",
|
||||
"decription": "The L2 vlan tag that shall be added (1q,1ad ) ",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"802.1ad",
|
||||
@@ -669,6 +670,47 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
},
|
||||
"interface.ipv4.port-forward": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tcp",
|
||||
"udp",
|
||||
"any"
|
||||
],
|
||||
"default": "any"
|
||||
},
|
||||
"external-port": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"minimum": 0,
|
||||
"maximum": 65535,
|
||||
"format": "uc-portrange"
|
||||
},
|
||||
"internal-address": {
|
||||
"type": "string",
|
||||
"format": "ipv4",
|
||||
"example": "0.0.0.120"
|
||||
},
|
||||
"internal-port": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"minimum": 0,
|
||||
"maximum": 65535,
|
||||
"format": "uc-portrange"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"external-port",
|
||||
"internal-address"
|
||||
]
|
||||
},
|
||||
"interface.ipv4": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -722,6 +764,12 @@ namespace OpenWifi {
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ipv4.dhcp-lease"
|
||||
}
|
||||
},
|
||||
"port-forward": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ipv4.port-forward"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -751,6 +799,96 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
},
|
||||
"interface.ipv6.port-forward": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tcp",
|
||||
"udp",
|
||||
"any"
|
||||
],
|
||||
"default": "any"
|
||||
},
|
||||
"external-port": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"minimum": 0,
|
||||
"maximum": 65535,
|
||||
"format": "uc-portrange"
|
||||
},
|
||||
"internal-address": {
|
||||
"type": "string",
|
||||
"format": "ipv6",
|
||||
"example": "::1234:abcd"
|
||||
},
|
||||
"internal-port": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"minimum": 0,
|
||||
"maximum": 65535,
|
||||
"format": "uc-portrange"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"external-port",
|
||||
"internal-address"
|
||||
]
|
||||
},
|
||||
"interface.ipv6.traffic-allow": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol": {
|
||||
"type": "string",
|
||||
"default": "any"
|
||||
},
|
||||
"source-address": {
|
||||
"type": "string",
|
||||
"format": "uc-cidr6",
|
||||
"example": "2001:db8:1234:abcd::/64",
|
||||
"default": "::/0"
|
||||
},
|
||||
"source-ports": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"minimum": 0,
|
||||
"maximum": 65535,
|
||||
"format": "uc-portrange"
|
||||
}
|
||||
},
|
||||
"destination-address": {
|
||||
"type": "string",
|
||||
"format": "ipv6",
|
||||
"example": "::1000"
|
||||
},
|
||||
"destination-ports": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"minimum": 0,
|
||||
"maximum": 65535,
|
||||
"format": "uc-portrange"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"destination-address"
|
||||
]
|
||||
},
|
||||
"interface.ipv6": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -782,6 +920,18 @@ namespace OpenWifi {
|
||||
},
|
||||
"dhcpv6": {
|
||||
"$ref": "#/$defs/interface.ipv6.dhcpv6"
|
||||
},
|
||||
"port-forward": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ipv6.port-forward"
|
||||
}
|
||||
},
|
||||
"traffic-allow": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/interface.ipv6.traffic-allow"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -866,7 +1016,7 @@ namespace OpenWifi {
|
||||
},
|
||||
"gateway-fqdn": {
|
||||
"type": "string",
|
||||
"format": "fqdn",
|
||||
"format": "uc-fqdn",
|
||||
"default": "ucentral.splash"
|
||||
},
|
||||
"max-clients": {
|
||||
@@ -901,6 +1051,7 @@ namespace OpenWifi {
|
||||
"psk",
|
||||
"psk2",
|
||||
"psk-mixed",
|
||||
"psk2-radius",
|
||||
"wpa",
|
||||
"wpa2",
|
||||
"wpa-mixed",
|
||||
@@ -961,6 +1112,10 @@ namespace OpenWifi {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"reduced-neighbor-reporting": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"lci": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -1527,6 +1682,11 @@ namespace OpenWifi {
|
||||
"decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.",
|
||||
"type": "string"
|
||||
},
|
||||
"fils-discovery-interval": {
|
||||
"type": "integer",
|
||||
"default": 20,
|
||||
"maximum": 10000
|
||||
},
|
||||
"encryption": {
|
||||
"$ref": "#/$defs/interface.ssid.encryption"
|
||||
},
|
||||
@@ -2087,6 +2247,10 @@ namespace OpenWifi {
|
||||
"auto-channel": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"ipv6": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2193,7 +2357,7 @@ namespace OpenWifi {
|
||||
"properties": {
|
||||
"fqdn": {
|
||||
"type": "string",
|
||||
"format": "fqdn"
|
||||
"format": "uc-fqdn"
|
||||
},
|
||||
"suffix-matching": {
|
||||
"type": "boolean",
|
||||
@@ -2444,8 +2608,7 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
)"_json;
|
||||
)"_json;
|
||||
|
||||
class custom_error_handler : public nlohmann::json_schema::basic_error_handler
|
||||
{
|
||||
@@ -2460,9 +2623,18 @@ namespace OpenWifi {
|
||||
void ConfigurationValidator::Init() {
|
||||
if(Initialized_)
|
||||
return;
|
||||
|
||||
std::string GitSchema;
|
||||
if(MicroService::instance().ConfigGetBool("ucentral.datamodel.internal",true)) {
|
||||
RootSchema_ = DefaultUCentralSchema;
|
||||
Logger().information("Using uCentral validation from built-in default.");
|
||||
Initialized_ = Working_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
|
||||
auto GitURI = MicroService::instance().ConfigGetString("ucentral.datamodel.uri",GitUCentralJSONSchemaFile);
|
||||
if(Utils::wgets(GitURI, GitSchema)) {
|
||||
RootSchema_ = json::parse(GitSchema);
|
||||
Logger().information("Using uCentral validation schema from GIT.");
|
||||
} else {
|
||||
@@ -2528,6 +2700,17 @@ namespace OpenWifi {
|
||||
return IsCIDRv4(value) || IsCIDRv6(value);
|
||||
}
|
||||
|
||||
static inline bool IsPortRangeIsValid(const std::string &r) {
|
||||
const auto ports = Poco::StringTokenizer("-",r,Poco::StringTokenizer::TOK_TRIM);
|
||||
|
||||
for(const auto &port:ports) {
|
||||
uint32_t port_num = std::stoul(port);
|
||||
if(port_num==0 || port_num>65535)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigurationValidator::my_format_checker(const std::string &format, const std::string &value)
|
||||
{
|
||||
static const std::regex host_regex{"^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}$"};
|
||||
@@ -2578,6 +2761,14 @@ namespace OpenWifi {
|
||||
} catch (...) {
|
||||
}
|
||||
throw std::invalid_argument(value + " is not a valid URI: should be something like https://hello.world.com.");
|
||||
} else if(format == "uc-portrange") {
|
||||
try {
|
||||
if(IsPortRangeIsValid(value))
|
||||
return;
|
||||
throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port.");
|
||||
} catch (...) {
|
||||
}
|
||||
throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port.");
|
||||
} else if(format == "ip") {
|
||||
if (IsIP(value))
|
||||
return;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
169
src/framework/MicroServiceErrorHandler.h
Normal file
169
src/framework/MicroServiceErrorHandler.h
Normal file
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-09-29.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "Poco/Util/Application.h"
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/SSLException.h"
|
||||
#include "Poco/JSON/Template.h"
|
||||
#include "Poco/Thread.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class MicroServiceErrorHandler : public Poco::ErrorHandler {
|
||||
public:
|
||||
explicit MicroServiceErrorHandler(Poco::Util::Application &App) : App_(App) {
|
||||
}
|
||||
|
||||
inline void exception(const Poco::Exception & Base) override {
|
||||
try {
|
||||
if(Poco::Thread::current()!= nullptr) {
|
||||
t_name = Poco::Thread::current()->getName();
|
||||
t_id = Poco::Thread::current()->id();
|
||||
} else {
|
||||
t_name = "startup_code";
|
||||
t_id = 0;
|
||||
}
|
||||
|
||||
App_.logger().log(Base);
|
||||
Base.rethrow();
|
||||
|
||||
} catch (const Poco::Net::InvalidCertificateException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidCertificateException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::InvalidSocketException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidSocketException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::WebSocketException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::WebSocketException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::ConnectionResetException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::ConnectionResetException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::CertificateValidationException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::CertificateValidationException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::SSLConnectionUnexpectedlyClosedException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::SSLContextException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::SSLContextException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Net::SSLException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::SSLException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
|
||||
} catch (const Poco::Net::InvalidAddressException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidAddressException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
|
||||
} catch (const Poco::Net::NetException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Net::NetException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
|
||||
} catch (const Poco::IOException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::IOException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::RuntimeException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::JSON::JSONTemplateException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONTemplateException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::JSON::JSONException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::ApplicationException &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::ApplicationException thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (const Poco::Exception &E) {
|
||||
poco_error(App_.logger(), fmt::format("Poco::Exception thr_name={} thr_id={} code={} text={} msg={} what={}",
|
||||
t_name, t_id, E.code(),
|
||||
E.displayText(),
|
||||
E.message(),
|
||||
E.what()));
|
||||
} catch (...) {
|
||||
poco_error(App_.logger(), fmt::format("Poco:Generic thr_name={}",t_name, t_id));
|
||||
}
|
||||
}
|
||||
|
||||
inline void exception(const std::exception & E) override {
|
||||
if(Poco::Thread::current()!= nullptr) {
|
||||
t_name = Poco::Thread::current()->getName();
|
||||
t_id = Poco::Thread::current()->id();
|
||||
} else {
|
||||
t_name = "startup_code";
|
||||
t_id = 0;
|
||||
}
|
||||
poco_warning(App_.logger(), fmt::format("std::exception in {}: {} thr_id={}",
|
||||
t_name,E.what(),
|
||||
t_id));
|
||||
}
|
||||
|
||||
inline void exception() override {
|
||||
if(Poco::Thread::current()!= nullptr) {
|
||||
t_name = Poco::Thread::current()->getName();
|
||||
t_id = Poco::Thread::current()->id();
|
||||
} else {
|
||||
t_name = "startup_code";
|
||||
t_id = 0;
|
||||
}
|
||||
poco_warning(App_.logger(), fmt::format("generic exception in {} thr_id={}",
|
||||
t_name, t_id));
|
||||
}
|
||||
private:
|
||||
Poco::Util::Application &App_;
|
||||
std::string t_name;
|
||||
int t_id=0;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -33,7 +33,6 @@ namespace OpenWifi {
|
||||
int Start() override {
|
||||
std::lock_guard Guard(Mutex_);
|
||||
|
||||
Logger().setLevel(Poco::Message::PRIO_INFORMATION);
|
||||
Logger().notice("Starting.");
|
||||
std::string DBType = MicroService::instance().ConfigGetString("storage.type");
|
||||
|
||||
|
||||
@@ -146,6 +146,10 @@ namespace OpenWifi {
|
||||
WebSocketClientServer()->SendUserNotification(User,N);
|
||||
}
|
||||
|
||||
/////
|
||||
/////
|
||||
/////
|
||||
|
||||
struct WebSocketNotificationRebootList {
|
||||
std::string title,
|
||||
details,
|
||||
@@ -189,5 +193,58 @@ namespace OpenWifi {
|
||||
WebSocketClientServer()->SendUserNotification(User,N);
|
||||
}
|
||||
|
||||
/////
|
||||
/////
|
||||
/////
|
||||
|
||||
struct WebSocketNotificationUpgradeList {
|
||||
std::string title,
|
||||
details,
|
||||
jobId;
|
||||
std::vector<std::string> success,
|
||||
skipped,
|
||||
no_firmware,
|
||||
not_connected;
|
||||
uint64_t timeStamp=OpenWifi::Now();
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
};
|
||||
|
||||
typedef WebSocketNotification<WebSocketNotificationUpgradeList> WebSocketClientNotificationVenueUpgradeList_t;
|
||||
|
||||
inline void WebSocketNotificationUpgradeList::to_json(Poco::JSON::Object &Obj) const {
|
||||
RESTAPI_utils::field_to_json(Obj,"title",title);
|
||||
RESTAPI_utils::field_to_json(Obj,"jobId",jobId);
|
||||
RESTAPI_utils::field_to_json(Obj,"success",success);
|
||||
RESTAPI_utils::field_to_json(Obj,"notConnected",not_connected);
|
||||
RESTAPI_utils::field_to_json(Obj,"noFirmware",no_firmware);
|
||||
RESTAPI_utils::field_to_json(Obj,"skipped",skipped);
|
||||
RESTAPI_utils::field_to_json(Obj,"timeStamp",timeStamp);
|
||||
RESTAPI_utils::field_to_json(Obj,"details",details);
|
||||
}
|
||||
|
||||
inline bool WebSocketNotificationUpgradeList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
try {
|
||||
RESTAPI_utils::field_from_json(Obj,"title",title);
|
||||
RESTAPI_utils::field_from_json(Obj,"jobId",jobId);
|
||||
RESTAPI_utils::field_from_json(Obj,"success",success);
|
||||
RESTAPI_utils::field_from_json(Obj,"notConnected",not_connected);
|
||||
RESTAPI_utils::field_from_json(Obj,"noFirmware",no_firmware);
|
||||
RESTAPI_utils::field_from_json(Obj,"skipped",skipped);
|
||||
RESTAPI_utils::field_from_json(Obj,"timeStamp",timeStamp);
|
||||
RESTAPI_utils::field_from_json(Obj,"details",details);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void WebSocketClientNotificationVenueUpgradeCompletionToUser( const std::string & User, WebSocketClientNotificationVenueUpgradeList_t &N) {
|
||||
N.type = "venue_upgrader";
|
||||
WebSocketClientServer()->SendUserNotification(User,N);
|
||||
}
|
||||
|
||||
} // namespace OpenWifi
|
||||
|
||||
|
||||
@@ -133,6 +133,37 @@ namespace ORM {
|
||||
return R;
|
||||
}
|
||||
|
||||
inline std::string WHERE_AND_(std::string Result) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) {
|
||||
if constexpr(std::is_same_v<T,std::string>)
|
||||
{
|
||||
if(!Value.empty()) {
|
||||
if(!Result.empty())
|
||||
Result += " and ";
|
||||
Result += fieldName;
|
||||
Result += '=';
|
||||
Result += "'";
|
||||
Result += Escape(Value);
|
||||
Result += "'";
|
||||
}
|
||||
} else {
|
||||
if(!Result.empty())
|
||||
Result += " and ";
|
||||
Result += fieldName ;
|
||||
Result += '=';
|
||||
Result += std::to_string(Value);
|
||||
}
|
||||
return WHERE_AND_(Result,args...);
|
||||
}
|
||||
|
||||
template <typename... Args> std::string WHERE_AND(Args... args) {
|
||||
std::string Result;
|
||||
return WHERE_AND_(Result, args...);
|
||||
}
|
||||
|
||||
enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE };
|
||||
enum SqlBinaryOp { AND = 0 , OR };
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include "Poco/String.h"
|
||||
|
||||
#if defined(__GNUC__)
|
||||
@@ -195,6 +196,8 @@ namespace OpenWifi::RESTAPI::Errors {
|
||||
static const struct msg InvalidRadiusServerEntry{1142,"RADIUS Server IP address invalid or port missing."};
|
||||
static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."};
|
||||
|
||||
static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"};
|
||||
static const struct msg DeviceIsAlreadyBusy{1145,"Device is already executing a command. Please try later."};
|
||||
}
|
||||
|
||||
|
||||
@@ -427,7 +430,9 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char *RADIUSDATA = "data";
|
||||
static const char *RADIUSACCT = "acct";
|
||||
static const char *RADIUSAUTH = "auth";
|
||||
static const char *RADIUSCOA = "coa";
|
||||
static const char *RADIUSDST = "dst";
|
||||
static const char *IES = "ies";
|
||||
}
|
||||
|
||||
namespace OpenWifi::uCentralProtocol::Events {
|
||||
@@ -442,6 +447,7 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
static const char *RECOVERY = "recovery";
|
||||
static const char *TELEMETRY = "telemetry";
|
||||
static const char *DEVICEUPDATE = "deviceupdate";
|
||||
static const char *VENUE_BROADCAST = "venue_broadcast";
|
||||
|
||||
enum EVENT_MSG {
|
||||
ET_UNKNOWN,
|
||||
@@ -454,28 +460,34 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
ET_CFGPENDING,
|
||||
ET_RECOVERY,
|
||||
ET_DEVICEUPDATE,
|
||||
ET_TELEMETRY
|
||||
ET_TELEMETRY,
|
||||
ET_VENUEBROADCAST
|
||||
};
|
||||
|
||||
inline static EVENT_MSG EventFromString(const std::string & Method) {
|
||||
static std::vector<std::pair<const char *,EVENT_MSG>> Values{
|
||||
{ CFGPENDING , ET_CFGPENDING },
|
||||
{ CONNECT, ET_CONNECT },
|
||||
{ CRASHLOG, ET_CRASHLOG },
|
||||
{ DEVICEUPDATE, ET_DEVICEUPDATE },
|
||||
{ HEALTHCHECK, ET_HEALTHCHECK },
|
||||
{ LOG, ET_LOG },
|
||||
{ PING, ET_PING },
|
||||
{ RECOVERY, ET_RECOVERY },
|
||||
{ STATE, ET_STATE },
|
||||
{ TELEMETRY, ET_TELEMETRY }
|
||||
};
|
||||
|
||||
std::string L = Poco::toLower(Method);
|
||||
auto hint = std::find_if(cbegin(Values),cend(Values),[&](const std::pair<const char *,EVENT_MSG> &v) ->bool { return strcmp(v.first,L.c_str())==0; });
|
||||
if(hint == cend(Values))
|
||||
return ET_UNKNOWN;
|
||||
return hint->second;
|
||||
inline EVENT_MSG EventFromString(const std::string & Method) {
|
||||
if(strcmp(STATE,Method.c_str())==0)
|
||||
return ET_STATE;
|
||||
else if(strcmp(HEALTHCHECK,Method.c_str())==0)
|
||||
return ET_HEALTHCHECK;
|
||||
else if(strcmp(CONNECT,Method.c_str())==0)
|
||||
return ET_CONNECT;
|
||||
else if(strcmp(CFGPENDING,Method.c_str())==0)
|
||||
return ET_CFGPENDING;
|
||||
else if(strcmp(CRASHLOG,Method.c_str())==0)
|
||||
return ET_CRASHLOG;
|
||||
else if(strcmp(DEVICEUPDATE,Method.c_str())==0)
|
||||
return ET_DEVICEUPDATE;
|
||||
else if(strcmp(LOG,Method.c_str())==0)
|
||||
return ET_LOG;
|
||||
else if(strcmp(PING,Method.c_str())==0)
|
||||
return ET_PING;
|
||||
else if(strcmp(RECOVERY,Method.c_str())==0)
|
||||
return ET_RECOVERY;
|
||||
else if(strcmp(TELEMETRY,Method.c_str())==0)
|
||||
return ET_TELEMETRY;
|
||||
else if(strcmp(VENUE_BROADCAST,Method.c_str())==0)
|
||||
return ET_VENUEBROADCAST;
|
||||
return ET_UNKNOWN;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
7552
src/last_stats_2.json
Normal file
7552
src/last_stats_2.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@ namespace OpenWifi {
|
||||
} else if (LastDate) {
|
||||
WhereClause = fmt::format(" boardId='{}' and (timestamp <= {}) ", boardId, LastDate);
|
||||
}
|
||||
GetRecords(0,MaxRecords,Recs,WhereClause," order by timestamp ASC ");
|
||||
GetRecords(0,MaxRecords,Recs,WhereClause," order by timestamp, serialNumber ASC ");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace OpenWifi {
|
||||
Poco::Data::Session Session = Pool_.get();
|
||||
Poco::Data::Statement Select(Session);
|
||||
|
||||
std::string St = "Select distinct stationId, venue_id from " + TableName_;
|
||||
std::string St = "Select distinct station_id, venue_id from " + TableName_;
|
||||
typedef Poco::Tuple< std::string, std::string > Record;
|
||||
std::vector<Record> RecordList;
|
||||
|
||||
|
||||
7491
stats_sample/bridge-stats-show-clients.json
Normal file
7491
stats_sample/bridge-stats-show-clients.json
Normal file
File diff suppressed because it is too large
Load Diff
7554
stats_sample/last_stats.json
Normal file
7554
stats_sample/last_stats.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -144,25 +144,9 @@ logout() {
|
||||
rm -rf token.json
|
||||
}
|
||||
|
||||
venuecount() {
|
||||
curl ${FLAGS} "https://${OWPROV}/api/v1/venue?countOnly=true" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
-H "accept: application/json" > ${result_file}
|
||||
jq < ${result_file}
|
||||
}
|
||||
|
||||
contactcount() {
|
||||
curl ${FLAGS} "https://${OWPROV}/api/v1/contact?countOnly=true" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
-H "Accept: application/json" > ${result_file}
|
||||
jq < ${result_file}
|
||||
}
|
||||
|
||||
setloglevel() {
|
||||
payload="{ \"command\" : \"setloglevel\" , \"subsystems\" : [ { \"tag\" : \"$1\" , \"value\" : \"$2\" } ] }"
|
||||
curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/system" \
|
||||
curl ${FLAGS} -X POST "https://${OWANALYTICS}/api/v1/system" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
@@ -171,7 +155,7 @@ setloglevel() {
|
||||
|
||||
getloglevels() {
|
||||
payload="{ \"command\" : \"getloglevels\" }"
|
||||
curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/system" \
|
||||
curl ${FLAGS} -X POST "https://${OWANALYTICS}/api/v1/system" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
@@ -180,7 +164,7 @@ getloglevels() {
|
||||
|
||||
getloglevelnames() {
|
||||
payload="{ \"command\" : \"getloglevelnames\" }"
|
||||
curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/system" \
|
||||
curl ${FLAGS} -X POST "https://${OWANALYTICS}/api/v1/system" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
@@ -189,7 +173,7 @@ getloglevelnames() {
|
||||
|
||||
getsubsystemnames() {
|
||||
payload="{ \"command\" : \"getsubsystemnames\" }"
|
||||
curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/system" \
|
||||
curl ${FLAGS} -X POST "https://${OWANALYTICS}/api/v1/system" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
@@ -197,7 +181,7 @@ getsubsystemnames() {
|
||||
}
|
||||
|
||||
systeminfo() {
|
||||
curl ${FLAGS} -X GET "https://${OWPROV}/api/v1/system?command=info" \
|
||||
curl ${FLAGS} -X GET "https://${OWANALYTICS}/api/v1/system?command=info" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: Bearer ${token}" > ${result_file}
|
||||
jq < ${result_file}
|
||||
@@ -205,7 +189,7 @@ systeminfo() {
|
||||
|
||||
reloadsubsystem() {
|
||||
payload="{ \"command\" : \"reload\", \"subsystems\" : [ \"$1\" ] }"
|
||||
curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/system" \
|
||||
curl ${FLAGS} -X POST "https://${OWANALYTICS}/api/v1/system" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"children":[{"children":[{"children":[{"children":[],"name":"Ottawa Operations","type":"entity","uuid":"323054d0-3ff0-11ec-82ff-061b87871e04","venues":[{"children":[],"name":"Living Lab","type":"venue","uuid":"4159ea84-3ff0-11ec-9edb-061b87871e04"}]}],"name":"Ontario","type":"entity","uuid":"21dfa464-3ff0-11ec-9a86-061b87871e04","venues":[]},{"children":[{"children":[],"name":"Quebec","type":"entity","uuid":"27b74e1b-52d7-4414-a1b4-47574c799beb","venues":[]},{"children":[],"name":"Ontario","type":"entity","uuid":"3cb15a80-3550-11ec-9a22-061b87871e04","venues":[{"children":[],"name":"CN Tower","type":"venue","uuid":"3cb28f0e-3550-11ec-acfa-061b87871e04"},{"children":[],"name":"Rogers Center","type":"venue","uuid":"3cb3c798-3550-11ec-8c1a-061b87871e04"}]},{"children":[],"name":"BC","type":"entity","uuid":"3cb503c4-3550-11ec-b436-061b87871e04","venues":[{"children":[],"name":"BC Place","type":"venue","uuid":"3cb76452-3550-11ec-a5ab-061b87871e04"},{"children":[],"name":"Stanley Park","type":"venue","uuid":"3cb8b230-3550-11ec-bbe6-061b87871e04"},{"children":[],"name":"MegaLab","type":"venue","uuid":"a73a23c4-6f3d-4031-bc92-d28c205f2d85"},{"children":[],"name":"Bowen Development","type":"venue","uuid":"d656500b-9f00-4c09-9096-e209085c2a3e"}]}],"name":"Provinces","type":"entity","uuid":"3cac92ca-3550-11ec-b360-061b87871e04","venues":[]}],"name":"Canada","type":"entity","uuid":"3cab2c32-3550-11ec-8a03-061b87871e04","venues":[]},{"children":[],"name":"USA","type":"entity","uuid":"6392c6b3-ef48-4b81-8785-1b5b4888bbd2","venues":[]},{"children":[{"children":[],"name":"Hamburg","type":"entity","uuid":"5939f995-e059-439d-ab0c-29a6f7c0a495","venues":[]}],"name":"Germany","type":"entity","uuid":"6fb5662d-dc48-4fbd-b8f9-69d0308bb902","venues":[]},{"children":[],"name":"Test Land","type":"entity","uuid":"70161a6f-98af-45d7-b0ed-e6b15ba5d84e","venues":[{"children":[],"name":"Test","type":"venue","uuid":"1d06b289-449e-4669-abc9-1f2dcdd1fbbc"}]}],"name":"World","type":"entity","uuid":"0000-0000-0000","venues":[]}
|
||||
Reference in New Issue
Block a user