wyzeapy 0.5.31__py3-none-any.whl → 0.5.31rc1__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.
@@ -15,20 +15,7 @@ _LOGGER = logging.getLogger(__name__)
15
15
 
16
16
 
17
17
  class Bulb(Device):
18
- """Bulb class for interacting with Wyze bulbs.
19
-
20
- Note: When created via get_bulbs(), bulb properties (brightness, color,
21
- color_temp, on) are initialized with default values. Call
22
- BulbService.update(bulb) to fetch the actual current values from the
23
- Wyze API.
24
-
25
- Example:
26
- bulb_service = await client.bulb_service
27
- bulbs = await bulb_service.get_bulbs()
28
- for bulb in bulbs:
29
- bulb = await bulb_service.update(bulb) # Fetches actual values
30
- print(f"Brightness: {bulb.brightness}, Color: {bulb.color}")
31
- """
18
+ """Bulb class for interacting with Wyze bulbs."""
32
19
 
33
20
  _brightness: int = 0
34
21
  _color_temp: int = 1800
@@ -103,14 +90,10 @@ class BulbService(BaseService):
103
90
  """Bulb service for interacting with Wyze bulbs."""
104
91
 
105
92
  async def update(self, bulb: Bulb) -> Bulb:
106
- """Fetch and update the bulb's current state from the Wyze API.
107
-
108
- This method retrieves the actual values for brightness, color,
109
- color_temp, on/off state, and other properties from the Wyze API.
110
- Must be called after get_bulbs() to get accurate property values.
93
+ """Update the bulb object with the latest device parameters.
111
94
 
112
95
  :param bulb: Bulb object to update
113
- :return: Updated bulb object with current property values
96
+ :return: Updated bulb object
114
97
  """
115
98
  # Get updated device_params
116
99
  async with BaseService._update_lock:
@@ -148,11 +131,7 @@ class BulbService(BaseService):
148
131
  async def get_bulbs(self) -> List[Bulb]:
149
132
  """Get a list of all bulbs.
150
133
 
151
- Note: Returned bulbs have default property values (brightness=0,
152
- color="000000", etc.). Call update(bulb) on each bulb to fetch
153
- the actual current values from the Wyze API.
154
-
155
- :return: List of Bulb objects with default property values
134
+ :return: List of Bulb objects
156
135
  """
157
136
  if self._devices is None:
158
137
  self._devices = await self.get_object_list()
@@ -88,8 +88,10 @@ class CameraService(BaseService):
88
88
  if property is PropertyIDs.CAMERA_SIREN:
89
89
  camera.siren = value == "1"
90
90
  if property is PropertyIDs.ACCESSORY:
91
+ # Bulb Cam (HL_BC): '1' = ON, '2' = OFF
92
+ # Other cameras with accessories: same logic
91
93
  camera.floodlight = value == "1"
92
- if camera.device_params["dongle_product_model"] == "HL_CGDC":
94
+ if camera.device_params.get("dongle_product_model") == "HL_CGDC":
93
95
  camera.garage = (
94
96
  value == "1"
95
97
  ) # 1 = open, 2 = closed by automation or smart platform (Alexa, Google Home, Rules), 0 = closed by app
@@ -186,7 +188,7 @@ class CameraService(BaseService):
186
188
  else:
187
189
  await self._run_action(camera, "siren_off")
188
190
 
189
- # Also controls lamp socket and BCP spotlight
191
+ # Also controls lamp socket, BCP spotlight, and Bulb Cam light
190
192
  async def floodlight_on(self, camera: Camera):
191
193
  if camera.product_model == "AN_RSCW":
192
194
  await self._run_action_devicemgmt(
@@ -196,10 +198,13 @@ class CameraService(BaseService):
196
198
  await self._run_action_devicemgmt(
197
199
  camera, "floodlight", "1"
198
200
  ) # Some camera models use a diffrent api
201
+ elif camera.product_model == "HL_BC":
202
+ # Bulb Cam uses run_action with floodlight_on action
203
+ await self._run_action(camera, "floodlight_on")
199
204
  else:
200
205
  await self._set_property(camera, PropertyIDs.ACCESSORY.value, "1")
201
206
 
202
- # Also controls lamp socket and BCP spotlight
207
+ # Also controls lamp socket, BCP spotlight, and Bulb Cam light
203
208
  async def floodlight_off(self, camera: Camera):
204
209
  if camera.product_model == "AN_RSCW":
205
210
  await self._run_action_devicemgmt(
@@ -209,6 +214,9 @@ class CameraService(BaseService):
209
214
  await self._run_action_devicemgmt(
210
215
  camera, "floodlight", "0"
211
216
  ) # Some camera models use a diffrent api
217
+ elif camera.product_model == "HL_BC":
218
+ # Bulb Cam uses run_action with floodlight_off action
219
+ await self._run_action(camera, "floodlight_off")
212
220
  else:
213
221
  await self._set_property(camera, PropertyIDs.ACCESSORY.value, "2")
214
222
 
wyzeapy/utils.py CHANGED
@@ -81,13 +81,8 @@ def wyze_decrypt_cbc(key: str, enc_hex_str: str) -> str:
81
81
 
82
82
  Returns:
83
83
  The decrypted plaintext string.
84
-
85
- Note:
86
- MD5 is used here because it is required by Wyze's proprietary API protocol.
87
- This is not a security vulnerability - it's mandatory for API compatibility.
88
84
  """
89
- # MD5 is required by Wyze's API protocol - not a security choice but API compatibility
90
- key_hash = hashlib.md5(key.encode("utf-8")).digest() # nosec B324
85
+ key_hash = hashlib.md5(key.encode("utf-8")).digest()
91
86
 
92
87
  iv = b"0123456789ABCDEF"
93
88
  cipher = AES.new(key_hash, AES.MODE_CBC, iv)
@@ -109,15 +104,10 @@ def create_password(password: str) -> str:
109
104
 
110
105
  Returns:
111
106
  The hashed password as a hex string.
112
-
113
- Note:
114
- Triple MD5 is mandated by Wyze's authentication API. This cannot be changed
115
- without breaking compatibility with Wyze's servers.
116
107
  """
117
- # MD5 is required by Wyze's authentication protocol - not a security choice
118
- hex1 = hashlib.md5(password.encode()).hexdigest() # nosec B324
119
- hex2 = hashlib.md5(hex1.encode()).hexdigest() # nosec B324
120
- return hashlib.md5(hex2.encode()).hexdigest() # nosec B324
108
+ hex1 = hashlib.md5(password.encode()).hexdigest()
109
+ hex2 = hashlib.md5(hex1.encode()).hexdigest()
110
+ return hashlib.md5(hex2.encode()).hexdigest()
121
111
 
122
112
 
123
113
  def check_for_errors_standard(service, response_json: Dict[str, Any]) -> None:
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wyzeapy
3
- Version: 0.5.31
3
+ Version: 0.5.31rc1
4
4
  Summary: A library for interacting with Wyze devices
5
5
  Author-email: Katie Mulliken <katie@mulliken.net>
6
6
  License: GPL-3.0-only
7
7
  Requires-Python: >=3.11.0
8
- Requires-Dist: aiodns<5.0.0,>=3.2.0
8
+ Requires-Dist: aiodns<4.0.0,>=3.2.0
9
9
  Requires-Dist: aiohttp<4.0.0,>=3.11.12
10
10
  Requires-Dist: pycryptodome<4.0.0,>=3.21.0
11
11
  Provides-Extra: dev
@@ -4,12 +4,12 @@ wyzeapy/crypto.py,sha256=ApzPL0hrrd0D4k2jB5psNatJvUSzx1Kxui6_l4NJGO8,2057
4
4
  wyzeapy/exceptions.py,sha256=uKVWooofK22DZ3o9kwxnlJXnhk0VMJXnp-26pNavAis,1136
5
5
  wyzeapy/payload_factory.py,sha256=1QUEgqSSDwEjKv1ew-jQYoXcFk0uf5B4gODw83ep2zg,20638
6
6
  wyzeapy/types.py,sha256=LPLc86FkEy8rUoPMwG8xB73NCTVRkJ1O5w7uSfDydLQ,6785
7
- wyzeapy/utils.py,sha256=_aoP9H7RXuND3nCMP3gJRLBxX6Dsxag81RLm83G5Pu4,7969
7
+ wyzeapy/utils.py,sha256=EXnsZFBxgI3LsIh9Ttg4gq3Aq1VMLOxBUPCspWJX9IQ,7407
8
8
  wyzeapy/wyze_auth_lib.py,sha256=CiWdl_UAzYxKLS8yCfjXxEI87gStJede2eS4g7KlnjE,18273
9
9
  wyzeapy/services/__init__.py,sha256=hbdyglbWQjM4XlNqPIACOEbspdsEEm4k5VXZ1hI0gc8,77
10
10
  wyzeapy/services/base_service.py,sha256=3FsbZHm6ndc6pSGCwrwh6SRgGb7HDK_L5lzuSjaLgO0,35547
11
- wyzeapy/services/bulb_service.py,sha256=4Z_rX40OGqzRuKz_fgyWGb4di7jtyJSB_ZvFFCDlcCo,8821
12
- wyzeapy/services/camera_service.py,sha256=vaJIChKDMg3zWcoC_JqITDBjw4sgFdyUEkl3_w2ML8I,11170
11
+ wyzeapy/services/bulb_service.py,sha256=DNuT9PBmFhXpaD9rcjoYZMt-TLWWEAC3o0Yyvw_itHA,7825
12
+ wyzeapy/services/camera_service.py,sha256=1j9dmIp2LsjWgGmo1TCKTQpdyxrfn2O1wjaqyzLE0DM,11677
13
13
  wyzeapy/services/hms_service.py,sha256=lQojRASz9AlwqkRfj7W7gOKXpLHrHHVwBGMw5WJ23Nc,2450
14
14
  wyzeapy/services/irrigation_service.py,sha256=6HzwFRTjZcM4-Y9exSn5EmS2DZbl1gF_uaiMpK2Kd6c,8670
15
15
  wyzeapy/services/lock_service.py,sha256=NBjlr7pL5zJqdJaH33v1i6BbLHb7TXCkoCql4hCr8J8,2234
@@ -19,6 +19,6 @@ wyzeapy/services/thermostat_service.py,sha256=_d-UbD65JArhwsslawvwpTmfVC4tMksY-L
19
19
  wyzeapy/services/update_manager.py,sha256=5pZJmnyN4rlYJwMtEY13NlPBssnRLhtlLLmXr9t990Q,6770
20
20
  wyzeapy/services/wall_switch_service.py,sha256=cBKmnB2InHKIuoPwQ47t1rDtDplyOyGQYvnfX4fXFcc,4339
21
21
  wyzeapy/tests/test_irrigation_service.py,sha256=ui3ZlqLUkoLb-uebK8Q1A83d9lAV9WIuHGbIrqPLyqg,28926
22
- wyzeapy-0.5.31.dist-info/METADATA,sha256=ps5g5kCz_rY2XLNeVS31nSuX4ZXp1xVQmNJTrCLsTOw,446
23
- wyzeapy-0.5.31.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
24
- wyzeapy-0.5.31.dist-info/RECORD,,
22
+ wyzeapy-0.5.31rc1.dist-info/METADATA,sha256=iqzslNb99YA6j_NLFgR_NGMmz1_ZzHvgAgrXyTlz820,449
23
+ wyzeapy-0.5.31rc1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
24
+ wyzeapy-0.5.31rc1.dist-info/RECORD,,