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:
parent
78b0837cb8
commit
9f5baa0bf7
3 changed files with 72 additions and 30 deletions
homeassistant/components/syncthru
|
@ -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
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
"""Samsung SyncThru exceptions."""
|
||||
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
|
||||
class SyncThruNotSupported(HomeAssistantError):
|
||||
"""Error to indicate SyncThru is not supported."""
|
|
@ -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."""
|
||||
|
|
Loading…
Add table
Reference in a new issue