pypetkitapi 1.7.8__tar.gz → 1.7.10__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.1
2
2
  Name: pypetkitapi
3
- Version: 1.7.8
3
+ Version: 1.7.10
4
4
  Summary: Python client for PetKit API
5
5
  Home-page: https://github.com/Jezza34000/pypetkit
6
6
  License: MIT
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
16
16
  Requires-Dist: aiohttp (>=3.10.10,<4.0.0)
17
17
  Requires-Dist: pycryptodome (>=3.19.1,<4.0.0)
18
- Requires-Dist: pydantic (>=1.10.18,<2.0.0)
18
+ Requires-Dist: pydantic (>=1.10.18,<3.0.0)
19
19
  Description-Content-Type: text/markdown
20
20
 
21
21
  # Petkit API Client
@@ -0,0 +1,56 @@
1
+ """Pypetkit: A Python library for interfacing with PetKit"""
2
+
3
+ from .client import PetKitClient
4
+ from .command import FeederCommand, LBAction, LBCommand, LitterCommand, PetCommand
5
+ from .const import (
6
+ CTW3,
7
+ D3,
8
+ D4,
9
+ D4H,
10
+ D4S,
11
+ DEVICES_FEEDER,
12
+ DEVICES_LITTER_BOX,
13
+ DEVICES_WATER_FOUNTAIN,
14
+ FEEDER,
15
+ FEEDER_MINI,
16
+ K2,
17
+ K3,
18
+ T3,
19
+ T4,
20
+ T5,
21
+ T6,
22
+ W5,
23
+ RecordType,
24
+ )
25
+ from .medias import MediaHandler, MediasFiles
26
+
27
+ __version__ = "1.7.10"
28
+
29
+ __all__ = [
30
+ "MediasFiles",
31
+ "MediaHandler",
32
+ "D3",
33
+ "D4",
34
+ "D4H",
35
+ "D4S",
36
+ "FEEDER",
37
+ "FEEDER_MINI",
38
+ "T3",
39
+ "T4",
40
+ "T5",
41
+ "T6",
42
+ "W5",
43
+ "CTW3",
44
+ "K2",
45
+ "K3",
46
+ "DEVICES_FEEDER",
47
+ "DEVICES_LITTER_BOX",
48
+ "DEVICES_WATER_FOUNTAIN",
49
+ "RecordType",
50
+ "PetKitClient",
51
+ "FeederCommand",
52
+ "LitterCommand",
53
+ "PetCommand",
54
+ "LBCommand",
55
+ "LBAction",
56
+ ]
@@ -29,6 +29,7 @@ T6 = "t6"
29
29
  W5 = "w5"
30
30
  CTW3 = "ctw3"
31
31
  K2 = "k2"
32
+ K3 = "k3"
32
33
 
33
34
  DEVICES_LITTER_BOX = [T3, T4, T5, T6]
34
35
  DEVICES_FEEDER = [FEEDER, FEEDER_MINI, D3, D4, D4S, D4H, D4SH]
@@ -86,6 +87,18 @@ LOGIN_DATA = {
86
87
  }
87
88
 
88
89
 
90
+ class RecordType(StrEnum):
91
+ """Record Type constants"""
92
+
93
+ EAT = "eat"
94
+ FEED = "feed"
95
+ MOVE = "move"
96
+ PET = "pet"
97
+
98
+
99
+ RecordTypeLST = [RecordType.EAT, RecordType.FEED, RecordType.MOVE, RecordType.PET]
100
+
101
+
89
102
  class PetkitEndpoint(StrEnum):
90
103
  """Petkit Endpoint constants"""
91
104
 
@@ -119,6 +132,11 @@ class PetkitEndpoint(StrEnum):
119
132
  STATISTIC_RELEASE = "statisticRelease"
120
133
  GET_PET_OUT_GRAPH = "getPetOutGraph"
121
134
 
135
+ # Video features
136
+ CLOUD_VIDEO = "cloud/video"
137
+ GET_DOWNLOAD_M3U8 = "getDownloadM3u8"
138
+ GET_M3U8 = "getM3u8"
139
+
122
140
  # Feeders
123
141
  REPLENISHED_FOOD = "added"
124
142
  FRESH_ELEMENT_CALIBRATION = "food_reset"
@@ -1,6 +1,6 @@
1
1
  """Dataclasses container for petkit API."""
2
2
 
3
- from pydantic import BaseModel, Field, root_validator
3
+ from pydantic import BaseModel, Field
4
4
 
5
5
 
6
6
  class RegionInfo(BaseModel):
@@ -69,25 +69,28 @@ class Pet(BaseModel):
69
69
  created_at: int = Field(alias="createdAt")
70
70
  pet_id: int = Field(alias="petId")
71
71
  pet_name: str | None = Field(None, alias="petName")
72
- id: int | None = None # Fictive field (for HA compatibility) copied from id
73
- sn: str # Fictive field (for HA compatibility) copied from id
74
- name: str | None = None # Fictive field (for HA compatibility) copied from pet_name
75
- device_type: str = "pet" # Fictive field (for HA compatibility) fixed
76
- firmware: str | None = None # Fictive field (for HA compatibility) fixed
72
+ id: int | None = None # Fictive field copied from id (for HA compatibility)
73
+ sn: str | None = None # Fictive field copied from id (for HA compatibility)
74
+ name: str | None = None # Fictive field copied from pet_name (for HA compatibility)
75
+ device_type: str = "pet" # Fictive fixed field (for HA compatibility)
76
+ firmware: str | None = None # Fictive fixed field (for HA compatibility)
77
77
 
78
- # Got from Litter stats
78
+ # Litter stats
79
79
  last_litter_usage: int = 0
80
80
  last_device_used: str | None = None
81
81
  last_duration_usage: int = 0
82
82
  last_measured_weight: int = 0
83
83
 
84
- @root_validator(pre=True)
85
- def populate_fictive_fields(cls, values): # noqa: N805
86
- """Populate fictive fields based on other fields."""
87
- values["id"] = values.get("id") or values.get("petId")
88
- values["sn"] = values.get("sn") or values.get("id")
89
- values["name"] = values.get("name") or values.get("petName")
90
- return values
84
+ def __init__(self, **data):
85
+ """Initialize the Pet dataclass.
86
+ This method is used to fill the fictive fields after the standard initialization.
87
+ """
88
+ # Appeler l'initialisation standard de Pydantic
89
+ super().__init__(**data)
90
+ # Remplir les champs fictifs après l'initialisation
91
+ self.id = self.id or self.pet_id
92
+ self.sn = self.sn or str(self.id)
93
+ self.name = self.name or self.pet_name
91
94
 
92
95
 
93
96
  class User(BaseModel):
@@ -12,12 +12,12 @@ from pypetkitapi.containers import CloudProduct, Device, FirmwareDetail, Wifi
12
12
  class FeedItem(BaseModel):
13
13
  """Dataclass for feed item data."""
14
14
 
15
- id: str | None = None
16
- name: str | None = None
17
- time: int | None = None
18
15
  amount: int | None = None
19
16
  amount1: int | None = Field(None, alias="amount1")
20
17
  amount2: int | None = Field(None, alias="amount2")
18
+ id: str | None = None
19
+ name: str | None = None
20
+ time: int | None = None
21
21
 
22
22
 
23
23
  class FeedDailyList(BaseModel):
@@ -50,9 +50,14 @@ class SettingsFeeder(BaseModel):
50
50
  attire_id: int | None = Field(None, alias="attireId")
51
51
  attire_switch: int | None = Field(None, alias="attireSwitch")
52
52
  auto_product: int | None = Field(None, alias="autoProduct")
53
+ bucket_name1: str | None = Field(None, alias="bucketName1")
54
+ bucket_name2: str | None = Field(None, alias="bucketName2")
53
55
  camera: int | None = None
54
56
  camera_config: int | None = Field(None, alias="cameraConfig")
57
+ camera_multi_new: list[CameraMultiNew] | None = Field(None, alias="cameraMultiNew")
55
58
  camera_multi_range: list | None = Field(None, alias="cameraMultiRange")
59
+ color_setting: int | None = None
60
+ conservation: int | None = None
56
61
  control_settings: int | None = Field(None, alias="controlSettings")
57
62
  desiccant_notify: int | None = Field(None, alias="desiccantNotify")
58
63
  detect_config: int | None = Field(None, alias="detectConfig")
@@ -62,8 +67,10 @@ class SettingsFeeder(BaseModel):
62
67
  eat_notify: int | None = Field(None, alias="eatNotify")
63
68
  eat_sensitivity: int | None = Field(None, alias="eatSensitivity")
64
69
  eat_video: int | None = Field(None, alias="eatVideo")
70
+ factor: int | None = None
65
71
  feed_notify: int | None = Field(None, alias="feedNotify")
66
72
  feed_picture: int | None = Field(None, alias="feedPicture")
73
+ feed_sound: int | None = Field(None, alias="feedSound")
67
74
  food_notify: int | None = Field(None, alias="foodNotify")
68
75
  food_warn: int | None = Field(None, alias="foodWarn")
69
76
  food_warn_range: list[int] | None = Field(None, alias="foodWarnRange")
@@ -87,6 +94,7 @@ class SettingsFeeder(BaseModel):
87
94
  pet_sensitivity: int | None = Field(None, alias="petSensitivity")
88
95
  pre_live: int | None = Field(None, alias="preLive")
89
96
  selected_sound: int | None = Field(None, alias="selectedSound")
97
+ shortest: int | None = None # D4S
90
98
  smart_frame: int | None = Field(None, alias="smartFrame")
91
99
  sound_enable: int | None = Field(None, alias="soundEnable")
92
100
  surplus: int | None = None # D3
@@ -99,35 +107,29 @@ class SettingsFeeder(BaseModel):
99
107
  tone_multi_range: list[tuple[int, int]] | None = Field(None, alias="toneMultiRange")
100
108
  upload: int | None = None
101
109
  volume: int | None = None
102
- feed_sound: int | None = Field(None, alias="feedSound")
103
- factor: int | None = None
104
- color_setting: int | None = Field(None, alias="colorSetting")
105
- conservation: int | None = None
106
- bucket_name1: str | None = Field(None, alias="bucketName1")
107
- bucket_name2: str | None = Field(None, alias="bucketName2")
108
- camera_multi_new: list[CameraMultiNew] | None = Field(None, alias="cameraMultiNew")
109
110
 
110
111
 
111
112
  class FeedState(BaseModel):
112
113
  """Dataclass for feed state data."""
113
114
 
115
+ add_amount_total: int | None = Field(None, alias="addAmountTotal")
116
+ add_amount_total1: int | None = Field(None, alias="addAmountTotal1")
117
+ add_amount_total2: int | None = Field(None, alias="addAmountTotal2")
118
+ eat_amount_total: int | None = Field(None, alias="eatAmountTotal") # D3
114
119
  eat_avg: int | None = Field(None, alias="eatAvg")
115
120
  eat_count: int | None = Field(None, alias="eatCount")
116
121
  eat_times: list[int] | None = Field(None, alias="eatTimes")
117
122
  feed_times: dict | list | None = Field(None, alias="feedTimes")
118
- times: int | None = None
119
- add_amount_total: int | None = Field(None, alias="addAmountTotal")
120
123
  plan_amount_total: int | None = Field(None, alias="planAmountTotal")
121
- plan_real_amount_total: int | None = Field(None, alias="planRealAmountTotal")
122
- real_amount_total: int | None = Field(None, alias="realAmountTotal")
123
- add_amount_total1: int | None = Field(None, alias="addAmountTotal1")
124
- add_amount_total2: int | None = Field(None, alias="addAmountTotal2")
125
124
  plan_amount_total1: int | None = Field(None, alias="planAmountTotal1")
126
125
  plan_amount_total2: int | None = Field(None, alias="planAmountTotal2")
126
+ plan_real_amount_total: int | None = Field(None, alias="planRealAmountTotal")
127
127
  plan_real_amount_total1: int | None = Field(None, alias="planRealAmountTotal1")
128
128
  plan_real_amount_total2: int | None = Field(None, alias="planRealAmountTotal2")
129
+ real_amount_total: int | None = Field(None, alias="realAmountTotal")
129
130
  real_amount_total1: int | None = Field(None, alias="realAmountTotal1")
130
131
  real_amount_total2: int | None = Field(None, alias="realAmountTotal2")
132
+ times: int | None = None
131
133
 
132
134
 
133
135
  class StateFeeder(BaseModel):
@@ -135,31 +137,31 @@ class StateFeeder(BaseModel):
135
137
 
136
138
  battery_power: int | None = Field(None, alias="batteryPower")
137
139
  battery_status: int | None = Field(None, alias="batteryStatus")
138
- bowl: int | None = None
139
140
  block: int | None = None
141
+ bowl: int | None = None
140
142
  broadcast: dict | None = None
141
143
  camera_status: int | None = Field(None, alias="cameraStatus")
142
144
  charge: int | None = None
145
+ conservation_status: int | None = Field(None, alias="conservationStatus")
143
146
  desiccant_left_days: int | None = Field(None, alias="desiccantLeftDays")
144
147
  desiccant_time: int | None = Field(None, alias="desiccantTime")
145
148
  door: int | None = None
146
- feed_state: FeedState | None = Field(None, alias="feedState")
147
- feeding: int | None = None
149
+ eating: int | None = None
148
150
  error_code: str | None = Field(None, alias="errorCode")
149
151
  error_detail: str | None = Field(None, alias="errorDetail")
150
152
  error_level: int | None = Field(None, alias="errorLevel")
151
153
  error_msg: str | None = Field(None, alias="errorMsg")
154
+ feed_state: FeedState | None = Field(None, alias="feedState")
155
+ feeding: int | None = None
156
+ food: int | None = None
157
+ food1: int | None = Field(None, alias="food1")
158
+ food2: int | None = Field(None, alias="food2")
152
159
  ota: int | None = None
153
160
  overall: int | None = None
154
161
  pim: int | None = None
155
162
  runtime: int | None = None
156
163
  weight: int | None = None
157
164
  wifi: Wifi | None = None
158
- eating: int | None = None
159
- food: int | None = None
160
- food1: int | None = Field(None, alias="food1")
161
- food2: int | None = Field(None, alias="food2")
162
- conservation_status: int | None = Field(None, alias="conservationStatus")
163
165
 
164
166
 
165
167
  class ManualFeed(BaseModel):
@@ -302,15 +304,20 @@ class Feeder(BaseModel):
302
304
  bt_mac: str | None = Field(None, alias="btMac")
303
305
  cloud_product: CloudProduct | None = Field(None, alias="cloudProduct")
304
306
  created_at: str | None = Field(None, alias="createdAt")
307
+ device_records: FeederRecord | None = None
308
+ device_type: str | None = Field(None, alias="deviceType")
305
309
  firmware: float
306
310
  firmware_details: list[FirmwareDetail] | None = Field(None, alias="firmwareDetails")
307
311
  hardware: int
308
312
  id: int
309
313
  locale: str | None = None
310
314
  mac: str | None = None
315
+ manual_feed: ManualFeed | None = None
311
316
  model_code: int | None = Field(None, alias="modelCode")
317
+ multi_config: bool | None = Field(None, alias="multiConfig")
312
318
  multi_feed_item: MultiFeedItem | None = Field(None, alias="multiFeedItem")
313
319
  name: str | None = None
320
+ p2p_type: int | None = Field(None, alias="p2pType")
314
321
  secret: str | None = None
315
322
  service_status: int | None = Field(None, alias="serviceStatus")
316
323
  settings: SettingsFeeder | None = None
@@ -319,11 +326,6 @@ class Feeder(BaseModel):
319
326
  sn: str
320
327
  state: StateFeeder | None = None
321
328
  timezone: float | None = None
322
- p2p_type: int | None = Field(None, alias="p2pType")
323
- multi_config: bool | None = Field(None, alias="multiConfig")
324
- device_type: str | None = Field(None, alias="deviceType")
325
- manual_feed: ManualFeed | None = None
326
- device_records: FeederRecord | None = None
327
329
 
328
330
  @classmethod
329
331
  def get_endpoint(cls, device_type: str) -> str:
@@ -10,6 +10,7 @@ from pypetkitapi.const import (
10
10
  DEVICE_RECORDS,
11
11
  DEVICE_STATS,
12
12
  T4,
13
+ T5,
13
14
  T6,
14
15
  PetkitEndpoint,
15
16
  )
@@ -51,6 +52,7 @@ class SettingsLitter(BaseModel):
51
52
  lightest: int | None = Field(None, alias="lightest")
52
53
  litter_full_notify: int | None = Field(None, alias="litterFullNotify")
53
54
  manual_lock: int | None = Field(None, alias="manualLock")
55
+ no_remind: int | None = Field(None, alias="noRemind")
54
56
  pet_in_notify: int | None = Field(None, alias="petInNotify")
55
57
  relate_k3_switch: int | None = Field(None, alias="relateK3Switch")
56
58
  sand_type: int | None = Field(None, alias="sandType")
@@ -240,7 +242,7 @@ class LitterRecord(BaseModel):
240
242
  """Get the endpoint URL for the given device type."""
241
243
  if device_type == T4:
242
244
  return PetkitEndpoint.GET_DEVICE_RECORD
243
- if device_type == T6:
245
+ if device_type in [T5, T6]:
244
246
  return PetkitEndpoint.GET_DEVICE_RECORD_RELEASE
245
247
  raise ValueError(f"Invalid device type: {device_type}")
246
248
 
@@ -257,7 +259,7 @@ class LitterRecord(BaseModel):
257
259
  if request_date is None:
258
260
  request_date = datetime.now().strftime("%Y%m%d")
259
261
  return {"date": int(request_date), "deviceId": device.device_id}
260
- if device_type == T6:
262
+ if device_type in [T5, T6]:
261
263
  return {
262
264
  "timestamp": int(datetime.now().timestamp()),
263
265
  "deviceId": device.device_id,
@@ -187,7 +187,7 @@ build-backend = "poetry.core.masonry.api"
187
187
 
188
188
  [tool.poetry]
189
189
  name = "pypetkitapi"
190
- version = "1.7.8"
190
+ version = "1.7.10"
191
191
  description = "Python client for PetKit API"
192
192
  authors = ["Jezza34000 <info@mail.com>"]
193
193
  readme = "README.md"
@@ -199,7 +199,7 @@ python = ">=3.11"
199
199
  aiohttp = "^3.10.10"
200
200
  aiofiles = "^24.1.0"
201
201
  pycryptodome = "^3.19.1"
202
- pydantic = "^1.10.18"
202
+ pydantic = ">=1.10.18,<3.0.0"
203
203
 
204
204
  [tool.poetry.dev-dependencies]
205
205
  pre-commit = "^4.0.1"
@@ -208,7 +208,7 @@ ruff = "^0.8.1"
208
208
  types-aiofiles = "^24.1.0.20240626"
209
209
 
210
210
  [tool.bumpver]
211
- current_version = "1.7.8"
211
+ current_version = "1.7.10"
212
212
  version_pattern = "MAJOR.MINOR.PATCH"
213
213
  commit_message = "bump version {old_version} -> {new_version}"
214
214
  tag_message = "{new_version}"
@@ -224,6 +224,9 @@ push = true
224
224
  '^version = "{version}"',
225
225
  '^current_version = "{version}"',
226
226
  ]
227
+ "pypetkitapi/__init__.py" = [
228
+ '^__version__ = "{version}"',
229
+ ]
227
230
 
228
231
  [tool.tox]
229
232
  envlist = ["pre-commit"]
@@ -1 +0,0 @@
1
- """Pypetkit: A Python library for interfacing with PetKit"""
File without changes
File without changes