154 lines
4.9 KiB
Python
154 lines
4.9 KiB
Python
"""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
|