Skip to content

Commit

Permalink
Merge pull request #65 from mariusz-ostoja-swierczynski/add_57
Browse files Browse the repository at this point in the history
✨ Add support for zone actuators
  • Loading branch information
anarion80 authored Mar 24, 2024
2 parents f5d76ca + 2d4af1f commit 6d6db2d
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 9 deletions.
4 changes: 4 additions & 0 deletions custom_components/tech/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
VALUE = "value"
MANUFACTURER = "TechControllers"
WORKING_STATUS = "workingStatus"
ACTUATORS = "actuators"
BATTERY_LEVEL = "batteryLevel"
SIGNAL_STRENGTH = "signalStrength"
ACTUATORS_OPEN = "actuatorsOpen"

DEFAULT_ICON = "mdi:eye"

Expand Down
123 changes: 114 additions & 9 deletions custom_components/tech/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@

from . import TechCoordinator, assets
from .const import (
ACTUATORS,
ACTUATORS_OPEN,
BATTERY_LEVEL,
CONTROLLER,
DOMAIN,
MANUFACTURER,
Expand Down Expand Up @@ -103,6 +106,7 @@ async def async_setup_entry(
battery_devices = map_to_battery_sensors(zones, coordinator, config_entry)
temperature_sensors = map_to_temperature_sensors(zones, coordinator, config_entry)
humidity_sensors = map_to_humidity_sensors(zones, coordinator, config_entry)
actuator_sensors = map_to_actuator_sensors(zones, coordinator, config_entry)
signal_strength_sensors = map_to_signal_strength_sensors(
zones, coordinator, config_entry
)
Expand All @@ -113,6 +117,7 @@ async def async_setup_entry(
battery_devices,
temperature_sensors,
humidity_sensors, # , tile_sensors
actuator_sensors,
signal_strength_sensors,
),
True,
Expand Down Expand Up @@ -151,7 +156,7 @@ def is_battery_operating_device(device) -> bool:
bool - True if the device is operating on battery, False otherwise.
"""
return device[CONF_ZONE]["batteryLevel"] is not None
return device[CONF_ZONE][BATTERY_LEVEL] is not None


def map_to_temperature_sensors(zones, coordinator, config_entry):
Expand Down Expand Up @@ -228,6 +233,45 @@ def is_humidity_operating_device(device) -> bool:
)


def map_to_actuator_sensors(zones, coordinator, config_entry):
"""Map zones to actuator sensors.
Args:
zones: list of zones
coordinator: API to interact with actuators
config_entry: configuration entry for the sensors
Returns:
list of ZoneActuatorSensor instances
"""
# Filter devices that are actuator operating devices
devices = [
deviceIndex
for deviceIndex in zones
if is_actuator_operating_device(zones[deviceIndex])
]

return [
ZoneActuatorSensor(zones[deviceIndex], coordinator, config_entry, idx)
for deviceIndex in devices
for idx in range(len(zones[deviceIndex][ACTUATORS]))
]


def is_actuator_operating_device(device) -> bool:
"""Check if the device has any actuators.
Args:
device: dict - The device information containing the zone and humidity level.
Returns:
bool - True if the device has any actuators, False otherwise.
"""
return len(device[ACTUATORS]) > 0


def map_to_tile_sensors(tiles, coordinator, config_entry):
"""Map tiles to corresponding sensor objects based on the device type and create a list of sensor objects.
Expand Down Expand Up @@ -341,7 +385,7 @@ def update_properties(self, device):
"""
self._name = device[CONF_DESCRIPTION][CONF_NAME]
self._attr_native_value = device[CONF_ZONE]["batteryLevel"]
self._attr_native_value = device[CONF_ZONE][BATTERY_LEVEL]

@callback
def _handle_coordinator_update(self, *args: Any) -> None:
Expand Down Expand Up @@ -640,7 +684,6 @@ def __init__(
self, device: Dict, coordinator: TechCoordinator, config_entry: ConfigEntry
):
"""Initialize the sensor."""
_LOGGER.debug("Init ZoneSensor...")
super().__init__(coordinator)
self._config_entry = config_entry
self._coordinator = coordinator
Expand Down Expand Up @@ -782,7 +825,7 @@ def update_properties(self, device):
"""
self._name = device[CONF_DESCRIPTION][CONF_NAME]
self._attr_native_value = device[CONF_ZONE]["batteryLevel"]
self._attr_native_value = device[CONF_ZONE][BATTERY_LEVEL]


class ZoneSignalStrengthSensor(ZoneSensor):
Expand All @@ -792,11 +835,6 @@ class ZoneSignalStrengthSensor(ZoneSensor):
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_icon = "mdi:signal"

def __init__(self, device, coordinator, controller_udid):
"""Initialize the sensor."""
self.attrs: Dict[str, Any] = {}
super().__init__(device, coordinator, controller_udid)

@property
def name(self):
"""Return the name of the device."""
Expand Down Expand Up @@ -858,6 +896,73 @@ def update_properties(self, device):
self._attr_native_value = None


class ZoneActuatorSensor(ZoneSensor):
"""Representation of a Zone Actuator Sensor."""

_attr_native_unit_of_measurement = PERCENTAGE
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_icon = assets.get_icon_by_type(TYPE_VALVE)

def __init__(self, device, coordinator, config_entry, actuator_index):
"""Initialize the sensor.
These are needed before the call to super, as ZoneSensor class
calls update_properties in its init, which actually calls this class
update_properties, which does not know attrs and _actuator_index already.
"""
self._actuator_index = actuator_index
self.attrs: Dict[str, Any] = {}
super().__init__(device, coordinator, config_entry)
self.attrs[BATTERY_LEVEL] = device[ACTUATORS][self._actuator_index][
BATTERY_LEVEL
]
self.attrs[SIGNAL_STRENGTH] = device[ACTUATORS][self._actuator_index][
SIGNAL_STRENGTH
]

@property
def unique_id(self) -> str:
"""Return a unique ID."""
return f"{self._unique_id}_zone_actuator_{str(self._actuator_index + 1)}"

@property
def name(self):
"""Return the name of the entity."""
return f"{self._name} actuator {str(self._actuator_index + 1)}"

@property
def extra_state_attributes(self) -> Dict[str, Any]:
"""Return the state attributes."""
attributes = {}
attributes.update(self.attrs)
return attributes

def update_properties(self, device):
"""Update the properties of the ZoneActuatorSensor object.
Args:
device (dict): The device information.
Returns:
None
"""
# Update the name of the device
self._name = device[CONF_DESCRIPTION][CONF_NAME]

# Update the native value attribute
self._attr_native_value = device[CONF_ZONE][ACTUATORS_OPEN]

# Update battery and signal strength
self.attrs[BATTERY_LEVEL] = device[ACTUATORS][self._actuator_index][
BATTERY_LEVEL
]
self.attrs[SIGNAL_STRENGTH] = device[ACTUATORS][self._actuator_index][
SIGNAL_STRENGTH
]


class ZoneOutsideTempTile(ZoneSensor):
"""Representation of a Zone Temperature Sensor."""

Expand Down

0 comments on commit 6d6db2d

Please sign in to comment.