From a42d43d054b8a0104e2d9dbf8ed8583b230ed23c Mon Sep 17 00:00:00 2001 From: Xiaonan Shen Date: Sun, 17 Jan 2021 17:24:26 +0800 Subject: [PATCH] Improve dyson code (#45172) * Improve air_quality * Improve climate * Improve sensor * Improve vacuum * Improve fan * Fix pylint * Improve on_message * Change unique ID back * Remove unused attribute * Remove redundant current_humidity * Merge current_temperature * Rename fan device to fan entity * Fix filter life sensors * Remove unneeded context switch * Remove entity_type * Fix pylint * Add comment on humidity check --- homeassistant/components/dyson/__init__.py | 43 ++++ homeassistant/components/dyson/air_quality.py | 33 +-- homeassistant/components/dyson/climate.py | 196 ++++++------------ homeassistant/components/dyson/fan.py | 79 ++----- homeassistant/components/dyson/sensor.py | 55 +++-- homeassistant/components/dyson/vacuum.py | 29 +-- tests/components/dyson/test_fan.py | 54 ++--- 7 files changed, 179 insertions(+), 310 deletions(-) diff --git a/homeassistant/components/dyson/__init__.py b/homeassistant/components/dyson/__init__.py index fbe7897e6bb..b39af2a2fd1 100644 --- a/homeassistant/components/dyson/__init__.py +++ b/homeassistant/components/dyson/__init__.py @@ -7,6 +7,7 @@ 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__) @@ -108,3 +109,45 @@ def setup(hass, config): 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 diff --git a/homeassistant/components/dyson/air_quality.py b/homeassistant/components/dyson/air_quality.py index 4bc41e3b8fc..3a5731587f6 100644 --- a/homeassistant/components/dyson/air_quality.py +++ b/homeassistant/components/dyson/air_quality.py @@ -4,9 +4,9 @@ import logging from libpurecool.dyson_pure_cool import DysonPureCool from libpurecool.dyson_pure_state_v2 import DysonEnvironmentalSensorV2State -from homeassistant.components.air_quality import DOMAIN, AirQualityEntity +from homeassistant.components.air_quality import AirQualityEntity -from . import DYSON_DEVICES +from . import DYSON_DEVICES, DysonEntity ATTRIBUTION = "Dyson purifier air quality sensor" @@ -39,41 +39,23 @@ def setup_platform(hass, config, add_entities, discovery_info=None): add_entities(hass.data[DYSON_AIQ_DEVICES]) -class DysonAirSensor(AirQualityEntity): +class DysonAirSensor(DysonEntity, AirQualityEntity): """Representation of a generic Dyson air quality sensor.""" def __init__(self, device): """Create a new generic air quality Dyson sensor.""" - self._device = device + super().__init__(device, DysonEnvironmentalSensorV2State) self._old_value = None - self._name = device.name - - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) def on_message(self, message): """Handle new messages which are received from the fan.""" - _LOGGER.debug( - "%s: Message received for %s device: %s", DOMAIN, self.name, message - ) if ( self._old_value is None or self._old_value != self._device.environmental_state - ) and isinstance(message, DysonEnvironmentalSensorV2State): + ): self._old_value = self._device.environmental_state 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._name - @property def attribution(self): """Return the attribution.""" @@ -117,11 +99,6 @@ class DysonAirSensor(AirQualityEntity): return int(self._device.environmental_state.volatile_organic_compounds) return None - @property - def unique_id(self): - """Return the sensor's unique id.""" - return self._device.serial - @property def device_state_attributes(self): """Return the device state attributes.""" diff --git a/homeassistant/components/dyson/climate.py b/homeassistant/components/dyson/climate.py index a71c124c633..e7b8f42f1b1 100644 --- a/homeassistant/components/dyson/climate.py +++ b/homeassistant/components/dyson/climate.py @@ -37,13 +37,13 @@ from homeassistant.components.climate.const import ( ) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS -from . import DYSON_DEVICES +from . import DYSON_DEVICES, DysonEntity _LOGGER = logging.getLogger(__name__) SUPPORT_FAN = [FAN_FOCUS, FAN_DIFFUSE] SUPPORT_FAN_PCOOL = [FAN_OFF, FAN_AUTO, FAN_LOW, FAN_MEDIUM, FAN_HIGH] -SUPPORT_HVAG = [HVAC_MODE_COOL, HVAC_MODE_HEAT] +SUPPORT_HVAC = [HVAC_MODE_COOL, HVAC_MODE_HEAT] SUPPORT_HVAC_PCOOL = [HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF] SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE @@ -88,41 +88,14 @@ def setup_platform(hass, config, add_entities, discovery_info=None): add_entities(new_entities) -class DysonPureHotCoolLinkEntity(ClimateEntity): +class DysonClimateEntity(DysonEntity, ClimateEntity): """Representation of a Dyson climate fan.""" - def __init__(self, device): - """Initialize the fan.""" - self._device = device - self._current_temp = None - - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) - - def on_message(self, message): - """Call when new messages received from the climate.""" - if isinstance(message, DysonPureHotCoolState): - _LOGGER.debug( - "Message received for climate device %s : %s", self.name, message - ) - self.schedule_update_ha_state() - - @property - def should_poll(self): - """No polling needed.""" - return False - @property def supported_features(self): """Return the list of supported features.""" return SUPPORT_FLAGS - @property - def name(self): - """Return the display name of this climate.""" - return self._device.name - @property def temperature_unit(self): """Return the unit of measurement.""" @@ -131,11 +104,13 @@ class DysonPureHotCoolLinkEntity(ClimateEntity): @property def current_temperature(self): """Return the current temperature.""" - if self._device.environmental_state: + if ( + self._device.environmental_state + and self._device.environmental_state.temperature + ): temperature_kelvin = self._device.environmental_state.temperature - if temperature_kelvin != 0: - self._current_temp = float(f"{(temperature_kelvin - 273):.1f}") - return self._current_temp + return float("{:.1f}".format(temperature_kelvin - 273)) + return None @property def target_temperature(self): @@ -146,12 +121,49 @@ class DysonPureHotCoolLinkEntity(ClimateEntity): @property def current_humidity(self): """Return the current humidity.""" - if self._device.environmental_state: - if self._device.environmental_state.humidity == 0: - return None + # Humidity equaling to 0 means invalid value so we don't check for None here + # https://github.com/home-assistant/core/pull/45172#discussion_r559069756 + if ( + self._device.environmental_state + and self._device.environmental_state.humidity + ): return self._device.environmental_state.humidity return None + @property + def min_temp(self): + """Return the minimum temperature.""" + return 1 + + @property + def max_temp(self): + """Return the maximum temperature.""" + return 37 + + def set_temperature(self, **kwargs): + """Set new target temperature.""" + target_temp = kwargs.get(ATTR_TEMPERATURE) + if target_temp is None: + _LOGGER.error("Missing target temperature %s", kwargs) + return + target_temp = int(target_temp) + _LOGGER.debug("Set %s temperature %s", self.name, target_temp) + # Limit the target temperature into acceptable range. + target_temp = min(self.max_temp, target_temp) + target_temp = max(self.min_temp, target_temp) + self.set_heat_target(HeatTarget.celsius(target_temp)) + + def set_heat_target(self, heat_target): + """Set heating target temperature.""" + + +class DysonPureHotCoolLinkEntity(DysonClimateEntity): + """Representation of a Dyson climate fan.""" + + def __init__(self, device): + """Initialize the fan.""" + super().__init__(device, DysonPureHotCoolState) + @property def hvac_mode(self): """Return hvac operation ie. heat, cool mode. @@ -168,7 +180,7 @@ class DysonPureHotCoolLinkEntity(ClimateEntity): Need to be a subset of HVAC_MODES. """ - return SUPPORT_HVAG + return SUPPORT_HVAC @property def hvac_action(self): @@ -194,18 +206,10 @@ class DysonPureHotCoolLinkEntity(ClimateEntity): """Return the list of available fan modes.""" return SUPPORT_FAN - def set_temperature(self, **kwargs): - """Set new target temperature.""" - target_temp = kwargs.get(ATTR_TEMPERATURE) - if target_temp is None: - return - target_temp = int(target_temp) - _LOGGER.debug("Set %s temperature %s", self.name, target_temp) - # Limit the target temperature into acceptable range. - target_temp = min(self.max_temp, target_temp) - target_temp = max(self.min_temp, target_temp) + def set_heat_target(self, heat_target): + """Set heating target temperature.""" self._device.set_configuration( - heat_target=HeatTarget.celsius(target_temp), heat_mode=HeatMode.HEAT_ON + heat_target=heat_target, heat_mode=HeatMode.HEAT_ON ) def set_fan_mode(self, fan_mode): @@ -224,78 +228,13 @@ class DysonPureHotCoolLinkEntity(ClimateEntity): elif hvac_mode == HVAC_MODE_COOL: self._device.set_configuration(heat_mode=HeatMode.HEAT_OFF) - @property - def min_temp(self): - """Return the minimum temperature.""" - return 1 - @property - def max_temp(self): - """Return the maximum temperature.""" - return 37 - - -class DysonPureHotCoolEntity(ClimateEntity): +class DysonPureHotCoolEntity(DysonClimateEntity): """Representation of a Dyson climate hot+cool fan.""" def __init__(self, device): """Initialize the fan.""" - self._device = device - - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) - - def on_message(self, message): - """Call when new messages received from the climate device.""" - if isinstance(message, DysonPureHotCoolV2State): - _LOGGER.debug( - "Message received for climate device %s : %s", self.name, message - ) - self.schedule_update_ha_state() - - @property - def should_poll(self): - """No polling needed.""" - return False - - @property - def supported_features(self): - """Return the list of supported features.""" - return SUPPORT_FLAGS - - @property - def name(self): - """Return the display name of this climate.""" - return self._device.name - - @property - def temperature_unit(self): - """Return the unit of measurement.""" - return TEMP_CELSIUS - - @property - def current_temperature(self): - """Return the current temperature.""" - if self._device.environmental_state.temperature is not None: - temperature_kelvin = self._device.environmental_state.temperature - if temperature_kelvin != 0: - return float("{:.1f}".format(temperature_kelvin - 273)) - return None - - @property - def target_temperature(self): - """Return the target temperature.""" - heat_target = int(self._device.state.heat_target) / 10 - return int(heat_target - 273) - - @property - def current_humidity(self): - """Return the current humidity.""" - if self._device.environmental_state.humidity is not None: - if self._device.environmental_state.humidity != 0: - return self._device.environmental_state.humidity - return None + super().__init__(device, DysonPureHotCoolV2State) @property def hvac_mode(self): @@ -347,18 +286,9 @@ class DysonPureHotCoolEntity(ClimateEntity): """Return the list of available fan modes.""" return SUPPORT_FAN_PCOOL - def set_temperature(self, **kwargs): - """Set new target temperature.""" - target_temp = kwargs.get(ATTR_TEMPERATURE) - if target_temp is None: - _LOGGER.error("Missing target temperature %s", kwargs) - return - target_temp = int(target_temp) - _LOGGER.debug("Set %s temperature %s", self.name, target_temp) - # Limit the target temperature into acceptable range. - target_temp = min(self.max_temp, target_temp) - target_temp = max(self.min_temp, target_temp) - self._device.set_heat_target(HeatTarget.celsius(target_temp)) + def set_heat_target(self, heat_target): + """Set heating target temperature.""" + self._device.set_heat_target(heat_target) def set_fan_mode(self, fan_mode): """Set new fan mode.""" @@ -385,13 +315,3 @@ class DysonPureHotCoolEntity(ClimateEntity): self._device.enable_heat_mode() elif hvac_mode == HVAC_MODE_COOL: self._device.disable_heat_mode() - - @property - def min_temp(self): - """Return the minimum temperature.""" - return 1 - - @property - def max_temp(self): - """Return the maximum temperature.""" - return 37 diff --git a/homeassistant/components/dyson/fan.py b/homeassistant/components/dyson/fan.py index ca685f36a13..62d857affa9 100644 --- a/homeassistant/components/dyson/fan.py +++ b/homeassistant/components/dyson/fan.py @@ -19,7 +19,7 @@ from homeassistant.components.fan import ( from homeassistant.const import ATTR_ENTITY_ID import homeassistant.helpers.config_validation as cv -from . import DYSON_DEVICES +from . import DYSON_DEVICES, DysonEntity _LOGGER = logging.getLogger(__name__) @@ -105,10 +105,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None): if device.serial not in device_serials: if isinstance(device, DysonPureCool): has_purecool_devices = True - dyson_entity = DysonPureCoolDevice(device) + dyson_entity = DysonPureCoolEntity(device) hass.data[DYSON_FAN_DEVICES].append(dyson_entity) elif isinstance(device, DysonPureCoolLink): - dyson_entity = DysonPureCoolLinkDevice(hass, device) + dyson_entity = DysonPureCoolLinkEntity(device) hass.data[DYSON_FAN_DEVICES].append(dyson_entity) add_entities(hass.data[DYSON_FAN_DEVICES]) @@ -179,35 +179,21 @@ def setup_platform(hass, config, add_entities, discovery_info=None): ) -class DysonPureCoolLinkDevice(FanEntity): +class DysonFanEntity(DysonEntity, FanEntity): """Representation of a Dyson fan.""" - def __init__(self, hass, device): + @property + def night_mode(self): + """Return Night mode.""" + return self._device.state.night_mode == "ON" + + +class DysonPureCoolLinkEntity(DysonFanEntity): + """Representation of a Dyson fan.""" + + def __init__(self, device): """Initialize the fan.""" - _LOGGER.debug("Creating device %s", device.name) - self.hass = hass - self._device = device - - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) - - def on_message(self, message): - """Call when new messages received from the fan.""" - - if isinstance(message, DysonPureCoolState): - _LOGGER.debug("Message received for fan device %s: %s", self.name, message) - self.schedule_update_ha_state() - - @property - def should_poll(self): - """No polling needed.""" - return False - - @property - def name(self): - """Return the display name of this fan.""" - return self._device.name + super().__init__(device, DysonPureCoolState) def set_speed(self, speed: str) -> None: """Set the speed of the fan. Never called ??.""" @@ -274,11 +260,6 @@ class DysonPureCoolLinkDevice(FanEntity): """Return direction of the fan [forward, reverse].""" return None - @property - def night_mode(self): - """Return Night mode.""" - return self._device.state.night_mode == "ON" - def set_night_mode(self, night_mode: bool) -> None: """Turn fan in night mode.""" _LOGGER.debug("Set %s night mode %s", self.name, night_mode) @@ -330,32 +311,12 @@ class DysonPureCoolLinkDevice(FanEntity): return {ATTR_NIGHT_MODE: self.night_mode, ATTR_AUTO_MODE: self.auto_mode} -class DysonPureCoolDevice(FanEntity): +class DysonPureCoolEntity(DysonFanEntity): """Representation of a Dyson Purecool (TP04/DP04) fan.""" def __init__(self, device): """Initialize the fan.""" - self._device = device - - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) - - def on_message(self, message): - """Call when new messages received from the fan.""" - if isinstance(message, DysonPureCoolV2State): - _LOGGER.debug("Message received for fan device %s: %s", self.name, message) - self.schedule_update_ha_state() - - @property - def should_poll(self): - """No polling needed.""" - return False - - @property - def name(self): - """Return the display name of this fan.""" - return self._device.name + super().__init__(device, DysonPureCoolV2State) def turn_on(self, speed: str = None, **kwargs) -> None: """Turn on the fan.""" @@ -455,6 +416,7 @@ class DysonPureCoolDevice(FanEntity): """Return true if the entity is on.""" if self._device.state: return self._device.state.fan_power == "ON" + return False @property def speed(self): @@ -483,11 +445,6 @@ class DysonPureCoolDevice(FanEntity): return self._device.state.speed return int(self._device.state.speed) - @property - def night_mode(self): - """Return Night mode.""" - return self._device.state.night_mode == "ON" - @property def auto_mode(self): """Return Auto mode.""" diff --git a/homeassistant/components/dyson/sensor.py b/homeassistant/components/dyson/sensor.py index 1629d0fa06b..f4df4c83ab0 100644 --- a/homeassistant/components/dyson/sensor.py +++ b/homeassistant/components/dyson/sensor.py @@ -7,7 +7,7 @@ from libpurecool.dyson_pure_cool_link import DysonPureCoolLink from homeassistant.const import PERCENTAGE, STATE_OFF, TEMP_CELSIUS, TIME_HOURS from homeassistant.helpers.entity import Entity -from . import DYSON_DEVICES +from . import DYSON_DEVICES, DysonEntity SENSOR_UNITS = { "air_quality": None, @@ -15,6 +15,7 @@ SENSOR_UNITS = { "filter_life": TIME_HOURS, "carbon_filter_state": PERCENTAGE, "hepa_filter_state": PERCENTAGE, + "combi_filter_state": PERCENTAGE, "humidity": PERCENTAGE, } @@ -24,10 +25,22 @@ SENSOR_ICONS = { "filter_life": "mdi:filter-outline", "carbon_filter_state": "mdi:filter-outline", "hepa_filter_state": "mdi:filter-outline", + "combi_filter_state": "mdi:filter-outline", "humidity": "mdi:water-percent", "temperature": "mdi:thermometer", } +SENSOR_NAMES = { + "air_quality": "AQI", + "dust": "Dust", + "filter_life": "Filter Life", + "humidity": "Humidity", + "carbon_filter_state": "Carbon Filter Remaining Life", + "hepa_filter_state": "HEPA Filter Remaining Life", + "combi_filter_state": "Combi Filter Remaining Life", + "temperature": "Temperature", +} + DYSON_SENSOR_DEVICES = "dyson_sensor_devices" _LOGGER = logging.getLogger(__name__) @@ -57,7 +70,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): # It's reported with the HEPA state, while the Carbon state is set to INValid. if device.state and device.state.carbon_filter_state == "INV": if f"{device.serial}-hepa_filter_state" not in device_ids: - new_entities.append(DysonHepaFilterLifeSensor(device, "Combi")) + new_entities.append(DysonHepaFilterLifeSensor(device, "combi")) else: if f"{device.serial}-hepa_filter_state" not in device_ids: new_entities.append(DysonHepaFilterLifeSensor(device)) @@ -77,37 +90,31 @@ def setup_platform(hass, config, add_entities, discovery_info=None): add_entities(devices) -class DysonSensor(Entity): +class DysonSensor(DysonEntity, Entity): """Representation of a generic Dyson sensor.""" def __init__(self, device, sensor_type): """Create a new generic Dyson sensor.""" - self._device = device + super().__init__(device, None) self._old_value = None - self._name = None self._sensor_type = sensor_type - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) - def on_message(self, message): """Handle new messages which are received from the fan.""" # Prevent refreshing if not needed if self._old_value is None or self._old_value != self.state: - _LOGGER.debug("Message received for %s device: %s", self.name, message) self._old_value = self.state 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 name.""" - return self._name + return f"{super().name} {SENSOR_NAMES[self._sensor_type]}" + + @property + def unique_id(self): + """Return the sensor's unique id.""" + return f"{self._device.serial}-{self._sensor_type}" @property def unit_of_measurement(self): @@ -119,11 +126,6 @@ class DysonSensor(Entity): """Return the icon for this sensor.""" return SENSOR_ICONS[self._sensor_type] - @property - def unique_id(self): - """Return the sensor's unique id.""" - return f"{self._device.serial}-{self._sensor_type}" - class DysonFilterLifeSensor(DysonSensor): """Representation of Dyson Filter Life sensor (in hours).""" @@ -131,7 +133,6 @@ class DysonFilterLifeSensor(DysonSensor): def __init__(self, device): """Create a new Dyson Filter Life sensor.""" super().__init__(device, "filter_life") - self._name = f"{self._device.name} Filter Life" @property def state(self): @@ -147,7 +148,6 @@ class DysonCarbonFilterLifeSensor(DysonSensor): def __init__(self, device): """Create a new Dyson Carbon Filter Life sensor.""" super().__init__(device, "carbon_filter_state") - self._name = f"{self._device.name} Carbon Filter Remaining Life" @property def state(self): @@ -160,10 +160,9 @@ class DysonCarbonFilterLifeSensor(DysonSensor): class DysonHepaFilterLifeSensor(DysonSensor): """Representation of Dyson HEPA (or Combi) Filter Life sensor (in percent).""" - def __init__(self, device, filter_type="HEPA"): + def __init__(self, device, filter_type="hepa"): """Create a new Dyson Filter Life sensor.""" - super().__init__(device, "hepa_filter_state") - self._name = f"{self._device.name} {filter_type} Filter Remaining Life" + super().__init__(device, f"{filter_type}_filter_state") @property def state(self): @@ -179,7 +178,6 @@ class DysonDustSensor(DysonSensor): def __init__(self, device): """Create a new Dyson Dust sensor.""" super().__init__(device, "dust") - self._name = f"{self._device.name} Dust" @property def state(self): @@ -195,7 +193,6 @@ class DysonHumiditySensor(DysonSensor): def __init__(self, device): """Create a new Dyson Humidity sensor.""" super().__init__(device, "humidity") - self._name = f"{self._device.name} Humidity" @property def state(self): @@ -213,7 +210,6 @@ class DysonTemperatureSensor(DysonSensor): def __init__(self, device, unit): """Create a new Dyson Temperature sensor.""" super().__init__(device, "temperature") - self._name = f"{self._device.name} Temperature" self._unit = unit @property @@ -240,7 +236,6 @@ class DysonAirQualitySensor(DysonSensor): def __init__(self, device): """Create a new Dyson Air Quality sensor.""" super().__init__(device, "air_quality") - self._name = f"{self._device.name} AQI" @property def state(self): diff --git a/homeassistant/components/dyson/vacuum.py b/homeassistant/components/dyson/vacuum.py index a3db4f9c4d3..466b409c342 100644 --- a/homeassistant/components/dyson/vacuum.py +++ b/homeassistant/components/dyson/vacuum.py @@ -17,7 +17,7 @@ from homeassistant.components.vacuum import ( ) from homeassistant.helpers.icon import icon_for_battery_level -from . import DYSON_DEVICES +from . import DYSON_DEVICES, DysonEntity _LOGGER = logging.getLogger(__name__) @@ -54,35 +54,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None): return True -class Dyson360EyeDevice(VacuumEntity): +class Dyson360EyeDevice(DysonEntity, VacuumEntity): """Dyson 360 Eye robot vacuum device.""" def __init__(self, device): """Dyson 360 Eye robot vacuum device.""" - _LOGGER.debug("Creating device %s", device.name) - self._device = device - - async def async_added_to_hass(self): - """Call when entity is added to hass.""" - self._device.add_message_listener(self.on_message) - - def on_message(self, message): - """Handle a new messages that was received from the vacuum.""" - _LOGGER.debug("Message received for %s device: %s", self.name, message) - self.schedule_update_ha_state() - - @property - def should_poll(self) -> bool: - """Return True if entity has to be polled for state. - - False if entity pushes its state to HA. - """ - return False - - @property - def name(self): - """Return the name of the device.""" - return self._device.name + super().__init__(device, None) @property def status(self): diff --git a/tests/components/dyson/test_fan.py b/tests/components/dyson/test_fan.py index 8fa75e818ef..ee3a87917e9 100644 --- a/tests/components/dyson/test_fan.py +++ b/tests/components/dyson/test_fan.py @@ -187,7 +187,7 @@ class DysonTest(unittest.TestCase): def test_dyson_set_speed(self): """Test set fan speed.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.should_poll component.set_speed("1") set_config = device.set_configuration @@ -202,7 +202,7 @@ class DysonTest(unittest.TestCase): def test_dyson_turn_on(self): """Test turn on fan.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.should_poll component.turn_on() set_config = device.set_configuration @@ -211,7 +211,7 @@ class DysonTest(unittest.TestCase): def test_dyson_turn_night_mode(self): """Test turn on fan with night mode.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.should_poll component.set_night_mode(True) set_config = device.set_configuration @@ -224,17 +224,17 @@ class DysonTest(unittest.TestCase): def test_is_night_mode(self): """Test night mode.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.night_mode device = _get_device_off() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.night_mode def test_dyson_turn_auto_mode(self): """Test turn on/off fan with auto mode.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.should_poll component.set_auto_mode(True) set_config = device.set_configuration @@ -247,17 +247,17 @@ class DysonTest(unittest.TestCase): def test_is_auto_mode(self): """Test auto mode.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.auto_mode device = _get_device_auto() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.auto_mode def test_dyson_turn_on_speed(self): """Test turn on fan with specified speed.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.should_poll component.turn_on("1") set_config = device.set_configuration @@ -272,7 +272,7 @@ class DysonTest(unittest.TestCase): def test_dyson_turn_off(self): """Test turn off fan.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.should_poll component.turn_off() set_config = device.set_configuration @@ -281,7 +281,7 @@ class DysonTest(unittest.TestCase): def test_dyson_oscillate_off(self): """Test turn off oscillation.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) component.oscillate(False) set_config = device.set_configuration set_config.assert_called_with(oscillation=Oscillation.OSCILLATION_OFF) @@ -289,7 +289,7 @@ class DysonTest(unittest.TestCase): def test_dyson_oscillate_on(self): """Test turn on oscillation.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) component.oscillate(True) set_config = device.set_configuration set_config.assert_called_with(oscillation=Oscillation.OSCILLATION_ON) @@ -297,71 +297,71 @@ class DysonTest(unittest.TestCase): def test_dyson_oscillate_value_on(self): """Test get oscillation value on.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.oscillating def test_dyson_oscillate_value_off(self): """Test get oscillation value off.""" device = _get_device_off() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.oscillating def test_dyson_on(self): """Test device is on.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.is_on def test_dyson_off(self): """Test device is off.""" device = _get_device_off() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.is_on device = _get_device_with_no_state() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert not component.is_on def test_dyson_get_speed(self): """Test get device speed.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.speed == 1 device = _get_device_off() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.speed == 4 device = _get_device_with_no_state() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.speed is None device = _get_device_auto() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.speed == "AUTO" def test_dyson_get_direction(self): """Test get device direction.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.current_direction is None def test_dyson_get_speed_list(self): """Test get speeds list.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert len(component.speed_list) == 11 def test_dyson_supported_features(self): """Test supported features.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) assert component.supported_features == 3 def test_on_message(self): """Test when message is received.""" device = _get_device_on() - component = dyson.DysonPureCoolLinkDevice(self.hass, device) + component = dyson.DysonPureCoolLinkEntity(device) component.entity_id = "entity_id" component.schedule_update_ha_state = mock.Mock() component.on_message(MockDysonState()) @@ -788,7 +788,7 @@ async def test_purecool_update_state(devices, login, hass): for call in device.add_message_listener.call_args_list: callback = call[0][0] - if type(callback.__self__) == dyson.DysonPureCoolDevice: + if type(callback.__self__) == dyson.DysonPureCoolEntity: callback(device.state) await hass.async_block_till_done() @@ -849,7 +849,7 @@ async def test_purecool_update_state_filter_inv(devices, login, hass): for call in device.add_message_listener.call_args_list: callback = call[0][0] - if type(callback.__self__) == dyson.DysonPureCoolDevice: + if type(callback.__self__) == dyson.DysonPureCoolEntity: callback(device.state) await hass.async_block_till_done()