ul-data-logger-api-sdk 3.3.3__tar.gz → 3.3.5__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.
Files changed (17) hide show
  1. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/PKG-INFO +1 -1
  2. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/data_logger_api_sdk.py +32 -27
  3. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/pyproject.toml +1 -1
  4. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/api_base_stations.py +3 -32
  5. ul_data_logger_api_sdk-3.3.5/types/api_bs_device_links.py +30 -0
  6. ul_data_logger_api_sdk-3.3.5/types/api_uplink_signal.py +22 -0
  7. ul_data_logger_api_sdk-3.3.3/types/api_uplink_signal.py +0 -29
  8. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/.gitignore +0 -0
  9. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/__init__.py +0 -0
  10. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/data_logger_sdk_config.py +0 -0
  11. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/py.typed +0 -0
  12. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/__init__.py +0 -0
  13. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/api_bs_traffic_stats.py +0 -0
  14. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/api_device_data_history.py +0 -0
  15. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/api_last_bs_data_by_device_macs.py +0 -0
  16. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/api_packet_types.py +0 -0
  17. {ul_data_logger_api_sdk-3.3.3 → ul_data_logger_api_sdk-3.3.5}/types/api_protocol_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ul-data-logger-api-sdk
3
- Version: 3.3.3
3
+ Version: 3.3.5
4
4
  Summary: Data logger API sdk
5
5
  Author: Unic-lab
6
6
  License-Expression: MIT
@@ -25,6 +25,7 @@ from data_logger_api_sdk.types.api_base_stations import (
25
25
  ApiBaseStationSystemLogResponse,
26
26
  ApiBaseStationSystemLogsListResult,
27
27
  )
28
+ from data_logger_api_sdk.types.api_bs_device_links import ApiBsDeviceLinkResponse, ApiBsDeviceLinksListResult
28
29
  from data_logger_api_sdk.types.api_bs_traffic_stats import ApiBsTrafficStatsResponse, ApiDeviceTrafficStatsQuery
29
30
  from data_logger_api_sdk.types.api_uplink_signal import (
30
31
  ApiDeviceUplinkSignalLatestResponse,
@@ -179,7 +180,6 @@ class DataLoggerApiSdk:
179
180
  serial_number: int | None = None,
180
181
  log_stat_days: int = 0,
181
182
  ) -> ApiBaseStationsListResult:
182
- """GET /base-stations — список базовых станций Data Logger."""
183
183
  query: Dict[str, Any] = {
184
184
  "limit": limit,
185
185
  "offset": offset,
@@ -201,12 +201,7 @@ class DataLoggerApiSdk:
201
201
  offset: int = 0,
202
202
  macs: List[int] | None = None,
203
203
  ) -> ApiDeviceUplinkSignalsListResult:
204
- """GET /uplink-signal-latest — последний uplink-сигнал каждого мака.
205
-
206
- Последний по метеру, группировка по маку (один мак = одна строка);
207
- macs — рантайм-фильтр по конкретным устройствам. bs_id —
208
- идентификатор БС Data Logger (= external_bs_id потребителя).
209
- """
204
+ """Последний uplink-сигнал каждого мака (один мак — одна строка)."""
210
205
  query: Dict[str, Any] = {"limit": limit, "offset": offset}
211
206
  if macs:
212
207
  query["mac"] = macs
@@ -218,17 +213,42 @@ class DataLoggerApiSdk:
218
213
  )
219
214
  return ApiDeviceUplinkSignalsListResult(items=items, total_count=total_count)
220
215
 
216
+ def get_bs_device_links(
217
+ self,
218
+ start_at: datetime,
219
+ end_at: datetime | None = None,
220
+ limit: int = 500,
221
+ after_bs_id: UUID | None = None,
222
+ after_device_id: UUID | None = None,
223
+ ) -> ApiBsDeviceLinksListResult:
224
+ """GET /bs-device-links — связи «мак ↔ БС» за период («когда-либо» при start_at из далёкого прошлого).
225
+
226
+ Keyset-пагинация по (bs_id, device_id): курсор — последняя пара
227
+ предыдущей страницы; без курсора (первая страница) приходит и
228
+ total_count. Обход до пустой страницы — для ночного синка слоя
229
+ «Объекты и устройства».
230
+ """
231
+ query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit}
232
+ if end_at is not None:
233
+ query["end_at"] = end_at.isoformat()
234
+ if after_bs_id is not None and after_device_id is not None:
235
+ query["after_bs_id"] = str(after_bs_id)
236
+ query["after_device_id"] = str(after_device_id)
237
+ response = self._api.request(
238
+ method=ApiMethod.GET,
239
+ path="/bs-device-links",
240
+ json=None,
241
+ q=query,
242
+ ).typed(List[ApiBsDeviceLinkResponse]).check()
243
+ return ApiBsDeviceLinksListResult(items=response.payload, total_count=response.total_count)
244
+
221
245
  def get_base_station(
222
246
  self,
223
247
  base_station_id: UUID,
224
248
  log_stat_days: int = 0,
225
249
  exclude_log_types: List[str] | None = None,
226
250
  ) -> ApiBaseStationDetailResponse:
227
- """GET /base-stations/<uuid> — карточка базовой станции Data Logger.
228
-
229
- exclude_log_types исключает типы из logs_stat (например, ['heartbit']);
230
- без него счётчики включают служебные heartbeat-логи.
231
- """
251
+ """exclude_log_types исключает типы из счётчиков logs_stat (например, ['heartbit'])."""
232
252
  query: Dict[str, Any] = {"log_stat_days": log_stat_days}
233
253
  if exclude_log_types:
234
254
  query["exclude_log_types"] = exclude_log_types
@@ -249,11 +269,6 @@ class DataLoggerApiSdk:
249
269
  exclude_log_types: List[str] | None = None,
250
270
  sort: str | None = None,
251
271
  ) -> ApiBaseStationLogsListResult:
252
- """GET /base-stations/<uuid>/logs — журнал логов базовой станции.
253
-
254
- exclude_log_types передаётся стандартным filter-параметром
255
- (например, ['heartbit'] прячет служебные heartbeat-логи).
256
- """
257
272
  query: Dict[str, Any] = {"limit": limit, "offset": offset}
258
273
  if start_at is not None:
259
274
  query["start_at"] = start_at.isoformat()
@@ -276,7 +291,6 @@ class DataLoggerApiSdk:
276
291
  base_station_id: UUID,
277
292
  log_id: UUID,
278
293
  ) -> ApiBaseStationLogDetailResponse:
279
- """GET /base-stations/<uuid>/logs/<uuid> — конкретный лог БС с сырым JSON пакета."""
280
294
  return self._request_payload_once(
281
295
  ApiMethod.GET,
282
296
  f"/base-stations/{base_station_id}/logs/{log_id}",
@@ -291,7 +305,6 @@ class DataLoggerApiSdk:
291
305
  limit: int = 100,
292
306
  offset: int = 0,
293
307
  ) -> ApiBaseStationSystemLogsListResult:
294
- """GET /base-stations/<uuid>/system-logs — журнал системных логов базовой станции."""
295
308
  query: Dict[str, Any] = {"limit": limit, "offset": offset}
296
309
  if start_at is not None:
297
310
  query["start_at"] = start_at.isoformat()
@@ -311,10 +324,6 @@ class DataLoggerApiSdk:
311
324
  day: date,
312
325
  exclude_log_types: List[str] | None = None,
313
326
  ) -> ApiBaseStationLogsStatResponse:
314
- """GET /base-stations/<uuid>/logs-stat — статистика логов базовой станции за сутки.
315
-
316
- exclude_log_types исключает типы из поминутных счётчиков (['heartbit'] прячет heartbeat).
317
- """
318
327
  query: Dict[str, Any] = {"day": day.isoformat()}
319
328
  if exclude_log_types:
320
329
  query["exclude_log_types"] = exclude_log_types
@@ -331,7 +340,6 @@ class DataLoggerApiSdk:
331
340
  start_at: datetime,
332
341
  end_at: datetime | None = None,
333
342
  ) -> ApiBaseStationDeviceLogsStatResponse:
334
- """GET /base-stations/<uuid>/device-logs-stat — число логов устройств БС по дням."""
335
343
  query: Dict[str, Any] = {"start_at": start_at.isoformat()}
336
344
  if end_at is not None:
337
345
  query["end_at"] = end_at.isoformat()
@@ -348,7 +356,6 @@ class DataLoggerApiSdk:
348
356
  start_at: datetime,
349
357
  end_at: datetime | None = None,
350
358
  ) -> ApiBaseStationLogsStatForIntervalsResponse:
351
- """GET /base-stations/<uuid>/logs-stat-for-intervals — метки времени логов за интервал."""
352
359
  query: Dict[str, Any] = {"start_at": start_at.isoformat()}
353
360
  if end_at is not None:
354
361
  query["end_at"] = end_at.isoformat()
@@ -367,7 +374,6 @@ class DataLoggerApiSdk:
367
374
  limit: int = 100,
368
375
  offset: int = 0,
369
376
  ) -> ApiBaseStationDevicesResponse:
370
- """GET /base-stations/<uuid>/devices — устройства, работающие через базовую станцию."""
371
377
  query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
372
378
  if end_at is not None:
373
379
  query["end_at"] = end_at.isoformat()
@@ -386,7 +392,6 @@ class DataLoggerApiSdk:
386
392
  limit: int = 100,
387
393
  offset: int = 0,
388
394
  ) -> ApiBaseStationDeviceLogsResponse:
389
- """GET /base-stations/<uuid>/device-logs — логи устройств базовой станции."""
390
395
  query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
391
396
  if end_at is not None:
392
397
  query["end_at"] = end_at.isoformat()
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ul-data-logger-api-sdk"
7
- version = "3.3.3"
7
+ version = "3.3.5"
8
8
  description = "Data logger API sdk"
9
9
  license = "MIT"
10
10
  requires-python = ">=3.14"
@@ -9,29 +9,21 @@ BS__LOG_TYPE__HEARTBIT = "heartbit"
9
9
 
10
10
 
11
11
  class ApiBaseStationsListResult(NamedTuple):
12
- """Результат спискового вызова BS-endpoint Data Logger: страница элементов и total_count."""
13
-
14
12
  items: List["ApiBaseStationResponse"]
15
13
  total_count: int
16
14
 
17
15
 
18
16
  class ApiBaseStationLogsListResult(NamedTuple):
19
- """Результат вызова GET /base-stations/<uuid>/logs."""
20
-
21
17
  items: List["ApiBaseStationLogResponse"]
22
18
  total_count: int
23
19
 
24
20
 
25
21
  class ApiBaseStationSystemLogsListResult(NamedTuple):
26
- """Результат вызова GET /base-stations/<uuid>/system-logs."""
27
-
28
22
  items: List["ApiBaseStationSystemLogResponse"]
29
23
  total_count: int
30
24
 
31
25
 
32
26
  class ApiBaseStationResponse(JsonApiResponsePayload):
33
- """Элемент ответа GET /base-stations (BsListShortResponse на стороне Data Logger)."""
34
-
35
27
  id: UUID4
36
28
  date_created: datetime
37
29
  date_modified: datetime
@@ -55,8 +47,6 @@ class ApiBaseStationResponse(JsonApiResponsePayload):
55
47
 
56
48
 
57
49
  class ApiBaseStationDetailResponse(ApiBaseStationResponse):
58
- """Ответ GET /base-stations/<uuid> (BsResponse на стороне Data Logger)."""
59
-
60
50
  latest_sdr_config: Dict[str, Any] | None = None
61
51
  device_counts: List[Tuple[datetime, int]] | None = None
62
52
  system_logs_stat: List[Tuple[datetime, int]] | None = None
@@ -65,12 +55,7 @@ class ApiBaseStationDetailResponse(ApiBaseStationResponse):
65
55
 
66
56
 
67
57
  class ApiBaseStationLogResponse(JsonApiResponsePayload):
68
- """Элемент ответа GET /base-stations/<uuid>/logs (ApiBsLogsResponse на стороне Data Logger).
69
-
70
- rssi/snr/protocol_type/packet_type_name/network_sys_type/error_* обогащаются
71
- из сырого документа пакета (блок meta.bs_http / meta.nbfi_bs0); null, если
72
- документа нет или в нём нет этих полей.
73
- """
58
+ """Лог БС; rssi/snr и поля пакета (protocol_type, error_*) — из сырого документа, null при его отсутствии."""
74
59
 
75
60
  id: UUID4
76
61
  date_created: datetime
@@ -98,14 +83,10 @@ class ApiBaseStationLogResponse(JsonApiResponsePayload):
98
83
 
99
84
 
100
85
  class ApiBaseStationLogDetailResponse(ApiBaseStationLogResponse):
101
- """Ответ GET /base-stations/<uuid>/logs/<uuid> — лог с сырым JSON пакета (ApiBsLogDetailResponse в DL)."""
102
-
103
86
  data: Dict[str, Any] | None = None
104
87
 
105
88
 
106
89
  class ApiBaseStationSystemLogResponse(JsonApiResponsePayload):
107
- """Элемент ответа GET /base-stations/<uuid>/system-logs (ApiBsSystemLogsResponse)."""
108
-
109
90
  id: UUID4
110
91
  date_created: datetime
111
92
 
@@ -118,26 +99,22 @@ class ApiBaseStationSystemLogResponse(JsonApiResponsePayload):
118
99
 
119
100
 
120
101
  class ApiBaseStationLogsStatResponse(JsonApiResponsePayload):
121
- """Ответ GET /base-stations/<uuid>/logs-stat (ApiBsLogsStatResponse)."""
122
-
123
102
  stats: List[Tuple[datetime, int]]
124
103
 
125
104
 
126
105
  class ApiBaseStationLogsStatForIntervalsResponse(JsonApiResponsePayload):
127
- """Ответ GET /base-stations/<uuid>/logs-stat-for-intervals (ApiBsLogsStatForIntervalsGraphResponse)."""
106
+ """Метки времени логов за интервал."""
128
107
 
129
108
  stats: List[datetime]
130
109
 
131
110
 
132
111
  class ApiBaseStationDeviceLogsStatResponse(JsonApiResponsePayload):
133
- """Ответ GET /base-stations/<uuid>/device-logs-stat: число логов устройств по дням."""
112
+ """Число логов устройств БС по дням."""
134
113
 
135
114
  stats: List[Tuple[date, int]]
136
115
 
137
116
 
138
117
  class ApiBaseStationDeviceResponse(JsonApiResponsePayload):
139
- """Элемент devices ответа GET /base-stations/<uuid>/devices (ApiDeviceResponse без вложенной БС)."""
140
-
141
118
  id: UUID4
142
119
  date_created: datetime
143
120
  date_modified: datetime
@@ -163,15 +140,11 @@ class ApiBaseStationDeviceResponse(JsonApiResponsePayload):
163
140
 
164
141
 
165
142
  class ApiBaseStationDevicesResponse(JsonApiResponsePayload):
166
- """Ответ GET /base-stations/<uuid>/devices (ApiBsDevicesResponse)."""
167
-
168
143
  devices: List[ApiBaseStationDeviceResponse]
169
144
  device_count: int
170
145
 
171
146
 
172
147
  class ApiBaseStationDeviceLogResponse(JsonApiResponsePayload):
173
- """Элемент device_logs ответа GET /base-stations/<uuid>/device-logs (ApiDeviceLogsResponse)."""
174
-
175
148
  id: UUID4
176
149
  date_created: datetime
177
150
 
@@ -202,8 +175,6 @@ class ApiBaseStationDeviceLogResponse(JsonApiResponsePayload):
202
175
 
203
176
 
204
177
  class ApiBaseStationDeviceLogsResponse(JsonApiResponsePayload):
205
- """Ответ GET /base-stations/<uuid>/device-logs (ApiBsDeviceLogsResponse)."""
206
-
207
178
  device_logs: List[ApiBaseStationDeviceLogResponse]
208
179
  device_logs_count: int
209
180
  device_count: int
@@ -0,0 +1,30 @@
1
+ from typing import List, NamedTuple, Optional
2
+
3
+ from pydantic import UUID4
4
+ from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
5
+
6
+
7
+ class ApiBsDeviceLinkResponse(JsonApiResponsePayload):
8
+ """Связь «мак ↔ БС» за период: элемент ответа GET /bs-device-links.
9
+
10
+ Пара существует, если БС когда-либо получала пакет устройства в
11
+ запрошенном окне (дистинкт по журналу device_log). bs_id — идентификатор
12
+ БС Data Logger (у потребителя unified API это external_bs_id);
13
+ bs_identifier — её серийный номер.
14
+ """
15
+
16
+ device_network_mac: int
17
+ bs_id: UUID4
18
+ device_id: UUID4
19
+ bs_identifier: str
20
+
21
+
22
+ class ApiBsDeviceLinksListResult(NamedTuple):
23
+ """Результат спискового вызова: страница элементов и total_count.
24
+
25
+ total_count приходит только на первой странице (без курсора); дальше —
26
+ None, обход идёт до пустой страницы.
27
+ """
28
+
29
+ items: List[ApiBsDeviceLinkResponse]
30
+ total_count: Optional[int]
@@ -0,0 +1,22 @@
1
+ from datetime import datetime
2
+ from typing import List, NamedTuple
3
+
4
+ from pydantic import UUID4
5
+ from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
6
+
7
+
8
+ class ApiDeviceUplinkSignalLatestResponse(JsonApiResponsePayload):
9
+ """Последний uplink-сигнал мака; bs_identifier — серийный номер БС, packet_date — время последнего пакета."""
10
+
11
+ mac: int
12
+ device_id: UUID4
13
+ bs_id: UUID4 | None = None
14
+ bs_identifier: str | None = None
15
+ rssi: int | None = None
16
+ snr: int | None = None
17
+ packet_date: datetime | None = None
18
+
19
+
20
+ class ApiDeviceUplinkSignalsListResult(NamedTuple):
21
+ items: List[ApiDeviceUplinkSignalLatestResponse]
22
+ total_count: int
@@ -1,29 +0,0 @@
1
- from datetime import datetime
2
- from typing import List, NamedTuple
3
-
4
- from pydantic import UUID4
5
- from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
6
-
7
-
8
- class ApiDeviceUplinkSignalLatestResponse(JsonApiResponsePayload):
9
- """Последний uplink-сигнал мака: элемент ответа GET /uplink-signal-latest.
10
-
11
- bs_id — идентификатор базовой станции Data Logger (у потребителя unified
12
- API это external_bs_id, маппинг по серийнику не нужен); bs_identifier —
13
- серийный номер БС. packet_date — время последнего пакета устройства.
14
- """
15
-
16
- mac: int
17
- device_id: UUID4
18
- bs_id: UUID4 | None = None
19
- bs_identifier: str | None = None
20
- rssi: int | None = None
21
- snr: int | None = None
22
- packet_date: datetime | None = None
23
-
24
-
25
- class ApiDeviceUplinkSignalsListResult(NamedTuple):
26
- """Результат спискового вызова: страница элементов и total_count."""
27
-
28
- items: List[ApiDeviceUplinkSignalLatestResponse]
29
- total_count: int