Skip to content

Commit

Permalink
Merge pull request #21 from Tvalley71/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Tvalley71 authored Apr 28, 2024
2 parents a2b4f0c + 25dc32b commit 7d5a0dd
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 61 deletions.
2 changes: 1 addition & 1 deletion custom_components/dantherm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
)

PLATFORMS = [
"button",
# "button", # left out for now
"cover",
"number",
"select",
Expand Down
14 changes: 9 additions & 5 deletions custom_components/dantherm/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
from typing import Any

from homeassistant.components.button import ButtonEntityDescription
from homeassistant.components.cover import CoverDeviceClass, CoverEntityDescription
from homeassistant.components.cover import (
CoverDeviceClass,
CoverEntityDescription,
CoverEntityFeature,
)
from homeassistant.components.number import (
NumberDeviceClass,
NumberEntityDescription,
Expand Down Expand Up @@ -95,7 +99,9 @@ class DanthermButtonEntityDescription(ButtonEntityDescription):
class DanthermCoverEntityDescription(CoverEntityDescription):
"""Dantherm Cover Entity Description."""

supported_features: CoverEntityFeature | None = None
data_setaddress: int | None = None
data_setinternal: str | None = None
data_setclass: DataClass | None = None
state_open: int = None
state_close: int = None
Expand Down Expand Up @@ -201,10 +207,8 @@ class DanthermSwitchEntityDescription(SwitchEntityDescription):
COVER_TYPES: dict[str, list[DanthermCoverEntityDescription]] = {
"bypass_damper": DanthermCoverEntityDescription(
key="bypass_damper",
data_setaddress=168,
data_setclass=DataClass.UInt16,
state_open=0x0080,
state_close=0x8080,
supported_features=CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE,
data_setinternal="set_bypass_damper",
data_address=198,
data_class=DataClass.UInt16,
state_opening=64,
Expand Down
116 changes: 64 additions & 52 deletions custom_components/dantherm/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@
from typing import Any

from homeassistant.components.cover import CoverEntity, CoverEntityFeature
from homeassistant.const import (
STATE_CLOSED,
STATE_CLOSING,
STATE_OPEN,
STATE_OPENING,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.const import STATE_CLOSED, STATE_CLOSING, STATE_OPEN, STATE_OPENING
from homeassistant.core import HomeAssistant

from .const import COVER_TYPES, DOMAIN, DanthermCoverEntityDescription
Expand Down Expand Up @@ -49,46 +42,63 @@ def __init__(
self.has_entity_name = True
self.entity_description: DanthermCoverEntityDescription = description
self._attr_supported_features = 0
if description.state_open:
self._attr_supported_features |= CoverEntityFeature.OPEN
if description.state_close:
self._attr_supported_features |= CoverEntityFeature.CLOSE
if description.state_stop:
self._attr_supported_features |= CoverEntityFeature.STOP
if description.supported_features:
self._attr_supported_features = description.supported_features
else:
if description.state_open:
self._attr_supported_features |= CoverEntityFeature.OPEN
if description.state_close:
self._attr_supported_features |= CoverEntityFeature.CLOSE
if description.state_stop:
self._attr_supported_features |= CoverEntityFeature.STOP

# states
self._attr_available = False
self._attr_is_closed = False
self._attr_is_closing = False
self._attr_is_opening = False
self._attr_last_state: int = 0
self._call_active = False

async def async_open_cover(self, **kwargs: Any) -> None:
"""Open cover."""
result = await self._device.write_holding_registers(
description=self.entity_description,
value=self.entity_description.state_open,
)
self._attr_available = result is not None
self.async_update_ha_state(True)

if self.entity_description.data_setinternal:
await getattr(self._device, self.entity_description.data_setinternal)(
CoverEntityFeature.OPEN
)
else:
await self._device.write_holding_registers(
description=self.entity_description,
value=self.entity_description.state_open,
)
# await self.async_update_ha_state(True)

async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover."""
result = await self._device.write_holding_registers(
description=self.entity_description,
value=self.entity_description.state_close,
)
self._attr_available = result is not None
self.async_update_ha_state(True)

if self.entity_description.data_setinternal:
await getattr(self._device, self.entity_description.data_setinternal)(
CoverEntityFeature.CLOSE
)
else:
await self._device.write_holding_registers(
description=self.entity_description,
value=self.entity_description.state_close,
)
# await self.async_update_ha_state(True)

async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop cover."""
result = await self._device.write_holding_registers(
description=self.entity_description,
value=self.entity_description.state_stop,
)
self._attr_available = result is not None
self.async_update_ha_state(True)

if self.entity_description.data_setinternal:
await getattr(self._device, self.entity_description.data_setinternal)(
CoverEntityFeature.STOP
)
else:
await self._device.write_holding_registers(
description=self.entity_description,
value=self.entity_description.state_stop,
)
# await self.async_update_ha_state(True)

@property
def native_value(self):
Expand All @@ -98,28 +108,30 @@ def native_value(self):
async def async_update(self, now: datetime | None = None) -> None:
"""Update the state of the cover."""

self._attr_last_state = STATE_UNKNOWN
result = await self._device.read_holding_registers(
description=self.entity_description
)

if result is None:
self._attr_available = False
elif result == self.entity_description.state_closed:
self._attr_state = STATE_CLOSED
self._attr_is_closed = True
self._attr_is_closing = False
self._attr_is_opening = False
elif result == self.entity_description.state_closing:
self._attr_state = STATE_CLOSING
self._attr_is_closing = True
elif result == self.entity_description.state_opening:
self._attr_state = STATE_OPENING
self._attr_is_opening = True
elif result == self.entity_description.state_open:
self._attr_state = STATE_OPEN
self._attr_is_closed = False
self._attr_is_closing = False
self._attr_is_opening = False
else:
self._attr_state = STATE_UNAVAILABLE
self._attr_available = True

if result == self.entity_description.state_closed:
self._attr_state = STATE_CLOSED
self._attr_is_closed = True
self._attr_is_closing = False
self._attr_is_opening = False
elif result == self.entity_description.state_closing:
self._attr_state = STATE_CLOSING
self._attr_is_closing = True
self._attr_is_opening = False
elif result == self.entity_description.state_opening:
self._attr_state = STATE_OPENING
self._attr_is_opening = True
self._attr_is_closing = False
elif result == self.entity_description.state_opened:
self._attr_state = STATE_OPEN
self._attr_is_closed = False
self._attr_is_closing = False
self._attr_is_opening = False
21 changes: 18 additions & 3 deletions custom_components/dantherm/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadBuilder, BinaryPayloadDecoder

from homeassistant.components.cover import CoverEntityFeature
from homeassistant.components.modbus import modbus
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import Entity, EntityDescription
Expand Down Expand Up @@ -134,7 +135,11 @@ async def setup(self):
_LOGGER.error("Modbus setup was unsuccessful")
raise ValueError("Modbus setup was unsuccessful")

self._device_installed_components = await self._read_holding_uint16(610)
result = await self._read_holding_uint16(610)
if result is None:
raise ValueError("Dantherm unit probably not responding")

self._device_installed_components = result
_LOGGER.debug(
"Installed components (610) = %s",
hex(self._device_installed_components),
Expand Down Expand Up @@ -304,6 +309,14 @@ async def set_fan_level(self, value):

await self._write_holding_uint32(324, value)

async def set_bypass_damper(self, feature: CoverEntityFeature = None):
"""Set bypass damper."""

if self.get_active_unit_mode & 0x80 == 0x80:
await self.set_active_unit_mode(0x8080)
else:
await self.set_active_unit_mode(0x80)

async def read_holding_registers(
self,
description: EntityDescription | None = None,
Expand Down Expand Up @@ -421,7 +434,7 @@ async def _read_holding_registers(self, address, count):
self._unit_id, address, count, "holding"
)
if result is None:
_LOGGER.log(
_LOGGER.error(
"Error reading holding register=%s count=%s", str(address), str(count)
)
return result
Expand All @@ -436,7 +449,7 @@ async def _write_holding_registers(self, address, values: list[int] | int):
"write_registers",
)
if result is None:
_LOGGER.log(
_LOGGER.error(
"Error writing holding register=%s values=%s", str(address), str(values)
)

Expand Down Expand Up @@ -495,6 +508,8 @@ async def _read_holding_uint16(self, address):
"""Read holding uint16 registers."""

result = await self._read_holding_registers(address, 1)
if result is None:
return None
decoder = BinaryPayloadDecoder.fromRegisters(
result.registers, byteorder=Endian.BIG, wordorder=Endian.LITTLE
)
Expand Down

0 comments on commit 7d5a0dd

Please sign in to comment.