pypetkitapi 0.3.0__py3-none-any.whl → 0.5.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/client.py CHANGED
@@ -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
- "Found server %s for region : %s", regional_server, self.region
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 == SUCCESS_KEY:
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")
pypetkitapi/command.py CHANGED
@@ -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.MINI_MANUAL_FEED
208
+ return PetkitEndpoint.MANUAL_FEED_MINI
164
209
  if device.device_type == FEEDER:
165
- return PetkitEndpoint.FRESH_ELEMENT_MANUAL_FEED
166
- return PetkitEndpoint.MANUAL_FEED
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=DEVICES_FEEDER, # TODO: Check if this is correct
240
+ supported_device=[FEEDER, FEEDER_MINI, D3, D4, D4H],
196
241
  ),
197
242
  FeederCommand.MANUAL_FEED_DUAL: CmdData(
198
- endpoint=PetkitEndpoint.UPDATE_SETTING,
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=ALL_DEVICES,
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
- # TODO : Find how to support power ON/OFF
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
- # TODO : Find how to support Pet Setting with send_api_request
273
- # PetCommand.UPDATE_SETTING: CmdData(
274
- # endpoint=PetkitEndpoint.CONTROL_DEVICE,
275
- # params=lambda pet, setting: {
276
- # "petId": pet,
277
- # "kv": json.dumps(setting),
278
- # },
279
- # supported_device=ALL_DEVICES,
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": water_fountain.data["id"],
336
+ # "bleId": device.id,
285
337
  # "cmd": cmnd_code,
286
338
  # "data": ble_data,
287
- # "mac": water_fountain.data["mac"],
339
+ # "mac": device.mac,
288
340
  # "type": water_fountain.ble_relay,
289
341
  # },
290
342
  # supported_device=[CTW3],
pypetkitapi/const.py CHANGED
@@ -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
- MINI_MANUAL_FEED = "feedermini/save_dailyfeed"
112
- FRESH_ELEMENT_MANUAL_FEED = "feeder/save_dailyfeed"
113
- MANUAL_FEED = "saveDailyFeed"
119
+ MANUAL_FEED_MINI = "feedermini/save_dailyfeed"
120
+ MANUAL_FEED_FRESH_ELEMENT = "feeder/save_dailyfeed"
121
+ MANUAL_FEED_DUAL = "saveDailyFeed"
pypetkitapi/containers.py CHANGED
@@ -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 :
pypetkitapi/exceptions.py CHANGED
@@ -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
- manual_feed_id: int = 0
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypetkitapi
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: Python client for PetKit API
5
5
  Home-page: https://github.com/Jezza34000/pypetkit
6
6
  License: MIT
@@ -0,0 +1,13 @@
1
+ pypetkitapi/__init__.py,sha256=eVpyGMD3tkYtiHUkdKEeNSZhQlZ4woI2Y5oVoV7CwXM,61
2
+ pypetkitapi/client.py,sha256=wQqX5qH0NMWx0uSLo6fmn4ELhBHcegiEjEwsOrLJaOA,14945
3
+ pypetkitapi/command.py,sha256=MZbnmWpmekVzlWCg_ubcrFnOoqUCZh1Bamcf_QUos38,10605
4
+ pypetkitapi/const.py,sha256=lFu2_fnzUsJOvOUZaFpCw2wlKCensDr4M0YZPsY4Uh8,3179
5
+ pypetkitapi/containers.py,sha256=4O79O9HZn4kksQysXGXcqVwvkdxbvhs1pr-0WRNCANc,3425
6
+ pypetkitapi/exceptions.py,sha256=NWmpsI2ewC4HaIeu_uFwCeuPIHIJxZBzjoCP7aNwvhs,1139
7
+ pypetkitapi/feeder_container.py,sha256=6a1Y_mTSGuD8qK1YqmiCfxPbZl84bcoIIP_d5g-UctQ,11381
8
+ pypetkitapi/litter_container.py,sha256=hl1mS0YBZ_D391OAzAgU4sZeCJEY7wVbM51Zqm3oNxk,9276
9
+ pypetkitapi/water_fountain_container.py,sha256=LcCTDjk7eSbnF7e38xev3D5mCv5wwJ6go8WGGBv-CaU,5278
10
+ pypetkitapi-0.5.0.dist-info/LICENSE,sha256=4FWnKolNLc1e3w6cVlT61YxfPh0DQNeQLN1CepKKSBg,1067
11
+ pypetkitapi-0.5.0.dist-info/METADATA,sha256=yhEy7uWQEhfva1vXemrxpWS51G7dZWfZ1AojnL57l1s,3611
12
+ pypetkitapi-0.5.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
13
+ pypetkitapi-0.5.0.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- pypetkitapi/__init__.py,sha256=eVpyGMD3tkYtiHUkdKEeNSZhQlZ4woI2Y5oVoV7CwXM,61
2
- pypetkitapi/client.py,sha256=yb7RWlr_F1yrmmYRvQNKEt2Zd6PClsctRZYa0nRVtH0,14791
3
- pypetkitapi/command.py,sha256=ibJ0zenONy-FBvUvyIA_IvUnYEUezLpPxhC_9XZ6SwM,9282
4
- pypetkitapi/const.py,sha256=XKiybtizB115OwVo7l9d2bZyVfkFjYWEtt9mBwYLcDk,2988
5
- pypetkitapi/containers.py,sha256=XhNbRUztnBpIr9cypDoyE3MHojic831G5GSisK9B7kU,3123
6
- pypetkitapi/exceptions.py,sha256=f9QY1EME9ha_vJJx4DuL_OBNpoynYVdtMFtVZbdfook,1129
7
- pypetkitapi/feeder_container.py,sha256=IGXeAEbLkZhOTCzF2MhwqadIAKXg6jHbfU037dt6byY,10985
8
- pypetkitapi/litter_container.py,sha256=aLAvcB8K_nx7iBRkAarZs-48HAj2NkG7XjJFonWMuME,8948
9
- pypetkitapi/water_fountain_container.py,sha256=LcCTDjk7eSbnF7e38xev3D5mCv5wwJ6go8WGGBv-CaU,5278
10
- pypetkitapi-0.3.0.dist-info/LICENSE,sha256=4FWnKolNLc1e3w6cVlT61YxfPh0DQNeQLN1CepKKSBg,1067
11
- pypetkitapi-0.3.0.dist-info/METADATA,sha256=FaCJfahbgxUuDf8kfEeVhwn22vDPWu9bEfvmVRO43sk,3611
12
- pypetkitapi-0.3.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
13
- pypetkitapi-0.3.0.dist-info/RECORD,,