mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 09:23:17 -04:00
Vesync add oscillation to fan (#153297)
This commit is contained in:
@@ -18,7 +18,7 @@ from homeassistant.util.percentage import (
|
||||
percentage_to_ordered_list_item,
|
||||
)
|
||||
|
||||
from .common import is_fan, is_purifier
|
||||
from .common import is_fan, is_purifier, rgetattr
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
VS_COORDINATOR,
|
||||
@@ -90,11 +90,26 @@ class VeSyncFanHA(VeSyncBaseEntity, FanEntity):
|
||||
_attr_name = None
|
||||
_attr_translation_key = "vesync"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device: VeSyncBaseDevice,
|
||||
coordinator: VeSyncDataCoordinator,
|
||||
) -> None:
|
||||
"""Initialize the fan."""
|
||||
super().__init__(device, coordinator)
|
||||
if rgetattr(device, "state.oscillation_status") is not None:
|
||||
self._attr_supported_features |= FanEntityFeature.OSCILLATE
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if device is on."""
|
||||
return self.device.state.device_status == "on"
|
||||
|
||||
@property
|
||||
def oscillating(self) -> bool:
|
||||
"""Return True if device is oscillating."""
|
||||
return rgetattr(self.device, "state.oscillation_status") == "on"
|
||||
|
||||
@property
|
||||
def percentage(self) -> int | None:
|
||||
"""Return the currently set speed."""
|
||||
@@ -248,3 +263,10 @@ class VeSyncFanHA(VeSyncBaseEntity, FanEntity):
|
||||
if not success:
|
||||
raise HomeAssistantError(self.device.last_response.message)
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
async def async_oscillate(self, oscillating: bool) -> None:
|
||||
"""Set oscillation."""
|
||||
success = await self.device.toggle_oscillation(oscillating)
|
||||
if not success:
|
||||
raise HomeAssistantError(self.device.last_response.message)
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
'friendly_name': 'Test Fan',
|
||||
'preset_modes': list([
|
||||
]),
|
||||
'supported_features': 57,
|
||||
'supported_features': 59,
|
||||
}),
|
||||
'entity_id': 'fan.test_fan',
|
||||
'last_changed': str,
|
||||
|
||||
@@ -656,7 +656,7 @@
|
||||
'platform': 'vesync',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <FanEntityFeature: 57>,
|
||||
'supported_features': <FanEntityFeature: 59>,
|
||||
'translation_key': 'vesync',
|
||||
'unique_id': 'smarttowerfan',
|
||||
'unit_of_measurement': None,
|
||||
@@ -670,6 +670,7 @@
|
||||
'display_status': 'off',
|
||||
'friendly_name': 'SmartTowerFan',
|
||||
'mode': 'normal',
|
||||
'oscillating': True,
|
||||
'percentage': None,
|
||||
'percentage_step': 8.333333333333334,
|
||||
'preset_mode': 'normal',
|
||||
@@ -679,7 +680,7 @@
|
||||
'normal',
|
||||
'turbo',
|
||||
]),
|
||||
'supported_features': <FanEntityFeature: 57>,
|
||||
'supported_features': <FanEntityFeature: 59>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'fan.smarttowerfan',
|
||||
|
||||
@@ -107,6 +107,9 @@ async def test_async_get_device_diagnostics__single_fan(
|
||||
"home_assistant.entities.6.state.last_changed": (str,),
|
||||
"home_assistant.entities.6.state.last_reported": (str,),
|
||||
"home_assistant.entities.6.state.last_updated": (str,),
|
||||
"home_assistant.entities.7.state.last_changed": (str,),
|
||||
"home_assistant.entities.7.state.last_reported": (str,),
|
||||
"home_assistant.entities.7.state.last_updated": (str,),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -181,3 +181,48 @@ async def test_set_preset_mode(
|
||||
await hass.async_block_till_done()
|
||||
method_mock.assert_called_once()
|
||||
update_mock.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("action", "command"),
|
||||
[
|
||||
("true", "pyvesync.devices.vesyncfan.VeSyncTowerFan.toggle_oscillation"),
|
||||
("false", "pyvesync.devices.vesyncfan.VeSyncTowerFan.toggle_oscillation"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("api_response", "expectation"),
|
||||
[(True, NoException), (False, pytest.raises(HomeAssistantError))],
|
||||
)
|
||||
async def test_oscillation_success(
|
||||
hass: HomeAssistant,
|
||||
fan_config_entry: MockConfigEntry,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
action: str,
|
||||
command: str,
|
||||
api_response: bool,
|
||||
expectation,
|
||||
) -> None:
|
||||
"""Test oscillation on and off."""
|
||||
|
||||
mock_devices_response(aioclient_mock, "SmartTowerFan")
|
||||
|
||||
with (
|
||||
expectation,
|
||||
patch(
|
||||
command, new_callable=AsyncMock, return_value=api_response
|
||||
) as method_mock,
|
||||
):
|
||||
with patch(
|
||||
"homeassistant.components.vesync.fan.VeSyncFanHA.schedule_update_ha_state"
|
||||
) as update_mock:
|
||||
await hass.services.async_call(
|
||||
FAN_DOMAIN,
|
||||
"oscillate",
|
||||
{ATTR_ENTITY_ID: ENTITY_FAN, "oscillating": action},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
method_mock.assert_called_once()
|
||||
update_mock.assert_called_once()
|
||||
|
||||
Reference in New Issue
Block a user