hass-core/homeassistant/components/sisyphus/__init__.py
Jonathan Keljo 8da1879599 Fix background crash in sisyphus integration (#26032)
I think I was thinking in another language, since this was not valid Python. Result was that the thread that maintained the SocketIO connection to the table would die early on, so no status updates were actually flowing from the table.
2019-08-17 21:32:01 -05:00

121 lines
3.8 KiB
Python

"""Support for controlling Sisyphus Kinetic Art Tables."""
import asyncio
import logging
import voluptuous as vol
from homeassistant.const import CONF_HOST, CONF_NAME, EVENT_HOMEASSISTANT_STOP
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.discovery import async_load_platform
_LOGGER = logging.getLogger(__name__)
DATA_SISYPHUS = "sisyphus"
DOMAIN = "sisyphus"
AUTODETECT_SCHEMA = vol.Schema({})
TABLE_SCHEMA = vol.Schema(
{vol.Required(CONF_NAME): cv.string, vol.Required(CONF_HOST): cv.string}
)
TABLES_SCHEMA = vol.Schema([TABLE_SCHEMA])
CONFIG_SCHEMA = vol.Schema(
{DOMAIN: vol.Any(AUTODETECT_SCHEMA, TABLES_SCHEMA)}, extra=vol.ALLOW_EXTRA
)
async def async_setup(hass, config):
"""Set up the sisyphus component."""
from sisyphus_control import Table
class SocketIONoiseFilter(logging.Filter):
"""Filters out excessively verbose logs from SocketIO."""
def filter(self, record):
if "waiting for connection" in record.msg:
return False
return True
logging.getLogger("socketIO-client").addFilter(SocketIONoiseFilter())
tables = hass.data.setdefault(DATA_SISYPHUS, {})
table_configs = config.get(DOMAIN)
session = async_get_clientsession(hass)
async def add_table(host, name=None):
"""Add platforms for a single table with the given hostname."""
tables[host] = TableHolder(hass, session, host, name)
hass.async_create_task(
async_load_platform(hass, "light", DOMAIN, {CONF_HOST: host}, config)
)
hass.async_create_task(
async_load_platform(hass, "media_player", DOMAIN, {CONF_HOST: host}, config)
)
if isinstance(table_configs, dict): # AUTODETECT_SCHEMA
for ip_address in await Table.find_table_ips(session):
await add_table(ip_address)
else: # TABLES_SCHEMA
for conf in table_configs:
await add_table(conf[CONF_HOST], conf[CONF_NAME])
async def close_tables(*args):
"""Close all table objects."""
tasks = [table.close() for table in tables.values()]
if tasks:
await asyncio.wait(tasks)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, close_tables)
return True
class TableHolder:
"""Holds table objects and makes them available to platforms."""
def __init__(self, hass, session, host, name):
"""Initialize the table holder."""
self._hass = hass
self._session = session
self._host = host
self._name = name
self._table = None
self._table_task = None
@property
def available(self):
"""Return true if the table is responding to heartbeats."""
if self._table_task and self._table_task.done():
return self._table_task.result().is_connected
return False
@property
def name(self):
"""Return the name of the table."""
return self._name
async def get_table(self):
"""Return the Table held by this holder, connecting to it if needed."""
if not self._table_task:
self._table_task = self._hass.async_create_task(self._connect_table())
return await self._table_task
async def _connect_table(self):
from sisyphus_control import Table
self._table = await Table.connect(self._host, self._session)
if self._name is None:
self._name = self._table.name
_LOGGER.debug("Connected to %s at %s", self._name, self._host)
return self._table
async def close(self):
"""Close the table held by this holder, if any."""
if self._table:
await self._table.close()
self._table = None
self._table_task = None