ul-data-logger-api-sdk 2.0.6__tar.gz → 3.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ul_data_logger_api_sdk-3.1.1/.gitignore +299 -0
- ul_data_logger_api_sdk-3.1.1/PKG-INFO +13 -0
- ul_data_logger_api_sdk-3.1.1/data_logger_api_sdk.py +316 -0
- ul_data_logger_api_sdk-3.1.1/pyproject.toml +35 -0
- ul_data_logger_api_sdk-3.1.1/types/api_base_stations.py +184 -0
- ul-data-logger-api-sdk-2.0.6/PKG-INFO +0 -30
- ul-data-logger-api-sdk-2.0.6/README.md +0 -13
- ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk/data_logger_api_sdk.py +0 -123
- ul-data-logger-api-sdk-2.0.6/pyproject.toml +0 -133
- ul-data-logger-api-sdk-2.0.6/setup.cfg +0 -4
- ul-data-logger-api-sdk-2.0.6/setup.py +0 -84
- ul-data-logger-api-sdk-2.0.6/ul_data_logger_api_sdk.egg-info/PKG-INFO +0 -30
- ul-data-logger-api-sdk-2.0.6/ul_data_logger_api_sdk.egg-info/SOURCES.txt +0 -18
- ul-data-logger-api-sdk-2.0.6/ul_data_logger_api_sdk.egg-info/dependency_links.txt +0 -1
- ul-data-logger-api-sdk-2.0.6/ul_data_logger_api_sdk.egg-info/requires.txt +0 -2
- ul-data-logger-api-sdk-2.0.6/ul_data_logger_api_sdk.egg-info/top_level.txt +0 -1
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/__init__.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/data_logger_sdk_config.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/py.typed +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/__init__.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/api_bs_traffic_stats.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/api_device_data_history.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/api_last_bs_data_by_device_macs.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/api_packet_types.py +0 -0
- {ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/api_protocol_types.py +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
### Python template
|
|
2
|
+
# Byte-compiled / optimized / DLL files
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
|
|
7
|
+
# C extensions
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
/srv/ci-build/requirements.txt
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.coverage
|
|
43
|
+
.coverage.*
|
|
44
|
+
.cache
|
|
45
|
+
nosetests.xml
|
|
46
|
+
coverage.xml
|
|
47
|
+
*.cover
|
|
48
|
+
.hypothesis/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.mo
|
|
52
|
+
*.pot
|
|
53
|
+
|
|
54
|
+
# Django stuff:
|
|
55
|
+
staticfiles/
|
|
56
|
+
|
|
57
|
+
# PyBuilder
|
|
58
|
+
target/
|
|
59
|
+
|
|
60
|
+
# celery beat schedule file
|
|
61
|
+
celerybeat-schedule
|
|
62
|
+
|
|
63
|
+
# Environments
|
|
64
|
+
.venv
|
|
65
|
+
venv/
|
|
66
|
+
|
|
67
|
+
# Rope project settings
|
|
68
|
+
.ropeproject
|
|
69
|
+
|
|
70
|
+
# mkdocs documentation
|
|
71
|
+
/site
|
|
72
|
+
|
|
73
|
+
# mypy
|
|
74
|
+
.mypy_cache/
|
|
75
|
+
|
|
76
|
+
# ruff
|
|
77
|
+
.ruff_cache/
|
|
78
|
+
|
|
79
|
+
### Node template
|
|
80
|
+
# Logs
|
|
81
|
+
logs
|
|
82
|
+
*.log
|
|
83
|
+
npm-debug.log*
|
|
84
|
+
yarn-debug.log*
|
|
85
|
+
yarn-error.log*
|
|
86
|
+
|
|
87
|
+
# Runtime data
|
|
88
|
+
pids
|
|
89
|
+
*.pid
|
|
90
|
+
*.seed
|
|
91
|
+
*.pid.lock
|
|
92
|
+
|
|
93
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
94
|
+
lib-cov
|
|
95
|
+
|
|
96
|
+
# Coverage directory used by tools like istanbul
|
|
97
|
+
coverage
|
|
98
|
+
|
|
99
|
+
# nyc test coverage
|
|
100
|
+
.nyc_output
|
|
101
|
+
|
|
102
|
+
# Bower dependency directory (https://bower.io/)
|
|
103
|
+
bower_components
|
|
104
|
+
|
|
105
|
+
# node-waf configuration
|
|
106
|
+
.lock-wscript
|
|
107
|
+
|
|
108
|
+
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
|
109
|
+
build/Release
|
|
110
|
+
|
|
111
|
+
# Dependency directories
|
|
112
|
+
node_modules/
|
|
113
|
+
jspm_packages/
|
|
114
|
+
|
|
115
|
+
# Typescript v1 declaration files
|
|
116
|
+
typings/
|
|
117
|
+
|
|
118
|
+
# Optional npm cache directory
|
|
119
|
+
.npm
|
|
120
|
+
|
|
121
|
+
# Optional eslint cache
|
|
122
|
+
.eslintcache
|
|
123
|
+
|
|
124
|
+
# Optional REPL history
|
|
125
|
+
.node_repl_history
|
|
126
|
+
|
|
127
|
+
# Output of 'npm pack'
|
|
128
|
+
*.tgz
|
|
129
|
+
|
|
130
|
+
# Yarn Integrity file
|
|
131
|
+
.yarn-integrity
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
### Linux template
|
|
135
|
+
*~
|
|
136
|
+
|
|
137
|
+
# temporary files which can be created if a process still has a handle open of a deleted file
|
|
138
|
+
.fuse_hidden*
|
|
139
|
+
|
|
140
|
+
# KDE directory preferences
|
|
141
|
+
.directory
|
|
142
|
+
|
|
143
|
+
# Linux trash folder which might appear on any partition or disk
|
|
144
|
+
.Trash-*
|
|
145
|
+
|
|
146
|
+
# .nfs files are created when an open file is removed but is still being accessed
|
|
147
|
+
.nfs*
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
### VisualStudioCode template
|
|
151
|
+
.vscode/*
|
|
152
|
+
!.vscode/settings.json
|
|
153
|
+
!.vscode/tasks.json
|
|
154
|
+
!.vscode/launch.json
|
|
155
|
+
!.vscode/extensions.json
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
### Windows template
|
|
162
|
+
# Windows thumbnail cache files
|
|
163
|
+
Thumbs.db
|
|
164
|
+
ehthumbs.db
|
|
165
|
+
ehthumbs_vista.db
|
|
166
|
+
|
|
167
|
+
# Dump file
|
|
168
|
+
*.stackdump
|
|
169
|
+
|
|
170
|
+
# Folder config file
|
|
171
|
+
Desktop.ini
|
|
172
|
+
|
|
173
|
+
# Recycle Bin used on file shares
|
|
174
|
+
$RECYCLE.BIN/
|
|
175
|
+
|
|
176
|
+
# Windows Installer files
|
|
177
|
+
*.cab
|
|
178
|
+
*.msi
|
|
179
|
+
*.msm
|
|
180
|
+
*.msp
|
|
181
|
+
|
|
182
|
+
# Windows shortcuts
|
|
183
|
+
*.lnk
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
### macOS template
|
|
187
|
+
# General
|
|
188
|
+
*.DS_Store
|
|
189
|
+
.AppleDouble
|
|
190
|
+
.LSOverride
|
|
191
|
+
|
|
192
|
+
# Icon must end with two \r
|
|
193
|
+
Icon
|
|
194
|
+
|
|
195
|
+
# Thumbnails
|
|
196
|
+
._*
|
|
197
|
+
|
|
198
|
+
# Files that might appear in the root of a volume
|
|
199
|
+
.DocumentRevisions-V100
|
|
200
|
+
.fseventsd
|
|
201
|
+
.Spotlight-V100
|
|
202
|
+
.TemporaryItems
|
|
203
|
+
.Trashes
|
|
204
|
+
.VolumeIcon.icns
|
|
205
|
+
.com.apple.timemachine.donotpresent
|
|
206
|
+
|
|
207
|
+
# Directories potentially created on remote AFP share
|
|
208
|
+
.AppleDB
|
|
209
|
+
.AppleDesktop
|
|
210
|
+
Network Trash Folder
|
|
211
|
+
Temporary Items
|
|
212
|
+
.apdisk
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
### SublimeText template
|
|
216
|
+
# Cache files for Sublime Text
|
|
217
|
+
*.tmlanguage.cache
|
|
218
|
+
*.tmPreferences.cache
|
|
219
|
+
*.stTheme.cache
|
|
220
|
+
|
|
221
|
+
# Workspace files are user-specific
|
|
222
|
+
*.sublime-workspace
|
|
223
|
+
|
|
224
|
+
# Project files should be checked into the repository, unless a significant
|
|
225
|
+
# proportion of contributors will probably not be using Sublime Text
|
|
226
|
+
# *.sublime-project
|
|
227
|
+
|
|
228
|
+
# SFTP configuration file
|
|
229
|
+
sftp-config.json
|
|
230
|
+
|
|
231
|
+
# Package control specific files
|
|
232
|
+
Package Control.last-run
|
|
233
|
+
Package Control.ca-list
|
|
234
|
+
Package Control.ca-bundle
|
|
235
|
+
Package Control.system-ca-bundle
|
|
236
|
+
Package Control.cache/
|
|
237
|
+
Package Control.ca-certs/
|
|
238
|
+
Package Control.merged-ca-bundle
|
|
239
|
+
Package Control.user-ca-bundle
|
|
240
|
+
oscrypto-ca-bundle.crt
|
|
241
|
+
bh_unicode_properties.cache
|
|
242
|
+
|
|
243
|
+
# Sublime-github package stores a github token in this file
|
|
244
|
+
# https://packagecontrol.io/packages/sublime-github
|
|
245
|
+
GitHub.sublime-settings
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
### Vim template
|
|
249
|
+
# Swap
|
|
250
|
+
[._]*.s[a-v][a-z]
|
|
251
|
+
[._]*.sw[a-p]
|
|
252
|
+
[._]s[a-v][a-z]
|
|
253
|
+
[._]sw[a-p]
|
|
254
|
+
|
|
255
|
+
# Session
|
|
256
|
+
Session.vim
|
|
257
|
+
|
|
258
|
+
# Temporary
|
|
259
|
+
.netrwhist
|
|
260
|
+
|
|
261
|
+
# Auto-generated tag files
|
|
262
|
+
tags
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
### Project template
|
|
266
|
+
|
|
267
|
+
.pytest_cache/
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
.ipython/
|
|
271
|
+
.envs/*
|
|
272
|
+
!.envs/.local/
|
|
273
|
+
!srv/merge_dotenvs.py
|
|
274
|
+
*.env
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
.ipynb_checkpoints/
|
|
278
|
+
.idea/
|
|
279
|
+
__pycache__
|
|
280
|
+
venv
|
|
281
|
+
.*.ipynb
|
|
282
|
+
_*.ipynb
|
|
283
|
+
.ipynb_checkpoints
|
|
284
|
+
.history/
|
|
285
|
+
.var/
|
|
286
|
+
.tmp/
|
|
287
|
+
*.orig
|
|
288
|
+
*.zip
|
|
289
|
+
*.bz2
|
|
290
|
+
*.gz
|
|
291
|
+
*.xz
|
|
292
|
+
|
|
293
|
+
/srv/*.retry
|
|
294
|
+
|
|
295
|
+
# Локальный overlay для demo-стенда (пароли, адреса Patroni)
|
|
296
|
+
srv/docker_compose/docker-compose.demo.yml
|
|
297
|
+
|
|
298
|
+
# Swagger spec
|
|
299
|
+
/src/conf/*docs.yml
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: ul-data-logger-api-sdk
|
|
3
|
+
Version: 3.1.1
|
|
4
|
+
Summary: Data logger API sdk
|
|
5
|
+
Author: Unic-lab
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Requires-Python: >=3.14
|
|
13
|
+
Requires-Dist: ul-unipipeline>=2.0.0
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
from datetime import date, datetime
|
|
4
|
+
from functools import lru_cache
|
|
5
|
+
from typing import Any, Dict, List, Type
|
|
6
|
+
from uuid import UUID
|
|
7
|
+
|
|
8
|
+
from ul_api_utils.internal_api.internal_api import InternalApi
|
|
9
|
+
from ul_api_utils.internal_api.internal_api_response import TPyloadType
|
|
10
|
+
from ul_api_utils.utils.api_method import ApiMethod
|
|
11
|
+
|
|
12
|
+
from data_logger_api_sdk.data_logger_sdk_config import DataLoggerApiSdkConfig
|
|
13
|
+
from data_logger_api_sdk.types.api_base_stations import (
|
|
14
|
+
ApiBaseStationDetailResponse,
|
|
15
|
+
ApiBaseStationDeviceLogsResponse,
|
|
16
|
+
ApiBaseStationDevicesResponse,
|
|
17
|
+
ApiBaseStationLogsStatForIntervalsResponse,
|
|
18
|
+
ApiBaseStationLogsStatResponse,
|
|
19
|
+
ApiBaseStationLogResponse,
|
|
20
|
+
ApiBaseStationLogsListResult,
|
|
21
|
+
ApiBaseStationsListResult,
|
|
22
|
+
ApiBaseStationResponse,
|
|
23
|
+
ApiBaseStationSystemLogResponse,
|
|
24
|
+
ApiBaseStationSystemLogsListResult,
|
|
25
|
+
)
|
|
26
|
+
from data_logger_api_sdk.types.api_bs_traffic_stats import ApiBsTrafficStatsResponse, ApiDeviceTrafficStatsQuery
|
|
27
|
+
from data_logger_api_sdk.types.api_device_data_history import ApiDeviceDataHistoryBody, ApiDeviceDataHistoryResponse
|
|
28
|
+
from data_logger_api_sdk.types.api_last_bs_data_by_device_macs import ApiDeviceLastBsDataResponse, ApiDeviceMacsListBodyModel
|
|
29
|
+
from data_logger_api_sdk.types.api_packet_types import ApiPacketTypesListResponse
|
|
30
|
+
from data_logger_api_sdk.types.api_protocol_types import ApiProtocolTypesListResponse
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DataLoggerApiSdk:
|
|
34
|
+
|
|
35
|
+
def __init__(self, config: DataLoggerApiSdkConfig) -> None:
|
|
36
|
+
self._config = config
|
|
37
|
+
self._api = InternalApi(entry_point=self._config.api_url, default_auth_token=self._config.api_token)
|
|
38
|
+
|
|
39
|
+
@lru_cache(maxsize=None) # there should not be leaks memory leaks. flake8 just scared inmemory cache ;)
|
|
40
|
+
def request_payload(
|
|
41
|
+
self,
|
|
42
|
+
_: int,
|
|
43
|
+
method: ApiMethod,
|
|
44
|
+
endpoint: str,
|
|
45
|
+
typed_as: Type[TPyloadType],
|
|
46
|
+
body: str | None,
|
|
47
|
+
query: str | None = None,
|
|
48
|
+
) -> TPyloadType:
|
|
49
|
+
return (
|
|
50
|
+
self._api.request(
|
|
51
|
+
method=method,
|
|
52
|
+
path=endpoint,
|
|
53
|
+
json=json.loads(body) if body is not None else None,
|
|
54
|
+
q=json.loads(query) if query is not None else None,
|
|
55
|
+
)
|
|
56
|
+
.typed(typed_as)
|
|
57
|
+
.check()
|
|
58
|
+
.payload
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def _get_cache_post_payload(
|
|
62
|
+
self,
|
|
63
|
+
method: ApiMethod,
|
|
64
|
+
path: str,
|
|
65
|
+
typed: Type[TPyloadType],
|
|
66
|
+
body: str | None = None,
|
|
67
|
+
query: str | None = None,
|
|
68
|
+
) -> TPyloadType:
|
|
69
|
+
ttl_status = round(time.time() / self._config.cache_ttl_s)
|
|
70
|
+
return self.request_payload(ttl_status, method, path, typed, body, query) # type: ignore # Type[TPyloadType] is hashable
|
|
71
|
+
|
|
72
|
+
def _request_payload_once(
|
|
73
|
+
self,
|
|
74
|
+
method: ApiMethod,
|
|
75
|
+
path: str,
|
|
76
|
+
typed: Type[TPyloadType],
|
|
77
|
+
query: Dict[str, Any] | None = None,
|
|
78
|
+
) -> TPyloadType:
|
|
79
|
+
response = self._api.request(
|
|
80
|
+
method=method,
|
|
81
|
+
path=path,
|
|
82
|
+
json=None,
|
|
83
|
+
q=query,
|
|
84
|
+
).typed(typed).check()
|
|
85
|
+
return response.payload
|
|
86
|
+
|
|
87
|
+
def _request_list_payload_once(
|
|
88
|
+
self,
|
|
89
|
+
method: ApiMethod,
|
|
90
|
+
path: str,
|
|
91
|
+
typed: Type[TPyloadType],
|
|
92
|
+
query: Dict[str, Any] | None = None,
|
|
93
|
+
) -> tuple[TPyloadType, int]:
|
|
94
|
+
response = self._api.request(
|
|
95
|
+
method=method,
|
|
96
|
+
path=path,
|
|
97
|
+
json=None,
|
|
98
|
+
q=query,
|
|
99
|
+
).typed(typed).check()
|
|
100
|
+
total_count = response.total_count
|
|
101
|
+
assert total_count is not None, "total_count must be present for array payloads"
|
|
102
|
+
return response.payload, total_count
|
|
103
|
+
|
|
104
|
+
def get_protocol_types_list(self, mac: int) -> List[str]:
|
|
105
|
+
return self._get_cache_post_payload(
|
|
106
|
+
ApiMethod.GET,
|
|
107
|
+
f"/devices/mac/{mac}/logs/protocol-types",
|
|
108
|
+
ApiProtocolTypesListResponse,
|
|
109
|
+
).protocol_types
|
|
110
|
+
|
|
111
|
+
def get_packet_types_list(self, mac: int) -> List[str]:
|
|
112
|
+
return self._get_cache_post_payload(
|
|
113
|
+
ApiMethod.GET,
|
|
114
|
+
f"/devices/mac/{mac}/logs/packet-types",
|
|
115
|
+
ApiPacketTypesListResponse,
|
|
116
|
+
).packet_types
|
|
117
|
+
|
|
118
|
+
def get_device_data_history(
|
|
119
|
+
self,
|
|
120
|
+
period_from: datetime,
|
|
121
|
+
period_to: datetime,
|
|
122
|
+
mac: int,
|
|
123
|
+
protocol_type: str | None = None,
|
|
124
|
+
packet_type: str | None = None,
|
|
125
|
+
) -> List[ApiDeviceDataHistoryResponse]:
|
|
126
|
+
api_device_history_body = ApiDeviceDataHistoryBody(
|
|
127
|
+
period_from=period_from,
|
|
128
|
+
period_to=period_to,
|
|
129
|
+
mac=mac,
|
|
130
|
+
protocol_type=protocol_type,
|
|
131
|
+
packet_type=packet_type,
|
|
132
|
+
).model_dump_json()
|
|
133
|
+
return self._get_cache_post_payload(
|
|
134
|
+
ApiMethod.POST,
|
|
135
|
+
"/device-data-history",
|
|
136
|
+
List[ApiDeviceDataHistoryResponse], # type: ignore
|
|
137
|
+
api_device_history_body,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
def get_last_bs_data_by_device_macs(
|
|
141
|
+
self,
|
|
142
|
+
macs: set[int],
|
|
143
|
+
) -> List[ApiDeviceLastBsDataResponse]:
|
|
144
|
+
return self._get_cache_post_payload(
|
|
145
|
+
ApiMethod.POST,
|
|
146
|
+
"/devices/last-bs-data",
|
|
147
|
+
List[ApiDeviceLastBsDataResponse], # type: ignore
|
|
148
|
+
ApiDeviceMacsListBodyModel(macs=macs).model_dump_json(),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
def get_bs_traffic_stats(
|
|
152
|
+
self,
|
|
153
|
+
base_station_id: UUID,
|
|
154
|
+
start_at: datetime,
|
|
155
|
+
end_at: datetime,
|
|
156
|
+
) -> List[ApiBsTrafficStatsResponse]:
|
|
157
|
+
api_bs_traffic_stats_query = ApiDeviceTrafficStatsQuery(
|
|
158
|
+
start_at=start_at,
|
|
159
|
+
end_at=end_at,
|
|
160
|
+
)
|
|
161
|
+
return self._get_cache_post_payload(
|
|
162
|
+
ApiMethod.GET,
|
|
163
|
+
f"/base-stations/{base_station_id}/traffic-stats",
|
|
164
|
+
List[ApiBsTrafficStatsResponse], # type: ignore
|
|
165
|
+
None,
|
|
166
|
+
api_bs_traffic_stats_query.model_dump_json(),
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def get_base_stations(
|
|
170
|
+
self,
|
|
171
|
+
limit: int,
|
|
172
|
+
offset: int = 0,
|
|
173
|
+
serial_number: int | None = None,
|
|
174
|
+
log_stat_days: int = 0,
|
|
175
|
+
) -> ApiBaseStationsListResult:
|
|
176
|
+
"""GET /base-stations — список базовых станций Data Logger."""
|
|
177
|
+
query: Dict[str, Any] = {
|
|
178
|
+
"limit": limit,
|
|
179
|
+
"offset": offset,
|
|
180
|
+
"log_stat_days": log_stat_days,
|
|
181
|
+
}
|
|
182
|
+
if serial_number is not None:
|
|
183
|
+
query["serial_number"] = serial_number
|
|
184
|
+
items, total_count = self._request_list_payload_once(
|
|
185
|
+
ApiMethod.GET,
|
|
186
|
+
"/base-stations",
|
|
187
|
+
List[ApiBaseStationResponse], # type: ignore
|
|
188
|
+
query,
|
|
189
|
+
)
|
|
190
|
+
return ApiBaseStationsListResult(items=items, total_count=total_count)
|
|
191
|
+
|
|
192
|
+
def get_base_station(
|
|
193
|
+
self,
|
|
194
|
+
base_station_id: UUID,
|
|
195
|
+
log_stat_days: int = 0,
|
|
196
|
+
) -> ApiBaseStationDetailResponse:
|
|
197
|
+
"""GET /base-stations/<uuid> — карточка базовой станции Data Logger."""
|
|
198
|
+
return self._request_payload_once(
|
|
199
|
+
ApiMethod.GET,
|
|
200
|
+
f"/base-stations/{base_station_id}",
|
|
201
|
+
ApiBaseStationDetailResponse,
|
|
202
|
+
{"log_stat_days": log_stat_days},
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def get_base_station_logs(
|
|
206
|
+
self,
|
|
207
|
+
base_station_id: UUID,
|
|
208
|
+
start_at: datetime | None = None,
|
|
209
|
+
end_at: datetime | None = None,
|
|
210
|
+
limit: int = 100,
|
|
211
|
+
offset: int = 0,
|
|
212
|
+
) -> ApiBaseStationLogsListResult:
|
|
213
|
+
"""GET /base-stations/<uuid>/logs — журнал логов базовой станции."""
|
|
214
|
+
query: Dict[str, Any] = {"limit": limit, "offset": offset}
|
|
215
|
+
if start_at is not None:
|
|
216
|
+
query["start_at"] = start_at.isoformat()
|
|
217
|
+
if end_at is not None:
|
|
218
|
+
query["end_at"] = end_at.isoformat()
|
|
219
|
+
items, total_count = self._request_list_payload_once(
|
|
220
|
+
ApiMethod.GET,
|
|
221
|
+
f"/base-stations/{base_station_id}/logs",
|
|
222
|
+
List[ApiBaseStationLogResponse], # type: ignore
|
|
223
|
+
query,
|
|
224
|
+
)
|
|
225
|
+
return ApiBaseStationLogsListResult(items=items, total_count=total_count)
|
|
226
|
+
|
|
227
|
+
def get_base_station_system_logs(
|
|
228
|
+
self,
|
|
229
|
+
base_station_id: UUID,
|
|
230
|
+
start_at: datetime | None = None,
|
|
231
|
+
end_at: datetime | None = None,
|
|
232
|
+
limit: int = 100,
|
|
233
|
+
offset: int = 0,
|
|
234
|
+
) -> ApiBaseStationSystemLogsListResult:
|
|
235
|
+
"""GET /base-stations/<uuid>/system-logs — журнал системных логов базовой станции."""
|
|
236
|
+
query: Dict[str, Any] = {"limit": limit, "offset": offset}
|
|
237
|
+
if start_at is not None:
|
|
238
|
+
query["start_at"] = start_at.isoformat()
|
|
239
|
+
if end_at is not None:
|
|
240
|
+
query["end_at"] = end_at.isoformat()
|
|
241
|
+
items, total_count = self._request_list_payload_once(
|
|
242
|
+
ApiMethod.GET,
|
|
243
|
+
f"/base-stations/{base_station_id}/system-logs",
|
|
244
|
+
List[ApiBaseStationSystemLogResponse], # type: ignore
|
|
245
|
+
query,
|
|
246
|
+
)
|
|
247
|
+
return ApiBaseStationSystemLogsListResult(items=items, total_count=total_count)
|
|
248
|
+
|
|
249
|
+
def get_base_station_logs_stat(
|
|
250
|
+
self,
|
|
251
|
+
base_station_id: UUID,
|
|
252
|
+
day: date,
|
|
253
|
+
) -> ApiBaseStationLogsStatResponse:
|
|
254
|
+
"""GET /base-stations/<uuid>/logs-stat — статистика логов базовой станции за сутки."""
|
|
255
|
+
return self._request_payload_once(
|
|
256
|
+
ApiMethod.GET,
|
|
257
|
+
f"/base-stations/{base_station_id}/logs-stat",
|
|
258
|
+
ApiBaseStationLogsStatResponse,
|
|
259
|
+
{"day": day.isoformat()},
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
def get_base_station_logs_stat_for_intervals(
|
|
263
|
+
self,
|
|
264
|
+
base_station_id: UUID,
|
|
265
|
+
start_at: datetime,
|
|
266
|
+
end_at: datetime | None = None,
|
|
267
|
+
) -> ApiBaseStationLogsStatForIntervalsResponse:
|
|
268
|
+
"""GET /base-stations/<uuid>/logs-stat-for-intervals — метки времени логов за интервал."""
|
|
269
|
+
query: Dict[str, Any] = {"start_at": start_at.isoformat()}
|
|
270
|
+
if end_at is not None:
|
|
271
|
+
query["end_at"] = end_at.isoformat()
|
|
272
|
+
return self._request_payload_once(
|
|
273
|
+
ApiMethod.GET,
|
|
274
|
+
f"/base-stations/{base_station_id}/logs-stat-for-intervals",
|
|
275
|
+
ApiBaseStationLogsStatForIntervalsResponse,
|
|
276
|
+
query,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
def get_base_station_devices(
|
|
280
|
+
self,
|
|
281
|
+
base_station_id: UUID,
|
|
282
|
+
start_at: datetime,
|
|
283
|
+
end_at: datetime | None = None,
|
|
284
|
+
limit: int = 100,
|
|
285
|
+
offset: int = 0,
|
|
286
|
+
) -> ApiBaseStationDevicesResponse:
|
|
287
|
+
"""GET /base-stations/<uuid>/devices — устройства, работающие через базовую станцию."""
|
|
288
|
+
query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
|
|
289
|
+
if end_at is not None:
|
|
290
|
+
query["end_at"] = end_at.isoformat()
|
|
291
|
+
return self._request_payload_once(
|
|
292
|
+
ApiMethod.GET,
|
|
293
|
+
f"/base-stations/{base_station_id}/devices",
|
|
294
|
+
ApiBaseStationDevicesResponse,
|
|
295
|
+
query,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
def get_base_station_device_logs(
|
|
299
|
+
self,
|
|
300
|
+
base_station_id: UUID,
|
|
301
|
+
start_at: datetime,
|
|
302
|
+
end_at: datetime | None = None,
|
|
303
|
+
limit: int = 100,
|
|
304
|
+
offset: int = 0,
|
|
305
|
+
) -> ApiBaseStationDeviceLogsResponse:
|
|
306
|
+
"""GET /base-stations/<uuid>/device-logs — логи устройств базовой станции."""
|
|
307
|
+
query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
|
|
308
|
+
if end_at is not None:
|
|
309
|
+
query["end_at"] = end_at.isoformat()
|
|
310
|
+
return self._request_payload_once(
|
|
311
|
+
ApiMethod.GET,
|
|
312
|
+
f"/base-stations/{base_station_id}/device-logs",
|
|
313
|
+
ApiBaseStationDeviceLogsResponse,
|
|
314
|
+
query,
|
|
315
|
+
)
|
|
316
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ul-data-logger-api-sdk"
|
|
7
|
+
version = "3.1.1"
|
|
8
|
+
description = "Data logger API sdk"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
authors = [{ name = "Unic-lab" }]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Programming Language :: Python",
|
|
16
|
+
"Programming Language :: Python :: 3.14",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"ul-unipipeline>=2.0.0",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[tool.hatch.build]
|
|
24
|
+
include = ["**/*.py", "**/*.yml", "**/py.typed"]
|
|
25
|
+
exclude = ["dist/**", "*.egg-info/**", ".gitignore", "PKG-INFO", "pyproject.toml"]
|
|
26
|
+
|
|
27
|
+
[tool.hatch.build.targets.wheel]
|
|
28
|
+
packages = ["."]
|
|
29
|
+
|
|
30
|
+
[tool.hatch.build.targets.wheel.sources]
|
|
31
|
+
"." = "data_logger_api_sdk"
|
|
32
|
+
|
|
33
|
+
[[tool.uv.index]]
|
|
34
|
+
url = "https://pip-cache.dev-unic-lab.by/repository/pip-cache/simple"
|
|
35
|
+
default = true
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, Dict, List, NamedTuple, Tuple
|
|
3
|
+
|
|
4
|
+
from pydantic.types import UUID4
|
|
5
|
+
from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
|
|
6
|
+
|
|
7
|
+
BS__LOG_TYPE__DEVICE_DATA = "device_data"
|
|
8
|
+
BS__LOG_TYPE__HEARTBIT = "heartbit"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ApiBaseStationsListResult(NamedTuple):
|
|
12
|
+
"""Результат спискового вызова BS-endpoint Data Logger: страница элементов и total_count."""
|
|
13
|
+
|
|
14
|
+
items: List["ApiBaseStationResponse"]
|
|
15
|
+
total_count: int
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ApiBaseStationLogsListResult(NamedTuple):
|
|
19
|
+
"""Результат вызова GET /base-stations/<uuid>/logs."""
|
|
20
|
+
|
|
21
|
+
items: List["ApiBaseStationLogResponse"]
|
|
22
|
+
total_count: int
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ApiBaseStationSystemLogsListResult(NamedTuple):
|
|
26
|
+
"""Результат вызова GET /base-stations/<uuid>/system-logs."""
|
|
27
|
+
|
|
28
|
+
items: List["ApiBaseStationSystemLogResponse"]
|
|
29
|
+
total_count: int
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ApiBaseStationResponse(JsonApiResponsePayload):
|
|
33
|
+
"""Элемент ответа GET /base-stations (BsListShortResponse на стороне Data Logger)."""
|
|
34
|
+
|
|
35
|
+
id: UUID4
|
|
36
|
+
date_created: datetime
|
|
37
|
+
date_modified: datetime
|
|
38
|
+
is_alive: bool
|
|
39
|
+
|
|
40
|
+
api_user_modified_id: UUID4 | None = None
|
|
41
|
+
note: str = ""
|
|
42
|
+
permission_id: int
|
|
43
|
+
|
|
44
|
+
type: str
|
|
45
|
+
serial_number: int
|
|
46
|
+
|
|
47
|
+
latest_log_datetime: datetime | None = None
|
|
48
|
+
latest_geo_latitude: float | None = None
|
|
49
|
+
latest_geo_longitude: float | None = None
|
|
50
|
+
latest_soft_version: str | None = None
|
|
51
|
+
latest_geo_is_actual: bool | None = None
|
|
52
|
+
latest_sdr_config_id: UUID4 | None = None
|
|
53
|
+
|
|
54
|
+
logs_stat: List[Tuple[datetime, int]] | None = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ApiBaseStationDetailResponse(ApiBaseStationResponse):
|
|
58
|
+
"""Ответ GET /base-stations/<uuid> (BsResponse на стороне Data Logger)."""
|
|
59
|
+
|
|
60
|
+
latest_sdr_config: Dict[str, Any] | None = None
|
|
61
|
+
device_counts: List[Tuple[datetime, int]] | None = None
|
|
62
|
+
system_logs_stat: List[Tuple[datetime, int]] | None = None
|
|
63
|
+
environment_spectrums_stat: List[Tuple[datetime, int]] | None = None
|
|
64
|
+
sdr_config_data_list: List[Dict[str, Any] | None] | None = None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ApiBaseStationLogResponse(JsonApiResponsePayload):
|
|
68
|
+
"""Элемент ответа GET /base-stations/<uuid>/logs (ApiBsLogsResponse на стороне Data Logger)."""
|
|
69
|
+
|
|
70
|
+
id: UUID4
|
|
71
|
+
date_created: datetime
|
|
72
|
+
|
|
73
|
+
bs_id: UUID4 | None = None
|
|
74
|
+
protocol: str | None = None
|
|
75
|
+
log_type: str
|
|
76
|
+
|
|
77
|
+
date_sending: datetime
|
|
78
|
+
|
|
79
|
+
latitude: float | None = None
|
|
80
|
+
longitude: float | None = None
|
|
81
|
+
soft_version: str | None = None
|
|
82
|
+
uptime_s: int | None = None
|
|
83
|
+
|
|
84
|
+
external_document_id: UUID4 | None = None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ApiBaseStationSystemLogResponse(JsonApiResponsePayload):
|
|
88
|
+
"""Элемент ответа GET /base-stations/<uuid>/system-logs (ApiBsSystemLogsResponse)."""
|
|
89
|
+
|
|
90
|
+
id: UUID4
|
|
91
|
+
date_created: datetime
|
|
92
|
+
|
|
93
|
+
bs_id: UUID4 | None = None
|
|
94
|
+
bs_log_id: UUID4 | None = None
|
|
95
|
+
date: datetime
|
|
96
|
+
type: str
|
|
97
|
+
mdl: str | None = None
|
|
98
|
+
text: str | None = None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class ApiBaseStationLogsStatResponse(JsonApiResponsePayload):
|
|
102
|
+
"""Ответ GET /base-stations/<uuid>/logs-stat (ApiBsLogsStatResponse)."""
|
|
103
|
+
|
|
104
|
+
stats: List[Tuple[datetime, int]]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ApiBaseStationLogsStatForIntervalsResponse(JsonApiResponsePayload):
|
|
108
|
+
"""Ответ GET /base-stations/<uuid>/logs-stat-for-intervals (ApiBsLogsStatForIntervalsGraphResponse)."""
|
|
109
|
+
|
|
110
|
+
stats: List[datetime]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ApiBaseStationDeviceResponse(JsonApiResponsePayload):
|
|
114
|
+
"""Элемент devices ответа GET /base-stations/<uuid>/devices (ApiDeviceResponse без вложенной БС)."""
|
|
115
|
+
|
|
116
|
+
id: UUID4
|
|
117
|
+
date_created: datetime
|
|
118
|
+
date_modified: datetime
|
|
119
|
+
is_alive: bool
|
|
120
|
+
|
|
121
|
+
api_user_modified_id: UUID4
|
|
122
|
+
note: str
|
|
123
|
+
|
|
124
|
+
device_id: UUID4
|
|
125
|
+
device_network_id: UUID4
|
|
126
|
+
device_network_mac: int
|
|
127
|
+
|
|
128
|
+
latest_device_gateway_id: UUID4 | None = None
|
|
129
|
+
latest_device_protocol_id: UUID4
|
|
130
|
+
latest_device_protocol_type: str | None = None
|
|
131
|
+
latest_device_network_sys_type: str | None = None
|
|
132
|
+
latest_log_datetime: datetime
|
|
133
|
+
latest_bs_id: UUID4 | None = None
|
|
134
|
+
latest_signal_rssi: int | None = None
|
|
135
|
+
latest_signal_snr: int | None = None
|
|
136
|
+
|
|
137
|
+
logs_stat: List[Tuple[datetime, int]] | None = None
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ApiBaseStationDevicesResponse(JsonApiResponsePayload):
|
|
141
|
+
"""Ответ GET /base-stations/<uuid>/devices (ApiBsDevicesResponse)."""
|
|
142
|
+
|
|
143
|
+
devices: List[ApiBaseStationDeviceResponse]
|
|
144
|
+
device_count: int
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class ApiBaseStationDeviceLogResponse(JsonApiResponsePayload):
|
|
148
|
+
"""Элемент device_logs ответа GET /base-stations/<uuid>/device-logs (ApiDeviceLogsResponse)."""
|
|
149
|
+
|
|
150
|
+
id: UUID4
|
|
151
|
+
date_created: datetime
|
|
152
|
+
|
|
153
|
+
bs_id: UUID4 | None = None
|
|
154
|
+
device_id: UUID4
|
|
155
|
+
|
|
156
|
+
device_gateway_id: UUID4 | None = None
|
|
157
|
+
device_protocol_id: UUID4
|
|
158
|
+
|
|
159
|
+
signal_rssi: int | None = None
|
|
160
|
+
signal_snr: int | None = None
|
|
161
|
+
|
|
162
|
+
date_sending: datetime
|
|
163
|
+
|
|
164
|
+
is_verified: bool | None = None
|
|
165
|
+
protocol_type: str | None = None
|
|
166
|
+
packet_type_name: str | None = None
|
|
167
|
+
network_id: UUID4 | None = None
|
|
168
|
+
network_sys_type: str | None = None
|
|
169
|
+
decrypted_payload: str | None = None
|
|
170
|
+
raw_payload: str | None = None
|
|
171
|
+
|
|
172
|
+
error_message: str | None = None
|
|
173
|
+
error_type: str | None = None
|
|
174
|
+
|
|
175
|
+
device: Dict[str, Any] | None = None
|
|
176
|
+
external_document_id: UUID4 | None = None
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class ApiBaseStationDeviceLogsResponse(JsonApiResponsePayload):
|
|
180
|
+
"""Ответ GET /base-stations/<uuid>/device-logs (ApiBsDeviceLogsResponse)."""
|
|
181
|
+
|
|
182
|
+
device_logs: List[ApiBaseStationDeviceLogResponse]
|
|
183
|
+
device_logs_count: int
|
|
184
|
+
device_count: int
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: ul-data-logger-api-sdk
|
|
3
|
-
Version: 2.0.6
|
|
4
|
-
Summary: Data logger API sdk
|
|
5
|
-
Author: Unic-lab
|
|
6
|
-
License: MIT
|
|
7
|
-
Platform: any
|
|
8
|
-
Classifier: Intended Audience :: Developers
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Programming Language :: Python
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Description-Content-Type: text/markdown
|
|
17
|
-
|
|
18
|
-
# ul_iot_account_data_logger
|
|
19
|
-
|
|
20
|
-
## Restoring the db dump
|
|
21
|
-
|
|
22
|
-
1) add your dump to ./tmp
|
|
23
|
-
2) run bash in manager
|
|
24
|
-
```bash
|
|
25
|
-
docker-compose run --rm manager__data_logger__db bash
|
|
26
|
-
```
|
|
27
|
-
3) run inside of manager
|
|
28
|
-
```bash
|
|
29
|
-
pg_restore -U admin -h data_logger__db -d data_logger_db -p 5432 -1 --data-only -t device_log /temporary/dump.sql
|
|
30
|
-
```
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# ul_iot_account_data_logger
|
|
2
|
-
|
|
3
|
-
## Restoring the db dump
|
|
4
|
-
|
|
5
|
-
1) add your dump to ./tmp
|
|
6
|
-
2) run bash in manager
|
|
7
|
-
```bash
|
|
8
|
-
docker-compose run --rm manager__data_logger__db bash
|
|
9
|
-
```
|
|
10
|
-
3) run inside of manager
|
|
11
|
-
```bash
|
|
12
|
-
pg_restore -U admin -h data_logger__db -d data_logger_db -p 5432 -1 --data-only -t device_log /temporary/dump.sql
|
|
13
|
-
```
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import time
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
from functools import lru_cache
|
|
5
|
-
from typing import List, Type
|
|
6
|
-
from uuid import UUID
|
|
7
|
-
|
|
8
|
-
from ul_api_utils.internal_api.internal_api import InternalApi
|
|
9
|
-
from ul_api_utils.internal_api.internal_api_response import TPyloadType
|
|
10
|
-
from ul_api_utils.utils.api_method import ApiMethod
|
|
11
|
-
|
|
12
|
-
from data_logger_api_sdk.data_logger_sdk_config import DataLoggerApiSdkConfig
|
|
13
|
-
from data_logger_api_sdk.types.api_bs_traffic_stats import ApiBsTrafficStatsResponse, ApiDeviceTrafficStatsQuery
|
|
14
|
-
from data_logger_api_sdk.types.api_device_data_history import ApiDeviceDataHistoryBody, ApiDeviceDataHistoryResponse
|
|
15
|
-
from data_logger_api_sdk.types.api_last_bs_data_by_device_macs import ApiDeviceLastBsDataResponse, ApiDeviceMacsListBodyModel
|
|
16
|
-
from data_logger_api_sdk.types.api_packet_types import ApiPacketTypesListResponse
|
|
17
|
-
from data_logger_api_sdk.types.api_protocol_types import ApiProtocolTypesListResponse
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class DataLoggerApiSdk:
|
|
21
|
-
|
|
22
|
-
def __init__(self, config: DataLoggerApiSdkConfig) -> None:
|
|
23
|
-
self._config = config
|
|
24
|
-
self._api = InternalApi(entry_point=self._config.api_url, default_auth_token=self._config.api_token)
|
|
25
|
-
|
|
26
|
-
@lru_cache(maxsize=None) # there should not be leaks memory leaks. flake8 just scared inmemory cache ;)
|
|
27
|
-
def request_payload(
|
|
28
|
-
self,
|
|
29
|
-
_: int,
|
|
30
|
-
method: ApiMethod,
|
|
31
|
-
endpoint: str,
|
|
32
|
-
typed_as: Type[TPyloadType],
|
|
33
|
-
body: str | None,
|
|
34
|
-
query: str | None = None,
|
|
35
|
-
) -> TPyloadType:
|
|
36
|
-
return (
|
|
37
|
-
self._api.request(
|
|
38
|
-
method=method,
|
|
39
|
-
path=endpoint,
|
|
40
|
-
json=json.loads(body) if body is not None else None,
|
|
41
|
-
q=json.loads(query) if query is not None else None,
|
|
42
|
-
)
|
|
43
|
-
.typed(typed_as)
|
|
44
|
-
.check()
|
|
45
|
-
.payload
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
def _get_cache_post_payload(
|
|
49
|
-
self,
|
|
50
|
-
method: ApiMethod,
|
|
51
|
-
path: str,
|
|
52
|
-
typed: Type[TPyloadType],
|
|
53
|
-
body: str | None = None,
|
|
54
|
-
query: str | None = None,
|
|
55
|
-
) -> TPyloadType:
|
|
56
|
-
ttl_status = round(time.time() / self._config.cache_ttl_s)
|
|
57
|
-
return self.request_payload(ttl_status, method, path, typed, body, query) # type: ignore # Type[TPyloadType] is hashable
|
|
58
|
-
|
|
59
|
-
def get_protocol_types_list(self, mac: int) -> List[str]:
|
|
60
|
-
return self._get_cache_post_payload(
|
|
61
|
-
ApiMethod.GET,
|
|
62
|
-
f"/devices/mac/{mac}/logs/protocol-types",
|
|
63
|
-
ApiProtocolTypesListResponse,
|
|
64
|
-
).protocol_types
|
|
65
|
-
|
|
66
|
-
def get_packet_types_list(self, mac: int) -> List[str]:
|
|
67
|
-
return self._get_cache_post_payload(
|
|
68
|
-
ApiMethod.GET,
|
|
69
|
-
f"/devices/mac/{mac}/logs/packet-types",
|
|
70
|
-
ApiPacketTypesListResponse,
|
|
71
|
-
).packet_types
|
|
72
|
-
|
|
73
|
-
def get_device_data_history(
|
|
74
|
-
self,
|
|
75
|
-
period_from: datetime,
|
|
76
|
-
period_to: datetime,
|
|
77
|
-
mac: int,
|
|
78
|
-
protocol_type: str | None = None,
|
|
79
|
-
packet_type: str | None = None,
|
|
80
|
-
) -> List[ApiDeviceDataHistoryResponse]:
|
|
81
|
-
api_device_history_body = ApiDeviceDataHistoryBody(
|
|
82
|
-
period_from=period_from,
|
|
83
|
-
period_to=period_to,
|
|
84
|
-
mac=mac,
|
|
85
|
-
protocol_type=protocol_type,
|
|
86
|
-
packet_type=packet_type,
|
|
87
|
-
).model_dump_json()
|
|
88
|
-
return self._get_cache_post_payload(
|
|
89
|
-
ApiMethod.POST,
|
|
90
|
-
"/device-data-history",
|
|
91
|
-
List[ApiDeviceDataHistoryResponse], # type: ignore
|
|
92
|
-
api_device_history_body,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
def get_last_bs_data_by_device_macs(
|
|
96
|
-
self,
|
|
97
|
-
macs: set[int],
|
|
98
|
-
) -> List[ApiDeviceLastBsDataResponse]:
|
|
99
|
-
return self._get_cache_post_payload(
|
|
100
|
-
ApiMethod.POST,
|
|
101
|
-
"/devices/last-bs-data",
|
|
102
|
-
List[ApiDeviceLastBsDataResponse], # type: ignore
|
|
103
|
-
ApiDeviceMacsListBodyModel(macs=macs).model_dump_json(),
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
def get_bs_traffic_stats(
|
|
107
|
-
self,
|
|
108
|
-
base_station_id: UUID,
|
|
109
|
-
start_at: datetime,
|
|
110
|
-
end_at: datetime,
|
|
111
|
-
) -> List[ApiBsTrafficStatsResponse]:
|
|
112
|
-
api_bs_traffic_stats_query = ApiDeviceTrafficStatsQuery(
|
|
113
|
-
start_at=start_at,
|
|
114
|
-
end_at=end_at,
|
|
115
|
-
)
|
|
116
|
-
return self._get_cache_post_payload(
|
|
117
|
-
ApiMethod.GET,
|
|
118
|
-
f"/base-stations/{base_station_id}/traffic-stats",
|
|
119
|
-
List[ApiBsTrafficStatsResponse], # type: ignore
|
|
120
|
-
None,
|
|
121
|
-
api_bs_traffic_stats_query.model_dump_json(),
|
|
122
|
-
)
|
|
123
|
-
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
[tool.pytest.ini_options]
|
|
2
|
-
addopts = """
|
|
3
|
-
--cov src \
|
|
4
|
-
--no-cov-on-fail \
|
|
5
|
-
--cov-report term-missing \
|
|
6
|
-
--cov-report html:./.tmp/coverage \
|
|
7
|
-
--maxfail=1 \
|
|
8
|
-
--tb=short \
|
|
9
|
-
-vvv \
|
|
10
|
-
-ra \
|
|
11
|
-
-q \
|
|
12
|
-
--showlocals \
|
|
13
|
-
-p pytest_cov"""
|
|
14
|
-
log_cli = true
|
|
15
|
-
cache_dir = "./.tmp/pytest-cache"
|
|
16
|
-
testpaths = [
|
|
17
|
-
"__tests__",
|
|
18
|
-
]
|
|
19
|
-
norecursedirs = [
|
|
20
|
-
".*",
|
|
21
|
-
".git",
|
|
22
|
-
".tmp",
|
|
23
|
-
"srv",
|
|
24
|
-
"node_modules",
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
[tool.mypy]
|
|
28
|
-
plugins = [
|
|
29
|
-
"sqlmypy",
|
|
30
|
-
"sqlalchemy.ext.mypy.plugin",
|
|
31
|
-
"pydantic.mypy"
|
|
32
|
-
]
|
|
33
|
-
#packages = [
|
|
34
|
-
# "src",
|
|
35
|
-
# "__tests__",
|
|
36
|
-
#]
|
|
37
|
-
exclude = ["migrations"]
|
|
38
|
-
cache_dir = "./.tmp/mypy-cache"
|
|
39
|
-
python_version = "3.10"
|
|
40
|
-
warn_return_any = false
|
|
41
|
-
warn_unused_configs = true
|
|
42
|
-
ignore_missing_imports = false
|
|
43
|
-
follow_imports = "normal"
|
|
44
|
-
namespace_packages = true
|
|
45
|
-
explicit_package_bases = true
|
|
46
|
-
follow_imports_for_stubs = true
|
|
47
|
-
implicit_reexport = true
|
|
48
|
-
allow_untyped_globals = false
|
|
49
|
-
disallow_any_generics = true
|
|
50
|
-
disallow_untyped_defs = true
|
|
51
|
-
disallow_incomplete_defs = true
|
|
52
|
-
check_untyped_defs = true
|
|
53
|
-
disallow_untyped_decorators = false
|
|
54
|
-
no_implicit_optional = true
|
|
55
|
-
strict_optional = true
|
|
56
|
-
warn_unused_ignores = true
|
|
57
|
-
warn_no_return = true
|
|
58
|
-
show_none_errors = true
|
|
59
|
-
ignore_errors = false
|
|
60
|
-
allow_redefinition = false
|
|
61
|
-
strict_equality = true
|
|
62
|
-
show_error_context = false
|
|
63
|
-
show_column_numbers = false
|
|
64
|
-
warn_redundant_casts = true
|
|
65
|
-
warn_unreachable = true
|
|
66
|
-
|
|
67
|
-
[tool.pydantic-mypy]
|
|
68
|
-
init_forbid_extra = true
|
|
69
|
-
init_typed = true
|
|
70
|
-
warn_required_dynamic_aliases = true
|
|
71
|
-
warn_untyped_fields = true
|
|
72
|
-
|
|
73
|
-
[[tool.mypy.overrides]]
|
|
74
|
-
module = [
|
|
75
|
-
"sqlalchemy_serializer",
|
|
76
|
-
"api_utils"
|
|
77
|
-
]
|
|
78
|
-
ignore_missing_imports = true
|
|
79
|
-
|
|
80
|
-
[tool.ruff]
|
|
81
|
-
exclude = ["migrations"]
|
|
82
|
-
line-length = 150
|
|
83
|
-
target-version = "py310"
|
|
84
|
-
cache-dir = "./.tmp/ruff-cache"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
[tool.ruff.lint]
|
|
88
|
-
select = ["ALL"]
|
|
89
|
-
ignore = ["D", "RUF001", "PGH003"]
|
|
90
|
-
extend-ignore = [
|
|
91
|
-
"S311", # Generated data isn't always used for cryptographic purposes
|
|
92
|
-
"N805", # First argument of a method should be named `self` - but pydantic docs use cls
|
|
93
|
-
"TRY003", # Avoid specifying long messages outside the exception class - but pydantic allow to use simple raise error
|
|
94
|
-
"EM101", # Exception must not use a string literal, assign to variable first - duplicate msg? ok
|
|
95
|
-
"S101", # Use of `assert` detected - only way to deal with paranoic mypy
|
|
96
|
-
"PLR0913", # Too many arguments in function definition (6 > 5) - maybe good. wiil be refactored later
|
|
97
|
-
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - sqlalchemy allow to mutations
|
|
98
|
-
"G004", # Logging statement uses f-string - it's OK
|
|
99
|
-
"UP035", # `typing.List` is deprecated, use `list` instead - yes, but `list` broke api-utils @rest_api
|
|
100
|
-
"UP006", # Use `list` instead of `List` for type annotation - yes, but `list` broke api-utils @rest_api
|
|
101
|
-
"ANN401", # Checks that function arguments are annotated with a more specific type than Any
|
|
102
|
-
"ANN101", # This rule is commonly disabled because type checkers can infer this type without annotation. It will be removed in a future release
|
|
103
|
-
"C901", # Checks for functions with a high McCabe complexity
|
|
104
|
-
"ERA001", # Checks for commented-out Python code
|
|
105
|
-
"ANN102", # Checks that class method cls arguments have type annotations
|
|
106
|
-
"PGH004", # Check for noqa annotations that suppress all diagnostics, as opposed to targeting specific diagnostics
|
|
107
|
-
"A002", # Checks for any function arguments that use the same name as a builtin
|
|
108
|
-
"A001", # Checks for variable (and function) assignments that use the same name as a builtin
|
|
109
|
-
"B019", # Checks for uses of the functools.lru_cache and functools.cache decorators on methods
|
|
110
|
-
"PLW0603", # Checks for the use of global statements to update identifiers
|
|
111
|
-
"UP033", # Checks for uses of functools.lru_cache that set maxsize=None
|
|
112
|
-
"FIX002", # Checks for "TODO" comments
|
|
113
|
-
"TD002", # Checks that a TODO comment includes an author
|
|
114
|
-
"TD003", # Checks that a TODO comment is associated with a link to a relevant issue or ticket
|
|
115
|
-
"FBT001", # Checks for the use of boolean positional arguments in function definitions, as determined by the presence of a bool type hint
|
|
116
|
-
"PERF203", # Checks for uses of except handling via try-except within for and while loops
|
|
117
|
-
"A005", # Checks if module shadows a Python standard-library module
|
|
118
|
-
"C420", # Unnecessary dict comprehension for iterable; use dict.fromkeys instead
|
|
119
|
-
"LOG015", # {}() call on root logger
|
|
120
|
-
"TC006", # Add quotes to type expression in typing.cast()
|
|
121
|
-
]
|
|
122
|
-
|
|
123
|
-
[tool.ruff.lint.mccabe]
|
|
124
|
-
max-complexity = 4
|
|
125
|
-
|
|
126
|
-
[tool.black]
|
|
127
|
-
target-version = ["py310"]
|
|
128
|
-
exclude = "migrations"
|
|
129
|
-
#include = [
|
|
130
|
-
# "^/src",
|
|
131
|
-
# "^/notification_sdk",
|
|
132
|
-
#]
|
|
133
|
-
check = false
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
from setuptools import find_packages, setup
|
|
5
|
-
|
|
6
|
-
HERE = Path(__file__).resolve().parent
|
|
7
|
-
|
|
8
|
-
with Path.open(Path(HERE) / "README.md", encoding="utf-8") as f:
|
|
9
|
-
long_description = f.read()
|
|
10
|
-
|
|
11
|
-
if sys.argv:
|
|
12
|
-
if "broker_sdk" in set(sys.argv):
|
|
13
|
-
sys.argv.remove("broker_sdk")
|
|
14
|
-
setup(
|
|
15
|
-
name="ul-data-logger-sdk",
|
|
16
|
-
version="3.0.4",
|
|
17
|
-
description="Data logger sdk",
|
|
18
|
-
author="Unic-lab",
|
|
19
|
-
long_description=long_description,
|
|
20
|
-
long_description_content_type="text/markdown",
|
|
21
|
-
packages=find_packages(include=["data_logger_sdk*"]),
|
|
22
|
-
include_package_data=True,
|
|
23
|
-
package_data={
|
|
24
|
-
"": ["*.yml", "py.typed"],
|
|
25
|
-
"data_logger_sdk": ["py.typed"],
|
|
26
|
-
},
|
|
27
|
-
license="MIT",
|
|
28
|
-
classifiers=[
|
|
29
|
-
"Intended Audience :: Developers",
|
|
30
|
-
"License :: OSI Approved :: MIT License",
|
|
31
|
-
"Programming Language :: Python",
|
|
32
|
-
"Programming Language :: Python :: 3.6",
|
|
33
|
-
"Programming Language :: Python :: 3.7",
|
|
34
|
-
"Programming Language :: Python :: 3.8",
|
|
35
|
-
"Programming Language :: Python :: 3.9",
|
|
36
|
-
"Operating System :: OS Independent",
|
|
37
|
-
],
|
|
38
|
-
platforms="any",
|
|
39
|
-
install_requires=[
|
|
40
|
-
"ul-unipipeline>=2.0.0",
|
|
41
|
-
# "ul-data-aggregator-sdk>=8.13.2",
|
|
42
|
-
# "ul-py-tool==2.1.3,
|
|
43
|
-
# "ul-api-utils==8.1.9",
|
|
44
|
-
# "ul-db-utils==4.0.2",
|
|
45
|
-
# "ul-data-gateway-sdk==1.0.6",
|
|
46
|
-
],
|
|
47
|
-
)
|
|
48
|
-
elif "api_sdk" in set(sys.argv):
|
|
49
|
-
sys.argv.remove("api_sdk")
|
|
50
|
-
setup(
|
|
51
|
-
name="ul-data-logger-api-sdk",
|
|
52
|
-
version="2.0.6",
|
|
53
|
-
description="Data logger API sdk",
|
|
54
|
-
author="Unic-lab",
|
|
55
|
-
long_description=long_description,
|
|
56
|
-
long_description_content_type="text/markdown",
|
|
57
|
-
packages=find_packages(include=["data_logger_api_sdk*"]),
|
|
58
|
-
include_package_data=True,
|
|
59
|
-
package_data={
|
|
60
|
-
"": ["*.yml", "py.typed"],
|
|
61
|
-
"data_logger_api_sdk": ["py.typed"],
|
|
62
|
-
},
|
|
63
|
-
license="MIT",
|
|
64
|
-
classifiers=[
|
|
65
|
-
"Intended Audience :: Developers",
|
|
66
|
-
"License :: OSI Approved :: MIT License",
|
|
67
|
-
"Programming Language :: Python",
|
|
68
|
-
"Programming Language :: Python :: 3.6",
|
|
69
|
-
"Programming Language :: Python :: 3.7",
|
|
70
|
-
"Programming Language :: Python :: 3.8",
|
|
71
|
-
"Programming Language :: Python :: 3.9",
|
|
72
|
-
"Operating System :: OS Independent",
|
|
73
|
-
],
|
|
74
|
-
platforms="any",
|
|
75
|
-
install_requires=[
|
|
76
|
-
"ul-unipipeline>=2.0.0",
|
|
77
|
-
"tqdm==4.66.1",
|
|
78
|
-
# "ul-data-aggregator-sdk>=8.13.2",
|
|
79
|
-
# "ul-py-tool==2.1.4,
|
|
80
|
-
# "ul-api-utils==9.1.1",
|
|
81
|
-
# "ul-db-utils==5.1.0",
|
|
82
|
-
# "ul-data-gateway-sdk==1.0.6",
|
|
83
|
-
],
|
|
84
|
-
)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: ul-data-logger-api-sdk
|
|
3
|
-
Version: 2.0.6
|
|
4
|
-
Summary: Data logger API sdk
|
|
5
|
-
Author: Unic-lab
|
|
6
|
-
License: MIT
|
|
7
|
-
Platform: any
|
|
8
|
-
Classifier: Intended Audience :: Developers
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Programming Language :: Python
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Description-Content-Type: text/markdown
|
|
17
|
-
|
|
18
|
-
# ul_iot_account_data_logger
|
|
19
|
-
|
|
20
|
-
## Restoring the db dump
|
|
21
|
-
|
|
22
|
-
1) add your dump to ./tmp
|
|
23
|
-
2) run bash in manager
|
|
24
|
-
```bash
|
|
25
|
-
docker-compose run --rm manager__data_logger__db bash
|
|
26
|
-
```
|
|
27
|
-
3) run inside of manager
|
|
28
|
-
```bash
|
|
29
|
-
pg_restore -U admin -h data_logger__db -d data_logger_db -p 5432 -1 --data-only -t device_log /temporary/dump.sql
|
|
30
|
-
```
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
README.md
|
|
2
|
-
pyproject.toml
|
|
3
|
-
setup.py
|
|
4
|
-
data_logger_api_sdk/__init__.py
|
|
5
|
-
data_logger_api_sdk/data_logger_api_sdk.py
|
|
6
|
-
data_logger_api_sdk/data_logger_sdk_config.py
|
|
7
|
-
data_logger_api_sdk/py.typed
|
|
8
|
-
data_logger_api_sdk/types/__init__.py
|
|
9
|
-
data_logger_api_sdk/types/api_bs_traffic_stats.py
|
|
10
|
-
data_logger_api_sdk/types/api_device_data_history.py
|
|
11
|
-
data_logger_api_sdk/types/api_last_bs_data_by_device_macs.py
|
|
12
|
-
data_logger_api_sdk/types/api_packet_types.py
|
|
13
|
-
data_logger_api_sdk/types/api_protocol_types.py
|
|
14
|
-
ul_data_logger_api_sdk.egg-info/PKG-INFO
|
|
15
|
-
ul_data_logger_api_sdk.egg-info/SOURCES.txt
|
|
16
|
-
ul_data_logger_api_sdk.egg-info/dependency_links.txt
|
|
17
|
-
ul_data_logger_api_sdk.egg-info/requires.txt
|
|
18
|
-
ul_data_logger_api_sdk.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
data_logger_api_sdk
|
{ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ul-data-logger-api-sdk-2.0.6/data_logger_api_sdk → ul_data_logger_api_sdk-3.1.1}/types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|