Skip to content

Commit

Permalink
chore(deps): update dependency libdyson-wg/ha-dyson to v1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jnewland-renovate committed Aug 18, 2024
1 parent f2c4928 commit 368df6c
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 19 deletions.
22 changes: 9 additions & 13 deletions custom_components/dyson_local/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .vendor.libdyson import (
Dyson360Eye,
Dyson360Heurist,
Dyson360VisNav,
DysonPureHotCool,
DysonPureHotCoolLink,
DysonPurifierHumidifyCool,
Expand Down Expand Up @@ -94,11 +95,8 @@ async def async_setup_account(hass: HomeAssistant, entry: ConfigEntry) -> bool:
DATA_ACCOUNT: account,
DATA_DEVICES: devices,
}
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True


Expand All @@ -113,7 +111,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
entry.data[CONF_DEVICE_TYPE],
)

if not isinstance(device, Dyson360Eye) and not isinstance(device, Dyson360Heurist):
if (not isinstance(device, Dyson360Eye)
and not isinstance(device, Dyson360Heurist)
and not isinstance(device, Dyson360VisNav)):
# Set up coordinator
async def async_update_data():
"""Poll environmental data from the device."""
Expand All @@ -132,12 +132,6 @@ async def async_update_data():
else:
coordinator = None

async def _async_forward_entry_setup():
for component in _async_get_platforms(device):
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)

def setup_entry(host: str, is_discovery: bool = True) -> bool:
try:
device.connect(host)
Expand All @@ -153,7 +147,7 @@ def setup_entry(host: str, is_discovery: bool = True) -> bool:
hass.data[DOMAIN][DATA_DEVICES][entry.entry_id] = device
hass.data[DOMAIN][DATA_COORDINATORS][entry.entry_id] = coordinator
asyncio.run_coroutine_threadsafe(
_async_forward_entry_setup(), hass.loop
hass.config_entries.async_forward_entry_setups(entry, _async_get_platforms(device)), hass.loop
).result()

host = entry.data.get(CONF_HOST)
Expand Down Expand Up @@ -203,7 +197,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

@callback
def _async_get_platforms(device: DysonDevice) -> List[str]:
if isinstance(device, Dyson360Eye) or isinstance(device, Dyson360Heurist):
if (isinstance(device, Dyson360Eye)
or isinstance(device, Dyson360Heurist)
or isinstance(device, Dyson360VisNav)):
return ["binary_sensor", "sensor", "vacuum"]
platforms = ["fan", "select", "sensor", "switch"]
if isinstance(device, DysonPureHotCool):
Expand Down
40 changes: 39 additions & 1 deletion custom_components/dyson_local/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

from typing import Callable

from .vendor.libdyson import Dyson360Eye, Dyson360Heurist, DysonPureHotCoolLink
from .vendor.libdyson import (
Dyson360Eye,
Dyson360Heurist,
Dyson360VisNav,
DysonPureHotCoolLink,
)

from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
Expand All @@ -29,6 +34,13 @@ async def async_setup_entry(
if isinstance(device, Dyson360Eye):
entities.append(DysonVacuumBatteryChargingSensor(device, name))
if isinstance(device, Dyson360Heurist):
entities.extend(
[
DysonVacuumBatteryChargingSensor(device, name),
Dyson360VisNavBinFullSensor(device, name),
]
)
if isinstance(device, Dyson360VisNav):
entities.extend(
[
DysonVacuumBatteryChargingSensor(device, name),
Expand Down Expand Up @@ -92,6 +104,32 @@ def sub_unique_id(self):
return "bin_full"


class Dyson360VisNavBinFullSensor(DysonEntity, BinarySensorEntity):
"""Dyson 360 VisNav bin full sensor."""

_attr_entity_category = EntityCategory.DIAGNOSTIC

@property
def is_on(self) -> bool:
"""Return if the sensor is on."""
return self._device.is_bin_full

@property
def icon(self) -> str:
"""Return the sensor icon."""
return ICON_BIN_FULL

@property
def sub_name(self) -> str:
"""Return the name of the sensor."""
return "Bin Full"

@property
def sub_unique_id(self):
"""Return the sensor's unique id."""
return "bin_full"


class DysonPureHotCoolLinkTiltSensor(DysonEntity, BinarySensorEntity):
"""Dyson Pure Hot+Cool Link tilt sensor."""

Expand Down
8 changes: 8 additions & 0 deletions custom_components/dyson_local/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ async def async_setup_entry(
class DysonClimateEntity(DysonEntity, ClimateEntity):
"""Dyson climate entity base class."""

_enable_turn_on_off_backwards_compatibility = False

@property
def hvac_mode(self) -> str:
"""Return hvac operation."""
Expand Down Expand Up @@ -76,6 +78,12 @@ def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_FLAGS

def turn_on(self) -> None:
self._device.turn_on()

def turn_off(self) -> None:
self._device.turn_off()

@property
def temperature_unit(self) -> str:
"""Return the unit of measurement."""
Expand Down
2 changes: 1 addition & 1 deletion custom_components/dyson_local/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"import_executor": true,
"iot_class": "local_push",
"issue_tracker": "https://github.com/libdyson-wg/ha-dyson/issues",
"version": "1.3.11",
"version": "1.4.0-rc3",
"import_executor": true
}
3 changes: 2 additions & 1 deletion custom_components/dyson_local/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .vendor.libdyson import (
Dyson360Eye,
Dyson360Heurist,
Dyson360VisNav,
DysonDevice,
DysonPureCoolLink,
DysonPurifierHumidifyCool,
Expand Down Expand Up @@ -44,7 +45,7 @@ async def async_setup_entry(
"""Set up Dyson sensor from a config entry."""
device = hass.data[DOMAIN][DATA_DEVICES][config_entry.entry_id]
name = config_entry.data[CONF_NAME]
if isinstance(device, Dyson360Eye) or isinstance(device, Dyson360Heurist):
if isinstance(device, Dyson360Eye) or isinstance(device, Dyson360Heurist) or isinstance(device, Dyson360VisNav):
entities = [DysonBatterySensor(device, name)]
else:
coordinator = hass.data[DOMAIN][DATA_COORDINATORS][config_entry.entry_id]
Expand Down
33 changes: 33 additions & 0 deletions custom_components/dyson_local/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

from .vendor.libdyson import (
Dyson360Eye,
Dyson360VisNav,
VacuumEyePowerMode,
VacuumHeuristPowerMode,
VacuumVisNavPowerMode,
VacuumState,
)

Expand Down Expand Up @@ -68,6 +70,7 @@
VacuumState.MAPPING_NEEDS_CHARGE: "Mapping - Needs charging",
VacuumState.MAPPING_PAUSED: "Mapping - Paused",
VacuumState.MAPPING_RUNNING: "Mapping - Running",
VacuumState.MACHINE_OFF: "Off",
}

DYSON_STATES = {
Expand Down Expand Up @@ -103,6 +106,7 @@
VacuumState.MAPPING_NEEDS_CHARGE: STATE_RETURNING,
VacuumState.MAPPING_PAUSED: STATE_PAUSED,
VacuumState.MAPPING_RUNNING: STATE_CLEANING,
VacuumState.MACHINE_OFF: STATE_DOCKED,
}

EYE_POWER_MODE_ENUM_TO_STR = {
Expand All @@ -120,6 +124,15 @@
HEURIST_POWER_MODE_STR_TO_ENUM = {
value: key for key, value in HEURIST_POWER_MODE_ENUM_TO_STR.items()
}
VIS_NAV_POWER_MODE_ENUM_TO_STR = {
VacuumVisNavPowerMode.AUTO: "Auto",
VacuumVisNavPowerMode.QUICK: "Quick",
VacuumVisNavPowerMode.QUIET: "Quiet",
VacuumVisNavPowerMode.BOOST: "Boost",
}
VIS_NAV_POWER_MODE_STR_TO_ENUM = {
value: key for key, value in VIS_NAV_POWER_MODE_ENUM_TO_STR.items()
}

ATTR_POSITION = "position"

Expand All @@ -132,6 +145,8 @@ async def async_setup_entry(
name = config_entry.data[CONF_NAME]
if isinstance(device, Dyson360Eye):
entity = Dyson360EyeEntity(device, name)
elif isinstance(device, Dyson360VisNav): # Dyson360VisNav
entity = Dyson360VisNavEntity(device, name)
else: # Dyson360Heurist
entity = Dyson360HeuristEntity(device, name)
async_add_entities([entity])
Expand Down Expand Up @@ -230,3 +245,21 @@ def start(self) -> None:
def set_fan_speed(self, fan_speed: str, **kwargs) -> None:
"""Set fan speed."""
self._device.set_default_power_mode(HEURIST_POWER_MODE_STR_TO_ENUM[fan_speed])


class Dyson360VisNavEntity(Dyson360HeuristEntity):
"""Dyson 360 Vis Nav robot vacuum entity."""

@property
def fan_speed(self) -> str:
"""Return the fan speed of the vacuum cleaner."""
return VIS_NAV_POWER_MODE_ENUM_TO_STR[self._device.current_power_mode]

@property
def fan_speed_list(self) -> List[str]:
"""Get the list of available fan speed steps of the vacuum cleaner."""
return list(VIS_NAV_POWER_MODE_STR_TO_ENUM.keys())

def set_fan_speed(self, fan_speed: str, **kwargs) -> None:
"""Set fan speed."""
self._device.set_default_power_mode(VIS_NAV_POWER_MODE_STR_TO_ENUM[fan_speed])
6 changes: 6 additions & 0 deletions custom_components/dyson_local/vendor/libdyson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .const import (
DEVICE_TYPE_360_EYE,
DEVICE_TYPE_360_HEURIST,
DEVICE_TYPE_360_VIS_NAV,
DEVICE_TYPE_PURE_COOL,
DEVICE_TYPE_PURIFIER_COOL_E,
DEVICE_TYPE_PURIFIER_COOL_K,
Expand All @@ -27,11 +28,13 @@
from .const import MessageType # noqa: F401
from .const import VacuumEyePowerMode # noqa: F401
from .const import VacuumHeuristPowerMode # noqa: F401
from .const import VacuumVisNavPowerMode # noqa: F401
from .const import VacuumState # noqa: F401
from .const import WaterHardness # noqa: F401
from .discovery import DysonDiscovery # noqa: F401
from .dyson_360_eye import Dyson360Eye
from .dyson_360_heurist import Dyson360Heurist
from .dyson_360_vis_nav import Dyson360VisNav
from .dyson_device import DysonDevice
from .dyson_pure_cool import DysonPureCool
from .dyson_pure_cool_link import DysonPureCoolLink
Expand All @@ -48,6 +51,8 @@ def get_device(serial: str, credential: str, device_type: str) -> Optional[Dyson
return Dyson360Eye(serial, credential)
if device_type == DEVICE_TYPE_360_HEURIST:
return Dyson360Heurist(serial, credential)
if device_type == DEVICE_TYPE_360_VIS_NAV:
return Dyson360VisNav(serial, credential)
if device_type in [
DEVICE_TYPE_PURE_COOL_LINK_DESK,
DEVICE_TYPE_PURE_COOL_LINK,
Expand Down Expand Up @@ -79,3 +84,4 @@ def get_device(serial: str, credential: str, device_type: str) -> Optional[Dyson
}:
return DysonBigQuiet(serial, credential, device_type)
return None

Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

FILE_PATH = pathlib.Path(__file__).parent.absolute()


class HTTPBearerAuth(AuthBase):
"""Attaches HTTP Bearder Authentication to the given Request object."""

Expand Down
12 changes: 12 additions & 0 deletions custom_components/dyson_local/vendor/libdyson/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

DEVICE_TYPE_360_EYE = "N223"
DEVICE_TYPE_360_HEURIST = "276"
DEVICE_TYPE_360_VIS_NAV = "277"
DEVICE_TYPE_PURE_COOL_LINK_DESK = "469" # DP01? DP02? This one's a bit older, and scraping the Dyson website is unclear
DEVICE_TYPE_PURE_COOL_DESK = "520" # AM06? This one's also a bit older, and also hard to scrape off the Dyson website
DEVICE_TYPE_PURE_COOL_LINK = "475" # TP02
Expand All @@ -21,6 +22,7 @@
DEVICE_TYPE_NAMES = {
DEVICE_TYPE_360_EYE: "360 Eye robot vacuum",
DEVICE_TYPE_360_HEURIST: "360 Heurist robot vacuum",
DEVICE_TYPE_360_VIS_NAV: "360 Vis Nav robot vacuum",
DEVICE_TYPE_PURE_COOL: "Pure Cool",
DEVICE_TYPE_PURIFIER_COOL_K: "Purifier Cool",
DEVICE_TYPE_PURIFIER_COOL_E: "Purifier Cool",
Expand Down Expand Up @@ -111,6 +113,7 @@ class VacuumState(Enum):
MAPPING_NEEDS_CHARGE = "MAPPING_NEEDS_CHARGE"
MAPPING_PAUSED = "MAPPING_PAUSED"
MAPPING_RUNNING = "MAPPING_RUNNING"
MACHINE_OFF = "MACHINE_OFF"


class VacuumEyePowerMode(Enum):
Expand All @@ -128,6 +131,15 @@ class VacuumHeuristPowerMode(Enum):
MAX = "3"


class VacuumVisNavPowerMode(Enum):
"""Dyson 360 Heurist power mode."""

AUTO = "1"
QUICK = "2"
QUIET = "3"
BOOST = "4"


class CleaningType(Enum):
"""Vacuum cleaning type."""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
class DysonPureCoolLink(DysonFanDevice):
"""Dyson Pure Cool Link device."""

def __init__(self, serial: str, credential: str, device_type: str):
super().__init__(serial, credential, device_type)
self.preset_mode = "FAN"

@property
def fan_mode(self) -> str:
"""Return the fan mode of the fan."""
Expand All @@ -20,7 +24,11 @@ def is_on(self) -> bool:
@property
def auto_mode(self) -> bool:
"""Return auto mode status."""
return self.fan_mode == "AUTO"
if not self.is_on:
return self.preset_mode == "AUTO"
else:
self.preset_mode = self.fan_mode
return self.preset_mode == "AUTO"

@property
def oscillation(self) -> bool:
Expand Down Expand Up @@ -49,7 +57,7 @@ def volatile_organic_compounds(self) -> int:

def turn_on(self) -> None:
"""Turn on the device."""
self._set_configuration(fmod="FAN")
self._set_configuration(fmod=self.preset_mode)

def turn_off(self) -> None:
"""Turn off the device."""
Expand All @@ -60,10 +68,12 @@ def _set_speed(self, speed: int) -> None:

def enable_auto_mode(self) -> None:
"""Turn on auto mode."""
self.preset_mode = "AUTO"
self._set_configuration(fmod="AUTO")

def disable_auto_mode(self) -> None:
"""Turn off auto mode."""
self.preset_mode = "FAN"
self._set_configuration(fmod="FAN")

def enable_oscillation(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion script/sync-components
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ rm -rf custom_components/ember_mug
mv $TMPDIR/$$-ember/custom_components/ember_mug custom_components

# renovate: datasource=github-releases depName=libdyson-wg/ha-dyson
DYSON_LOCAL_VERSION=v1.3.11
DYSON_LOCAL_VERSION=v1.4.0
git clone --depth 1 --branch $DYSON_LOCAL_VERSION https://github.com/libdyson-wg/ha-dyson $TMPDIR/$$-dyson-local
rm -rf custom_components/dyson_local
mv $TMPDIR/$$-dyson-local/custom_components/dyson_local custom_components
Expand Down

0 comments on commit 368df6c

Please sign in to comment.