switchbot-api 2.10.0__tar.gz → 2.11.1__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.4
2
2
  Name: switchbot_api
3
- Version: 2.10.0
3
+ Version: 2.11.1
4
4
  Summary: An asynchronous library to use Switchbot API
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
16
  Classifier: Programming Language :: Python :: 3.14
17
17
  Requires-Dist: aiohttp (>=3.0.0)
18
+ Requires-Dist: pycryptodome (>=3.23.0,<4.0.0)
18
19
  Project-URL: Repository, https://github.com/SeraphicCorp/py-switchbot-api
19
20
  Description-Content-Type: text/markdown
20
21
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "switchbot_api"
3
- version = "2.10.0"
3
+ version = "2.11.1"
4
4
  description = "An asynchronous library to use Switchbot API"
5
5
  authors = ["Ravaka Razafimanantsoa <contact@ravaka.dev>"]
6
6
  license = "MIT"
@@ -11,6 +11,7 @@ repository = "https://github.com/SeraphicCorp/py-switchbot-api"
11
11
  [tool.poetry.dependencies]
12
12
  python = "^3.10"
13
13
  aiohttp = ">=3.0.0"
14
+ pycryptodome = "^3.23.0"
14
15
 
15
16
 
16
17
  [tool.poetry.group.dev.dependencies]
@@ -14,6 +14,8 @@ import uuid
14
14
 
15
15
  from aiohttp import ClientError, ClientResponseError, ClientSession
16
16
  from aiohttp.hdrs import METH_GET, METH_POST
17
+ from Crypto.Cipher import AES
18
+ from Crypto.Util.Padding import unpad
17
19
 
18
20
  from switchbot_api.commands import (
19
21
  AirConditionerCommands,
@@ -56,6 +58,8 @@ from switchbot_api.exceptions import (
56
58
  SwitchBotDeviceOfflineError,
57
59
  )
58
60
  from switchbot_api.models import (
61
+ AirPurifierFanGear,
62
+ AirPurifierMode,
59
63
  BatteryCirculatorFanMode,
60
64
  BatteryLevel,
61
65
  PowerState,
@@ -68,6 +72,8 @@ from switchbot_api.models import (
68
72
  __all__ = [
69
73
  "AirConditionerCommands",
70
74
  "AirPurifierCommands",
75
+ "AirPurifierFanGear",
76
+ "AirPurifierMode",
71
77
  "ArtFrameCommands",
72
78
  "BatteryCirculatorFanCommands",
73
79
  "BatteryCirculatorFanMode",
@@ -244,9 +250,22 @@ class SwitchBotAPI:
244
250
  ]
245
251
  return [*devices, *remotes]
246
252
 
253
+ async def get_device(self, device_id: str) -> dict[str, Any]:
254
+ """Get target device."""
255
+ body = await self._request(METH_GET, "devices")
256
+ for device in body["deviceList"]:
257
+ if device_id == device["deviceId"]:
258
+ return device # type: ignore[no-any-return]
259
+ return {}
260
+
247
261
  async def get_status(self, device_id: str) -> dict[str, Any]:
248
262
  """No status for IR devices."""
249
- return await self._request(METH_GET, f"devices/{device_id}/status")
263
+ response = await self._request(METH_GET, f"devices/{device_id}/status")
264
+
265
+ device_type = response.get("deviceType")
266
+ if device_type and device_type in KeyPadCommands.get_supported_devices():
267
+ return await self.get_device(device_id)
268
+ return response
250
269
 
251
270
  async def get_webook_configuration(self) -> dict[str, Any]:
252
271
  """List webhooks."""
@@ -300,6 +319,23 @@ class SwitchBotAPI:
300
319
  if self.session and self._close_session:
301
320
  await self.session.close()
302
321
 
322
+ def aes_128_cbc_decrypt(self, encrypt_text: str, aes_iv: str) -> str:
323
+ """Aes 128 cbc decrypt.
324
+
325
+ Args:
326
+ encrypt_text (str):
327
+ aes_iv (str):
328
+
329
+ Notes : only for [Keypad, Keypad Touch, Keypad Vision, Keypad Vision Pro]
330
+
331
+ """
332
+ encrypt_bytes = base64.b64decode(encrypt_text)
333
+ cipher = AES.new(
334
+ bytes.fromhex(self.secret), AES.MODE_CBC, bytes.fromhex(aes_iv)
335
+ )
336
+ decrypt_bytes = unpad(cipher.decrypt(encrypt_bytes), AES.block_size)
337
+ return decrypt_bytes.decode("utf-8")
338
+
303
339
  async def __aenter__(self) -> Self:
304
340
  """Async enter.
305
341
 
@@ -148,6 +148,9 @@ class AirPurifierCommands(Commands):
148
148
 
149
149
  SET_MODE = "setMode"
150
150
  SET_CHILD_LOCK = "setChildLock"
151
+ SET_LIGHT_COLOR = "setLightColor"
152
+ SET_BRIGHTNESS = "setBrightness"
153
+ SET_LIGHT_SENSOR = "setLightSensor"
151
154
 
152
155
  @classmethod
153
156
  def get_supported_devices(cls) -> list[str]:
@@ -259,6 +262,7 @@ class ArtFrameCommands(Commands):
259
262
 
260
263
  PREVIOUS = "previous"
261
264
  NEXT = "next"
265
+ UPLOAD = "uploadImage"
262
266
 
263
267
  @classmethod
264
268
  def get_supported_devices(cls) -> list[str]:
@@ -441,7 +445,7 @@ class KeyPadCommands(Commands):
441
445
  @classmethod
442
446
  def get_supported_devices(cls) -> list[str]:
443
447
  """Get supported devices."""
444
- return ["Keypad", "Keypad Touch", "Keypad Vision", "Keypad Vision pro"]
448
+ return ["Keypad", "Keypad Touch", "Keypad Vision", "Keypad Vision Pro"]
445
449
 
446
450
 
447
451
  T = TypeVar("T", bound=CommonCommands)
@@ -21,6 +21,23 @@ class BatteryCirculatorFanMode(StrEnum):
21
21
  BABY = "baby"
22
22
 
23
23
 
24
+ class AirPurifierMode(Enum):
25
+ """mode types [Air Purifier] API."""
26
+
27
+ LEVEL = 1
28
+ AUTO = 2
29
+ SLEEP = 3
30
+ PET = 4
31
+
32
+
33
+ class AirPurifierFanGear(Enum):
34
+ """Air Purifier Fan Gear."""
35
+
36
+ High = 3
37
+ Medium = 2
38
+ Low = 1
39
+
40
+
24
41
  class VacuumFanSpeed(StrEnum):
25
42
  """Fan options for VacuumCommands supported devices."""
26
43
 
File without changes
File without changes