pypetkitapi 1.11.0__py3-none-any.whl → 1.11.2__py3-none-any.whl
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.
- pypetkitapi/__init__.py +1 -1
- pypetkitapi/media.py +19 -15
- {pypetkitapi-1.11.0.dist-info → pypetkitapi-1.11.2.dist-info}/METADATA +12 -10
- {pypetkitapi-1.11.0.dist-info → pypetkitapi-1.11.2.dist-info}/RECORD +6 -6
- {pypetkitapi-1.11.0.dist-info → pypetkitapi-1.11.2.dist-info}/LICENSE +0 -0
- {pypetkitapi-1.11.0.dist-info → pypetkitapi-1.11.2.dist-info}/WHEEL +0 -0
pypetkitapi/__init__.py
CHANGED
pypetkitapi/media.py
CHANGED
@@ -18,13 +18,14 @@ import aiohttp
|
|
18
18
|
from Crypto.Cipher import AES
|
19
19
|
from Crypto.Util.Padding import unpad
|
20
20
|
|
21
|
-
from pypetkitapi import Feeder, Litter, PetKitClient, RecordType
|
21
|
+
from pypetkitapi import Feeder, Litter, PetKitClient, RecordsItems, RecordType
|
22
22
|
from pypetkitapi.const import (
|
23
23
|
FEEDER_WITH_CAMERA,
|
24
24
|
LITTER_WITH_CAMERA,
|
25
25
|
MediaType,
|
26
26
|
RecordTypeLST,
|
27
27
|
)
|
28
|
+
from pypetkitapi.litter_container import LitterRecord
|
28
29
|
|
29
30
|
_LOGGER = logging.getLogger(__name__)
|
30
31
|
|
@@ -274,16 +275,19 @@ class MediaManager:
|
|
274
275
|
)
|
275
276
|
|
276
277
|
if not feeder_id:
|
277
|
-
_LOGGER.
|
278
|
+
_LOGGER.warning("Missing feeder_id for record")
|
278
279
|
return media_files
|
279
280
|
|
280
281
|
if not record.items:
|
281
282
|
return media_files
|
282
283
|
|
283
284
|
for item in record.items:
|
285
|
+
if not isinstance(item, RecordsItems):
|
286
|
+
_LOGGER.debug("Record is empty")
|
287
|
+
continue
|
284
288
|
timestamp = await self._get_timestamp(item)
|
285
289
|
if timestamp is None:
|
286
|
-
_LOGGER.
|
290
|
+
_LOGGER.warning("Missing timestamp for record item")
|
287
291
|
continue
|
288
292
|
if not item.event_id:
|
289
293
|
# Skip feed event in the future
|
@@ -292,10 +296,10 @@ class MediaManager:
|
|
292
296
|
)
|
293
297
|
continue
|
294
298
|
if not user_id:
|
295
|
-
_LOGGER.
|
299
|
+
_LOGGER.warning("Missing user_id for record item")
|
296
300
|
continue
|
297
301
|
if not item.aes_key:
|
298
|
-
_LOGGER.
|
302
|
+
_LOGGER.warning("Missing aes_key for record item")
|
299
303
|
continue
|
300
304
|
|
301
305
|
date_str = await self.get_date_from_ts(timestamp)
|
@@ -330,21 +334,24 @@ class MediaManager:
|
|
330
334
|
cp_sub = litter.cloud_product.subscribe if litter.cloud_product else None
|
331
335
|
|
332
336
|
if not litter_id:
|
333
|
-
_LOGGER.
|
337
|
+
_LOGGER.warning("Missing litter_id for record")
|
334
338
|
return media_files
|
335
339
|
|
336
340
|
if not device_type:
|
337
|
-
_LOGGER.
|
341
|
+
_LOGGER.warning("Missing device_type for record")
|
338
342
|
return media_files
|
339
343
|
|
340
344
|
if not user_id:
|
341
|
-
_LOGGER.
|
345
|
+
_LOGGER.warning("Missing user_id for record")
|
342
346
|
return media_files
|
343
347
|
|
344
348
|
if not records:
|
345
349
|
return media_files
|
346
350
|
|
347
351
|
for record in records:
|
352
|
+
if not isinstance(record, LitterRecord):
|
353
|
+
_LOGGER.debug("Record is empty")
|
354
|
+
continue
|
348
355
|
if not record.event_id:
|
349
356
|
_LOGGER.debug("Missing event_id for record item")
|
350
357
|
continue
|
@@ -404,12 +411,12 @@ class MediaManager:
|
|
404
411
|
return f"/{device_type}/cloud/video?startTime={param_dict.get("startTime")}&deviceId={param_dict.get("deviceId")}&userId={user_id}&mark={param_dict.get("mark")}"
|
405
412
|
|
406
413
|
@staticmethod
|
407
|
-
async def _get_timestamp(item) -> int:
|
414
|
+
async def _get_timestamp(item) -> int | None:
|
408
415
|
"""Extract timestamp from a record item and raise an exception if it is None.
|
409
416
|
:param item: Record item
|
410
417
|
:return: Timestamp
|
411
418
|
"""
|
412
|
-
|
419
|
+
return (
|
413
420
|
item.timestamp
|
414
421
|
or item.completed_at
|
415
422
|
or item.eat_start_time
|
@@ -419,9 +426,6 @@ class MediaManager:
|
|
419
426
|
or item.time
|
420
427
|
or None
|
421
428
|
)
|
422
|
-
if timestamp is None:
|
423
|
-
raise ValueError("Can't find timestamp in record item")
|
424
|
-
return timestamp
|
425
429
|
|
426
430
|
|
427
431
|
class DownloadDecryptMedia:
|
@@ -515,7 +519,7 @@ class DownloadDecryptMedia:
|
|
515
519
|
]
|
516
520
|
|
517
521
|
if not segment_files:
|
518
|
-
_LOGGER.
|
522
|
+
_LOGGER.warning("No segment files found")
|
519
523
|
elif len(segment_files) == 1:
|
520
524
|
_LOGGER.debug("Single file segment, no need to concatenate")
|
521
525
|
elif len(segment_files) > 1:
|
@@ -535,7 +539,7 @@ class DownloadDecryptMedia:
|
|
535
539
|
|
536
540
|
media_api = video_data.get("mediaApi", None)
|
537
541
|
if not media_api:
|
538
|
-
_LOGGER.
|
542
|
+
_LOGGER.warning("Missing mediaApi in video data")
|
539
543
|
raise ValueError("Missing mediaApi in video data")
|
540
544
|
return await self.client.extract_segments_m3u8(str(media_api))
|
541
545
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: pypetkitapi
|
3
|
-
Version: 1.11.
|
3
|
+
Version: 1.11.2
|
4
4
|
Summary: Python client for PetKit API
|
5
5
|
License: MIT
|
6
6
|
Author: Jezza34000
|
@@ -77,7 +77,7 @@ import asyncio
|
|
77
77
|
import logging
|
78
78
|
import aiohttp
|
79
79
|
from pypetkitapi.client import PetKitClient
|
80
|
-
from pypetkitapi.command import DeviceCommand, FeederCommand, LBCommand,
|
80
|
+
from pypetkitapi.command import DeviceCommand, FeederCommand, LBCommand, DeviceAction, LitterCommand
|
81
81
|
|
82
82
|
logging.basicConfig(level=logging.DEBUG)
|
83
83
|
|
@@ -86,8 +86,8 @@ async def main():
|
|
86
86
|
client = PetKitClient(
|
87
87
|
username="username", # Your PetKit account username or id
|
88
88
|
password="password", # Your PetKit account password
|
89
|
-
region="FR", # Your region or country code (e.g. FR, US, etc.)
|
90
|
-
timezone="Europe/Paris", # Your timezone
|
89
|
+
region="FR", # Your region or country code (e.g. FR, US,CN etc.)
|
90
|
+
timezone="Europe/Paris", # Your timezone(e.g. "Asia/Shanghai")
|
91
91
|
session=session,
|
92
92
|
)
|
93
93
|
|
@@ -98,26 +98,28 @@ async def main():
|
|
98
98
|
for key, value in client.petkit_entities.items():
|
99
99
|
print(f"{key}: {type(value).__name__} - {value.name}")
|
100
100
|
|
101
|
+
# Select a device
|
102
|
+
device_id = key
|
101
103
|
# Read devices or pet information
|
102
|
-
print(client.petkit_entities[
|
104
|
+
print(client.petkit_entities[device_id])
|
103
105
|
|
104
106
|
# Send command to the devices
|
105
107
|
### Example 1 : Turn on the indicator light
|
106
108
|
### Device_ID, Command, Payload
|
107
|
-
await client.send_api_request(
|
109
|
+
await client.send_api_request(device_id, DeviceCommand.UPDATE_SETTING, {"lightMode": 1})
|
108
110
|
|
109
111
|
### Example 2 : Feed the pet
|
110
112
|
### Device_ID, Command, Payload
|
111
113
|
# simple hopper :
|
112
|
-
await client.send_api_request(
|
114
|
+
await client.send_api_request(device_id, FeederCommand.MANUAL_FEED, {"amount": 1})
|
113
115
|
# dual hopper :
|
114
|
-
await client.send_api_request(
|
116
|
+
await client.send_api_request(device_id, FeederCommand.MANUAL_FEED, {"amount1": 2})
|
115
117
|
# or
|
116
|
-
await client.send_api_request(
|
118
|
+
await client.send_api_request(device_id, FeederCommand.MANUAL_FEED, {"amount2": 2})
|
117
119
|
|
118
120
|
### Example 3 : Start the cleaning process
|
119
121
|
### Device_ID, Command, Payload
|
120
|
-
await client.send_api_request(
|
122
|
+
await client.send_api_request(device_id, LitterCommand.CONTROL_DEVICE, {DeviceAction.START: LBCommand.CLEANING})
|
121
123
|
|
122
124
|
|
123
125
|
if __name__ == "__main__":
|
@@ -1,4 +1,4 @@
|
|
1
|
-
pypetkitapi/__init__.py,sha256=
|
1
|
+
pypetkitapi/__init__.py,sha256=qDhET_P65lnwbZgZnkYst3IgJxPlID7fLqYnfVSzJqM,2107
|
2
2
|
pypetkitapi/bluetooth.py,sha256=eu6c2h6YHBafAhhSSy4As6tn29i5WbOH9tZzRlMm44U,7843
|
3
3
|
pypetkitapi/client.py,sha256=wzZQUHg_ee6lmdAjli6zS7qw_sgPER9iLfcTZe4VTH4,27190
|
4
4
|
pypetkitapi/command.py,sha256=cMCUutZCQo9Ddvjl_FYR5UjU_CqFz1iyetMznYwjpzM,7500
|
@@ -7,13 +7,13 @@ pypetkitapi/containers.py,sha256=F_uyDBD0a5QD4s_ArjYiKTAAg1XHYBvmV_lEnO9RQ-U,478
|
|
7
7
|
pypetkitapi/exceptions.py,sha256=4BXUyYXLfZjNxdnOGJPjyE9ASIl7JmQphjws87jvHtE,1631
|
8
8
|
pypetkitapi/feeder_container.py,sha256=PhidWd5WpsZqtdKZy60PzE67YXgQfApjm8CqvMCHK3U,14743
|
9
9
|
pypetkitapi/litter_container.py,sha256=KWvHNAOJ6hDSeJ_55tqtzY9GxHtd9gAntPkbnVbdb-I,19275
|
10
|
-
pypetkitapi/media.py,sha256=
|
10
|
+
pypetkitapi/media.py,sha256=34q3pIfejO_z-Uk8ohQlOGaPOdaGtnI0zN1LtZ3k3F4,25904
|
11
11
|
pypetkitapi/purifier_container.py,sha256=ssyIxhNben5XJ4KlQTXTrtULg2ji6DqHqjzOq08d1-I,2491
|
12
12
|
pypetkitapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
pypetkitapi/schedule_container.py,sha256=OjLAY6FY-g14JNJJnYMNFV5ZtdkjUzNBit1VUiiZKnQ,2053
|
14
14
|
pypetkitapi/utils.py,sha256=z7325kcJQUburnF28HSXrJMvY_gY9007K73Zwxp-4DQ,743
|
15
15
|
pypetkitapi/water_fountain_container.py,sha256=5J0b-fDZYcFLNX2El7fifv8H6JMhBCt-ttxSow1ozRQ,6787
|
16
|
-
pypetkitapi-1.11.
|
17
|
-
pypetkitapi-1.11.
|
18
|
-
pypetkitapi-1.11.
|
19
|
-
pypetkitapi-1.11.
|
16
|
+
pypetkitapi-1.11.2.dist-info/LICENSE,sha256=u5jNkZEn6YMrtN4Kr5rU3TcBJ5-eAt0qMx4JDsbsnzM,1074
|
17
|
+
pypetkitapi-1.11.2.dist-info/METADATA,sha256=8HbQJ6UeGion-oO5Y5U0X7THfeDRYeP-EK-XVwF_Lb8,6338
|
18
|
+
pypetkitapi-1.11.2.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
19
|
+
pypetkitapi-1.11.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|