Add binary_sensor to venstar to track alerts (#58831)

* Add binary_sensor to venstar to track alerts

* Add binary_sensor.py to coveragerc

* Apply suggestions from code review by alengwenus

Co-authored-by: Andre Lengwenus <alengwenus@gmail.com>

* Fixup black any mypy complaints

* Yank the typing, it makes everything complain

Co-authored-by: Andre Lengwenus <alengwenus@gmail.com>
This commit is contained in:
Tim Rightnour 2021-11-05 04:00:57 -07:00 committed by GitHub
parent 8b25bd0cea
commit 5ac55b3443
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 1 deletions

View File

@ -1171,6 +1171,7 @@ omit =
homeassistant/components/velbus/switch.py
homeassistant/components/velux/*
homeassistant/components/venstar/__init__.py
homeassistant/components/venstar/binary_sensor.py
homeassistant/components/venstar/climate.py
homeassistant/components/verisure/__init__.py
homeassistant/components/verisure/alarm_control_panel.py

View File

@ -19,7 +19,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import _LOGGER, DOMAIN, VENSTAR_TIMEOUT
PLATFORMS = ["climate"]
PLATFORMS = ["climate", "binary_sensor"]
async def async_setup_entry(hass, config):
@ -96,6 +96,16 @@ class VenstarDataUpdateCoordinator(update_coordinator.DataUpdateCoordinator):
raise update_coordinator.UpdateFailed(
f"Exception during Venstar sensor update: {ex}"
) from ex
# older venstars sometimes cannot handle rapid sequential connections
await asyncio.sleep(3)
try:
await self.hass.async_add_executor_job(self.client.update_alerts)
except (OSError, RequestException) as ex:
raise update_coordinator.UpdateFailed(
f"Exception during Venstar alert update: {ex}"
) from ex
return None

View File

@ -0,0 +1,53 @@
"""Alarm sensors for the Venstar Thermostat."""
from homeassistant.components.binary_sensor import (
DEVICE_CLASS_PROBLEM,
BinarySensorEntity,
)
from . import VenstarEntity
from .const import DOMAIN
async def async_setup_entry(hass, config_entry, async_add_entities) -> None:
"""Set up Vensar device binary_sensors based on a config entry."""
coordinator = hass.data[DOMAIN][config_entry.entry_id]
if coordinator.client.alerts is None:
return
sensors = [
VenstarBinarySensor(coordinator, config_entry, alert["name"])
for alert in coordinator.client.alerts
]
async_add_entities(sensors, True)
class VenstarBinarySensor(VenstarEntity, BinarySensorEntity):
"""Represent a Venstar alert."""
_attr_device_class = DEVICE_CLASS_PROBLEM
def __init__(self, coordinator, config, alert):
"""Initialize the alert."""
super().__init__(coordinator, config)
self.alert = alert
self._config = config
self._unique_id = f"{self._config.entry_id}_{self.alert.replace(' ', '_')}"
self._name = f"{self._client.name} {self.alert}"
@property
def unique_id(self):
"""Return the unique id."""
return self._unique_id
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
for alert in self._client.alerts:
if alert["name"] == self.alert:
return alert["active"]

View File

@ -33,6 +33,9 @@ async def test_setup_entry(hass: HomeAssistant):
), patch(
"homeassistant.components.venstar.VenstarColorTouch.update_info",
new=VenstarColorTouchMock.update_info,
), patch(
"homeassistant.components.venstar.VenstarColorTouch.update_alerts",
new=VenstarColorTouchMock.update_alerts,
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@ -64,6 +67,9 @@ async def test_setup_entry_exception(hass: HomeAssistant):
), patch(
"homeassistant.components.venstar.VenstarColorTouch.update_info",
new=VenstarColorTouchMock.broken_update_info,
), patch(
"homeassistant.components.venstar.VenstarColorTouch.update_alerts",
new=VenstarColorTouchMock.update_alerts,
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()