瀏覽代碼

Add supported_color_modes to the light API.

This is required for lights that support brightness to function correctly.

Update tests.

Update docs for device configs, as it was missing some options.
Jason Rumney 4 年之前
父節點
當前提交
afb3a595da

+ 59 - 19
custom_components/tuya_local/devices/README.md

@@ -20,15 +20,13 @@ The name should also indicate to the user what type of device it is.
 
 ### `legacy_type`
 
-The `legacy_type` is a transitional link back to the device specific
-type enumeration that is used in the old device discovery and creation
-process. This allows a gradual transition to the new way of handling
-devices.  It is required only for devices that exist before the
-completion of migratation to generic device classes. It is recommended
-that any addition of new devices is deferred until the migration is
-complete, as during the transition period it will be neccesary to add
-both old device specific classes and device configuration files for
-any new devices.
+// Optional, deprecated. //
+
+The `legacy_type` is a transitional link back to an old name the device
+was known by.  It is used in the migration process to migrate old
+configs to the latest config which uses the config filename as the identifier
+for the device.  New devices should not define this.
+
 
 ### `primary_entity`
 
@@ -64,16 +62,29 @@ secondary entities, so only basic functionality is implemented.
 
 ### `legacy_class`
 
+//Optional, deprecated.//
+
 The `legacy_class` is a transitional link back to the device specific
-class that contains the implementation of this device. This will allow
-a transition to using device configuration files for discovery and
-initialization while the generic entity class implementation is still
-in progress. It is required only for devices that exist before the
-completion of migratation to generic device classes. It is recommended
-that any addition of new devices is deferred until the migration is
-complete, as during the transition period it will be neccesary to add
-both old device specific classes and device configuration files for
-any new devices.
+class that contains the implementation of this device. This allows
+a transition for more complex devices that are not yet fully supported
+by the generic implementations. It should not be used for new devices.
+
+### `deprecated`
+
+//Optional, deprecated//
+
+This boolean flag is used to mark an entity as deprecated.  This is mainly
+for older devices that were implemented when only climate devices were
+supported, but are better represented in HA as fan or humidifier devices.
+An entity should be moved to `secondary_entities` before being marked as
+deprecated, and the preferred device type moved to the `primary_entity`.
+
+### `class`
+
+//Optional.//
+
+For some entity types, a `class` can be set, for example `switch` entities
+can have a class of `outlet`.  This may slightly alter the UI behaviour.
 
 ### `dps`
 
@@ -159,7 +170,16 @@ is set to Eco.
 
 For integer attributes that are not readonly, a range can be set with `min`
 and `max` values that will limit the values that the user can enter in the
-Home Assistant UI.
+Home Assistant UI.  This can also be set in a `mapping` or `conditions` block.
+
+### `unit`
+
+//Optional. default="C" for temperature dps//
+
+For temperature dps, some devices will use Fahrenhiet.  This needs to be
+indicated back to HomeAssistant by defining `unit` as "F".  In future `unit`
+will also be used for other sensor types, with a bigger range of possible
+values.
 
 ## Mapping Rules
 
@@ -192,6 +212,26 @@ different than the DPS value from the Tuya protocol.  Normally it will be used
 with `dps_val` to map from one value to another. It could also be used at top
 level to override all values, but I can't imagine a useful purpose for that.
 
+### `scale`
+
+//Optional, default=1//
+
+This can be used in an `integer` dps mapping to scale the values.  For example
+some climate devices represent the temperature as an integer in tenths of
+degrees, and require a scale of 10 to convert them to degrees expected by
+Home Assistant.  The scale can also be the other way, for a fan with speeds
+1, 2 and 3 as DPS values, this can be converted to a percentage with a scale
+of 0.03.
+
+### `step`
+
+//Optional, default=1//
+
+This can be used in an `integer` dps mapping to make values jump by a specific
+step.  It can also be set in a conditions block so that the steps change only
+under certain conditions.  An example is where a value has a range of 0-100, but
+only allows settings that are divisible by 10, so a step of 10 would be set.
+
 ### `icon`
 
 //Optional.//

+ 10 - 0
custom_components/tuya_local/generic/light.py

@@ -70,6 +70,16 @@ class TuyaLocalLight(LightEntity):
         else:
             return super().icon
 
+    @property
+    def supported_color_modes(self):
+        """Return the supported color modes for this light."""
+        if self._brightness_dps:
+            return [COLOR_MODE_BRIGHTNESS]
+        elif self._switch_dps:
+            return [COLOR_MODE_ONOFF]
+        else:
+            return []
+
     @property
     def color_mode(self):
         """Return the color mode of the light"""

+ 6 - 0
tests/devices/test_deta_fan.py

@@ -79,6 +79,12 @@ class TestDetaFan(TuyaDeviceTestCase):
         self.assertEqual(self.subject.device_state_attributes, {"timer": 5})
         self.assertEqual(self.light.device_state_attributes, {"timer": 6})
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_electriq_12wminv_heatpump.py

@@ -307,6 +307,12 @@ class TestElectriq12WMINVHeatpump(TuyaDeviceTestCase):
     def test_light_state_attributes(self):
         self.assertEqual(self.light.device_state_attributes, {})
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_electriq_cd20_dehumidifier.py

@@ -209,6 +209,12 @@ class TestElectriqCD20ProDehumidifier(TuyaDeviceTestCase):
             await self.fan.async_set_preset_mode("Oscillate")
             self.subject._device.anticipate_property_value.assert_not_called()
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_electriq_cd25_dehumidifier.py

@@ -225,6 +225,12 @@ class TestElectriqCD25ProDehumidifier(TuyaDeviceTestCase):
         async with assert_device_properties_set(self.lock._device, {LOCK_DPS: False}):
             await self.lock.async_unlock()
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_goldair_dehumidifier.py

@@ -583,6 +583,12 @@ class TestGoldairDehumidifier(TuyaDeviceTestCase):
         async with assert_device_properties_set(self.lock._device, {LOCK_DPS: False}):
             await self.lock.async_unlock()
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_goldair_fan.py

@@ -320,6 +320,12 @@ class TestGoldairFan(TuyaDeviceTestCase):
         self.assertEqual(self.climate.device_state_attributes, {"timer": "5"})
         self.assertEqual(self.subject.device_state_attributes, {"timer": "5"})
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_goldair_gpph_heater.py

@@ -357,6 +357,12 @@ class TestGoldairHeater(TuyaDeviceTestCase):
         async with assert_device_properties_set(self.lock._device, {LOCK_DPS: False}):
             await self.lock.async_unlock()
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_lexy_f501_fan.py

@@ -154,6 +154,12 @@ class TestLexyF501Fan(TuyaDeviceTestCase):
         self.dps[TIMER_DPS] = "5"
         self.assertEqual(self.subject.device_state_attributes, {"timer": 5})
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_purline_m100_heater.py

@@ -207,6 +207,12 @@ class TestPulineM100Heater(TuyaDeviceTestCase):
         ):
             await self.subject.async_set_swing_mode(SWING_OFF)
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
 

+ 6 - 0
tests/devices/test_wetair_wch750_heater.py

@@ -203,6 +203,12 @@ class TestWetairWCH750Heater(TuyaDeviceTestCase):
             },
         )
 
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_BRIGHTNESS],
+        )
+
     def test_light_color_mode(self):
         self.assertEqual(self.light.color_mode, COLOR_MODE_BRIGHTNESS)