Parcourir la source

Use generic implementation for Goldair fan.

Jason Rumney il y a 4 ans
Parent
commit
00bc167864

+ 0 - 1
custom_components/tuya_local/devices/goldair_fan.yaml

@@ -38,7 +38,6 @@ primary_entity:
       name: timer
 secondary_entities:
   - entity: climate
-    legacy_class: ".legacy_fan.climate.GoldairFan"
     dps:
       - id: 1
         type: boolean

+ 0 - 0
custom_components/tuya_local/legacy_fan/__init__.py


+ 0 - 173
custom_components/tuya_local/legacy_fan/climate.py

@@ -1,173 +0,0 @@
-"""
-Goldair WiFi Fan device.
-"""
-from homeassistant.components.climate import ClimateEntity
-from homeassistant.components.climate.const import (
-    ATTR_FAN_MODE,
-    ATTR_HVAC_MODE,
-    ATTR_PRESET_MODE,
-    ATTR_SWING_MODE,
-    SUPPORT_FAN_MODE,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_SWING_MODE,
-)
-from homeassistant.const import ATTR_TEMPERATURE, STATE_UNAVAILABLE
-
-from ..device import TuyaLocalDevice
-from .const import (
-    FAN_MODES,
-    HVAC_MODE_TO_DPS_MODE,
-    PRESET_MODE_TO_DPS_MODE,
-    PROPERTY_TO_DPS_ID,
-    SWING_MODE_TO_DPS_MODE,
-)
-
-SUPPORT_FLAGS = SUPPORT_FAN_MODE | SUPPORT_PRESET_MODE | SUPPORT_SWING_MODE
-
-
-class GoldairFan(ClimateEntity):
-    """Representation of a Goldair WiFi fan."""
-
-    def __init__(self, device):
-        """Initialize the fan.
-        Args:
-            name (str): The device's name.
-            device (TuyaLocalDevice): The device API instance."""
-        self._device = device
-
-        self._support_flags = SUPPORT_FLAGS
-
-    @property
-    def supported_features(self):
-        """Return the list of supported features."""
-        return self._support_flags
-
-    @property
-    def should_poll(self):
-        """Return the polling state."""
-        return True
-
-    @property
-    def name(self):
-        """Return the name of the climate device."""
-        return self._device.name
-
-    @property
-    def unique_id(self):
-        """Return the unique id for this fan."""
-        return self._device.unique_id
-
-    @property
-    def device_info(self):
-        """Return device information about this fan."""
-        return self._device.device_info
-
-    @property
-    def icon(self):
-        """Return the icon to use in the frontend for this device."""
-        return "mdi:fan"
-
-    @property
-    def temperature_unit(self):
-        """This is not used but required by Home Assistant."""
-        return self._device.temperature_unit
-
-    @property
-    def hvac_mode(self):
-        """Return current HVAC mode, ie Fan Only or Off."""
-        dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE])
-
-        if dps_mode is not None:
-            return TuyaLocalDevice.get_key_for_value(HVAC_MODE_TO_DPS_MODE, dps_mode)
-        else:
-            return STATE_UNAVAILABLE
-
-    @property
-    def hvac_modes(self):
-        """Return the list of available HVAC modes."""
-        return list(HVAC_MODE_TO_DPS_MODE.keys())
-
-    async def async_set_hvac_mode(self, hvac_mode):
-        """Set new HVAC mode."""
-        dps_mode = HVAC_MODE_TO_DPS_MODE[hvac_mode]
-        await self._device.async_set_property(
-            PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE], dps_mode
-        )
-
-    @property
-    def preset_mode(self):
-        """Return current preset mode, ie Comfort, Eco, Anti-freeze."""
-        dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE])
-        if dps_mode is not None:
-            return TuyaLocalDevice.get_key_for_value(PRESET_MODE_TO_DPS_MODE, dps_mode)
-        else:
-            return None
-
-    @property
-    def preset_modes(self):
-        """Return the list of available preset modes."""
-        return list(PRESET_MODE_TO_DPS_MODE.keys())
-
-    async def async_set_preset_mode(self, preset_mode):
-        """Set new preset mode."""
-        dps_mode = PRESET_MODE_TO_DPS_MODE[preset_mode]
-        await self._device.async_set_property(
-            PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE], dps_mode
-        )
-
-    @property
-    def swing_mode(self):
-        """Return current swing mode: horizontal or off"""
-        dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_SWING_MODE])
-        if dps_mode is not None:
-            return TuyaLocalDevice.get_key_for_value(SWING_MODE_TO_DPS_MODE, dps_mode)
-        else:
-            return None
-
-    @property
-    def swing_modes(self):
-        """Return the list of available swing modes."""
-        return list(SWING_MODE_TO_DPS_MODE.keys())
-
-    async def async_set_swing_mode(self, swing_mode):
-        """Set new swing mode."""
-        dps_mode = SWING_MODE_TO_DPS_MODE[swing_mode]
-        await self._device.async_set_property(
-            PROPERTY_TO_DPS_ID[ATTR_SWING_MODE], dps_mode
-        )
-
-    @property
-    def fan_mode(self):
-        """Return current fan mode: 1-12 or 1-3 depending on the preset"""
-        dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE])
-        if (
-            dps_mode is not None
-            and self.preset_mode is not None
-            and dps_mode in FAN_MODES[self.preset_mode].values()
-        ):
-            return TuyaLocalDevice.get_key_for_value(
-                FAN_MODES[self.preset_mode], dps_mode
-            )
-        else:
-            return None
-
-    @property
-    def fan_modes(self):
-        """Return the list of available fan modes."""
-        if self.preset_mode is not None:
-            return list(FAN_MODES[self.preset_mode].keys())
-        else:
-            return []
-
-    async def async_set_fan_mode(self, fan_mode):
-        """Set new fan mode."""
-        if self.preset_mode is not None:
-            dps_mode = FAN_MODES[self.preset_mode][int(fan_mode)]
-            await self._device.async_set_property(
-                PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], dps_mode
-            )
-        else:
-            raise ValueError("Fan mode can only be set when a preset mode is set")
-
-    async def async_update(self):
-        await self._device.async_refresh()

+ 0 - 51
custom_components/tuya_local/legacy_fan/const.py

@@ -1,51 +0,0 @@
-from homeassistant.components.climate.const import (
-    ATTR_FAN_MODE,
-    ATTR_HVAC_MODE,
-    ATTR_PRESET_MODE,
-    ATTR_SWING_MODE,
-    HVAC_MODE_FAN_ONLY,
-    HVAC_MODE_OFF,
-    PRESET_ECO,
-    PRESET_SLEEP,
-    SWING_HORIZONTAL,
-    SWING_OFF,
-)
-
-ATTR_TARGET_TEMPERATURE = "target_temperature"
-ATTR_DISPLAY_ON = "display_on"
-
-PRESET_NORMAL = "normal"
-
-PROPERTY_TO_DPS_ID = {
-    ATTR_HVAC_MODE: "1",
-    ATTR_FAN_MODE: "2",
-    ATTR_PRESET_MODE: "3",
-    ATTR_SWING_MODE: "8",
-    ATTR_DISPLAY_ON: "101",
-}
-
-HVAC_MODE_TO_DPS_MODE = {HVAC_MODE_OFF: False, HVAC_MODE_FAN_ONLY: True}
-PRESET_MODE_TO_DPS_MODE = {
-    PRESET_NORMAL: "normal",
-    PRESET_ECO: "nature",
-    PRESET_SLEEP: "sleep",
-}
-SWING_MODE_TO_DPS_MODE = {SWING_OFF: False, SWING_HORIZONTAL: True}
-FAN_MODES = {
-    PRESET_NORMAL: {
-        1: "1",
-        2: "2",
-        3: "3",
-        4: "4",
-        5: "5",
-        6: "6",
-        7: "7",
-        8: "8",
-        9: "9",
-        10: "10",
-        11: "11",
-        12: "12",
-    },
-    PRESET_ECO: {1: "4", 2: "8", 3: "12"},
-    PRESET_SLEEP: {1: "4", 2: "8", 3: "12"},
-}

+ 0 - 9
tests/devices/test_goldair_fan.py

@@ -364,15 +364,6 @@ class TestGoldairFan(IsolatedAsyncioTestCase):
         ):
             await self.climate.async_set_fan_mode("medium")
 
-    @skip("Conditions not yet supported for setting")
-    async def test_climate_set_fan_mode_does_nothing_when_preset_mode_is_not_set(self):
-        self.dps[PRESET_DPS] = None
-
-        with self.assertRaises(
-            ValueError, msg="Fan mode can only be set when a preset mode is set"
-        ):
-            await self.climate.async_set_fan_mode(2)
-
     def test_device_state_attributes(self):
         self.dps[TIMER_DPS] = "5"
         self.assertEqual(self.climate.device_state_attributes, {"timer": "5"})

+ 0 - 0
tests/fan/__init__.py


+ 0 - 303
tests/fan/test_climate.py

@@ -1,303 +0,0 @@
-from unittest import IsolatedAsyncioTestCase
-from unittest.mock import AsyncMock, patch
-
-from homeassistant.components.climate.const import (
-    ATTR_FAN_MODE,
-    ATTR_HVAC_MODE,
-    ATTR_PRESET_MODE,
-    ATTR_SWING_MODE,
-    HVAC_MODE_FAN_ONLY,
-    HVAC_MODE_OFF,
-    PRESET_ECO,
-    PRESET_SLEEP,
-    SUPPORT_FAN_MODE,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_SWING_MODE,
-    SWING_HORIZONTAL,
-    SWING_OFF,
-)
-from homeassistant.const import ATTR_TEMPERATURE, STATE_UNAVAILABLE
-
-from custom_components.tuya_local.legacy_fan.climate import GoldairFan
-from custom_components.tuya_local.legacy_fan.const import (
-    FAN_MODES,
-    HVAC_MODE_TO_DPS_MODE,
-    PRESET_MODE_TO_DPS_MODE,
-    PRESET_NORMAL,
-    PROPERTY_TO_DPS_ID,
-    SWING_MODE_TO_DPS_MODE,
-)
-
-from ..const import FAN_PAYLOAD
-from ..helpers import assert_device_properties_set
-
-
-class TestGoldairFan(IsolatedAsyncioTestCase):
-    def setUp(self):
-        device_patcher = patch("custom_components.tuya_local.device.TuyaLocalDevice")
-        self.addCleanup(device_patcher.stop)
-        self.mock_device = device_patcher.start()
-
-        self.subject = GoldairFan(self.mock_device())
-
-        self.dps = FAN_PAYLOAD.copy()
-        self.subject._device.get_property.side_effect = lambda id: self.dps[id]
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_FAN_MODE | SUPPORT_PRESET_MODE | SUPPORT_SWING_MODE,
-        )
-
-    def test_should_poll(self):
-        self.assertTrue(self.subject.should_poll)
-
-    def test_name_returns_device_name(self):
-        self.assertEqual(self.subject.name, self.subject._device.name)
-
-    def test_unique_id_returns_device_unique_id(self):
-        self.assertEqual(self.subject.unique_id, self.subject._device.unique_id)
-
-    def test_device_info_returns_device_info_from_device(self):
-        self.assertEqual(self.subject.device_info, self.subject._device.device_info)
-
-    def test_icon_is_fan(self):
-        self.assertEqual(self.subject.icon, "mdi:fan")
-
-    def test_temperature_unit_returns_device_temperature_unit(self):
-        self.assertEqual(
-            self.subject.temperature_unit, self.subject._device.temperature_unit
-        )
-
-    def test_hvac_mode(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE]] = True
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_FAN_ONLY)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE]] = False
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE]] = None
-        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_hvac_modes(self):
-        self.assertEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_FAN_ONLY])
-
-    async def test_turn_on(self):
-        async with assert_device_properties_set(
-            self.subject._device, {PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE]: True}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_FAN_ONLY)
-
-    async def test_turn_off(self):
-        async with assert_device_properties_set(
-            self.subject._device, {PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE]: False}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
-
-    def test_preset_mode(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_NORMAL
-        ]
-        self.assertEqual(self.subject.preset_mode, PRESET_NORMAL)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_ECO
-        ]
-        self.assertEqual(self.subject.preset_mode, PRESET_ECO)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_SLEEP
-        ]
-        self.assertEqual(self.subject.preset_mode, PRESET_SLEEP)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = None
-        self.assertIs(self.subject.preset_mode, None)
-
-    def test_preset_modes(self):
-        self.assertEqual(
-            self.subject.preset_modes, [PRESET_NORMAL, PRESET_ECO, PRESET_SLEEP]
-        )
-
-    async def test_set_preset_mode_to_normal(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]: PRESET_MODE_TO_DPS_MODE[
-                    PRESET_NORMAL
-                ]
-            },
-        ):
-            await self.subject.async_set_preset_mode(PRESET_NORMAL)
-
-    async def test_set_preset_mode_to_eco(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]: PRESET_MODE_TO_DPS_MODE[PRESET_ECO]},
-        ):
-            await self.subject.async_set_preset_mode(PRESET_ECO)
-
-    async def test_set_preset_mode_to_sleep(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]: PRESET_MODE_TO_DPS_MODE[
-                    PRESET_SLEEP
-                ]
-            },
-        ):
-            await self.subject.async_set_preset_mode(PRESET_SLEEP)
-
-    def test_swing_mode(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_SWING_MODE]] = SWING_MODE_TO_DPS_MODE[
-            SWING_OFF
-        ]
-        self.assertEqual(self.subject.swing_mode, SWING_OFF)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_SWING_MODE]] = SWING_MODE_TO_DPS_MODE[
-            SWING_HORIZONTAL
-        ]
-        self.assertEqual(self.subject.swing_mode, SWING_HORIZONTAL)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_SWING_MODE]] = None
-        self.assertIs(self.subject.swing_mode, None)
-
-    def test_swing_modes(self):
-        self.assertEqual(self.subject.swing_modes, [SWING_OFF, SWING_HORIZONTAL])
-
-    async def test_set_swing_mode_to_off(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PROPERTY_TO_DPS_ID[ATTR_SWING_MODE]: SWING_MODE_TO_DPS_MODE[SWING_OFF]},
-        ):
-            await self.subject.async_set_swing_mode(SWING_OFF)
-
-    async def test_set_swing_mode_to_horizontal(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                PROPERTY_TO_DPS_ID[ATTR_SWING_MODE]: SWING_MODE_TO_DPS_MODE[
-                    SWING_HORIZONTAL
-                ]
-            },
-        ):
-            await self.subject.async_set_swing_mode(SWING_HORIZONTAL)
-
-    def test_fan_modes(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_NORMAL
-        ]
-        self.assertEqual(self.subject.fan_modes, list(range(1, 13)))
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_ECO
-        ]
-        self.assertEqual(self.subject.fan_modes, [1, 2, 3])
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_SLEEP
-        ]
-        self.assertEqual(self.subject.fan_modes, [1, 2, 3])
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = None
-        self.assertEqual(self.subject.fan_modes, [])
-
-    def test_fan_mode_for_normal_preset(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_NORMAL
-        ]
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "1"
-        self.assertEqual(self.subject.fan_mode, 1)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "6"
-        self.assertEqual(self.subject.fan_mode, 6)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "12"
-        self.assertEqual(self.subject.fan_mode, 12)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = None
-        self.assertEqual(self.subject.fan_mode, None)
-
-    async def test_set_fan_mode_for_normal_preset(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_NORMAL
-        ]
-
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]: "6"},
-        ):
-            await self.subject.async_set_fan_mode(6)
-
-    def test_fan_mode_for_eco_preset(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_ECO
-        ]
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "4"
-        self.assertEqual(self.subject.fan_mode, 1)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "8"
-        self.assertEqual(self.subject.fan_mode, 2)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "12"
-        self.assertEqual(self.subject.fan_mode, 3)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = None
-        self.assertEqual(self.subject.fan_mode, None)
-
-    async def test_set_fan_mode_for_eco_preset(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_ECO
-        ]
-
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]: "4"},
-        ):
-            await self.subject.async_set_fan_mode(1)
-
-    def test_fan_mode_for_sleep_preset(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_SLEEP
-        ]
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "4"
-        self.assertEqual(self.subject.fan_mode, 1)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "8"
-        self.assertEqual(self.subject.fan_mode, 2)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = "12"
-        self.assertEqual(self.subject.fan_mode, 3)
-
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]] = None
-        self.assertEqual(self.subject.fan_mode, None)
-
-    async def test_set_fan_mode_for_sleep_preset(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = PRESET_MODE_TO_DPS_MODE[
-            PRESET_SLEEP
-        ]
-
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PROPERTY_TO_DPS_ID[ATTR_FAN_MODE]: "8"},
-        ):
-            await self.subject.async_set_fan_mode(2)
-
-    async def test_set_fan_mode_does_nothing_when_preset_mode_is_not_set(self):
-        self.dps[PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE]] = None
-
-        with self.assertRaises(
-            ValueError, msg="Fan mode can only be set when a preset mode is set"
-        ):
-            await self.subject.async_set_fan_mode(2)
-
-    async def test_update(self):
-        result = AsyncMock()
-        self.subject._device.async_refresh.return_value = result()
-
-        await self.subject.async_update()
-
-        self.subject._device.async_refresh.assert_called_once()
-        result.assert_awaited()

+ 1 - 1
tests/test_device_config.py

@@ -193,7 +193,7 @@ class TestDeviceConfig(unittest.TestCase):
 
     def test_goldair_fan_detection(self):
         """Test that Goldair fan can be detected from its sample payload."""
-        self._test_detect(FAN_PAYLOAD, "fan", "GoldairFan")
+        self._test_detect(FAN_PAYLOAD, "fan", None)
 
     def test_kogan_socket_detection(self):
         """Test that 1st gen Kogan Socket can be detected from its sample payload."""