ul-data-logger-api-sdk 3.3.4__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.4 → ul_data_logger_api_sdk-3.3.5}/PKG-INFO +1 -1
  2. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/data_logger_api_sdk.py +19 -38
  3. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/pyproject.toml +1 -1
  4. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/types/api_base_stations.py +3 -32
  5. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/types/api_bs_device_links.py +8 -3
  6. ul_data_logger_api_sdk-3.3.5/types/api_uplink_signal.py +22 -0
  7. ul_data_logger_api_sdk-3.3.4/types/api_uplink_signal.py +0 -29
  8. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/.gitignore +0 -0
  9. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/__init__.py +0 -0
  10. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/data_logger_sdk_config.py +0 -0
  11. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/py.typed +0 -0
  12. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/types/__init__.py +0 -0
  13. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/types/api_bs_traffic_stats.py +0 -0
  14. {ul_data_logger_api_sdk-3.3.4 → ul_data_logger_api_sdk-3.3.5}/types/api_device_data_history.py +0 -0
  15. {ul_data_logger_api_sdk-3.3.4 → 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.4 → ul_data_logger_api_sdk-3.3.5}/types/api_packet_types.py +0 -0
  17. {ul_data_logger_api_sdk-3.3.4 → 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.4
3
+ Version: 3.3.5
4
4
  Summary: Data logger API sdk
5
5
  Author: Unic-lab
6
6
  License-Expression: MIT
@@ -180,7 +180,6 @@ class DataLoggerApiSdk:
180
180
  serial_number: int | None = None,
181
181
  log_stat_days: int = 0,
182
182
  ) -> ApiBaseStationsListResult:
183
- """GET /base-stations — список базовых станций Data Logger."""
184
183
  query: Dict[str, Any] = {
185
184
  "limit": limit,
186
185
  "offset": offset,
@@ -202,12 +201,7 @@ class DataLoggerApiSdk:
202
201
  offset: int = 0,
203
202
  macs: List[int] | None = None,
204
203
  ) -> ApiDeviceUplinkSignalsListResult:
205
- """GET /uplink-signal-latest — последний uplink-сигнал каждого мака.
206
-
207
- Последний по метеру, группировка по маку (один мак = одна строка);
208
- macs — рантайм-фильтр по конкретным устройствам. bs_id —
209
- идентификатор БС Data Logger (= external_bs_id потребителя).
210
- """
204
+ """Последний uplink-сигнал каждого мака (один мак — одна строка)."""
211
205
  query: Dict[str, Any] = {"limit": limit, "offset": offset}
212
206
  if macs:
213
207
  query["mac"] = macs
@@ -224,23 +218,29 @@ class DataLoggerApiSdk:
224
218
  start_at: datetime,
225
219
  end_at: datetime | None = None,
226
220
  limit: int = 500,
227
- offset: int = 0,
221
+ after_bs_id: UUID | None = None,
222
+ after_device_id: UUID | None = None,
228
223
  ) -> ApiBsDeviceLinksListResult:
229
224
  """GET /bs-device-links — связи «мак ↔ БС» за период («когда-либо» при start_at из далёкого прошлого).
230
225
 
231
- Один запрос по журналу device_log (дистинкт по паре мак+БС) вместо
232
- обхода всех БС; для ночного синка слоя «Объекты и устройства».
226
+ Keyset-пагинация по (bs_id, device_id): курсор — последняя пара
227
+ предыдущей страницы; без курсора (первая страница) приходит и
228
+ total_count. Обход до пустой страницы — для ночного синка слоя
229
+ «Объекты и устройства».
233
230
  """
234
- query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
231
+ query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit}
235
232
  if end_at is not None:
236
233
  query["end_at"] = end_at.isoformat()
237
- items, total_count = self._request_list_payload_once(
238
- ApiMethod.GET,
239
- "/bs-device-links",
240
- List[ApiBsDeviceLinkResponse], # type: ignore
241
- query,
242
- )
243
- return ApiBsDeviceLinksListResult(items=items, total_count=total_count)
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
244
 
245
245
  def get_base_station(
246
246
  self,
@@ -248,11 +248,7 @@ class DataLoggerApiSdk:
248
248
  log_stat_days: int = 0,
249
249
  exclude_log_types: List[str] | None = None,
250
250
  ) -> ApiBaseStationDetailResponse:
251
- """GET /base-stations/<uuid> — карточка базовой станции Data Logger.
252
-
253
- exclude_log_types исключает типы из logs_stat (например, ['heartbit']);
254
- без него счётчики включают служебные heartbeat-логи.
255
- """
251
+ """exclude_log_types исключает типы из счётчиков logs_stat (например, ['heartbit'])."""
256
252
  query: Dict[str, Any] = {"log_stat_days": log_stat_days}
257
253
  if exclude_log_types:
258
254
  query["exclude_log_types"] = exclude_log_types
@@ -273,11 +269,6 @@ class DataLoggerApiSdk:
273
269
  exclude_log_types: List[str] | None = None,
274
270
  sort: str | None = None,
275
271
  ) -> ApiBaseStationLogsListResult:
276
- """GET /base-stations/<uuid>/logs — журнал логов базовой станции.
277
-
278
- exclude_log_types передаётся стандартным filter-параметром
279
- (например, ['heartbit'] прячет служебные heartbeat-логи).
280
- """
281
272
  query: Dict[str, Any] = {"limit": limit, "offset": offset}
282
273
  if start_at is not None:
283
274
  query["start_at"] = start_at.isoformat()
@@ -300,7 +291,6 @@ class DataLoggerApiSdk:
300
291
  base_station_id: UUID,
301
292
  log_id: UUID,
302
293
  ) -> ApiBaseStationLogDetailResponse:
303
- """GET /base-stations/<uuid>/logs/<uuid> — конкретный лог БС с сырым JSON пакета."""
304
294
  return self._request_payload_once(
305
295
  ApiMethod.GET,
306
296
  f"/base-stations/{base_station_id}/logs/{log_id}",
@@ -315,7 +305,6 @@ class DataLoggerApiSdk:
315
305
  limit: int = 100,
316
306
  offset: int = 0,
317
307
  ) -> ApiBaseStationSystemLogsListResult:
318
- """GET /base-stations/<uuid>/system-logs — журнал системных логов базовой станции."""
319
308
  query: Dict[str, Any] = {"limit": limit, "offset": offset}
320
309
  if start_at is not None:
321
310
  query["start_at"] = start_at.isoformat()
@@ -335,10 +324,6 @@ class DataLoggerApiSdk:
335
324
  day: date,
336
325
  exclude_log_types: List[str] | None = None,
337
326
  ) -> ApiBaseStationLogsStatResponse:
338
- """GET /base-stations/<uuid>/logs-stat — статистика логов базовой станции за сутки.
339
-
340
- exclude_log_types исключает типы из поминутных счётчиков (['heartbit'] прячет heartbeat).
341
- """
342
327
  query: Dict[str, Any] = {"day": day.isoformat()}
343
328
  if exclude_log_types:
344
329
  query["exclude_log_types"] = exclude_log_types
@@ -355,7 +340,6 @@ class DataLoggerApiSdk:
355
340
  start_at: datetime,
356
341
  end_at: datetime | None = None,
357
342
  ) -> ApiBaseStationDeviceLogsStatResponse:
358
- """GET /base-stations/<uuid>/device-logs-stat — число логов устройств БС по дням."""
359
343
  query: Dict[str, Any] = {"start_at": start_at.isoformat()}
360
344
  if end_at is not None:
361
345
  query["end_at"] = end_at.isoformat()
@@ -372,7 +356,6 @@ class DataLoggerApiSdk:
372
356
  start_at: datetime,
373
357
  end_at: datetime | None = None,
374
358
  ) -> ApiBaseStationLogsStatForIntervalsResponse:
375
- """GET /base-stations/<uuid>/logs-stat-for-intervals — метки времени логов за интервал."""
376
359
  query: Dict[str, Any] = {"start_at": start_at.isoformat()}
377
360
  if end_at is not None:
378
361
  query["end_at"] = end_at.isoformat()
@@ -391,7 +374,6 @@ class DataLoggerApiSdk:
391
374
  limit: int = 100,
392
375
  offset: int = 0,
393
376
  ) -> ApiBaseStationDevicesResponse:
394
- """GET /base-stations/<uuid>/devices — устройства, работающие через базовую станцию."""
395
377
  query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
396
378
  if end_at is not None:
397
379
  query["end_at"] = end_at.isoformat()
@@ -410,7 +392,6 @@ class DataLoggerApiSdk:
410
392
  limit: int = 100,
411
393
  offset: int = 0,
412
394
  ) -> ApiBaseStationDeviceLogsResponse:
413
- """GET /base-stations/<uuid>/device-logs — логи устройств базовой станции."""
414
395
  query: Dict[str, Any] = {"start_at": start_at.isoformat(), "limit": limit, "offset": offset}
415
396
  if end_at is not None:
416
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.4"
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
@@ -1,4 +1,4 @@
1
- from typing import List, NamedTuple
1
+ from typing import List, NamedTuple, Optional
2
2
 
3
3
  from pydantic import UUID4
4
4
  from ul_api_utils.api_resource.api_response import JsonApiResponsePayload
@@ -15,11 +15,16 @@ class ApiBsDeviceLinkResponse(JsonApiResponsePayload):
15
15
 
16
16
  device_network_mac: int
17
17
  bs_id: UUID4
18
+ device_id: UUID4
18
19
  bs_identifier: str
19
20
 
20
21
 
21
22
  class ApiBsDeviceLinksListResult(NamedTuple):
22
- """Результат спискового вызова: страница элементов и total_count."""
23
+ """Результат спискового вызова: страница элементов и total_count.
24
+
25
+ total_count приходит только на первой странице (без курсора); дальше —
26
+ None, обход идёт до пустой страницы.
27
+ """
23
28
 
24
29
  items: List[ApiBsDeviceLinkResponse]
25
- total_count: int
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