diff --git a/custom_components/hunterdouglas_powerview_ble/api.py b/custom_components/hunterdouglas_powerview_ble/api.py index b2daf23..2826e20 100644 --- a/custom_components/hunterdouglas_powerview_ble/api.py +++ b/custom_components/hunterdouglas_powerview_ble/api.py @@ -51,6 +51,9 @@ SHADE_TYPE: Final[dict[int, str]] = { 9: "Duette DuoLite, Top Down Bottom Up", 33: "Duette Architella, Top Down Bottom Up", 47: "Pleated, Top Down Bottom Up", + # top down, tilt anywhere + 51: "Venetian, Tilt Anywhere", + 62: "Venetian, Tilt Anywhere", } OPEN_POSITION: Final[int] = 100 @@ -203,21 +206,21 @@ class PowerViewBLE: async def set_position( self, pos1: int, - pos2: int = 0x8000, - pos3: int = 0x8000, - tilt: int = 0x8000, + pos2: int | None = None, + pos3: int | None = None, + tilt: int | None = None, velocity: int = 0x0, disconnect: bool = True, ) -> None: """Set position of device.""" - LOGGER.debug("%s setting position to %i", self.name, pos1) + LOGGER.debug("%s setting position to %i, tilt %i", self.name, pos1, tilt) await self._cmd( ( ShadeCmd.SET_POSITION, - int.to_bytes(pos1 * 100, 2, byteorder="little") - + int.to_bytes(pos2 * 100, 2, byteorder="little") - + int.to_bytes(pos3 * 100, 2, byteorder="little") - + int.to_bytes(tilt * 100, 2, byteorder="little") + int.to_bytes(pos1, 2, byteorder="little") + + int.to_bytes(pos2 if pos2 is not None else 0x8000, 2, byteorder="little") + + int.to_bytes(pos3 if pos3 is not None else 0x8000, 2, byteorder="little") + + int.to_bytes(tilt if tilt is not None else 0x8000, 2, byteorder="little") + int.to_bytes(velocity, 1), ), disconnect, @@ -299,6 +302,9 @@ class PowerViewBLE: .copy() .decode("UTF-8") ) + except BleakError as ex: + LOGGER.debug("%s: querying failed: %s", ex) + raise finally: await self.disconnect() LOGGER.debug("%s device data: %s", self.name, data) @@ -315,7 +321,11 @@ class PowerViewBLE: if self._cipher is not None and self._is_encrypted: dec: AEADDecryptionContext = self._cipher.decryptor() self._data = bytearray(dec.update(data) + dec.finalize()) - LOGGER.debug("%s %s", "decoded data: ".rjust(19+len(self.name)), self._data.hex(" ")) + LOGGER.debug( + "%s %s", + "decoded data: ".rjust(19 + len(self.name)), + self._data.hex(" "), + ) self._data_event.set() diff --git a/custom_components/hunterdouglas_powerview_ble/cover.py b/custom_components/hunterdouglas_powerview_ble/cover.py index d5d9327..90be957 100644 --- a/custom_components/hunterdouglas_powerview_ble/cover.py +++ b/custom_components/hunterdouglas_powerview_ble/cover.py @@ -33,7 +33,11 @@ async def async_setup_entry( """Set up the demo cover platform.""" coordinator: PVCoordinator = config_entry.runtime_data - async_add_entities([PowerViewCover(coordinator)]) + async_add_entities( + [PowerViewCoverTilt(coordinator)] + if coordinator.dev_details.get("model") in ["51", "62"] + else [PowerViewCover(coordinator)] + ) class PowerViewCover(PassiveBluetoothCoordinatorEntity[PVCoordinator], CoverEntity): # type: ignore[reportIncompatibleVariableOverride] @@ -53,8 +57,9 @@ class PowerViewCover(PassiveBluetoothCoordinatorEntity[PVCoordinator], CoverEnti coordinator: PVCoordinator, ) -> None: """Initialize the shade.""" + LOGGER.debug("%s: init() PowerViewCover", coordinator.name) self._attr_name = CoverDeviceClass.SHADE - self._coord = coordinator + self._coord: PVCoordinator = coordinator self._attr_device_info = self._coord.device_info self._target_position: int | None = round( self._coord.data.get(ATTR_CURRENT_POSITION, OPEN_POSITION) @@ -187,6 +192,13 @@ class PowerViewCoverTilt(PowerViewCover): # | CoverEntityFeature.OPEN_TILT ) + def __init__( + self, + coordinator: PVCoordinator, + ) -> None: + LOGGER.debug("%s: init() PowerViewCoverTilt", coordinator.name) + super().__init__(coordinator) + @property def current_cover_tilt_position(self) -> int | None: # type: ignore[reportIncompatibleVariableOverride] """Return current tilt of cover.