From 4a8b77b8d834836e2eaff87d67c6fe2d9af962dc Mon Sep 17 00:00:00 2001 From: Aravind Jaimon Date: Fri, 7 Jun 2024 08:06:46 +0530 Subject: [PATCH 1/4] feat(fan): added support for gorilla fan v2 --- .../tuya_local/devices/gorilla_fan_v2.yaml | 58 +++++++++++++++ tests/devices/test_gorilla_fan_v2.py | 71 +++++++++++++++++++ tests/test_fan.py | 22 ++++++ 3 files changed, 151 insertions(+) create mode 100644 custom_components/tuya_local/devices/gorilla_fan_v2.yaml create mode 100644 tests/devices/test_gorilla_fan_v2.py diff --git a/custom_components/tuya_local/devices/gorilla_fan_v2.yaml b/custom_components/tuya_local/devices/gorilla_fan_v2.yaml new file mode 100644 index 0000000000..b6289094eb --- /dev/null +++ b/custom_components/tuya_local/devices/gorilla_fan_v2.yaml @@ -0,0 +1,58 @@ +name: Gorilla Fan V2 +primary_entity: + entity: fan + dps: + - id: 1 + type: boolean + name: switch + icon: mdi:ceiling-fan + - id: 2 + type: string + name: preset_mode + mapping: + - dps_value: normal + value: Normal + - dps_value: boost + value: Boost + - id: 3 + type: integer + name: speed + range: + min: 1 + max: 5 + +secondary_entities: + - entity: light + name: Night Light + icon: mdi:ceiling-fan-light + dps: + - id: 15 + type: boolean + name: switch + - entity: switch + name: Boost + icon: mdi:car-turbocharger + dps: + - id: 115 + type: boolean + name: switch + - entity: switch + name: Sleep + icon: mdi:sleep + dps: + - id: 113 + type: boolean + name: switch + - entity: number + name: Timer + icon: mdi:timer-edit + translation_key: timer + category: config + dps: + - id: 102 + type: integer + name: value + unit: min + range: + min: 0 + max: 360 diff --git a/tests/devices/test_gorilla_fan_v2.py b/tests/devices/test_gorilla_fan_v2.py new file mode 100644 index 0000000000..3e8ceb0e59 --- /dev/null +++ b/tests/devices/test_gorilla_fan_v2.py @@ -0,0 +1,71 @@ +from homeassistant.components.fan import FanEntityFeature + +from ..const import FAN_PAYLOAD +from ..helpers import assert_device_properties_set +from .base_device_tests import TuyaDeviceTestCase + +SWITCH_DPS = "1" +PRESET_DPS = "2" +FANMODE_DPS = "3" + +class TestGorillaFanV2(TuyaDeviceTestCase): + __test__ = True + + def setUp(self): + self.setUpForConfig("gorilla_fan_v2.yaml", FAN_PAYLOAD) + self.subject = self.entities.get("fan") + + def test_supported_features(self): + self.assertEqual( + self.subject.supported_features, + ( + FanEntityFeature.PRESET_MODE + | FanEntityFeature.SET_SPEED + ), + ) + + def test_preset_mode(self): + self.dps[PRESET_DPS] = "normal" + self.assertEqual(self.subject.preset_mode, "Normal") + + self.dps[PRESET_DPS] = "boost" + self.assertEqual(self.subject.preset_mode, "Boost") + + def test_preset_modes(self): + self.assertCountEqual(self.subject.preset_modes, ["normal", "boost"]) + + async def test_set_preset_mode_to_normal(self): + async with assert_device_properties_set( + self.subject._device, + {PRESET_DPS: "normal"}, + ): + await self.subject.async_set_preset_mode("Normal") + + async def test_set_preset_mode_to_boost(self): + async with assert_device_properties_set( + self.subject._device, + {PRESET_DPS: "boost"}, + ): + await self.subject.async_set_preset_mode("Boost") + + def test_speed(self): + self.dps[PRESET_DPS] = "normal" + self.dps[FANMODE_DPS] = 3 + self.assertEqual(self.subject.percentage, 60) + + async def test_set_speed_in_normal_mode(self): + self.dps[PRESET_DPS] = "normal" + async with assert_device_properties_set(self.subject._device, {FANMODE_DPS: 3}): + await self.subject.async_set_percentage(60) + + async def test_set_speed_in_boost_mode(self): + self.dps[PRESET_DPS] = "boost" + async with assert_device_properties_set(self.subject._device, {FANMODE_DPS: 5}): + await self.subject.async_set_percentage(100) + + async def test_set_speed_to_zero_turns_off(self): + async with assert_device_properties_set( + self.subject._device, {SWITCH_DPS: False} + ): + await self.subject.async_set_percentage(0) + diff --git a/tests/test_fan.py b/tests/test_fan.py index 9e157f4eb0..b4557caeda 100644 --- a/tests/test_fan.py +++ b/tests/test_fan.py @@ -120,3 +120,25 @@ async def test_init_entry_fails_if_config_is_missing(hass): except ValueError: pass m_add_entities.assert_not_called() + +@pytest.mark.asyncio +async def test_init_entry_for_gorilla_fan_v2(hass): + """Test initialisation for Gorilla Fan V2""" + entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_TYPE: "gorilla_fan_v2", + CONF_DEVICE_ID: "dummy", + CONF_PROTOCOL_VERSION: "auto", + }, + ) + m_add_entities = Mock() + m_device = AsyncMock() + + hass.data[DOMAIN] = {} + hass.data[DOMAIN]["dummy"] = {} + hass.data[DOMAIN]["dummy"]["device"] = m_device + + await async_setup_entry(hass, entry, m_add_entities) + assert type(hass.data[DOMAIN]["dummy"]["fan"]) == TuyaLocalFan + m_add_entities.assert_called_once() From d6f0c5c31076611f7f74ac1a390a13f1cfbd407f Mon Sep 17 00:00:00 2001 From: Aravind Jaimon Date: Fri, 7 Jun 2024 23:11:40 +0530 Subject: [PATCH 2/4] refactor(fan): removed testcases for gorilla --- tests/devices/test_gorilla_fan_v2.py | 71 ---------------------------- tests/test_fan.py | 22 --------- 2 files changed, 93 deletions(-) delete mode 100644 tests/devices/test_gorilla_fan_v2.py diff --git a/tests/devices/test_gorilla_fan_v2.py b/tests/devices/test_gorilla_fan_v2.py deleted file mode 100644 index 3e8ceb0e59..0000000000 --- a/tests/devices/test_gorilla_fan_v2.py +++ /dev/null @@ -1,71 +0,0 @@ -from homeassistant.components.fan import FanEntityFeature - -from ..const import FAN_PAYLOAD -from ..helpers import assert_device_properties_set -from .base_device_tests import TuyaDeviceTestCase - -SWITCH_DPS = "1" -PRESET_DPS = "2" -FANMODE_DPS = "3" - -class TestGorillaFanV2(TuyaDeviceTestCase): - __test__ = True - - def setUp(self): - self.setUpForConfig("gorilla_fan_v2.yaml", FAN_PAYLOAD) - self.subject = self.entities.get("fan") - - def test_supported_features(self): - self.assertEqual( - self.subject.supported_features, - ( - FanEntityFeature.PRESET_MODE - | FanEntityFeature.SET_SPEED - ), - ) - - def test_preset_mode(self): - self.dps[PRESET_DPS] = "normal" - self.assertEqual(self.subject.preset_mode, "Normal") - - self.dps[PRESET_DPS] = "boost" - self.assertEqual(self.subject.preset_mode, "Boost") - - def test_preset_modes(self): - self.assertCountEqual(self.subject.preset_modes, ["normal", "boost"]) - - async def test_set_preset_mode_to_normal(self): - async with assert_device_properties_set( - self.subject._device, - {PRESET_DPS: "normal"}, - ): - await self.subject.async_set_preset_mode("Normal") - - async def test_set_preset_mode_to_boost(self): - async with assert_device_properties_set( - self.subject._device, - {PRESET_DPS: "boost"}, - ): - await self.subject.async_set_preset_mode("Boost") - - def test_speed(self): - self.dps[PRESET_DPS] = "normal" - self.dps[FANMODE_DPS] = 3 - self.assertEqual(self.subject.percentage, 60) - - async def test_set_speed_in_normal_mode(self): - self.dps[PRESET_DPS] = "normal" - async with assert_device_properties_set(self.subject._device, {FANMODE_DPS: 3}): - await self.subject.async_set_percentage(60) - - async def test_set_speed_in_boost_mode(self): - self.dps[PRESET_DPS] = "boost" - async with assert_device_properties_set(self.subject._device, {FANMODE_DPS: 5}): - await self.subject.async_set_percentage(100) - - async def test_set_speed_to_zero_turns_off(self): - async with assert_device_properties_set( - self.subject._device, {SWITCH_DPS: False} - ): - await self.subject.async_set_percentage(0) - diff --git a/tests/test_fan.py b/tests/test_fan.py index b4557caeda..9e157f4eb0 100644 --- a/tests/test_fan.py +++ b/tests/test_fan.py @@ -120,25 +120,3 @@ async def test_init_entry_fails_if_config_is_missing(hass): except ValueError: pass m_add_entities.assert_not_called() - -@pytest.mark.asyncio -async def test_init_entry_for_gorilla_fan_v2(hass): - """Test initialisation for Gorilla Fan V2""" - entry = MockConfigEntry( - domain=DOMAIN, - data={ - CONF_TYPE: "gorilla_fan_v2", - CONF_DEVICE_ID: "dummy", - CONF_PROTOCOL_VERSION: "auto", - }, - ) - m_add_entities = Mock() - m_device = AsyncMock() - - hass.data[DOMAIN] = {} - hass.data[DOMAIN]["dummy"] = {} - hass.data[DOMAIN]["dummy"]["device"] = m_device - - await async_setup_entry(hass, entry, m_add_entities) - assert type(hass.data[DOMAIN]["dummy"]["fan"]) == TuyaLocalFan - m_add_entities.assert_called_once() From 1c1c12d04bccd05a1d1634265bfa0139149ff7c1 Mon Sep 17 00:00:00 2001 From: Aravind Jaimon Date: Fri, 7 Jun 2024 23:13:24 +0530 Subject: [PATCH 3/4] refactor(fan): improved gorilla fan implementation --- .../tuya_local/devices/gorilla_fan_v2.yaml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/custom_components/tuya_local/devices/gorilla_fan_v2.yaml b/custom_components/tuya_local/devices/gorilla_fan_v2.yaml index b6289094eb..f49baf4494 100644 --- a/custom_components/tuya_local/devices/gorilla_fan_v2.yaml +++ b/custom_components/tuya_local/devices/gorilla_fan_v2.yaml @@ -5,15 +5,6 @@ primary_entity: - id: 1 type: boolean name: switch - icon: mdi:ceiling-fan - - id: 2 - type: string - name: preset_mode - mapping: - - dps_value: normal - value: Normal - - dps_value: boost - value: Boost - id: 3 type: integer name: speed @@ -23,8 +14,7 @@ primary_entity: secondary_entities: - entity: light - name: Night Light - icon: mdi:ceiling-fan-light + translation_key: nightlight dps: - id: 15 type: boolean @@ -44,8 +34,6 @@ secondary_entities: type: boolean name: switch - entity: number - name: Timer - icon: mdi:timer-edit translation_key: timer category: config dps: From 7a99313cd513524788694e0fee9ea5873930a2d3 Mon Sep 17 00:00:00 2001 From: Jason Rumney Date: Thu, 27 Jun 2024 07:58:25 +0900 Subject: [PATCH 4/4] Gorilla fan: naming tweak Preference is to keep branding under products. Since no product id has been informed, add as a comment --- custom_components/tuya_local/devices/gorilla_fan_v2.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/custom_components/tuya_local/devices/gorilla_fan_v2.yaml b/custom_components/tuya_local/devices/gorilla_fan_v2.yaml index f49baf4494..46f91e2457 100644 --- a/custom_components/tuya_local/devices/gorilla_fan_v2.yaml +++ b/custom_components/tuya_local/devices/gorilla_fan_v2.yaml @@ -1,4 +1,7 @@ -name: Gorilla Fan V2 +name: Ceiling fan +# products: +# - id: UNKNOWN +# name: Atomberg Gorilla Fan V2 primary_entity: entity: fan dps: