Skip to content
217 changes: 215 additions & 2 deletions custom_components/wiser/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DATA, DOMAIN, MANUFACTURER
from .const import DATA, DOMAIN, MANUFACTURER, MANUFACTURER_SCHNEIDER
from .helpers import get_device_name, get_identifier, get_room_name, get_unique_id

_LOGGER = logging.getLogger(__name__)
Expand All @@ -21,6 +21,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie

binary_sensors = []

# System sensors
if data.wiserhub.system:
binary_sensors.extend(
[
WiserSummerDiscomfortPrevention(data, 0, "Summer Discomfort Prevention"),
WiserSummerComfortAvailable(data, 0, "Summer Comfort Available"),
WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached")
]
)

# Smoke alarm sensors
for device in data.wiserhub.devices.smokealarms.all:
binary_sensors.extend(
Expand All @@ -44,11 +54,22 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie
]
)

# Room binary sensors
for room in data.wiserhub.rooms.all:
binary_sensors.extend(
[
WiserRoomWindow(data, room.id, "Window Detection Active"),
]
)

# Light sensors
for device in data.wiserhub.devices.lights.all:
binary_sensors.extend(
[
WiserStateIsDimmable(data, device.id, "Is Dimmable"),
WiserStateIsDimmable(data, device.id, "Is LED Indicator Supported"),
WiserStateIsDimmable(data, device.id, "Is Output Mode Supported"),
WiserStateIsDimmable(data, device.id, "Is Power On Behaviour Supported"),
]
)

Expand All @@ -62,9 +83,21 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie
]
)

# Itrv sensors
for device in data.wiserhub.devices.smartvalves.all:
binary_sensors.extend(
[
WiserWindow(data, device.id, "Window State"),
]
)

# Binary sensors active
for device in data.wiserhub.devices.binary_sensor.all:
binary_sensors.extend([BaseBinarySensor(data, device.id, "Active")])
binary_sensors.extend(
[
WiserStateActive(data, device.id, "Active"),
]
)

async_add_entities(binary_sensors, True)

Expand All @@ -83,6 +116,13 @@ def __init__(
self._device_name = None
self._sensor_type = sensor_type
self._device_data_key = device_data_key
self._icon = "mdi:window-shutter"
if self._sensor_type == "Door":
self._icon = "mdi:door"
BinarySensorDeviceClass.DOOR
if self._sensor_type == "Window":
self._icon = "mdi:window-closed"
BinarySensorDeviceClass.WINDOW

_LOGGER.info(
f"{self._data.wiserhub.system.name} {self.name} initalise" # noqa: E501
Expand Down Expand Up @@ -125,6 +165,15 @@ def name(self):
"""Return the name of the sensor."""
return f"{get_device_name(self._data, self._device_id)} {self._sensor_type}"

@property
def icon(self):
"""Return an icon of the sensor."""
if self._sensor_type == "Door":
return "mdi:door"
if self._sensor_type == "Window":
return "mdi:window-closed"


@property
def unique_id(self):
"""Return uniqueid."""
Expand All @@ -143,6 +192,112 @@ def device_info(self):
}


class SystemBinarySensor(CoordinatorEntity, BinarySensorEntity):
"""Base binary sensor class."""

def __init__(self, coordinator, device_id=0, sensor_type="") -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self._data = coordinator
self._device_name = None
self._sensor_type = sensor_type
self._state = getattr(self._data.wiserhub.system, self._sensor_type.replace(" ", "_").lower())
_LOGGER.debug(
f"{self._data.wiserhub.system.name} {self.name} initalise" # noqa: E501
)

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
_LOGGER.debug(f"{self.name} device update requested")
HeatHub = self._data.wiserhub.system.name
HeatHub = HeatHub.replace("WiserHeat","HeatHub")
return f"{HeatHub} {self._sensor_type}"

@property
def is_on(self):
"""Return the state of the sensor."""
return self._state

@property
def name(self):
"""Return the name of the sensor."""
# return f"{get_device_name(self._data, self._data.wiserhub.system)} {self._sensor_type}"
HeatHub = self._data.wiserhub.system.name
HeatHub = HeatHub.replace("WiserHeat","HeatHub")
#return f"{HeatHub} {self._sensor_type}"
return f"{get_device_name(self._data, 0,self._sensor_type)}"

@property
def unique_id(self):
"""Return uniqueid."""
return get_unique_id(self._data, "sensor", self._sensor_type, self.name)

@property
def device_info(self):
"""Return device specific attributes."""
return {
"name": get_device_name(self._data, 0),
"identifiers": {(DOMAIN, get_identifier(self._data, 0))},
"manufacturer": MANUFACTURER_SCHNEIDER,
"model": self._data.wiserhub.system.product_type,
"sw_version": self._data.wiserhub.system.firmware_version,
"via_device": (DOMAIN, self._data.wiserhub.system.name),
}


class RoomBinarySensor(CoordinatorEntity, BinarySensorEntity):
"""Base binary sensor class."""

def __init__(self, coordinator, room_id=0, sensor_type="") -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self._data = coordinator
self._room_id = room_id
self._room = self._data.wiserhub.rooms.get_by_id(self._room_id)
self._room_name = None
self._sensor_type = sensor_type
self._state = getattr(self._room, self._sensor_type.replace(" ", "_").lower())
_LOGGER.debug(
f"{self._data.wiserhub.system.name} {self.name} initalise" # noqa: E501
)

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
_LOGGER.debug(f"{self.name} device update requested")
self._room = self._data.wiserhub.rooms.get_by_id(self._room_id)
self._state = getattr(self._room, self._sensor_type.replace(" ", "_").lower())
self.async_write_ha_state()

@property
def is_on(self):
"""Return the state of the sensor."""
return self._state

@property
def name(self):
"""Return the name of the sensor."""
return f"{get_room_name(self._data, self._room_id)} {self._sensor_type}"

@property
def unique_id(self):
"""Return uniqueid."""
return get_unique_id(self._data, "sensor", self._sensor_type, self._room_id)

@property
def device_info(self):
"""Return device specific attributes."""
return {
"name": get_room_name(self._data, self._room_id ),
"identifiers": {(DOMAIN, get_identifier(self._data, self._room_id, "room"))},
"manufacturer": MANUFACTURER_SCHNEIDER,
"model": self._data.wiserhub.system.product_type,
"sw_version": self._data.wiserhub.system.firmware_version,
"via_device": (DOMAIN, self._data.wiserhub.system.name),
}


class WiserSmokeAlarm(BaseBinarySensor):
"""Smoke Alarm sensor."""

Expand Down Expand Up @@ -192,6 +347,29 @@ class WiserRemoteAlarm(BaseBinarySensor):
class WiserEquipment(BaseBinarySensor):
"""Base binary sensor class."""

# binary sensor of System

class WiserSummerDiscomfortPrevention(SystemBinarySensor):
"""Summer Discomfort Prevention sensor."""
_attr_device_class = BinarySensorDeviceClass.HEAT

@property
def extra_state_attributes(self):
"""Return the state attributes of Summer discomfort prevention."""
attrs = {}
attrs["indoor_discomfort_temperature"] = self._data.wiserhub.system.indoor_discomfort_temperature
attrs["outdoor_discomfort_temperature"] = self._data.wiserhub.system.outdoor_discomfort_temperature
return attrs

class WiserSummerComfortAvailable(SystemBinarySensor):
"""Summer Comfort Available sensor."""
_attr_icon = "mdi:sofa"
#_attr_device_class = BinarySensorDeviceClass.HEAT

class WiserPCMDeviceLimitReached(SystemBinarySensor):
"""Summer Comfort Available sensor."""
_attr_device_class = BinarySensorDeviceClass.POWER


class WiserStateIsDimmable(BaseBinarySensor):
"""Light IsDimmable sensor."""
Expand All @@ -207,10 +385,45 @@ class WiserStateIsOpen(BaseBinarySensor):
"""Light IsDIs Open sensor."""

_attr_device_class = BinarySensorDeviceClass.OPENING
_attr_icon = "mdi:window-shutter-open"


class WiserStateIsClosed(BaseBinarySensor):
"""Light IsDimmable sensor."""

_attr_device_class = BinarySensorDeviceClass.OPENING
_attr_icon = "mdi:window-shutter"

## binary sensor of Room
class WiserRoomWindow(RoomBinarySensor):
"""Window of room sensor."""
# _attr_device_class = BinarySensorDeviceClass.WINDOW

class WiserWindow(BaseBinarySensor):
"""Window sensor."""
_attr_device_class = BinarySensorDeviceClass.WINDOW

#Windowdoor
class WiserStateActive(BaseBinarySensor):
"""WindowDoor sensor."""

@property
def extra_state_attributes(self):
"""Return the state attributes of WindowDoor sensor."""
attrs = {}
if self._data.wiserhub.devices.binary_sensor.get_by_id(
self._device_id
).type == "Door" :
attrs["device_class"] = BinarySensorDeviceClass.DOOR
else: attrs["device_class"] = BinarySensorDeviceClass.WINDOW
attrs["type"] = self._data.wiserhub.devices.binary_sensor.get_by_id(
self._device_id
).type

return attrs

#WindowDoor sensor
class WiserWindowDoorSensor(BaseBinarySensor):
"""Shutter Is Open sensor."""

_attr_device_class = BinarySensorDeviceClass.OPENING
14 changes: 14 additions & 0 deletions custom_components/wiser/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,17 @@ def get_config_entry_id_by_name(hass: HomeAssistant, name) -> str or None:
if entry:
return entry[0].entry_id
return None

# added by LGO for equipment management
def get_equipment_name(data, equipment_id):
"""Get the name of the equipment based on its ID."""
equipment = data.wiserhub.equipments.get_equip_by_id(equipment_id)
if equipment:
return f"{ENTITY_PREFIX} {equipment.name}"
return f"{ENTITY_PREFIX} Equipment {equipment_id}" # Fallback if no name found

def get_equipment_identifier(data, equipment_id, device_type):
return (
f"{data.wiserhub.system.name} {get_device_name(data, equipment_id, device_type)}"
)

2 changes: 1 addition & 1 deletion custom_components/wiser/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/asantaga/wiserHomeAssistantPlatform/issues",
"requirements": [
"aioWiserHeatAPI==1.7.0"
"aioWiserHeatAPI==1.7.1"
],
"version": "3.4.18",
"zeroconf": [
Expand Down
Loading
Loading