pypetkitapi 1.12.6__py3-none-any.whl → 1.15.0__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 CHANGED
@@ -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.12.6"
54
+ __version__ = "1.15.0"
55
55
 
56
56
  __all__ = [
57
57
  "CTW3",
pypetkitapi/client.py CHANGED
@@ -38,7 +38,14 @@ from pypetkitapi.const import (
38
38
  PetkitDomain,
39
39
  PetkitEndpoint,
40
40
  )
41
- from pypetkitapi.containers import AccountData, Device, Pet, RegionInfo, SessionInfo
41
+ from pypetkitapi.containers import (
42
+ AccountData,
43
+ Device,
44
+ Pet,
45
+ PetDetails,
46
+ RegionInfo,
47
+ SessionInfo,
48
+ )
42
49
  from pypetkitapi.exceptions import (
43
50
  PetkitAuthenticationError,
44
51
  PetkitAuthenticationUnregisteredEmailError,
@@ -227,6 +234,18 @@ class PetKitClient:
227
234
  raise PetkitSessionError("No session ID available")
228
235
  return {"F-Session": self._session.id, "X-Session": self._session.id}
229
236
 
237
+ async def _get_pet_details(self) -> list[PetDetails]:
238
+ """Fetch pet details from the PetKit API."""
239
+ _LOGGER.debug("Fetching user details")
240
+ response = await self.req.request(
241
+ method=HTTPMethod.GET,
242
+ url=PetkitEndpoint.DETAILS,
243
+ headers=await self.get_session_id(),
244
+ )
245
+ user_details = response.get("user", {})
246
+ dogs = user_details.get("dogs", [])
247
+ return [PetDetails(**dog) for dog in dogs]
248
+
230
249
  async def _get_account_data(self) -> None:
231
250
  """Get the account data from the PetKit service."""
232
251
  _LOGGER.debug("Fetching account data")
@@ -253,6 +272,13 @@ class PetKitClient:
253
272
  uniqueId=str(pet.sn),
254
273
  )
255
274
 
275
+ # Fetch pet details and update pet information
276
+ pet_details_list = await self._get_pet_details()
277
+ for pet_details in pet_details_list:
278
+ pet_id = pet_details.id
279
+ if pet_id in self.petkit_entities:
280
+ self.petkit_entities[pet_id].pet_details = pet_details
281
+
256
282
  async def get_devices_data(self) -> None:
257
283
  """Get the devices data from the PetKit servers."""
258
284
  start_time = datetime.now()
pypetkitapi/command.py CHANGED
@@ -98,7 +98,7 @@ class DeviceAction(StrEnum):
98
98
  END = "end_action"
99
99
  START = "start_action"
100
100
  STOP = "stop_action"
101
- # Purifier only
101
+ # Purifier K2 only
102
102
  MODE = "mode_action"
103
103
  # All devices
104
104
  POWER = "power_action"
@@ -159,8 +159,8 @@ def get_endpoint_reset_desiccant(device):
159
159
 
160
160
  def get_endpoint_update_setting(device):
161
161
  """Get the endpoint for the device"""
162
- if device.device_nfo.device_type == FEEDER_MINI:
163
- return PetkitEndpoint.UPDATE_SETTING_FEEDER_MINI
162
+ if device.device_nfo.device_type in [FEEDER_MINI, K3]:
163
+ return PetkitEndpoint.UPDATE_SETTING_OLD
164
164
  return PetkitEndpoint.UPDATE_SETTING
165
165
 
166
166
 
pypetkitapi/const.py CHANGED
@@ -46,7 +46,7 @@ DEVICES_FEEDER = [FEEDER, FEEDER_MINI, D3, D4, D4S, D4H, D4SH]
46
46
  # Water Fountain
47
47
  DEVICES_WATER_FOUNTAIN = [W4, W5, CTW2, CTW3]
48
48
  # Purifier
49
- DEVICES_PURIFIER = [K2]
49
+ DEVICES_PURIFIER = [K2, K3]
50
50
  # All devices
51
51
  ALL_DEVICES = [
52
52
  *DEVICES_LITTER_BOX,
@@ -78,7 +78,7 @@ class Header(StrEnum):
78
78
  ACCEPT = "*/*"
79
79
  ACCEPT_LANG = "en-US;q=1, it-US;q=0.9"
80
80
  ENCODING = "gzip, deflate"
81
- API_VERSION = "12.0.2"
81
+ API_VERSION = "12.1.0"
82
82
  CONTENT_TYPE = "application/x-www-form-urlencoded"
83
83
  AGENT = "okhttp/3.12.11"
84
84
  CLIENT = f"{Client.PLATFORM_TYPE}({Client.OS_VERSION};{Client.MODEL_NAME})"
@@ -152,7 +152,7 @@ class PetkitEndpoint(StrEnum):
152
152
  GET_DEVICE_RECORD = "getDeviceRecord"
153
153
  GET_DEVICE_RECORD_RELEASE = "getDeviceRecordRelease"
154
154
  UPDATE_SETTING = "updateSettings"
155
- UPDATE_SETTING_FEEDER_MINI = "update"
155
+ UPDATE_SETTING_OLD = "update"
156
156
 
157
157
  # Bluetooth
158
158
  BLE_AS_RELAY = "ble/ownSupportBleDevices"
pypetkitapi/containers.py CHANGED
@@ -1,5 +1,7 @@
1
1
  """Dataclasses container for petkit API."""
2
2
 
3
+ from typing import Any
4
+
3
5
  from pydantic import BaseModel, Field, field_validator
4
6
 
5
7
 
@@ -68,6 +70,40 @@ class Device(BaseModel):
68
70
  return value
69
71
 
70
72
 
73
+ class PetDetails(BaseModel):
74
+ """Dataclass for pet details.
75
+ Subclass of Pet.
76
+ """
77
+
78
+ active_degree: int | None = Field(None, alias="activeDegree")
79
+ avatar: str | None = None
80
+ birth: str | None = None
81
+ block_time: int | None = Field(None, alias="blockTime")
82
+ blocke: int | None = None
83
+ body_info: dict[str, Any] | None = Field(None, alias="bodyInfo")
84
+ category: dict[str, Any]
85
+ created_at: str | None = Field(None, alias="createdAt")
86
+ device_count: int | None = Field(None, alias="deviceCount")
87
+ emotion: int | None = None
88
+ family_id: int | None = Field(None, alias="familyId")
89
+ female_state: int | None = Field(None, alias="femaleState")
90
+ gender: int | None = None
91
+ id: int | None = None
92
+ is_royal_canin_pet: int | None = Field(None, alias="isRoyalCaninPet")
93
+ male_state: int | None = Field(None, alias="maleState")
94
+ name: str | None = None
95
+ oms_discern_pic: dict[str, Any] | None = Field(None, alias="omsDiscernPic")
96
+ owner: dict[str, Any] | None = None
97
+ size: dict[str, Any] | None = None
98
+ states: list[Any] | None = None
99
+ type: dict[str, Any] | None = None
100
+ updated_at: str | None = Field(None, alias="updatedAt")
101
+ weight: float | None = None
102
+ weight_control: int | None = Field(None, alias="weightControl")
103
+ weight_control_tips: dict[str, Any] | None = Field(None, alias="weightControlTips")
104
+ weight_label: str | None = Field(None, alias="weightLabel")
105
+
106
+
71
107
  class Pet(BaseModel):
72
108
  """Dataclass for pet data.
73
109
  Subclass of AccountData.
@@ -81,7 +117,8 @@ class Pet(BaseModel):
81
117
  sn: str | None = None # Fictive field copied from id (for HA compatibility)
82
118
  name: str | None = None # Fictive field copied from pet_name (for HA compatibility)
83
119
  firmware: str | None = None # Fictive fixed field (for HA compatibility)
84
- device_nfo: Device | None = None # Device is now optional
120
+ device_nfo: Device | None = None
121
+ pet_details: PetDetails | None = None
85
122
 
86
123
  # Litter stats
87
124
  last_litter_usage: int | None = None
@@ -21,6 +21,7 @@ from pypetkitapi.containers import (
21
21
  UserDevice,
22
22
  Wifi,
23
23
  )
24
+ from pypetkitapi.purifier_container import Purifier
24
25
 
25
26
 
26
27
  class SettingsLitter(BaseModel):
@@ -386,31 +387,6 @@ class PetOutGraph(BaseModel):
386
387
  }
387
388
 
388
389
 
389
- class K3Device(BaseModel):
390
- """Dataclass for K3 device data."""
391
-
392
- battery: int | None = None
393
- created_at: datetime | None = Field(None, alias="createdAt")
394
- firmware: int | None = None
395
- hardware: int | None = None
396
- id: int | None = None
397
- lighting: int | None = None
398
- liquid: int | None = None
399
- liquid_lack: int | None = Field(None, alias="liquidLack")
400
- mac: str | None = None
401
- name: str | None = None
402
- refreshing: int | None = None
403
- relate_t4: int | None = Field(None, alias="relateT4")
404
- relation: dict | None = None
405
- secret: str | None = None
406
- settings: dict | None = None
407
- sn: str | None = None
408
- timezone: float | None = None
409
- update_at: datetime | None = Field(None, alias="updateAt")
410
- user_id: str | None = Field(None, alias="userId")
411
- voltage: int | None = None
412
-
413
-
414
390
  class Litter(BaseModel):
415
391
  """Dataclass for Litter Data.
416
392
  Supported devices = T3, T4, T5, T6
@@ -425,7 +401,7 @@ class Litter(BaseModel):
425
401
  firmware_details: list[FirmwareDetail] = Field(alias="firmwareDetails")
426
402
  hardware: int
427
403
  id: int
428
- k3_device: K3Device | None = Field(None, alias="k3Device")
404
+ k3_device: Purifier | None = Field(None, alias="k3Device")
429
405
  is_pet_out_tips: int | None = Field(None, alias="isPetOutTips")
430
406
  locale: str | None = None
431
407
  mac: str | None = None
@@ -4,7 +4,7 @@ from typing import Any, ClassVar
4
4
 
5
5
  from pydantic import BaseModel, Field
6
6
 
7
- from pypetkitapi.const import DEVICE_DATA, PetkitEndpoint
7
+ from pypetkitapi.const import DEVICE_DATA, K3, PetkitEndpoint
8
8
  from pypetkitapi.containers import Device, FirmwareDetail, Wifi
9
9
 
10
10
 
@@ -12,9 +12,11 @@ class Settings(BaseModel):
12
12
  """Dataclass for settings data."""
13
13
 
14
14
  auto_work: int | None = Field(None, alias="autoWork")
15
+ fixed_time_refresh: int | None = Field(None, alias="fixedTimeRefresh")
15
16
  lack_notify: int | None = Field(None, alias="lackNotify")
16
17
  light_mode: int | None = Field(None, alias="lightMode")
17
18
  light_range: list[int] | None = Field(None, alias="lightRange")
19
+ liquid_lack_switch: int | None = Field(None, alias="liquidLackSwitch")
18
20
  log_notify: int | None = Field(None, alias="logNotify")
19
21
  manual_lock: int | None = Field(None, alias="manualLock")
20
22
  sound: int | None = None
@@ -42,29 +44,41 @@ class Purifier(BaseModel):
42
44
 
43
45
  data_type: ClassVar[str] = DEVICE_DATA
44
46
 
47
+ battery: int | None = None
45
48
  bt_mac: str | None = Field(None, alias="btMac")
46
49
  created_at: str | None = Field(None, alias="createdAt")
47
- firmware: str | None = None
50
+ firmware: str | int | None = None
48
51
  firmware_details: list[FirmwareDetail] | None = Field(None, alias="firmwareDetails")
49
52
  hardware: int | None = None
50
53
  id: int | None = None
54
+ lighting: int | None = None
55
+ liquid: int | None = None
56
+ liquid_lack: int | None = Field(None, alias="liquidLack")
51
57
  locale: str | None = None
52
58
  mac: str | None = None
53
59
  name: str | None = None
60
+ refreshing: int | None = None
61
+ relate_t4: int | None = Field(None, alias="relateT4")
54
62
  relation: dict[str, str]
55
63
  secret: str | None = None
56
64
  settings: Settings | None = None
57
65
  share_open: int | None = Field(None, alias="shareOpen")
58
66
  signup_at: str | None = Field(None, alias="signupAt")
59
67
  sn: str | None = None
68
+ spray_times: int | None = Field(None, alias="sprayTimes")
60
69
  state: State | None = None
61
70
  timezone: float | None = None
71
+ update_at: str | None = Field(None, alias="updateAt")
72
+ user_id: str | None = Field(None, alias="userId")
73
+ voltage: int | None = None
62
74
  work_time: list[tuple[int, int]] | None = Field(None, alias="workTime")
63
75
  device_nfo: Device | None = None
64
76
 
65
77
  @classmethod
66
78
  def get_endpoint(cls, device_type: str) -> str:
67
79
  """Get the endpoint URL for the given device type."""
80
+ if device_type == K3:
81
+ return PetkitEndpoint.DEVICE_DATA
68
82
  return PetkitEndpoint.DEVICE_DETAIL
69
83
 
70
84
  @classmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pypetkitapi
3
- Version: 1.12.6
3
+ Version: 1.15.0
4
4
  Summary: Python client for PetKit API
5
5
  License: MIT
6
6
  Author: Jezza34000
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
23
23
 
24
24
  ---
25
25
 
26
- [![Lifecycle:Maturing](https://img.shields.io/badge/Lifecycle-Maturing-007EC6)](https://github.com/Jezza34000/py-petkit-api/)
26
+ [![Lifecycle:Maturing](https://img.shields.io/badge/Lifecycle-Stable-007EC6)](https://github.com/Jezza34000/py-petkit-api/)
27
27
  [![Python Version](https://img.shields.io/pypi/pyversions/pypetkitapi)][python version] [![Actions status](https://github.com/Jezza34000/py-petkit-api/workflows/CI/badge.svg)](https://github.com/Jezza34000/py-petkit-api/actions)
28
28
 
29
29
  [![PyPI](https://img.shields.io/pypi/v/pypetkitapi.svg)][pypi_] [![PyPI Downloads](https://static.pepy.tech/badge/pypetkitapi)](https://pepy.tech/projects/pypetkitapi)
@@ -0,0 +1,19 @@
1
+ pypetkitapi/__init__.py,sha256=sEgLSfzU-CM7h7-yfbyp_wr7WhyOl7Txz03Vh0VrDOE,2107
2
+ pypetkitapi/bluetooth.py,sha256=1zEZIrKNTttrZpqBiQ-6V37Uphft5_T8CH9OBfYjwxE,9915
3
+ pypetkitapi/client.py,sha256=cn3JIh-3AU5Rzka2rX7FgkSfWeQCG9Vw82-moK_rOPY,30889
4
+ pypetkitapi/command.py,sha256=sRLgV7bkG_kZAWf7Un_UNHL-OkJMH1GLD_RGgg9z8Mw,7515
5
+ pypetkitapi/const.py,sha256=aAUPBZC56MwbAiDRsSHRvDI5zTy-lZP8uLk-gHPeT7g,4763
6
+ pypetkitapi/containers.py,sha256=7wYKmaoBpMKrqIVMsoD4Iv2in7Kh5nNxrl4vC4eF2fg,6305
7
+ pypetkitapi/exceptions.py,sha256=4BXUyYXLfZjNxdnOGJPjyE9ASIl7JmQphjws87jvHtE,1631
8
+ pypetkitapi/feeder_container.py,sha256=PhidWd5WpsZqtdKZy60PzE67YXgQfApjm8CqvMCHK3U,14743
9
+ pypetkitapi/litter_container.py,sha256=R79wHFKy6pTsHIPf7bJko1PGFsdI-JCAPK4zPyliBmQ,18559
10
+ pypetkitapi/media.py,sha256=LNY3khU5eZN4i1MGHxJaPHcf3LA1fFaPVkn-wdn0YLI,27168
11
+ pypetkitapi/purifier_container.py,sha256=mAnvPF8Mm6YI43fitdxXEWScshM6sPg0KK6GXbylU1I,3179
12
+ pypetkitapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ pypetkitapi/schedule_container.py,sha256=ycIHeQHkVILDp7ZBjaVdGI_9rhHrgqeKBfvQAX3JMGE,2071
14
+ pypetkitapi/utils.py,sha256=z7325kcJQUburnF28HSXrJMvY_gY9007K73Zwxp-4DQ,743
15
+ pypetkitapi/water_fountain_container.py,sha256=5J0b-fDZYcFLNX2El7fifv8H6JMhBCt-ttxSow1ozRQ,6787
16
+ pypetkitapi-1.15.0.dist-info/LICENSE,sha256=u5jNkZEn6YMrtN4Kr5rU3TcBJ5-eAt0qMx4JDsbsnzM,1074
17
+ pypetkitapi-1.15.0.dist-info/METADATA,sha256=q3okbsikRZd38LsZQKABic_7teS3tVcB5rheUJH3oqI,6944
18
+ pypetkitapi-1.15.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
19
+ pypetkitapi-1.15.0.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- pypetkitapi/__init__.py,sha256=9aYDp2exciCKqaGEwL9K23dY3sH05gih03womG0NnII,2107
2
- pypetkitapi/bluetooth.py,sha256=1zEZIrKNTttrZpqBiQ-6V37Uphft5_T8CH9OBfYjwxE,9915
3
- pypetkitapi/client.py,sha256=62QzLypzCa6nEfR-Ihams6uQuYyKpu6yrFfnjfFu1Cc,30057
4
- pypetkitapi/command.py,sha256=k04iC0ONiFx7pkr-LJI7qT3RprQ3ojT0jP6KWQk8eTQ,7514
5
- pypetkitapi/const.py,sha256=tDCbvDbJHKZEy6L5Api59O1NE3mi9X61YTYTBv_6E9E,4767
6
- pypetkitapi/containers.py,sha256=QshQ3PaN858jy0nSjeIZyyLijK_AfpzrIZeq2SDoqXQ,4816
7
- pypetkitapi/exceptions.py,sha256=4BXUyYXLfZjNxdnOGJPjyE9ASIl7JmQphjws87jvHtE,1631
8
- pypetkitapi/feeder_container.py,sha256=PhidWd5WpsZqtdKZy60PzE67YXgQfApjm8CqvMCHK3U,14743
9
- pypetkitapi/litter_container.py,sha256=VIQZyZwmsxgMsV80Bc1lnYMqJyTZSaiqwE4Y_CNTD9Q,19338
10
- pypetkitapi/media.py,sha256=LNY3khU5eZN4i1MGHxJaPHcf3LA1fFaPVkn-wdn0YLI,27168
11
- pypetkitapi/purifier_container.py,sha256=ssyIxhNben5XJ4KlQTXTrtULg2ji6DqHqjzOq08d1-I,2491
12
- pypetkitapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- pypetkitapi/schedule_container.py,sha256=ycIHeQHkVILDp7ZBjaVdGI_9rhHrgqeKBfvQAX3JMGE,2071
14
- pypetkitapi/utils.py,sha256=z7325kcJQUburnF28HSXrJMvY_gY9007K73Zwxp-4DQ,743
15
- pypetkitapi/water_fountain_container.py,sha256=5J0b-fDZYcFLNX2El7fifv8H6JMhBCt-ttxSow1ozRQ,6787
16
- pypetkitapi-1.12.6.dist-info/LICENSE,sha256=u5jNkZEn6YMrtN4Kr5rU3TcBJ5-eAt0qMx4JDsbsnzM,1074
17
- pypetkitapi-1.12.6.dist-info/METADATA,sha256=QaAgcHSi7rs1mRuz_LKb7zFPD3QHlqhnwd680OBC0bs,6946
18
- pypetkitapi-1.12.6.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
19
- pypetkitapi-1.12.6.dist-info/RECORD,,