pypetkitapi 1.16.7__tar.gz → 1.18.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pypetkitapi
3
- Version: 1.16.7
3
+ Version: 1.18.0
4
4
  Summary: Python client for PetKit API
5
5
  License: MIT
6
6
  Author: Jezza34000
@@ -51,7 +51,7 @@ from .media import DownloadDecryptMedia, MediaCloud, MediaFile, MediaManager
51
51
  from .purifier_container import Purifier
52
52
  from .water_fountain_container import WaterFountain
53
53
 
54
- __version__ = "1.16.7"
54
+ __version__ = "1.18.0"
55
55
 
56
56
  __all__ = [
57
57
  "CTW3",
@@ -81,7 +81,7 @@ class Header(StrEnum):
81
81
  ACCEPT = "*/*"
82
82
  ACCEPT_LANG = "en-US;q=1, it-US;q=0.9"
83
83
  ENCODING = "gzip, deflate"
84
- API_VERSION = "12.1.0"
84
+ API_VERSION = "12.4.1"
85
85
  CONTENT_TYPE = "application/x-www-form-urlencoded"
86
86
  AGENT = "okhttp/3.12.11"
87
87
  CLIENT = f"{Client.PLATFORM_TYPE}({Client.OS_VERSION};{Client.MODEL_NAME})"
@@ -126,6 +126,9 @@ class RecordType(StrEnum):
126
126
  MOVE = "move"
127
127
  PET = "pet"
128
128
  TOILETING = "toileting"
129
+ WASTE = "waste_check"
130
+ DISH_BEFORE = "dish_before"
131
+ DISH_AFTER = "dish_after"
129
132
 
130
133
 
131
134
  RecordTypeLST = [
@@ -134,6 +137,9 @@ RecordTypeLST = [
134
137
  RecordType.MOVE,
135
138
  RecordType.PET,
136
139
  RecordType.TOILETING,
140
+ RecordType.WASTE,
141
+ RecordType.DISH_BEFORE,
142
+ RecordType.DISH_AFTER,
137
143
  ]
138
144
 
139
145
 
@@ -81,6 +81,7 @@ class SettingsLitter(BaseModel):
81
81
  pet_detection: int | None = Field(None, alias="petDetection")
82
82
  pet_in_notify: int | None = Field(None, alias="petInNotify")
83
83
  pet_notify: int | None = Field(None, alias="petNotify")
84
+ ph_detection: int | None = Field(None, alias="phDetection")
84
85
  pre_live: int | None = Field(None, alias="preLive")
85
86
  relate_k3_switch: int | None = Field(None, alias="relateK3Switch")
86
87
  sand_saving: int | None = Field(None, alias="sandSaving")
@@ -92,6 +93,7 @@ class SettingsLitter(BaseModel):
92
93
  system_sound_enable: int | None = Field(None, alias="systemSoundEnable")
93
94
  time_display: int | None = Field(None, alias="timeDisplay")
94
95
  toilet_detection: int | None = Field(None, alias="toiletDetection")
96
+ toilet_light: int | None = Field(None, alias="toiletLight")
95
97
  toilet_notify: int | None = Field(None, alias="toiletNotify")
96
98
  tone_config: int | None = Field(None, alias="toneConfig")
97
99
  tone_mode: int | None = Field(None, alias="toneMode")
@@ -100,6 +102,7 @@ class SettingsLitter(BaseModel):
100
102
  underweight: int | None = Field(None, alias="underweight")
101
103
  unit: int | None = None
102
104
  upload: int | None = None
105
+ voice: int | None = None
103
106
  volume: int | None = None
104
107
  wander_detection: int | None = Field(None, alias="wanderDetection")
105
108
  weight_popup: int | None = Field(None, alias="weightPopup")
@@ -189,6 +192,7 @@ class ContentSC(BaseModel):
189
192
  litter_percent: int | None = Field(None, alias="litterPercent")
190
193
  mark: int | None = None
191
194
  media: int | None = None
195
+ ph_reason: int | None = Field(None, alias="phReason")
192
196
  result: int | None = None
193
197
  start_reason: int | None = Field(None, alias="startReason")
194
198
  start_time: int | None = Field(None, alias="startTime")
@@ -217,9 +221,20 @@ class LRContent(BaseModel):
217
221
  error: int | None = None
218
222
 
219
223
 
224
+ class ShitPictures(BaseModel):
225
+ """Dataclass for sub-content of LitterRecord.
226
+ LitterRecord -> ShitPictures
227
+ """
228
+
229
+ created_at: str | int | None = Field(None, alias="createdAt")
230
+ pic_id: str | None = Field(None, alias="picId")
231
+ shit_aes_key: str | None = Field(None, alias="shitAesKey")
232
+ shit_picture: str | None = Field(None, alias="shitPicture")
233
+
234
+
220
235
  class LRSubContent(BaseModel):
221
236
  """Subclass of LitterRecord.
222
- LitterRecord -> subContent
237
+ LitterRecord -> List[subContent]
223
238
  """
224
239
 
225
240
  aes_key: str | None = Field(None, alias="aesKey")
@@ -236,7 +251,7 @@ class LRSubContent(BaseModel):
236
251
  preview: str | None = None
237
252
  related_event: str | None = Field(None, alias="relatedEvent")
238
253
  shit_aes_key: str | None = Field(None, alias="shitAesKey")
239
- shit_picture: str | None = Field(None, alias="shitPicture")
254
+ shit_pictures: list[ShitPictures] | None = Field(None, alias="shitPictures")
240
255
  storage_space: int | None = Field(None, alias="storageSpace")
241
256
  sub_content: list[Any] | None = Field(None, alias="subContent")
242
257
  timestamp: int | None = None
@@ -244,16 +259,6 @@ class LRSubContent(BaseModel):
244
259
  user_id: str | None = Field(None, alias="userId")
245
260
 
246
261
 
247
- class ShitPictures(BaseModel):
248
- """Dataclass for sub-content of LitterRecord.
249
- LitterRecord -> ShitPictures
250
- """
251
-
252
- pic_id: str | None = Field(None, alias="picId")
253
- shit_aes_key: str | None = Field(None, alias="shitAesKey")
254
- shit_picture: str | None = Field(None, alias="shitPicture")
255
-
256
-
257
262
  class LitterRecord(BaseModel):
258
263
  """Dataclass for feeder record data.
259
264
  Litter records (Main class)
@@ -278,7 +283,7 @@ class LitterRecord(BaseModel):
278
283
  pet_name: str | None = Field(None, alias="petName")
279
284
  preview: str | None = None
280
285
  related_event: str | None = Field(None, alias="relatedEvent")
281
- shit_pictures: ShitPictures | None = None
286
+ shit_pictures: list[ShitPictures] | None = Field(None, alias="shitPictures")
282
287
  storage_space: int | None = Field(None, alias="storageSpace")
283
288
  sub_content: list[LRSubContent] | None = Field(None, alias="subContent")
284
289
  timestamp: int | None = None
@@ -345,7 +345,7 @@ class MediaManager:
345
345
  continue
346
346
 
347
347
  date_str = await self.get_date_from_ts(timestamp)
348
- filepath = f"{feeder_id}/{date_str}/{record_type.name.lower()}"
348
+ filepath = f"{feeder_id}/{date_str}"
349
349
  media_files.append(
350
350
  MediaCloud(
351
351
  event_id=item.event_id,
@@ -356,11 +356,44 @@ class MediaManager:
356
356
  video=await self.construct_video_url(
357
357
  device_type, item, user_id, cp_sub
358
358
  ),
359
- filepath=filepath,
359
+ filepath=f"{filepath}/{record_type.name.lower()}",
360
360
  aes_key=item.aes_key,
361
361
  timestamp=timestamp,
362
362
  )
363
363
  )
364
+
365
+ # Gather the dish before and after images for EAT records
366
+ if record_type == RecordType.EAT:
367
+ if hasattr(item, "preview1") and item.preview1:
368
+ # Preview1 is dish before image
369
+ media_files.append(
370
+ MediaCloud(
371
+ event_id=item.event_id,
372
+ event_type=RecordType.DISH_BEFORE,
373
+ device_id=feeder_id,
374
+ user_id=user_id,
375
+ image=item.preview1,
376
+ video=None,
377
+ filepath=f"{filepath}/{RecordType.DISH_BEFORE.name.lower()}",
378
+ aes_key=item.aes_key,
379
+ timestamp=timestamp,
380
+ )
381
+ )
382
+ if hasattr(item, "preview2") and item.preview2:
383
+ # Preview2 is dish after image
384
+ media_files.append(
385
+ MediaCloud(
386
+ event_id=item.event_id,
387
+ event_type=RecordType.DISH_AFTER,
388
+ device_id=feeder_id,
389
+ user_id=user_id,
390
+ image=item.preview2,
391
+ video=None,
392
+ filepath=f"{filepath}/{RecordType.DISH_AFTER.name.lower()}",
393
+ aes_key=item.aes_key,
394
+ timestamp=timestamp,
395
+ )
396
+ )
364
397
  return media_files
365
398
 
366
399
  async def _process_litter(self, litter: Litter) -> list[MediaCloud]:
@@ -399,11 +432,16 @@ class MediaManager:
399
432
  timestamp = record.timestamp or None
400
433
  date_str = await self.get_date_from_ts(timestamp)
401
434
 
402
- filepath = f"{litter_id}/{date_str}/toileting"
435
+ if getattr(record, "enum_event_type", None) == "pet_detect":
436
+ event_type = RecordType.PET
437
+ else:
438
+ event_type = RecordType.TOILETING
439
+
440
+ filepath = f"{litter_id}/{date_str}/{event_type.name.lower()}"
403
441
  media_files.append(
404
442
  MediaCloud(
405
443
  event_id=record.event_id,
406
- event_type=RecordType.TOILETING,
444
+ event_type=event_type,
407
445
  device_id=litter_id,
408
446
  user_id=user_id,
409
447
  image=record.preview,
@@ -415,6 +453,35 @@ class MediaManager:
415
453
  timestamp=record.timestamp,
416
454
  )
417
455
  )
456
+
457
+ # Gather Waste images if available
458
+ if hasattr(record, "sub_content") and record.sub_content:
459
+ for sub_record in record.sub_content:
460
+ if (
461
+ hasattr(sub_record, "shit_pictures")
462
+ and isinstance(sub_record.shit_pictures, list)
463
+ and len(sub_record.shit_pictures) > 2
464
+ ):
465
+ waste_image_data = sub_record.shit_pictures[2]
466
+ if (
467
+ waste_image_data.shit_picture
468
+ and waste_image_data.shit_aes_key
469
+ ):
470
+ waste_filepath = f"{litter_id}/{date_str}/{RecordType.WASTE.name.lower()}"
471
+ media_files.append(
472
+ MediaCloud(
473
+ event_id=record.event_id,
474
+ event_type=RecordType.WASTE,
475
+ device_id=litter_id,
476
+ user_id=user_id,
477
+ image=waste_image_data.shit_picture,
478
+ video=None,
479
+ filepath=waste_filepath,
480
+ aes_key=waste_image_data.shit_aes_key,
481
+ timestamp=record.timestamp,
482
+ )
483
+ )
484
+
418
485
  return media_files
419
486
 
420
487
  @staticmethod
@@ -187,7 +187,7 @@ build-backend = "poetry.core.masonry.api"
187
187
 
188
188
  [tool.poetry]
189
189
  name = "pypetkitapi"
190
- version = "1.16.7"
190
+ version = "1.18.0"
191
191
  description = "Python client for PetKit API"
192
192
  authors = ["Jezza34000 <info@mail.com>"]
193
193
  readme = "README.md"
@@ -209,7 +209,7 @@ ruff = "^0.8.1"
209
209
  types-aiofiles = "^24.1.0.20240626"
210
210
 
211
211
  [tool.bumpver]
212
- current_version = "1.16.7"
212
+ current_version = "1.18.0"
213
213
  version_pattern = "MAJOR.MINOR.PATCH"
214
214
  commit_message = "bump version {old_version} -> {new_version}"
215
215
  tag_message = "{new_version}"
File without changes
File without changes