casambi-bt-revamped 0.3.8.dev1__py3-none-any.whl → 0.3.8.dev3__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.
CasambiBt/_client.py CHANGED
@@ -233,18 +233,23 @@ class CasambiClient:
233
233
  self._callbackQueue.put_nowait((handle, data))
234
234
 
235
235
  async def _processCallbacks(self) -> None:
236
- while True:
237
- handle, data = await self._callbackQueue.get()
238
-
239
- # Try to loose any races here.
240
- # Otherwise a state change caused by the last packet might not have been handled yet
241
- await asyncio.sleep(0.001)
242
- await self._activityLock.acquire()
243
- try:
244
- self._callbackMulitplexer(handle, data)
245
- finally:
246
- self._callbackQueue.task_done()
247
- self._activityLock.release()
236
+ try:
237
+ while True:
238
+ handle, data = await self._callbackQueue.get()
239
+
240
+ # Try to loose any races here.
241
+ # Otherwise a state change caused by the last packet might not have been handled yet
242
+ await asyncio.sleep(0.001)
243
+ await self._activityLock.acquire()
244
+ try:
245
+ self._callbackMulitplexer(handle, data)
246
+ finally:
247
+ self._callbackQueue.task_done()
248
+ self._activityLock.release()
249
+ except asyncio.CancelledError:
250
+ # Task cancelled during shutdown; log at debug and exit cleanly.
251
+ self._logger.debug("Callback processing task cancelled during shutdown.")
252
+ raise
248
253
 
249
254
  def _callbackMulitplexer(
250
255
  self, handle: BleakGATTCharacteristic, data: bytes
@@ -759,8 +764,17 @@ class CasambiClient:
759
764
  self._logger.info("Disconnecting...")
760
765
 
761
766
  if self._callbackTask is not None:
767
+ # Cancel and await the background callback task to avoid
768
+ # 'Task was destroyed but it is pending' warnings.
762
769
  self._callbackTask.cancel()
763
- self._callbackTask = None
770
+ try:
771
+ await self._callbackTask
772
+ except asyncio.CancelledError:
773
+ pass
774
+ except Exception:
775
+ self._logger.debug("Callback task finished with exception during disconnect.", exc_info=True)
776
+ finally:
777
+ self._callbackTask = None
764
778
 
765
779
  if self._gattClient is not None and self._gattClient.is_connected:
766
780
  try:
CasambiBt/_unit.py CHANGED
@@ -111,6 +111,7 @@ class UnitState:
111
111
  self._colorsource: ColorSource | None = None
112
112
  self._xy: tuple[float, float] | None = None
113
113
  self._slider: int | None = None
114
+ self._onoff: bool | None = None
114
115
 
115
116
  def _check_range(
116
117
  self, value: int | float, min: int | float, max: int | float
@@ -269,9 +270,20 @@ class UnitState:
269
270
  def slider(self) -> None:
270
271
  self.slider = None
271
272
 
272
- def __repr__(self) -> str:
273
- return f"UnitState(dimmer={self.dimmer}, vertical={self._vertical}, rgb={self.rgb.__repr__()}, white={self.white}, temperature={self.temperature}, colorsource={self.colorsource}, xy={self.xy}, slider={self.slider})"
273
+ @property
274
+ def onoff(self) -> bool | None:
275
+ return self._onoff
276
+
277
+ @onoff.setter
278
+ def onoff(self, value: bool) -> None:
279
+ self._onoff = value
274
280
 
281
+ @onoff.deleter
282
+ def onoff(self) -> None:
283
+ self._onoff = None
284
+
285
+ def __repr__(self) -> str:
286
+ return f"UnitState(dimmer={self.dimmer}, vertical={self._vertical}, rgb={self.rgb.__repr__()}, white={self.white}, temperature={self.temperature}, colorsource={self.colorsource}, xy={self.xy}, slider={self.slider}, onoff={self.onoff})"
275
287
 
276
288
  # TODO: Make unit immutable (refactor state, on, online out of it)
277
289
  @dataclass(init=True, repr=True)
@@ -308,6 +320,8 @@ class Unit:
308
320
  @property
309
321
  def is_on(self) -> bool:
310
322
  """Determine whether the unit is turned on."""
323
+ if self.unitType.get_control(UnitControlType.ONOFF) and self._state:
324
+ return self._on and self._state.onoff is True
311
325
  if self.unitType.get_control(UnitControlType.DIMMER) and self._state:
312
326
  return (
313
327
  self._on and self._state.dimmer is not None and self._state.dimmer > 0
@@ -385,6 +399,8 @@ class Unit:
385
399
  elif c.type == UnitControlType.SLIDER and state.slider is not None:
386
400
  scale = UnitState.SLIDER_RESOLUTION - c.length
387
401
  scaledValue = state.slider >> scale
402
+ elif c.type == UnitControlType.ONOFF and state.onoff is not None:
403
+ scaledValue = 1 if state.onoff else 0
388
404
 
389
405
  # Use default if unsupported type or unset value in state
390
406
  else:
@@ -477,6 +493,8 @@ class Unit:
477
493
  elif c.type == UnitControlType.SLIDER:
478
494
  scale = UnitState.SLIDER_RESOLUTION - c.length
479
495
  self._state.slider = cInt << scale
496
+ elif c.type == UnitControlType.ONOFF:
497
+ self._state.onoff = cInt != 0
480
498
  elif c.type == UnitControlType.UNKOWN:
481
499
  # Might be useful for implementing more state types
482
500
  _LOGGER.debug(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: casambi-bt-revamped
3
- Version: 0.3.8.dev1
3
+ Version: 0.3.8.dev3
4
4
  Summary: Enhanced Casambi Bluetooth client library with switch event support
5
5
  Home-page: https://github.com/rankjie/casambi-bt
6
6
  Author: rankjie
@@ -1,18 +1,18 @@
1
1
  CasambiBt/__init__.py,sha256=TW445xSu5PV3TyMjJfwaA1JoWvQQ8LXhZgGdDTfWf3s,302
2
2
  CasambiBt/_cache.py,sha256=KZ2xbiHAHXUPa8Gw_75Nw9NL4QSY_sTWHbyYXYUDaB0,3865
3
3
  CasambiBt/_casambi.py,sha256=AfyuzEU2ylJOGLmZ87Qft-aNXI_JK8Ng9Tfk4fWYOwo,34345
4
- CasambiBt/_client.py,sha256=k2VQbmWpH6kOmGxF4zFvN0exFmWyKafgGEK3zORFTmc,31136
4
+ CasambiBt/_client.py,sha256=6uFawDzPJuLEhD5oVaFlxDSm3herw_eBUPFkUIHLgYw,31832
5
5
  CasambiBt/_constants.py,sha256=_AxkG7Btxl4VeS6mO7GJW5Kc9dFs3s9sDmtJ83ZEKNw,359
6
6
  CasambiBt/_discover.py,sha256=H7HpiFYIy9ELvmPXXd_ck-5O5invJf15dDIRk-vO5IE,1696
7
7
  CasambiBt/_encryption.py,sha256=CLcoOOrggQqhJbnr_emBnEnkizpWDvb_0yFnitq4_FM,3831
8
8
  CasambiBt/_keystore.py,sha256=Jdiq0zMPDmhfpheSojKY6sTUpmVrvX_qOyO7yCYd3kw,2788
9
9
  CasambiBt/_network.py,sha256=Gh0n3FEcOUHUMuBXALwcb3tws-AofpYLegKIquqtZl4,14665
10
10
  CasambiBt/_operation.py,sha256=Q5UccsrtNp_B_wWqwH_3eLFW_yF6A55FMmfUKDk2WrI,1059
11
- CasambiBt/_unit.py,sha256=M-Q8-Xd3qjJSUEvsFtic8E4xDc_gtWYakbTGyoIA-P8,16377
11
+ CasambiBt/_unit.py,sha256=KR_dvVhCH8WIPGJgZYHyAPVA6ru0KmMOL5NgkxYHIUQ,17042
12
12
  CasambiBt/errors.py,sha256=0JgDjaKlAKDes0poWzA8nrTUYQ8qdNfBb8dfaqqzCRA,1664
13
13
  CasambiBt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- casambi_bt_revamped-0.3.8.dev1.dist-info/licenses/LICENSE,sha256=TAIIitFxpxEDi6Iju7foW4TDQmWvC-IhLVLhl67jKmQ,11341
15
- casambi_bt_revamped-0.3.8.dev1.dist-info/METADATA,sha256=JVgVrFaryIi0V5MUG7VHTZrrDYTrW3MuosTTc2Zy3QA,3048
16
- casambi_bt_revamped-0.3.8.dev1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
17
- casambi_bt_revamped-0.3.8.dev1.dist-info/top_level.txt,sha256=uNbqLjtecFosoFzpGAC89-5icikWODKI8rOjbi8v_sA,10
18
- casambi_bt_revamped-0.3.8.dev1.dist-info/RECORD,,
14
+ casambi_bt_revamped-0.3.8.dev3.dist-info/licenses/LICENSE,sha256=TAIIitFxpxEDi6Iju7foW4TDQmWvC-IhLVLhl67jKmQ,11341
15
+ casambi_bt_revamped-0.3.8.dev3.dist-info/METADATA,sha256=Acuf-qcCilqoHwvqXl8FSw-T-C0kUP1z1378obAEaMM,3048
16
+ casambi_bt_revamped-0.3.8.dev3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
17
+ casambi_bt_revamped-0.3.8.dev3.dist-info/top_level.txt,sha256=uNbqLjtecFosoFzpGAC89-5icikWODKI8rOjbi8v_sA,10
18
+ casambi_bt_revamped-0.3.8.dev3.dist-info/RECORD,,