mirror of https://github.com/home-assistant/core
62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
"""Heartbeats for Broadlink devices."""
|
|
|
|
import datetime as dt
|
|
import logging
|
|
|
|
import broadlink as blk
|
|
|
|
from homeassistant.const import CONF_HOST
|
|
from homeassistant.core import CALLBACK_TYPE, HomeAssistant
|
|
from homeassistant.helpers import event
|
|
|
|
from .const import DOMAIN
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
class BroadlinkHeartbeat:
|
|
"""Manages heartbeats in the Broadlink integration.
|
|
|
|
Some devices reboot when they cannot reach the cloud. This mechanism
|
|
feeds their watchdog timers so they can be used offline.
|
|
"""
|
|
|
|
HEARTBEAT_INTERVAL = dt.timedelta(minutes=2)
|
|
|
|
def __init__(self, hass: HomeAssistant) -> None:
|
|
"""Initialize the heartbeat."""
|
|
self._hass = hass
|
|
self._unsubscribe: CALLBACK_TYPE | None = None
|
|
|
|
async def async_setup(self) -> None:
|
|
"""Set up the heartbeat."""
|
|
if self._unsubscribe is None:
|
|
await self.async_heartbeat(dt.datetime.now())
|
|
self._unsubscribe = event.async_track_time_interval(
|
|
self._hass, self.async_heartbeat, self.HEARTBEAT_INTERVAL
|
|
)
|
|
|
|
async def async_unload(self) -> None:
|
|
"""Unload the heartbeat."""
|
|
if self._unsubscribe is not None:
|
|
self._unsubscribe()
|
|
self._unsubscribe = None
|
|
|
|
async def async_heartbeat(self, _: dt.datetime) -> None:
|
|
"""Send packets to feed watchdog timers."""
|
|
hass = self._hass
|
|
config_entries = hass.config_entries.async_entries(DOMAIN)
|
|
hosts: set[str] = {entry.data[CONF_HOST] for entry in config_entries}
|
|
await hass.async_add_executor_job(self.heartbeat, hosts)
|
|
|
|
@staticmethod
|
|
def heartbeat(hosts: set[str]) -> None:
|
|
"""Send packets to feed watchdog timers."""
|
|
for host in hosts:
|
|
try:
|
|
blk.ping(host)
|
|
except OSError as err:
|
|
_LOGGER.debug("Failed to send heartbeat to %s: %s", host, err)
|
|
else:
|
|
_LOGGER.debug("Heartbeat sent to %s", host)
|