1
mirror of https://github.com/home-assistant/core synced 2024-07-30 21:18:57 +02:00

Syncthru device registry (#36750)

* Store printer instances in hass.data

* Add SyncThru device registry support

* Use config entry id as hass.data key

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>

* Use printer hostname as device registry name

* Handle non-syncthru device more gracefully on entry setup

* Use device identifiers rather than connections to link entities with devices

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
Ville Skyttä 2020-09-02 12:50:57 +03:00 committed by GitHub
parent 78b0837cb8
commit 9f5baa0bf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 30 deletions

View File

@ -1,23 +1,82 @@
"""The syncthru component."""
import logging
from typing import Set, Tuple
from pysyncthru import SyncThru
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_URL
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client, device_registry as dr
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
"""Set up."""
hass.data.setdefault(DOMAIN, {})
return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
"""Set up config entry."""
session = aiohttp_client.async_get_clientsession(hass)
printer = hass.data[DOMAIN][entry.entry_id] = SyncThru(
entry.data[CONF_URL], session
)
try:
await printer.update()
except ValueError:
_LOGGER.error(
"Device at %s not appear to be a SyncThru printer, aborting setup",
printer.url,
)
return False
else:
if printer.is_unknown_state():
raise ConfigEntryNotReady
device_registry = await dr.async_get_registry(hass)
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
connections=device_connections(printer),
identifiers=device_identifiers(printer),
model=printer.model(),
name=printer.hostname(),
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, SENSOR_DOMAIN)
)
return True
async def async_unload_entry(hass, entry):
async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
"""Unload the config entry."""
return await hass.config_entries.async_forward_entry_unload(entry, SENSOR_DOMAIN)
await hass.config_entries.async_forward_entry_unload(entry, SENSOR_DOMAIN)
hass.data[DOMAIN].pop(entry.entry_id, None)
return True
def device_identifiers(printer: SyncThru) -> Set[Tuple[str, str]]:
"""Get device identifiers for device registry."""
return {(DOMAIN, printer.serial_number())}
def device_connections(printer: SyncThru) -> Set[Tuple[str, str]]:
"""Get device connections for device registry."""
connections = set()
try:
mac = printer.raw()["identity"]["mac_addr"]
if mac:
connections.add((dr.CONNECTION_NETWORK_MAC, mac))
except AttributeError:
pass
return connections

View File

@ -1,7 +0,0 @@
"""Samsung SyncThru exceptions."""
from homeassistant.exceptions import HomeAssistantError
class SyncThruNotSupported(HomeAssistantError):
"""Error to indicate SyncThru is not supported."""

View File

@ -8,13 +8,11 @@ import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.config_entries import SOURCE_IMPORT
from homeassistant.const import CONF_NAME, CONF_RESOURCE, CONF_URL, UNIT_PERCENTAGE
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers import aiohttp_client
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from . import device_identifiers
from .const import DEFAULT_MODEL, DEFAULT_NAME_TEMPLATE, DOMAIN
from .exceptions import SyncThruNotSupported
_LOGGER = logging.getLogger(__name__)
@ -61,25 +59,12 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up from config entry."""
session = aiohttp_client.async_get_clientsession(hass)
printer = hass.data[DOMAIN][config_entry.entry_id]
printer = SyncThru(config_entry.data[CONF_URL], session)
# Test if the discovered device actually is a syncthru printer
# and fetch the available toner/drum/etc
try:
# No error is thrown when the device is off
# (only after user added it manually)
# therefore additional catches are inside the Sensor below
await printer.update()
supp_toner = printer.toner_status(filter_supported=True)
supp_drum = printer.drum_status(filter_supported=True)
supp_tray = printer.input_tray_status(filter_supported=True)
supp_output_tray = printer.output_tray_status()
except ValueError as ex:
raise SyncThruNotSupported from ex
else:
if printer.is_unknown_state():
raise PlatformNotReady
supp_toner = printer.toner_status(filter_supported=True)
supp_drum = printer.drum_status(filter_supported=True)
supp_tray = printer.input_tray_status(filter_supported=True)
supp_output_tray = printer.output_tray_status()
name = config_entry.data[CONF_NAME]
devices = [SyncThruMainSensor(printer, name)]
@ -140,6 +125,11 @@ class SyncThruSensor(Entity):
"""Return the state attributes of the device."""
return self._attributes
@property
def device_info(self):
"""Return device information."""
return {"identifiers": device_identifiers(self.syncthru)}
class SyncThruMainSensor(SyncThruSensor):
"""Implementation of the main sensor, conducting the actual polling."""