"""Support for Dyson Pure Cool Link devices.""" import logging from libpurecool.dyson import DysonAccount import voluptuous as vol from homeassistant.const import CONF_DEVICES, CONF_PASSWORD, CONF_TIMEOUT, CONF_USERNAME from homeassistant.helpers import discovery import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) CONF_LANGUAGE = "language" CONF_RETRY = "retry" DEFAULT_TIMEOUT = 5 DEFAULT_RETRY = 10 DYSON_DEVICES = "dyson_devices" PLATFORMS = ["sensor", "fan", "vacuum", "climate", "air_quality"] DOMAIN = "dyson" CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( { vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_LANGUAGE): cv.string, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, vol.Optional(CONF_RETRY, default=DEFAULT_RETRY): cv.positive_int, vol.Optional(CONF_DEVICES, default=[]): vol.All(cv.ensure_list, [dict]), } ) }, extra=vol.ALLOW_EXTRA, ) def setup(hass, config): """Set up the Dyson parent component.""" _LOGGER.info("Creating new Dyson component") if DYSON_DEVICES not in hass.data: hass.data[DYSON_DEVICES] = [] dyson_account = DysonAccount( config[DOMAIN].get(CONF_USERNAME), config[DOMAIN].get(CONF_PASSWORD), config[DOMAIN].get(CONF_LANGUAGE), ) logged = dyson_account.login() timeout = config[DOMAIN].get(CONF_TIMEOUT) retry = config[DOMAIN].get(CONF_RETRY) if not logged: _LOGGER.error("Not connected to Dyson account. Unable to add devices") return False _LOGGER.info("Connected to Dyson account") dyson_devices = dyson_account.devices() if CONF_DEVICES in config[DOMAIN] and config[DOMAIN].get(CONF_DEVICES): configured_devices = config[DOMAIN].get(CONF_DEVICES) for device in configured_devices: dyson_device = next( (d for d in dyson_devices if d.serial == device["device_id"]), None ) if dyson_device: try: connected = dyson_device.connect(device["device_ip"]) if connected: _LOGGER.info("Connected to device %s", dyson_device) hass.data[DYSON_DEVICES].append(dyson_device) else: _LOGGER.warning("Unable to connect to device %s", dyson_device) except OSError as ose: _LOGGER.error( "Unable to connect to device %s: %s", str(dyson_device.network_device), str(ose), ) else: _LOGGER.warning( "Unable to find device %s in Dyson account", device["device_id"] ) else: # Not yet reliable for device in dyson_devices: _LOGGER.info( "Trying to connect to device %s with timeout=%i and retry=%i", device, timeout, retry, ) connected = device.auto_connect(timeout, retry) if connected: _LOGGER.info("Connected to device %s", device) hass.data[DYSON_DEVICES].append(device) else: _LOGGER.warning("Unable to connect to device %s", device) # Start fan/sensors components if hass.data[DYSON_DEVICES]: _LOGGER.debug("Starting sensor/fan components") for platform in PLATFORMS: discovery.load_platform(hass, platform, DOMAIN, {}, config) return True class DysonEntity(Entity): """Representation of a Dyson entity.""" def __init__(self, device, state_type): """Initialize the entity.""" self._device = device self._state_type = state_type async def async_added_to_hass(self): """Call when entity is added to hass.""" self._device.add_message_listener(self.on_message_filter) def on_message_filter(self, message): """Filter new messages received.""" if self._state_type is None or isinstance(message, self._state_type): _LOGGER.debug( "Message received for device %s : %s", self.name, message, ) self.on_message(message) def on_message(self, message): """Handle new messages received.""" self.schedule_update_ha_state() @property def should_poll(self): """No polling needed.""" return False @property def name(self): """Return the name of the Dyson sensor.""" return self._device.name @property def unique_id(self): """Return the sensor's unique id.""" return self._device.serial