1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00

Add support for preset modes to bond fans (#64786)

This commit is contained in:
J. Nick Koston 2022-01-23 12:33:31 -10:00 committed by GitHub
parent 09408234a6
commit 74c16b977d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 121 additions and 2 deletions

View File

@ -35,6 +35,8 @@ from .utils import BondDevice, BondHub
_LOGGER = logging.getLogger(__name__)
PRESET_MODE_BREEZE = "Breeze"
async def async_setup_entry(
hass: HomeAssistant,
@ -74,11 +76,15 @@ class BondFan(BondEntity, FanEntity):
self._power: bool | None = None
self._speed: int | None = None
self._direction: int | None = None
if self._device.has_action(Action.BREEZE_ON):
self._attr_preset_modes = [PRESET_MODE_BREEZE]
def _apply_state(self, state: dict) -> None:
self._power = state.get("power")
self._speed = state.get("speed")
self._direction = state.get("direction")
breeze = state.get("breeze", [0, 0, 0])
self._attr_preset_mode = PRESET_MODE_BREEZE if breeze[0] else None
@property
def supported_features(self) -> int:
@ -185,13 +191,27 @@ class BondFan(BondEntity, FanEntity):
"""Turn on the fan."""
_LOGGER.debug("Fan async_turn_on called with percentage %s", percentage)
if percentage is not None:
if preset_mode is not None:
await self.async_set_preset_mode(preset_mode)
elif percentage is not None:
await self.async_set_percentage(percentage)
else:
await self._hub.bond.action(self._device.device_id, Action.turn_on())
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set the preset mode of the fan."""
if preset_mode != PRESET_MODE_BREEZE or not self._device.has_action(
Action.BREEZE_ON
):
raise ValueError(f"Invalid preset mode: {preset_mode}")
await self._hub.bond.action(self._device.device_id, Action(Action.BREEZE_ON))
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the fan off."""
if self.preset_mode == PRESET_MODE_BREEZE:
await self._hub.bond.action(
self._device.device_id, Action(Action.BREEZE_OFF)
)
await self._hub.bond.action(self._device.device_id, Action.turn_off())
async def async_set_direction(self, direction: str) -> None:

View File

@ -2,6 +2,7 @@
from __future__ import annotations
from datetime import timedelta
from unittest.mock import call
from bond_api import Action, DeviceType, Direction
import pytest
@ -12,14 +13,18 @@ from homeassistant.components.bond.const import (
DOMAIN as BOND_DOMAIN,
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
)
from homeassistant.components.bond.fan import PRESET_MODE_BREEZE
from homeassistant.components.fan import (
ATTR_DIRECTION,
ATTR_PRESET_MODE,
ATTR_PRESET_MODES,
ATTR_SPEED,
ATTR_SPEED_LIST,
DIRECTION_FORWARD,
DIRECTION_REVERSE,
DOMAIN as FAN_DOMAIN,
SERVICE_SET_DIRECTION,
SERVICE_SET_PRESET_MODE,
SERVICE_SET_SPEED,
SPEED_OFF,
)
@ -49,14 +54,26 @@ def ceiling_fan(name: str):
}
def ceiling_fan_with_breeze(name: str):
"""Create a ceiling fan with given name with breeze support."""
return {
"name": name,
"type": DeviceType.CEILING_FAN,
"actions": ["SetSpeed", "SetDirection", "BreezeOn"],
}
async def turn_fan_on(
hass: core.HomeAssistant,
fan_id: str,
speed: str | None = None,
percentage: int | None = None,
preset_mode: str | None = None,
) -> None:
"""Turn the fan on at the specified speed."""
service_data = {ATTR_ENTITY_ID: fan_id}
if preset_mode:
service_data[fan.ATTR_PRESET_MODE] = preset_mode
if speed:
service_data[fan.ATTR_SPEED] = speed
if percentage:
@ -205,6 +222,88 @@ async def test_turn_on_fan_with_percentage_6_speeds(hass: core.HomeAssistant):
mock_set_speed.assert_called_with("test-device-id", Action.set_speed(6))
async def test_turn_on_fan_preset_mode(hass: core.HomeAssistant):
"""Tests that turn on command delegates to breeze on API."""
await setup_platform(
hass,
FAN_DOMAIN,
ceiling_fan_with_breeze("name-1"),
bond_device_id="test-device-id",
props={"max_speed": 6},
)
assert hass.states.get("fan.name_1").attributes[ATTR_PRESET_MODES] == [
PRESET_MODE_BREEZE
]
with patch_bond_action() as mock_set_preset_mode, patch_bond_device_state():
await turn_fan_on(hass, "fan.name_1", preset_mode=PRESET_MODE_BREEZE)
mock_set_preset_mode.assert_called_with("test-device-id", Action(Action.BREEZE_ON))
with patch_bond_action() as mock_set_preset_mode, patch_bond_device_state():
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_PRESET_MODE,
service_data={
ATTR_PRESET_MODE: PRESET_MODE_BREEZE,
ATTR_ENTITY_ID: "fan.name_1",
},
blocking=True,
)
mock_set_preset_mode.assert_called_with("test-device-id", Action(Action.BREEZE_ON))
async def test_turn_on_fan_preset_mode_not_supported(hass: core.HomeAssistant):
"""Tests calling breeze mode on a fan that does not support it raises."""
await setup_platform(
hass,
FAN_DOMAIN,
ceiling_fan("name-1"),
bond_device_id="test-device-id",
props={"max_speed": 6},
)
with patch_bond_action(), patch_bond_device_state(), pytest.raises(
fan.NotValidPresetModeError
):
await turn_fan_on(hass, "fan.name_1", preset_mode=PRESET_MODE_BREEZE)
with patch_bond_action(), patch_bond_device_state(), pytest.raises(ValueError):
await hass.services.async_call(
FAN_DOMAIN,
SERVICE_SET_PRESET_MODE,
service_data={
ATTR_PRESET_MODE: PRESET_MODE_BREEZE,
ATTR_ENTITY_ID: "fan.name_1",
},
blocking=True,
)
async def test_turn_on_fan_with_off_with_breeze(hass: core.HomeAssistant):
"""Tests that turn off command delegates to turn off API."""
await setup_platform(
hass,
FAN_DOMAIN,
ceiling_fan_with_breeze("name-1"),
bond_device_id="test-device-id",
state={"breeze": [1, 0, 0]},
)
assert (
hass.states.get("fan.name_1").attributes[ATTR_PRESET_MODE] == PRESET_MODE_BREEZE
)
with patch_bond_action() as mock_actions, patch_bond_device_state():
await turn_fan_on(hass, "fan.name_1", fan.SPEED_OFF)
assert mock_actions.mock_calls == [
call("test-device-id", Action(Action.BREEZE_OFF)),
call("test-device-id", Action.turn_off()),
]
async def test_turn_on_fan_without_speed(hass: core.HomeAssistant):
"""Tests that turn on command delegates to turn on API."""
await setup_platform(
@ -218,7 +317,7 @@ async def test_turn_on_fan_without_speed(hass: core.HomeAssistant):
async def test_turn_on_fan_with_off_speed(hass: core.HomeAssistant):
"""Tests that turn on command delegates to turn off API."""
"""Tests that turn off command delegates to turn off API."""
await setup_platform(
hass, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
)