pypetkitapi 1.12.1__py3-none-any.whl → 1.12.4__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.1"
54
+ __version__ = "1.12.4"
55
55
 
56
56
  __all__ = [
57
57
  "CTW3",
pypetkitapi/bluetooth.py CHANGED
@@ -41,6 +41,9 @@ class BluetoothManager:
41
41
  if not isinstance(water_fountain, WaterFountain):
42
42
  _LOGGER.error("Water fountain with ID %s not found.", fountain_id)
43
43
  raise TypeError(f"Water fountain with ID {fountain_id} not found.")
44
+ if water_fountain.device_nfo is None:
45
+ raise ValueError(f"Device info not found for fountain {fountain_id}")
46
+
44
47
  return water_fountain
45
48
 
46
49
  async def check_relay_availability(self, fountain_id: int) -> bool:
@@ -94,7 +97,11 @@ class BluetoothManager:
94
97
  response = await self.client.req.request(
95
98
  method=HTTPMethod.POST,
96
99
  url=PetkitEndpoint.BLE_CONNECT,
97
- data={"bleId": fountain_id, "type": 24, "mac": water_fountain.mac},
100
+ data={
101
+ "bleId": fountain_id,
102
+ "type": water_fountain.device_nfo.type, # type: ignore[union-attr]
103
+ "mac": water_fountain.mac,
104
+ },
98
105
  headers=await self.client.get_session_id(),
99
106
  )
100
107
  if response != {"state": 1}:
@@ -111,7 +118,11 @@ class BluetoothManager:
111
118
  response = await self.client.req.request(
112
119
  method=HTTPMethod.POST,
113
120
  url=PetkitEndpoint.BLE_POLL,
114
- data={"bleId": fountain_id, "type": 24, "mac": water_fountain.mac},
121
+ data={
122
+ "bleId": fountain_id,
123
+ "type": water_fountain.device_nfo.type, # type: ignore[union-attr]
124
+ "mac": water_fountain.mac,
125
+ },
115
126
  headers=await self.client.get_session_id(),
116
127
  )
117
128
  if response == 1:
@@ -149,7 +160,11 @@ class BluetoothManager:
149
160
  await self.client.req.request(
150
161
  method=HTTPMethod.POST,
151
162
  url=PetkitEndpoint.BLE_CANCEL,
152
- data={"bleId": fountain_id, "type": 24, "mac": water_fountain.mac},
163
+ data={
164
+ "bleId": fountain_id,
165
+ "type": water_fountain.device_nfo.type, # type: ignore[union-attr]
166
+ "mac": water_fountain.mac,
167
+ },
153
168
  headers=await self.client.get_session_id(),
154
169
  )
155
170
  _LOGGER.debug("BLE connection closed successfully (id %s)", fountain_id)
@@ -206,7 +221,7 @@ class BluetoothManager:
206
221
  "cmd": cmd_code,
207
222
  "data": cmd_data,
208
223
  "mac": water_fountain.mac,
209
- "type": 24,
224
+ "type": water_fountain.device_nfo.type, # type: ignore[union-attr]
210
225
  },
211
226
  headers=await self.client.get_session_id(),
212
227
  )
pypetkitapi/client.py CHANGED
@@ -504,7 +504,6 @@ class PetKitClient:
504
504
  """Collect data from litter data to populate pet stats.
505
505
  :param stats_data: Litter data.
506
506
  """
507
-
508
507
  if not stats_data.device_nfo:
509
508
  _LOGGER.warning(
510
509
  "No device info for %s can't populate pet infos", stats_data
@@ -513,17 +512,24 @@ class PetKitClient:
513
512
 
514
513
  pets_list = await self.get_pets_list()
515
514
  for pet in pets_list:
516
- if (
517
- stats_data.device_nfo.device_type in [T3, T4]
518
- and stats_data.device_records
519
- ):
515
+ if stats_data.device_nfo.device_type in [T3, T4]:
516
+ await self.init_pet_stats(pet)
520
517
  await self._process_litter_no_camera(pet, stats_data)
521
- elif (
522
- stats_data.device_nfo.device_type in [T5, T6]
523
- and stats_data.device_pet_graph_out
524
- ):
518
+ elif stats_data.device_nfo.device_type in [T5, T6]:
519
+ await self.init_pet_stats(pet)
525
520
  await self._process_litter_camera(pet, stats_data)
526
521
 
522
+ @staticmethod
523
+ async def init_pet_stats(pet: Pet) -> None:
524
+ """Initialize pet stats.
525
+ Allow pet stats to be displayed in HA even if no data is available.
526
+ :param pet: Pet data.
527
+ """
528
+ pet.last_litter_usage = 0
529
+ pet.last_device_used = "Unknown"
530
+ pet.last_duration_usage = 0
531
+ pet.last_measured_weight = 0
532
+
527
533
  async def _process_litter_no_camera(self, pet: Pet, device_records: Litter) -> None:
528
534
  """Process litter T3/T4 records (litter without camera).
529
535
  :param pet: Pet data.
pypetkitapi/command.py CHANGED
@@ -17,6 +17,7 @@ from pypetkitapi.const import (
17
17
  FEEDER_MINI,
18
18
  K2,
19
19
  K3,
20
+ PET,
20
21
  T3,
21
22
  T4,
22
23
  T5,
@@ -265,11 +266,11 @@ ACTIONS_MAP = {
265
266
  supported_device=[D3],
266
267
  ),
267
268
  PetCommand.PET_UPDATE_SETTING: CmdData(
268
- endpoint=PetkitEndpoint.CONTROL_DEVICE,
269
+ endpoint=PetkitEndpoint.PET_UPDATE_SETTING,
269
270
  params=lambda pet, setting: {
270
- "petId": pet,
271
+ "petId": pet.pet_id,
271
272
  "kv": json.dumps(setting),
272
273
  },
273
- supported_device=ALL_DEVICES,
274
+ supported_device=[PET],
274
275
  ),
275
276
  }
pypetkitapi/const.py CHANGED
@@ -139,6 +139,8 @@ class PetkitEndpoint(StrEnum):
139
139
  LOGIN = "user/login"
140
140
  GET_LOGIN_CODE = "user/sendcodeforquicklogin"
141
141
  REFRESH_SESSION = "user/refreshsession"
142
+ DETAILS = "user/details2"
143
+ UNREAD_STATUS = "user/unreadStatus"
142
144
  FAMILY_LIST = "group/family/list"
143
145
  REFRESH_HOME_V2 = "refreshHomeV2"
144
146
 
@@ -195,3 +197,6 @@ class PetkitEndpoint(StrEnum):
195
197
  SCHEDULE_REMOVE = "schedule/remove"
196
198
  SCHEDULE_COMPLETE = "schedule/complete"
197
199
  SCHEDULE_HISTORY = "schedule/userHistorySchedules"
200
+
201
+ # Pet
202
+ PET_UPDATE_SETTING = "updatepetprops"
pypetkitapi/containers.py CHANGED
@@ -84,10 +84,10 @@ class Pet(BaseModel):
84
84
  device_nfo: Device | None = None # Device is now optional
85
85
 
86
86
  # Litter stats
87
- last_litter_usage: int = 0
87
+ last_litter_usage: int | None = None
88
88
  last_device_used: str | None = None
89
- last_duration_usage: int = 0
90
- last_measured_weight: int = 0
89
+ last_duration_usage: int | None = None
90
+ last_measured_weight: int | None = None
91
91
 
92
92
  def __init__(self, **data):
93
93
  """Initialize the Pet dataclass.
pypetkitapi/media.py CHANGED
@@ -272,13 +272,14 @@ class MediaManager:
272
272
  media_cloud: MediaCloud, missing_image: bool, missing_video: bool
273
273
  ) -> None:
274
274
  """Log details about missing media."""
275
- log_msg = "Media missing for event %s: "
276
275
  details = []
277
276
  if missing_image:
278
277
  details.append("IMAGE")
279
278
  if missing_video:
280
279
  details.append("VIDEO")
281
- _LOGGER.debug("%s %s %s", log_msg, media_cloud.event_id, " + ".join(details))
280
+ _LOGGER.debug(
281
+ "Media missing for event : %s %s", media_cloud.event_id, " + ".join(details)
282
+ )
282
283
 
283
284
  async def _process_feeder(self, feeder: Feeder) -> list[MediaCloud]:
284
285
  """Process media files for a Feeder device.
@@ -321,7 +322,7 @@ class MediaManager:
321
322
  cp_sub = self.is_subscription_active(device_obj)
322
323
 
323
324
  if not feeder_id or not record.items:
324
- _LOGGER.warning("Missing feeder_id or items for record")
325
+ _LOGGER.debug("Missing feeder_id or items for record")
325
326
  return media_files
326
327
 
327
328
  for item in record.items:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pypetkitapi
3
- Version: 1.12.1
3
+ Version: 1.12.4
4
4
  Summary: Python client for PetKit API
5
5
  License: MIT
6
6
  Author: Jezza34000
@@ -0,0 +1,19 @@
1
+ pypetkitapi/__init__.py,sha256=6zdURz_Sh7_mlBC4sHerwEOSoagp00FRioQHhswxuBA,2107
2
+ pypetkitapi/bluetooth.py,sha256=Nhmuy6s6V4_A5pgf_WrUc_3cW9P5gh6mSDN23vGoiBY,9534
3
+ pypetkitapi/client.py,sha256=62QzLypzCa6nEfR-Ihams6uQuYyKpu6yrFfnjfFu1Cc,30057
4
+ pypetkitapi/command.py,sha256=k04iC0ONiFx7pkr-LJI7qT3RprQ3ojT0jP6KWQk8eTQ,7514
5
+ pypetkitapi/const.py,sha256=76mR_g6qpqmkSj968W0lLyQAkAPenjk5dcs8ryWJUVA,4732
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=3PrjKNXYX7F1wXyXPxWFAJsQk2jlaFL7-dwVpMwy94o,26889
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.4.dist-info/LICENSE,sha256=u5jNkZEn6YMrtN4Kr5rU3TcBJ5-eAt0qMx4JDsbsnzM,1074
17
+ pypetkitapi-1.12.4.dist-info/METADATA,sha256=4UPiRUzvSuL7N9BsK_NwH-s5FjzL-SA6ZK1n3z7cFBE,6946
18
+ pypetkitapi-1.12.4.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
19
+ pypetkitapi-1.12.4.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- pypetkitapi/__init__.py,sha256=T4726e-xkLSV7y0cs9BXcEebn6vm4dLV2_96YqjmJ0k,2107
2
- pypetkitapi/bluetooth.py,sha256=JIj6mA5D1ZUUFSvnYco1XiGDbF4exKIU50zQIJMXLII,8976
3
- pypetkitapi/client.py,sha256=9K95_UuuBBsMYAssN8QrtLnS27IPso4Rnvn663RRs5Y,29760
4
- pypetkitapi/command.py,sha256=cMCUutZCQo9Ddvjl_FYR5UjU_CqFz1iyetMznYwjpzM,7500
5
- pypetkitapi/const.py,sha256=W0cWpBvOySEaPvVAnQHLeIWYEqKG051mVNv-qsfjo7I,4609
6
- pypetkitapi/containers.py,sha256=F_uyDBD0a5QD4s_ArjYiKTAAg1XHYBvmV_lEnO9RQ-U,4786
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=5XeiTQCaIgMisaZxdvdKK9RvDKmTR0zRBhKKXKBHTXI,26904
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.1.dist-info/LICENSE,sha256=u5jNkZEn6YMrtN4Kr5rU3TcBJ5-eAt0qMx4JDsbsnzM,1074
17
- pypetkitapi-1.12.1.dist-info/METADATA,sha256=zn4bNIG96NlL3PQ87aTIaSMo0VDXW4eru8ZbeXFyphE,6946
18
- pypetkitapi-1.12.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
19
- pypetkitapi-1.12.1.dist-info/RECORD,,