Complete strict typing for ElkM1 integration (#70334)

This commit is contained in:
Glenn Waters 2022-04-20 15:04:11 -04:00 committed by GitHub
parent 64381acbaf
commit 2abe551eef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 119 deletions

View file

@ -1,13 +1,22 @@
"""Support for control of ElkM1 sensors."""
from __future__ import annotations
from typing import Any
from elkm1_lib.const import (
SettingFormat,
ZoneLogicalStatus,
ZonePhysicalStatus,
ZoneType,
)
from elkm1_lib.counters import Counter
from elkm1_lib.elements import Element
from elkm1_lib.elk import Elk
from elkm1_lib.keypads import Keypad
from elkm1_lib.panel import Panel
from elkm1_lib.settings import Setting
from elkm1_lib.util import pretty_const
from elkm1_lib.zones import Zone
import voluptuous as vol
from homeassistant.components.sensor import SensorEntity
@ -73,43 +82,45 @@ async def async_setup_entry(
)
def temperature_to_state(temperature, undefined_temperature):
def temperature_to_state(temperature: int, undefined_temperature: int) -> str | None:
"""Convert temperature to a state."""
return temperature if temperature > undefined_temperature else None
return f"{temperature}" if temperature > undefined_temperature else None
class ElkSensor(ElkAttachedEntity, SensorEntity):
"""Base representation of Elk-M1 sensor."""
def __init__(self, element, elk, elk_data):
def __init__(self, element: Element, elk: Elk, elk_data: dict[str, Any]) -> None:
"""Initialize the base of all Elk sensors."""
super().__init__(element, elk, elk_data)
self._state = None
self._state: str | None = None
@property
def native_value(self):
def native_value(self) -> str | None:
"""Return the state of the sensor."""
return self._state
async def async_counter_refresh(self):
async def async_counter_refresh(self) -> None:
"""Refresh the value of a counter from the panel."""
if not isinstance(self, ElkCounter):
raise HomeAssistantError("supported only on ElkM1 Counter sensors")
self._element.get()
async def async_counter_set(self, value=None):
async def async_counter_set(self, value: int | None = None) -> None:
"""Set the value of a counter on the panel."""
if not isinstance(self, ElkCounter):
raise HomeAssistantError("supported only on ElkM1 Counter sensors")
self._element.set(value)
if value is not None:
self._element.set(value)
async def async_zone_bypass(self, code=None):
async def async_zone_bypass(self, code: int | None = None) -> None:
"""Bypass zone."""
if not isinstance(self, ElkZone):
raise HomeAssistantError("supported only on ElkM1 Zone sensors")
self._element.bypass(code)
if code is not None:
self._element.bypass(code)
async def async_zone_trigger(self):
async def async_zone_trigger(self) -> None:
"""Trigger zone."""
if not isinstance(self, ElkZone):
raise HomeAssistantError("supported only on ElkM1 Zone sensors")
@ -119,37 +130,41 @@ class ElkSensor(ElkAttachedEntity, SensorEntity):
class ElkCounter(ElkSensor):
"""Representation of an Elk-M1 Counter."""
_element: Counter
@property
def icon(self):
def icon(self) -> str:
"""Icon to use in the frontend."""
return "mdi:numeric"
def _element_changed(self, element, changeset):
def _element_changed(self, _: Element, changeset: Any) -> None:
self._state = self._element.value
class ElkKeypad(ElkSensor):
"""Representation of an Elk-M1 Keypad."""
_element: Keypad
@property
def temperature_unit(self):
def temperature_unit(self) -> str:
"""Return the temperature unit."""
return self._temperature_unit
@property
def native_unit_of_measurement(self):
def native_unit_of_measurement(self) -> str:
"""Return the unit of measurement."""
return self._temperature_unit
@property
def icon(self):
def icon(self) -> str:
"""Icon to use in the frontend."""
return "mdi:thermometer-lines"
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Attributes of the sensor."""
attrs = self.initial_attrs()
attrs: dict[str, Any] = self.initial_attrs()
attrs["area"] = self._element.area + 1
attrs["temperature"] = self._state
attrs["last_user_time"] = self._element.last_user_time.isoformat()
@ -159,7 +174,7 @@ class ElkKeypad(ElkSensor):
attrs["last_keypress"] = self._element.last_keypress
return attrs
def _element_changed(self, element, changeset):
def _element_changed(self, _: Element, changeset: Any) -> None:
self._state = temperature_to_state(
self._element.temperature, UNDEFINED_TEMPERATURE
)
@ -169,20 +184,21 @@ class ElkPanel(ElkSensor):
"""Representation of an Elk-M1 Panel."""
_attr_entity_category = EntityCategory.DIAGNOSTIC
_element: Panel
@property
def icon(self):
def icon(self) -> str:
"""Icon to use in the frontend."""
return "mdi:home"
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Attributes of the sensor."""
attrs = self.initial_attrs()
attrs["system_trouble_status"] = self._element.system_trouble_status
return attrs
def _element_changed(self, element, changeset):
def _element_changed(self, _: Element, changeset: Any) -> None:
if self._elk.is_connected():
self._state = (
"Paused" if self._element.remote_programming_status else "Connected"
@ -194,18 +210,20 @@ class ElkPanel(ElkSensor):
class ElkSetting(ElkSensor):
"""Representation of an Elk-M1 Setting."""
_element: Setting
@property
def icon(self):
def icon(self) -> str:
"""Icon to use in the frontend."""
return "mdi:numeric"
def _element_changed(self, element, changeset):
def _element_changed(self, _: Element, changeset: Any) -> None:
self._state = self._element.value
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Attributes of the sensor."""
attrs = self.initial_attrs()
attrs: dict[str, Any] = self.initial_attrs()
attrs["value_format"] = SettingFormat(self._element.value_format).name.lower()
return attrs
@ -213,8 +231,10 @@ class ElkSetting(ElkSensor):
class ElkZone(ElkSensor):
"""Representation of an Elk-M1 Zone."""
_element: Zone
@property
def icon(self):
def icon(self) -> str:
"""Icon to use in the frontend."""
zone_icons = {
ZoneType.FIRE_ALARM.value: "fire",
@ -240,9 +260,9 @@ class ElkZone(ElkSensor):
return f"mdi:{zone_icons.get(self._element.definition, 'alarm-bell')}"
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Attributes of the sensor."""
attrs = self.initial_attrs()
attrs: dict[str, Any] = self.initial_attrs()
attrs["physical_status"] = ZonePhysicalStatus(
self._element.physical_status
).name.lower()
@ -255,14 +275,14 @@ class ElkZone(ElkSensor):
return attrs
@property
def temperature_unit(self):
def temperature_unit(self) -> str | None:
"""Return the temperature unit."""
if self._element.definition == ZoneType.TEMPERATURE.value:
return self._temperature_unit
return None
@property
def native_unit_of_measurement(self):
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement."""
if self._element.definition == ZoneType.TEMPERATURE.value:
return self._temperature_unit
@ -270,13 +290,13 @@ class ElkZone(ElkSensor):
return ELECTRIC_POTENTIAL_VOLT
return None
def _element_changed(self, element, changeset):
def _element_changed(self, _: Element, changeset: Any) -> None:
if self._element.definition == ZoneType.TEMPERATURE.value:
self._state = temperature_to_state(
self._element.temperature, UNDEFINED_TEMPERATURE
)
elif self._element.definition == ZoneType.ANALOG_ZONE.value:
self._state = self._element.voltage
self._state = f"{self._element.voltage}"
else:
self._state = pretty_const(
ZoneLogicalStatus(self._element.logical_status).name