pypetkitapi 0.3.0__tar.gz → 0.5.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.
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/PKG-INFO +1 -1
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/client.py +6 -3
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/command.py +70 -18
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/const.py +12 -4
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/containers.py +15 -0
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/exceptions.py +2 -2
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/feeder_container.py +14 -1
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/litter_container.py +10 -0
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pyproject.toml +2 -2
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/LICENSE +0 -0
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/README.md +0 -0
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/__init__.py +0 -0
- {pypetkitapi-0.3.0 → pypetkitapi-0.5.0}/pypetkitapi/water_fountain_container.py +0 -0
@@ -46,6 +46,7 @@ class PetKitClient:
|
|
46
46
|
_session: SessionInfo | None = None
|
47
47
|
_servers_list: list[RegionInfo] = []
|
48
48
|
account_data: list[AccountData] = []
|
49
|
+
# TODO : Adding pet as entity ?
|
49
50
|
device_list: dict[int, Feeder | Litter | WaterFountain] = {}
|
50
51
|
|
51
52
|
def __init__(
|
@@ -101,6 +102,7 @@ class PetKitClient:
|
|
101
102
|
await self._get_api_server_list()
|
102
103
|
_LOGGER.debug("Finding region server for region: %s", self.region)
|
103
104
|
|
105
|
+
# TODO : Improve this
|
104
106
|
if self.region == "china":
|
105
107
|
self._base_url = PetkitURL.CHINA_SRV
|
106
108
|
return
|
@@ -117,7 +119,7 @@ class PetKitClient:
|
|
117
119
|
|
118
120
|
if regional_server:
|
119
121
|
_LOGGER.debug(
|
120
|
-
"
|
122
|
+
"Using server %s for region : %s", regional_server, self.region
|
121
123
|
)
|
122
124
|
self._base_url = regional_server.gateway
|
123
125
|
return
|
@@ -278,7 +280,7 @@ class PetKitClient:
|
|
278
280
|
self,
|
279
281
|
device_id: int,
|
280
282
|
action: StrEnum,
|
281
|
-
setting: dict | None = None,
|
283
|
+
setting: dict | StrEnum | None = None,
|
282
284
|
) -> None:
|
283
285
|
"""Control the device using the PetKit API."""
|
284
286
|
device = self.device_list.get(device_id)
|
@@ -330,7 +332,8 @@ class PetKitClient:
|
|
330
332
|
data=params,
|
331
333
|
headers=headers,
|
332
334
|
)
|
333
|
-
if res
|
335
|
+
if res in (SUCCESS_KEY, RES_KEY):
|
336
|
+
# TODO : Manage to get the response from manul feeding
|
334
337
|
_LOGGER.info("Command executed successfully")
|
335
338
|
else:
|
336
339
|
_LOGGER.error("Command execution failed")
|
@@ -9,6 +9,7 @@ import json
|
|
9
9
|
from pypetkitapi.const import (
|
10
10
|
ALL_DEVICES,
|
11
11
|
D3,
|
12
|
+
D4,
|
12
13
|
D4H,
|
13
14
|
D4S,
|
14
15
|
D4SH,
|
@@ -44,6 +45,7 @@ class FeederCommand(StrEnum):
|
|
44
45
|
class LitterCommand(StrEnum):
|
45
46
|
"""LitterCommand"""
|
46
47
|
|
48
|
+
POWER = "power"
|
47
49
|
CONTROL_DEVICE = "control_device"
|
48
50
|
RESET_DEODORIZER = "reset_deodorizer"
|
49
51
|
|
@@ -54,6 +56,12 @@ class PetCommand(StrEnum):
|
|
54
56
|
UPDATE_SETTING = "update_setting"
|
55
57
|
|
56
58
|
|
59
|
+
class FountainCommand(StrEnum):
|
60
|
+
"""Fountain Command"""
|
61
|
+
|
62
|
+
CONTROL_DEVICE = "control_device"
|
63
|
+
|
64
|
+
|
57
65
|
class LitterBoxCommand(StrEnum):
|
58
66
|
"""LitterBoxCommand"""
|
59
67
|
|
@@ -148,6 +156,43 @@ LB_CMD_TO_VALUE = {
|
|
148
156
|
}
|
149
157
|
|
150
158
|
|
159
|
+
class FountainAction(StrEnum):
|
160
|
+
"""Fountain Action"""
|
161
|
+
|
162
|
+
PAUSE = "Pause"
|
163
|
+
NORMAL_TO_PAUSE = "Normal To Pause"
|
164
|
+
SMART_TO_PAUSE = "Smart To Pause"
|
165
|
+
NORMAL = "Normal"
|
166
|
+
SMART = "Smart"
|
167
|
+
RESET_FILTER = "Reset Filter"
|
168
|
+
DO_NOT_DISTURB = "Do Not Disturb"
|
169
|
+
DO_NOT_DISTURB_OFF = "Do Not Disturb Off"
|
170
|
+
FIRST_BLE_CMND = "First BLE Command"
|
171
|
+
SECOND_BLE_CMND = "Second BLE Command"
|
172
|
+
LIGHT_LOW = "Light Low"
|
173
|
+
LIGHT_MEDIUM = "Light Medium"
|
174
|
+
LIGHT_HIGH = "Light High"
|
175
|
+
LIGHT_ON = "Light On"
|
176
|
+
LIGHT_OFF = "Light Off"
|
177
|
+
|
178
|
+
|
179
|
+
FOUNTAIN_COMMAND_TO_CODE = {
|
180
|
+
FountainAction.DO_NOT_DISTURB: "221",
|
181
|
+
FountainAction.DO_NOT_DISTURB_OFF: "221",
|
182
|
+
FountainAction.LIGHT_ON: "221",
|
183
|
+
FountainAction.LIGHT_OFF: "221",
|
184
|
+
FountainAction.LIGHT_LOW: "221",
|
185
|
+
FountainAction.LIGHT_MEDIUM: "221",
|
186
|
+
FountainAction.LIGHT_HIGH: "221",
|
187
|
+
FountainAction.PAUSE: "220",
|
188
|
+
FountainAction.RESET_FILTER: "222",
|
189
|
+
FountainAction.NORMAL: "220",
|
190
|
+
FountainAction.NORMAL_TO_PAUSE: "220",
|
191
|
+
FountainAction.SMART: "220",
|
192
|
+
FountainAction.SMART_TO_PAUSE: "220",
|
193
|
+
}
|
194
|
+
|
195
|
+
|
151
196
|
@dataclass
|
152
197
|
class CmdData:
|
153
198
|
"""Command Info"""
|
@@ -160,10 +205,10 @@ class CmdData:
|
|
160
205
|
def get_endpoint_manual_feed(device):
|
161
206
|
"""Get the endpoint for the device"""
|
162
207
|
if device.device_type == FEEDER_MINI:
|
163
|
-
return PetkitEndpoint.
|
208
|
+
return PetkitEndpoint.MANUAL_FEED_MINI
|
164
209
|
if device.device_type == FEEDER:
|
165
|
-
return PetkitEndpoint.
|
166
|
-
return PetkitEndpoint.
|
210
|
+
return PetkitEndpoint.MANUAL_FEED_FRESH_ELEMENT
|
211
|
+
return PetkitEndpoint.MANUAL_FEED_DUAL
|
167
212
|
|
168
213
|
|
169
214
|
def get_endpoint_reset_desiccant(device):
|
@@ -192,10 +237,10 @@ ACTIONS_MAP = {
|
|
192
237
|
"time": "-1",
|
193
238
|
**setting,
|
194
239
|
},
|
195
|
-
supported_device=
|
240
|
+
supported_device=[FEEDER, FEEDER_MINI, D3, D4, D4H],
|
196
241
|
),
|
197
242
|
FeederCommand.MANUAL_FEED_DUAL: CmdData(
|
198
|
-
endpoint=PetkitEndpoint.
|
243
|
+
endpoint=PetkitEndpoint.MANUAL_FEED_DUAL,
|
199
244
|
params=lambda device, setting: {
|
200
245
|
"day": datetime.datetime.now().strftime("%Y%m%d"),
|
201
246
|
"deviceId": device.id,
|
@@ -203,7 +248,7 @@ ACTIONS_MAP = {
|
|
203
248
|
"time": "-1",
|
204
249
|
**setting,
|
205
250
|
},
|
206
|
-
supported_device=
|
251
|
+
supported_device=[D4S, D4SH],
|
207
252
|
),
|
208
253
|
FeederCommand.CANCEL_MANUAL_FEED: CmdData(
|
209
254
|
endpoint=lambda device: (
|
@@ -259,7 +304,15 @@ ACTIONS_MAP = {
|
|
259
304
|
},
|
260
305
|
supported_device=[D3],
|
261
306
|
),
|
262
|
-
|
307
|
+
LitterCommand.POWER: CmdData(
|
308
|
+
endpoint=PetkitEndpoint.CONTROL_DEVICE,
|
309
|
+
params=lambda device, setting: {
|
310
|
+
"id": device.id,
|
311
|
+
"kv": json.dumps(setting),
|
312
|
+
"type": "power",
|
313
|
+
},
|
314
|
+
supported_device=[T3, T4, T5, T6],
|
315
|
+
),
|
263
316
|
LitterCommand.CONTROL_DEVICE: CmdData(
|
264
317
|
endpoint=PetkitEndpoint.CONTROL_DEVICE,
|
265
318
|
params=lambda device, command: {
|
@@ -269,22 +322,21 @@ ACTIONS_MAP = {
|
|
269
322
|
},
|
270
323
|
supported_device=[T3, T4, T5, T6],
|
271
324
|
),
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
# ),
|
325
|
+
PetCommand.UPDATE_SETTING: CmdData(
|
326
|
+
endpoint=PetkitEndpoint.CONTROL_DEVICE,
|
327
|
+
params=lambda pet, setting: {
|
328
|
+
"petId": pet,
|
329
|
+
"kv": json.dumps(setting),
|
330
|
+
},
|
331
|
+
supported_device=ALL_DEVICES,
|
332
|
+
),
|
281
333
|
# FountainCommand.CONTROL_DEVICE: CmdData(
|
282
334
|
# endpoint=PetkitEndpoint.CONTROL_DEVICE,
|
283
335
|
# params=lambda device, setting: {
|
284
|
-
# "bleId":
|
336
|
+
# "bleId": device.id,
|
285
337
|
# "cmd": cmnd_code,
|
286
338
|
# "data": ble_data,
|
287
|
-
# "mac":
|
339
|
+
# "mac": device.mac,
|
288
340
|
# "type": water_fountain.ble_relay,
|
289
341
|
# },
|
290
342
|
# supported_device=[CTW3],
|
@@ -95,9 +95,17 @@ class PetkitEndpoint(StrEnum):
|
|
95
95
|
GET_DEVICE_RECORD_RELEASE = "getDeviceRecordRelease"
|
96
96
|
UPDATE_SETTING = "updateSettings"
|
97
97
|
|
98
|
+
# Bluetooth relay
|
99
|
+
BLE_AS_RELAY = "ble/ownSupportBleDevices"
|
100
|
+
BLE_CONNECT = "ble/connect"
|
101
|
+
BLE_POLL = "ble/poll"
|
102
|
+
BLE_CANCEL = "ble/cancel"
|
103
|
+
|
104
|
+
# Fountain & Litter Box
|
105
|
+
CONTROL_DEVICE = "controlDevice"
|
106
|
+
|
98
107
|
# Litter Box
|
99
108
|
DEODORANT_RESET = "deodorantReset"
|
100
|
-
CONTROL_DEVICE = "controlDevice"
|
101
109
|
|
102
110
|
# Feeders
|
103
111
|
REPLENISHED_FOOD = "added"
|
@@ -108,6 +116,6 @@ class PetkitEndpoint(StrEnum):
|
|
108
116
|
FRESH_ELEMENT_DESICCANT_RESET = "feeder/desiccant_reset"
|
109
117
|
CALL_PET = "callPet"
|
110
118
|
CANCEL_FEED = "cancelRealtimeFeed"
|
111
|
-
|
112
|
-
|
113
|
-
|
119
|
+
MANUAL_FEED_MINI = "feedermini/save_dailyfeed"
|
120
|
+
MANUAL_FEED_FRESH_ELEMENT = "feeder/save_dailyfeed"
|
121
|
+
MANUAL_FEED_DUAL = "saveDailyFeed"
|
@@ -15,6 +15,21 @@ class RegionInfo(BaseModel):
|
|
15
15
|
name: str
|
16
16
|
|
17
17
|
|
18
|
+
class BleRelay(BaseModel):
|
19
|
+
"""Dataclass for BLE relay devices
|
20
|
+
Fetched from the API endpoint :
|
21
|
+
- ble/ownSupportBleDevices
|
22
|
+
"""
|
23
|
+
|
24
|
+
id: int
|
25
|
+
low_version: int = Field(alias="lowVersion")
|
26
|
+
mac: str
|
27
|
+
name: str
|
28
|
+
pim: int
|
29
|
+
sn: str
|
30
|
+
type_id: int = Field(alias="typeId")
|
31
|
+
|
32
|
+
|
18
33
|
class SessionInfo(BaseModel):
|
19
34
|
"""Dataclass for session data.
|
20
35
|
Fetched from the API endpoint :
|
@@ -22,8 +22,8 @@ class PetkitRegionalServerNotFoundError(PypetkitError):
|
|
22
22
|
"""Initialize the exception."""
|
23
23
|
self.region = region
|
24
24
|
self.message = (
|
25
|
-
f"Region you provided: '{region}' was not found in the server list. "
|
26
|
-
f"Are you sure you provided the correct region?"
|
25
|
+
f"Region you provided: '{region}' was not found in the Petkit's server list. "
|
26
|
+
f"Are you sure you provided the correct region ?"
|
27
27
|
)
|
28
28
|
super().__init__(self.message)
|
29
29
|
|
@@ -154,6 +154,19 @@ class StateFeeder(BaseModel):
|
|
154
154
|
conservation_status: int | None = Field(None, alias="conservationStatus")
|
155
155
|
|
156
156
|
|
157
|
+
class ManualFeed(BaseModel):
|
158
|
+
"""Dataclass for result data."""
|
159
|
+
|
160
|
+
amount1: int | None = None
|
161
|
+
amount2: int | None = None
|
162
|
+
id: str | None = None
|
163
|
+
is_executed: int | None = Field(None, alias="isExecuted")
|
164
|
+
is_need_upload_video: int | None = Field(None, alias="isNeedUploadVideo")
|
165
|
+
src: int | None = None
|
166
|
+
status: int | None = None
|
167
|
+
time: int | None = None
|
168
|
+
|
169
|
+
|
157
170
|
class Feeder(BaseModel):
|
158
171
|
"""Dataclass for feeder data."""
|
159
172
|
|
@@ -184,7 +197,7 @@ class Feeder(BaseModel):
|
|
184
197
|
p2p_type: int | None = Field(None, alias="p2pType")
|
185
198
|
multi_config: bool | None = Field(None, alias="multiConfig")
|
186
199
|
device_type: str | None = Field(None, alias="deviceType")
|
187
|
-
|
200
|
+
manual_feed: ManualFeed | None = None
|
188
201
|
|
189
202
|
@classmethod
|
190
203
|
def get_endpoint(cls, device_type: str) -> str:
|
@@ -130,6 +130,15 @@ class StateLitter(BaseModel):
|
|
130
130
|
wander_time: int | None = Field(None, alias="wanderTime")
|
131
131
|
|
132
132
|
|
133
|
+
class WorkState(BaseModel):
|
134
|
+
"""Dataclass for work state data."""
|
135
|
+
|
136
|
+
stop_time: int = Field(alias="stopTime")
|
137
|
+
work_mode: int = Field(alias="workMode")
|
138
|
+
work_process: int = Field(alias="workProcess")
|
139
|
+
work_reason: int = Field(alias="workReason")
|
140
|
+
|
141
|
+
|
133
142
|
class Litter(BaseModel):
|
134
143
|
"""Dataclass for Litter Data.
|
135
144
|
Supported devices = T4, T6
|
@@ -171,6 +180,7 @@ class Litter(BaseModel):
|
|
171
180
|
service_status: int | None = Field(None, alias="serviceStatus")
|
172
181
|
total_time: int | None = Field(None, alias="totalTime")
|
173
182
|
device_type: str | None = Field(None, alias="deviceType")
|
183
|
+
work_state: WorkState | None = Field(None, alias="workState")
|
174
184
|
|
175
185
|
@classmethod
|
176
186
|
def get_endpoint(cls, device_type: str) -> str:
|
@@ -187,7 +187,7 @@ build-backend = "poetry.core.masonry.api"
|
|
187
187
|
|
188
188
|
[tool.poetry]
|
189
189
|
name = "pypetkitapi"
|
190
|
-
version = "0.
|
190
|
+
version = "0.5.0"
|
191
191
|
description = "Python client for PetKit API"
|
192
192
|
authors = ["Jezza34000 <info@mail.com>"]
|
193
193
|
readme = "README.md"
|
@@ -204,7 +204,7 @@ black = "^24.10.0"
|
|
204
204
|
ruff = "^0.8.1"
|
205
205
|
|
206
206
|
[tool.bumpver]
|
207
|
-
current_version = "0.
|
207
|
+
current_version = "0.5.0"
|
208
208
|
version_pattern = "MAJOR.MINOR.PATCH"
|
209
209
|
commit_message = "bump version {old_version} -> {new_version}"
|
210
210
|
tag_message = "{new_version}"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|