mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Update dyson for the new fan entity model (#45762)
* Update dyson for the new fan entity model * Fix test * tweak * fix * adj * Update homeassistant/components/dyson/fan.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * move percentage is None block * move percentage is None block * no need to list comp Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
6b44636344
commit
ea7aa6af59
@ -1,5 +1,6 @@
|
|||||||
"""Support for Dyson Pure Cool link fan."""
|
"""Support for Dyson Pure Cool link fan."""
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from libpurecool.const import FanMode, FanSpeed, NightMode, Oscillation
|
from libpurecool.const import FanMode, FanSpeed, NightMode, Oscillation
|
||||||
@ -9,15 +10,12 @@ from libpurecool.dyson_pure_state import DysonPureCoolState
|
|||||||
from libpurecool.dyson_pure_state_v2 import DysonPureCoolV2State
|
from libpurecool.dyson_pure_state_v2 import DysonPureCoolV2State
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.fan import (
|
from homeassistant.components.fan import SUPPORT_OSCILLATE, SUPPORT_SET_SPEED, FanEntity
|
||||||
SPEED_HIGH,
|
|
||||||
SPEED_LOW,
|
|
||||||
SPEED_MEDIUM,
|
|
||||||
SUPPORT_OSCILLATE,
|
|
||||||
SUPPORT_SET_SPEED,
|
|
||||||
FanEntity,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
|
from homeassistant.util.percentage import (
|
||||||
|
percentage_to_ranged_value,
|
||||||
|
ranged_value_to_percentage,
|
||||||
|
)
|
||||||
|
|
||||||
from . import DYSON_DEVICES, DysonEntity
|
from . import DYSON_DEVICES, DysonEntity
|
||||||
|
|
||||||
@ -70,40 +68,30 @@ SET_DYSON_SPEED_SCHEMA = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SPEED_LIST_HA = [SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
|
PRESET_MODE_AUTO = "auto"
|
||||||
|
PRESET_MODES = [PRESET_MODE_AUTO]
|
||||||
|
|
||||||
SPEED_LIST_DYSON = [
|
ORDERED_DYSON_SPEEDS = [
|
||||||
int(FanSpeed.FAN_SPEED_1.value),
|
FanSpeed.FAN_SPEED_1,
|
||||||
int(FanSpeed.FAN_SPEED_2.value),
|
FanSpeed.FAN_SPEED_2,
|
||||||
int(FanSpeed.FAN_SPEED_3.value),
|
FanSpeed.FAN_SPEED_3,
|
||||||
int(FanSpeed.FAN_SPEED_4.value),
|
FanSpeed.FAN_SPEED_4,
|
||||||
int(FanSpeed.FAN_SPEED_5.value),
|
FanSpeed.FAN_SPEED_5,
|
||||||
int(FanSpeed.FAN_SPEED_6.value),
|
FanSpeed.FAN_SPEED_6,
|
||||||
int(FanSpeed.FAN_SPEED_7.value),
|
FanSpeed.FAN_SPEED_7,
|
||||||
int(FanSpeed.FAN_SPEED_8.value),
|
FanSpeed.FAN_SPEED_8,
|
||||||
int(FanSpeed.FAN_SPEED_9.value),
|
FanSpeed.FAN_SPEED_9,
|
||||||
int(FanSpeed.FAN_SPEED_10.value),
|
FanSpeed.FAN_SPEED_10,
|
||||||
]
|
]
|
||||||
|
DYSON_SPEED_TO_INT_VALUE = {k: int(k.value) for k in ORDERED_DYSON_SPEEDS}
|
||||||
|
INT_VALUE_TO_DYSON_SPEED = {v: k for k, v in DYSON_SPEED_TO_INT_VALUE.items()}
|
||||||
|
|
||||||
SPEED_DYSON_TO_HA = {
|
SPEED_LIST_DYSON = list(DYSON_SPEED_TO_INT_VALUE.values())
|
||||||
FanSpeed.FAN_SPEED_1.value: SPEED_LOW,
|
|
||||||
FanSpeed.FAN_SPEED_2.value: SPEED_LOW,
|
|
||||||
FanSpeed.FAN_SPEED_3.value: SPEED_LOW,
|
|
||||||
FanSpeed.FAN_SPEED_4.value: SPEED_LOW,
|
|
||||||
FanSpeed.FAN_SPEED_AUTO.value: SPEED_MEDIUM,
|
|
||||||
FanSpeed.FAN_SPEED_5.value: SPEED_MEDIUM,
|
|
||||||
FanSpeed.FAN_SPEED_6.value: SPEED_MEDIUM,
|
|
||||||
FanSpeed.FAN_SPEED_7.value: SPEED_MEDIUM,
|
|
||||||
FanSpeed.FAN_SPEED_8.value: SPEED_HIGH,
|
|
||||||
FanSpeed.FAN_SPEED_9.value: SPEED_HIGH,
|
|
||||||
FanSpeed.FAN_SPEED_10.value: SPEED_HIGH,
|
|
||||||
}
|
|
||||||
|
|
||||||
SPEED_HA_TO_DYSON = {
|
SPEED_RANGE = (
|
||||||
SPEED_LOW: FanSpeed.FAN_SPEED_4,
|
SPEED_LIST_DYSON[0],
|
||||||
SPEED_MEDIUM: FanSpeed.FAN_SPEED_7,
|
SPEED_LIST_DYSON[-1],
|
||||||
SPEED_HIGH: FanSpeed.FAN_SPEED_10,
|
) # off is not included
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
@ -160,14 +148,23 @@ class DysonFanEntity(DysonEntity, FanEntity):
|
|||||||
"""Representation of a Dyson fan."""
|
"""Representation of a Dyson fan."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def speed(self):
|
def percentage(self):
|
||||||
"""Return the current speed."""
|
"""Return the current speed percentage."""
|
||||||
return SPEED_DYSON_TO_HA[self._device.state.speed]
|
if self.auto_mode:
|
||||||
|
return None
|
||||||
|
return ranged_value_to_percentage(SPEED_RANGE, int(self._device.state.speed))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def speed_list(self) -> list:
|
def preset_modes(self):
|
||||||
"""Get the list of available speeds."""
|
"""Return the available preset modes."""
|
||||||
return SPEED_LIST_HA
|
return PRESET_MODES
|
||||||
|
|
||||||
|
@property
|
||||||
|
def preset_mode(self):
|
||||||
|
"""Return the current preset mode."""
|
||||||
|
if self.auto_mode:
|
||||||
|
return PRESET_MODE_AUTO
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dyson_speed(self):
|
def dyson_speed(self):
|
||||||
@ -206,12 +203,25 @@ class DysonFanEntity(DysonEntity, FanEntity):
|
|||||||
ATTR_DYSON_SPEED_LIST: self.dyson_speed_list,
|
ATTR_DYSON_SPEED_LIST: self.dyson_speed_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
def set_speed(self, speed: str) -> None:
|
def set_auto_mode(self, auto_mode: bool) -> None:
|
||||||
"""Set the speed of the fan."""
|
"""Set auto mode."""
|
||||||
if speed not in SPEED_LIST_HA:
|
raise NotImplementedError
|
||||||
raise ValueError(f'"{speed}" is not a valid speed')
|
|
||||||
_LOGGER.debug("Set fan speed to: %s", speed)
|
def set_percentage(self, percentage: int) -> None:
|
||||||
self.set_dyson_speed(SPEED_HA_TO_DYSON[speed])
|
"""Set the speed percentage of the fan."""
|
||||||
|
if percentage == 0:
|
||||||
|
self.turn_off()
|
||||||
|
return
|
||||||
|
dyson_speed = INT_VALUE_TO_DYSON_SPEED[
|
||||||
|
math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage))
|
||||||
|
]
|
||||||
|
self.set_dyson_speed(dyson_speed)
|
||||||
|
|
||||||
|
def set_preset_mode(self, preset_mode: str) -> None:
|
||||||
|
"""Set a preset mode on the fan."""
|
||||||
|
self._valid_preset_mode_or_raise(preset_mode)
|
||||||
|
# There currently is only one
|
||||||
|
self.set_auto_mode(True)
|
||||||
|
|
||||||
def set_dyson_speed(self, speed: FanSpeed) -> None:
|
def set_dyson_speed(self, speed: FanSpeed) -> None:
|
||||||
"""Set the exact speed of the fan."""
|
"""Set the exact speed of the fan."""
|
||||||
@ -225,21 +235,6 @@ class DysonFanEntity(DysonEntity, FanEntity):
|
|||||||
speed = FanSpeed(f"{int(dyson_speed):04d}")
|
speed = FanSpeed(f"{int(dyson_speed):04d}")
|
||||||
self.set_dyson_speed(speed)
|
self.set_dyson_speed(speed)
|
||||||
|
|
||||||
|
|
||||||
class DysonPureCoolLinkEntity(DysonFanEntity):
|
|
||||||
"""Representation of a Dyson fan."""
|
|
||||||
|
|
||||||
def __init__(self, device):
|
|
||||||
"""Initialize the fan."""
|
|
||||||
super().__init__(device, DysonPureCoolState)
|
|
||||||
|
|
||||||
#
|
|
||||||
# The fan entity model has changed to use percentages and preset_modes
|
|
||||||
# instead of speeds.
|
|
||||||
#
|
|
||||||
# Please review
|
|
||||||
# https://developers.home-assistant.io/docs/core/entity/fan/
|
|
||||||
#
|
|
||||||
def turn_on(
|
def turn_on(
|
||||||
self,
|
self,
|
||||||
speed: Optional[str] = None,
|
speed: Optional[str] = None,
|
||||||
@ -248,12 +243,22 @@ class DysonPureCoolLinkEntity(DysonFanEntity):
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Turn on the fan."""
|
"""Turn on the fan."""
|
||||||
_LOGGER.debug("Turn on fan %s with speed %s", self.name, speed)
|
_LOGGER.debug("Turn on fan %s with percentage %s", self.name, percentage)
|
||||||
if speed is not None:
|
if preset_mode:
|
||||||
self.set_speed(speed)
|
self.set_preset_mode(preset_mode)
|
||||||
else:
|
elif percentage is None:
|
||||||
# Speed not set, just turn on
|
# percentage not set, just turn on
|
||||||
self._device.set_configuration(fan_mode=FanMode.FAN)
|
self._device.set_configuration(fan_mode=FanMode.FAN)
|
||||||
|
else:
|
||||||
|
self.set_percentage(percentage)
|
||||||
|
|
||||||
|
|
||||||
|
class DysonPureCoolLinkEntity(DysonFanEntity):
|
||||||
|
"""Representation of a Dyson fan."""
|
||||||
|
|
||||||
|
def __init__(self, device):
|
||||||
|
"""Initialize the fan."""
|
||||||
|
super().__init__(device, DysonPureCoolState)
|
||||||
|
|
||||||
def turn_off(self, **kwargs) -> None:
|
def turn_off(self, **kwargs) -> None:
|
||||||
"""Turn off the fan."""
|
"""Turn off the fan."""
|
||||||
@ -312,13 +317,6 @@ class DysonPureCoolEntity(DysonFanEntity):
|
|||||||
"""Initialize the fan."""
|
"""Initialize the fan."""
|
||||||
super().__init__(device, DysonPureCoolV2State)
|
super().__init__(device, DysonPureCoolV2State)
|
||||||
|
|
||||||
#
|
|
||||||
# The fan entity model has changed to use percentages and preset_modes
|
|
||||||
# instead of speeds.
|
|
||||||
#
|
|
||||||
# Please review
|
|
||||||
# https://developers.home-assistant.io/docs/core/entity/fan/
|
|
||||||
#
|
|
||||||
def turn_on(
|
def turn_on(
|
||||||
self,
|
self,
|
||||||
speed: Optional[str] = None,
|
speed: Optional[str] = None,
|
||||||
@ -327,12 +325,14 @@ class DysonPureCoolEntity(DysonFanEntity):
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Turn on the fan."""
|
"""Turn on the fan."""
|
||||||
_LOGGER.debug("Turn on fan %s", self.name)
|
_LOGGER.debug("Turn on fan %s with percentage %s", self.name, percentage)
|
||||||
|
if preset_mode:
|
||||||
if speed is not None:
|
self.set_preset_mode(preset_mode)
|
||||||
self.set_speed(speed)
|
elif percentage is None:
|
||||||
else:
|
# percentage not set, just turn on
|
||||||
self._device.turn_on()
|
self._device.turn_on()
|
||||||
|
else:
|
||||||
|
self.set_percentage(percentage)
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
def turn_off(self, **kwargs):
|
||||||
"""Turn off the fan."""
|
"""Turn off the fan."""
|
||||||
|
@ -19,16 +19,18 @@ from homeassistant.components.dyson.fan import (
|
|||||||
ATTR_HEPA_FILTER,
|
ATTR_HEPA_FILTER,
|
||||||
ATTR_NIGHT_MODE,
|
ATTR_NIGHT_MODE,
|
||||||
ATTR_TIMER,
|
ATTR_TIMER,
|
||||||
|
PRESET_MODE_AUTO,
|
||||||
SERVICE_SET_ANGLE,
|
SERVICE_SET_ANGLE,
|
||||||
SERVICE_SET_AUTO_MODE,
|
SERVICE_SET_AUTO_MODE,
|
||||||
SERVICE_SET_DYSON_SPEED,
|
SERVICE_SET_DYSON_SPEED,
|
||||||
SERVICE_SET_FLOW_DIRECTION_FRONT,
|
SERVICE_SET_FLOW_DIRECTION_FRONT,
|
||||||
SERVICE_SET_NIGHT_MODE,
|
SERVICE_SET_NIGHT_MODE,
|
||||||
SERVICE_SET_TIMER,
|
SERVICE_SET_TIMER,
|
||||||
SPEED_LOW,
|
|
||||||
)
|
)
|
||||||
from homeassistant.components.fan import (
|
from homeassistant.components.fan import (
|
||||||
ATTR_OSCILLATING,
|
ATTR_OSCILLATING,
|
||||||
|
ATTR_PERCENTAGE,
|
||||||
|
ATTR_PRESET_MODE,
|
||||||
ATTR_SPEED,
|
ATTR_SPEED,
|
||||||
ATTR_SPEED_LIST,
|
ATTR_SPEED_LIST,
|
||||||
DOMAIN as PLATFORM_DOMAIN,
|
DOMAIN as PLATFORM_DOMAIN,
|
||||||
@ -37,7 +39,9 @@ from homeassistant.components.fan import (
|
|||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
SPEED_HIGH,
|
SPEED_HIGH,
|
||||||
|
SPEED_LOW,
|
||||||
SPEED_MEDIUM,
|
SPEED_MEDIUM,
|
||||||
|
SPEED_OFF,
|
||||||
SUPPORT_OSCILLATE,
|
SUPPORT_OSCILLATE,
|
||||||
SUPPORT_SET_SPEED,
|
SUPPORT_SET_SPEED,
|
||||||
)
|
)
|
||||||
@ -84,8 +88,16 @@ async def test_state_purecoollink(
|
|||||||
attributes = state.attributes
|
attributes = state.attributes
|
||||||
assert attributes[ATTR_NIGHT_MODE] is True
|
assert attributes[ATTR_NIGHT_MODE] is True
|
||||||
assert attributes[ATTR_OSCILLATING] is True
|
assert attributes[ATTR_OSCILLATING] is True
|
||||||
|
assert attributes[ATTR_PERCENTAGE] == 10
|
||||||
|
assert attributes[ATTR_PRESET_MODE] is None
|
||||||
assert attributes[ATTR_SPEED] == SPEED_LOW
|
assert attributes[ATTR_SPEED] == SPEED_LOW
|
||||||
assert attributes[ATTR_SPEED_LIST] == [SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
|
assert attributes[ATTR_SPEED_LIST] == [
|
||||||
|
SPEED_OFF,
|
||||||
|
SPEED_LOW,
|
||||||
|
SPEED_MEDIUM,
|
||||||
|
SPEED_HIGH,
|
||||||
|
PRESET_MODE_AUTO,
|
||||||
|
]
|
||||||
assert attributes[ATTR_DYSON_SPEED] == 1
|
assert attributes[ATTR_DYSON_SPEED] == 1
|
||||||
assert attributes[ATTR_DYSON_SPEED_LIST] == list(range(1, 11))
|
assert attributes[ATTR_DYSON_SPEED_LIST] == list(range(1, 11))
|
||||||
assert attributes[ATTR_AUTO_MODE] is False
|
assert attributes[ATTR_AUTO_MODE] is False
|
||||||
@ -106,7 +118,9 @@ async def test_state_purecoollink(
|
|||||||
attributes = state.attributes
|
attributes = state.attributes
|
||||||
assert attributes[ATTR_NIGHT_MODE] is False
|
assert attributes[ATTR_NIGHT_MODE] is False
|
||||||
assert attributes[ATTR_OSCILLATING] is False
|
assert attributes[ATTR_OSCILLATING] is False
|
||||||
assert attributes[ATTR_SPEED] == SPEED_MEDIUM
|
assert attributes[ATTR_PERCENTAGE] is None
|
||||||
|
assert attributes[ATTR_PRESET_MODE] == "auto"
|
||||||
|
assert attributes[ATTR_SPEED] == PRESET_MODE_AUTO
|
||||||
assert attributes[ATTR_DYSON_SPEED] == "AUTO"
|
assert attributes[ATTR_DYSON_SPEED] == "AUTO"
|
||||||
assert attributes[ATTR_AUTO_MODE] is True
|
assert attributes[ATTR_AUTO_MODE] is True
|
||||||
|
|
||||||
@ -125,8 +139,16 @@ async def test_state_purecool(hass: HomeAssistant, device: DysonPureCool) -> Non
|
|||||||
assert attributes[ATTR_OSCILLATING] is True
|
assert attributes[ATTR_OSCILLATING] is True
|
||||||
assert attributes[ATTR_ANGLE_LOW] == 24
|
assert attributes[ATTR_ANGLE_LOW] == 24
|
||||||
assert attributes[ATTR_ANGLE_HIGH] == 254
|
assert attributes[ATTR_ANGLE_HIGH] == 254
|
||||||
|
assert attributes[ATTR_PERCENTAGE] == 10
|
||||||
|
assert attributes[ATTR_PRESET_MODE] is None
|
||||||
assert attributes[ATTR_SPEED] == SPEED_LOW
|
assert attributes[ATTR_SPEED] == SPEED_LOW
|
||||||
assert attributes[ATTR_SPEED_LIST] == [SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
|
assert attributes[ATTR_SPEED_LIST] == [
|
||||||
|
SPEED_OFF,
|
||||||
|
SPEED_LOW,
|
||||||
|
SPEED_MEDIUM,
|
||||||
|
SPEED_HIGH,
|
||||||
|
PRESET_MODE_AUTO,
|
||||||
|
]
|
||||||
assert attributes[ATTR_DYSON_SPEED] == 1
|
assert attributes[ATTR_DYSON_SPEED] == 1
|
||||||
assert attributes[ATTR_DYSON_SPEED_LIST] == list(range(1, 11))
|
assert attributes[ATTR_DYSON_SPEED_LIST] == list(range(1, 11))
|
||||||
assert attributes[ATTR_AUTO_MODE] is False
|
assert attributes[ATTR_AUTO_MODE] is False
|
||||||
@ -148,7 +170,9 @@ async def test_state_purecool(hass: HomeAssistant, device: DysonPureCool) -> Non
|
|||||||
attributes = state.attributes
|
attributes = state.attributes
|
||||||
assert attributes[ATTR_NIGHT_MODE] is False
|
assert attributes[ATTR_NIGHT_MODE] is False
|
||||||
assert attributes[ATTR_OSCILLATING] is False
|
assert attributes[ATTR_OSCILLATING] is False
|
||||||
assert attributes[ATTR_SPEED] == SPEED_MEDIUM
|
assert attributes[ATTR_PERCENTAGE] is None
|
||||||
|
assert attributes[ATTR_PRESET_MODE] == "auto"
|
||||||
|
assert attributes[ATTR_SPEED] == PRESET_MODE_AUTO
|
||||||
assert attributes[ATTR_DYSON_SPEED] == "AUTO"
|
assert attributes[ATTR_DYSON_SPEED] == "AUTO"
|
||||||
assert attributes[ATTR_AUTO_MODE] is True
|
assert attributes[ATTR_AUTO_MODE] is True
|
||||||
assert attributes[ATTR_FLOW_DIRECTION_FRONT] is False
|
assert attributes[ATTR_FLOW_DIRECTION_FRONT] is False
|
||||||
@ -170,6 +194,11 @@ async def test_state_purecool(hass: HomeAssistant, device: DysonPureCool) -> Non
|
|||||||
{ATTR_SPEED: SPEED_LOW},
|
{ATTR_SPEED: SPEED_LOW},
|
||||||
{"fan_mode": FanMode.FAN, "fan_speed": FanSpeed.FAN_SPEED_4},
|
{"fan_mode": FanMode.FAN, "fan_speed": FanSpeed.FAN_SPEED_4},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_PERCENTAGE: 40},
|
||||||
|
{"fan_mode": FanMode.FAN, "fan_speed": FanSpeed.FAN_SPEED_4},
|
||||||
|
),
|
||||||
(SERVICE_TURN_OFF, {}, {"fan_mode": FanMode.OFF}),
|
(SERVICE_TURN_OFF, {}, {"fan_mode": FanMode.OFF}),
|
||||||
(
|
(
|
||||||
SERVICE_OSCILLATE,
|
SERVICE_OSCILLATE,
|
||||||
@ -229,6 +258,18 @@ async def test_commands_purecoollink(
|
|||||||
"set_fan_speed",
|
"set_fan_speed",
|
||||||
[FanSpeed.FAN_SPEED_4],
|
[FanSpeed.FAN_SPEED_4],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_PERCENTAGE: 40},
|
||||||
|
"set_fan_speed",
|
||||||
|
[FanSpeed.FAN_SPEED_4],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_PRESET_MODE: "auto"},
|
||||||
|
"enable_auto_mode",
|
||||||
|
[],
|
||||||
|
),
|
||||||
(SERVICE_TURN_OFF, {}, "turn_off", []),
|
(SERVICE_TURN_OFF, {}, "turn_off", []),
|
||||||
(SERVICE_OSCILLATE, {ATTR_OSCILLATING: True}, "enable_oscillation", []),
|
(SERVICE_OSCILLATE, {ATTR_OSCILLATING: True}, "enable_oscillation", []),
|
||||||
(SERVICE_OSCILLATE, {ATTR_OSCILLATING: False}, "disable_oscillation", []),
|
(SERVICE_OSCILLATE, {ATTR_OSCILLATING: False}, "disable_oscillation", []),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user