Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport binary_sensor entity #765

Merged
merged 4 commits into from
Feb 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 64 additions & 38 deletions custom_components/tahoma/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,147 +1,173 @@
"""Support for Overkiz binary sensors."""
from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass
from typing import cast

from pyoverkiz.enums import OverkizCommandParam, OverkizState
from pyoverkiz.types import StateType as OverkizStateType

from custom_components.tahoma import HomeAssistantOverkizData
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import HomeAssistantOverkizData
from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES
from .entity import OverkizBinarySensorDescription, OverkizDescriptiveEntity
from .entity import OverkizDescriptiveEntity


@dataclass
class OverkizBinarySensorDescriptionMixin:
"""Define an entity description mixin for binary sensor entities."""

value_fn: Callable[[OverkizStateType], bool]


@dataclass
class OverkizBinarySensorDescription(
BinarySensorEntityDescription, OverkizBinarySensorDescriptionMixin
):
"""Class to describe an Overkiz binary sensor."""

BINARY_SENSOR_DESCRIPTIONS = [

BINARY_SENSOR_DESCRIPTIONS: list[OverkizBinarySensorDescription] = [
# RainSensor/RainSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_RAIN,
name="Rain",
icon="mdi:weather-rainy",
is_on=lambda state: state == OverkizCommandParam.DETECTED,
value_fn=lambda state: state == OverkizCommandParam.DETECTED,
),
# SmokeSensor/SmokeSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_SMOKE,
name="Smoke",
device_class=BinarySensorDeviceClass.SMOKE,
is_on=lambda state: state == OverkizCommandParam.DETECTED,
value_fn=lambda state: state == OverkizCommandParam.DETECTED,
),
# WaterSensor/WaterDetectionSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_WATER_DETECTION,
name="Water",
icon="mdi:water",
is_on=lambda state: state == OverkizCommandParam.DETECTED,
value_fn=lambda state: state == OverkizCommandParam.DETECTED,
),
# AirSensor/AirFlowSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_GAS_DETECTION,
name="Gas",
device_class=BinarySensorDeviceClass.GAS,
is_on=lambda state: state == OverkizCommandParam.DETECTED,
value_fn=lambda state: state == OverkizCommandParam.DETECTED,
),
# OccupancySensor/OccupancySensor
# OccupancySensor/MotionSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_OCCUPANCY,
name="Occupancy",
device_class=BinarySensorDeviceClass.OCCUPANCY,
is_on=lambda state: state == OverkizCommandParam.PERSON_INSIDE,
value_fn=lambda state: state == OverkizCommandParam.PERSON_INSIDE,
),
# ContactSensor/WindowWithTiltSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_VIBRATION,
name="Vibration",
device_class=BinarySensorDeviceClass.VIBRATION,
is_on=lambda state: state == OverkizCommandParam.DETECTED,
value_fn=lambda state: state == OverkizCommandParam.DETECTED,
),
# ContactSensor/ContactSensor
OverkizBinarySensorDescription(
key=OverkizState.CORE_CONTACT,
name="Contact",
device_class=BinarySensorDeviceClass.DOOR,
is_on=lambda state: state == OverkizCommandParam.OPEN,
value_fn=lambda state: state == OverkizCommandParam.OPEN,
),
# Siren/SirenStatus
OverkizBinarySensorDescription(
key=OverkizState.CORE_ASSEMBLY,
name="Assembly",
device_class=BinarySensorDeviceClass.PROBLEM,
is_on=lambda state: state == OverkizCommandParam.OPEN,
value_fn=lambda state: state == OverkizCommandParam.OPEN,
),
# Unknown
OverkizBinarySensorDescription(
key=OverkizState.IO_VIBRATION_DETECTED,
name="Vibration",
device_class=BinarySensorDeviceClass.VIBRATION,
is_on=lambda state: state == OverkizCommandParam.DETECTED,
value_fn=lambda state: state == OverkizCommandParam.DETECTED,
),
# DomesticHotWaterProduction/WaterHeatingSystem
OverkizBinarySensorDescription(
key=OverkizState.IO_DHW_BOOST_MODE,
name="Boost Mode",
icon="hass:water-boiler-alert",
is_on=lambda state: state == OverkizCommandParam.ON,
value_fn=lambda state: state == OverkizCommandParam.ON,
),
OverkizBinarySensorDescription(
key=OverkizState.IO_DHW_ABSENCE_MODE,
name="Away Mode",
icon="hass:water-boiler-off",
is_on=lambda state: state == OverkizCommandParam.ON,
value_fn=lambda state: state == OverkizCommandParam.ON,
),
OverkizBinarySensorDescription(
key=OverkizState.IO_OPERATING_MODE_CAPABILITIES,
name="Energy Demand Status",
device_class=BinarySensorDeviceClass.HEAT,
is_on=lambda state: state.get(OverkizCommandParam.ENERGY_DEMAND_STATUS) == 1,
value_fn=lambda state: cast(dict, state).get(
OverkizCommandParam.ENERGY_DEMAND_STATUS
)
== 1,
),
]

SUPPORTED_STATES = {
description.key: description for description in BINARY_SENSOR_DESCRIPTIONS
}


async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
):
"""Set up the Overkiz sensors from a config entry."""
) -> None:
"""Set up the Overkiz binary sensors from a config entry."""
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
entities = []

key_supported_states = {
description.key: description for description in BINARY_SENSOR_DESCRIPTIONS
}
entities: list[OverkizBinarySensor] = []

for device in data.coordinator.data.values():
if (
device.widget not in IGNORED_OVERKIZ_DEVICES
and device.ui_class not in IGNORED_OVERKIZ_DEVICES
device.widget in IGNORED_OVERKIZ_DEVICES
or device.ui_class in IGNORED_OVERKIZ_DEVICES
):
for state in device.definition.states:
if description := key_supported_states.get(state.qualified_name):
entities.append(
OverkizBinarySensor(
device.device_url,
data.coordinator,
description,
)
continue

for state in device.definition.states:
if description := SUPPORTED_STATES.get(state.qualified_name):
entities.append(
OverkizBinarySensor(
device.device_url,
data.coordinator,
description,
)
)

async_add_entities(entities)


class OverkizBinarySensor(OverkizDescriptiveEntity, BinarySensorEntity):
"""Representation of an Overkiz Binary Sensor."""

entity_description: OverkizBinarySensorDescription

@property
def is_on(self):
def is_on(self) -> bool | None:
"""Return the state of the sensor."""
state = self.device.states.get(self.entity_description.key)

if not state:
return None
if state := self.device.states.get(self.entity_description.key):
return self.entity_description.value_fn(state.value)

return self.entity_description.is_on(state.value)
return None
8 changes: 0 additions & 8 deletions custom_components/tahoma/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pyoverkiz.enums import OverkizAttribute, OverkizCommandParam, OverkizState
from pyoverkiz.models import Device

from homeassistant.components.binary_sensor import BinarySensorEntityDescription
from homeassistant.components.select import SelectEntityDescription
from homeassistant.components.sensor import SensorEntityDescription
from homeassistant.const import ATTR_BATTERY_LEVEL
Expand Down Expand Up @@ -115,13 +114,6 @@ class OverkizSensorDescription(SensorEntityDescription):
] | None = lambda val: val


@dataclass
class OverkizBinarySensorDescription(BinarySensorEntityDescription):
"""Class to describe an Overkiz binary sensor."""

is_on: Callable[[str], bool] = lambda state: state


@dataclass
class OverkizSelectDescription(SelectEntityDescription):
"""Class to describe an Overkiz select entity."""
Expand Down