ul-data-logger-api-sdk 3.0.0__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.
@@ -271,6 +271,7 @@ tags
271
271
  .envs/*
272
272
  !.envs/.local/
273
273
  !srv/merge_dotenvs.py
274
+ *.env
274
275
 
275
276
 
276
277
  .ipynb_checkpoints/
@@ -291,5 +292,8 @@ _*.ipynb
291
292
 
292
293
  /srv/*.retry
293
294
 
295
+ # Локальный overlay для demo-стенда (пароли, адреса Patroni)
296
+ srv/docker_compose/docker-compose.demo.yml
297
+
294
298
  # Swagger spec
295
299
  /src/conf/*docs.yml
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: ul-data-logger-api-sdk
3
- Version: 3.0.0
3
+ Version: 3.1.1
4
4
  Summary: Data logger API sdk
5
5
  Author: Unic-lab
6
6
  License-Expression: MIT
@@ -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
+
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ul-data-logger-api-sdk"
7
- version = "3.0.0"
7
+ version = "3.1.1"
8
8
  description = "Data logger API sdk"
9
9
  license = "MIT"
10
10
  requires-python = ">=3.14"
@@ -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,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
-