فهرست منبع

Prefer non-legacy types.

Instead of searching through all config files for legacy types, first try
loading the config of that name directly. Only if that fails revert to using
legacy types.

This should speed up loading of non-legacy devices.  Later changes will save
the non-legacy type in the config, and migrate existing config entries.
Jason Rumney 4 سال پیش
والد
کامیت
c57c7bde70

+ 2 - 2
custom_components/tuya_local/climate.py

@@ -10,7 +10,7 @@ from .const import (
     CONF_TYPE,
     CONF_TYPE,
 )
 )
 from .generic.climate import TuyaLocalClimate
 from .generic.climate import TuyaLocalClimate
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -20,7 +20,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     device = data["device"]
     device = data["device"]
 
 
-    cfg = config_for_legacy_use(discovery_info[CONF_TYPE])
+    cfg = get_config(discovery_info[CONF_TYPE])
     if cfg is None:
     if cfg is None:
         raise ValueError(f"No device config found for {discovery_info}")
         raise ValueError(f"No device config found for {discovery_info}")
     ecfg = cfg.primary_entity
     ecfg = cfg.primary_entity

+ 3 - 3
custom_components/tuya_local/config_flow.py

@@ -8,7 +8,7 @@ from homeassistant.core import HomeAssistant, callback
 from . import DOMAIN
 from . import DOMAIN
 from .device import TuyaLocalDevice
 from .device import TuyaLocalDevice
 from .const import CONF_DEVICE_ID, CONF_LOCAL_KEY, CONF_TYPE
 from .const import CONF_DEVICE_ID, CONF_LOCAL_KEY, CONF_TYPE
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -94,7 +94,7 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
             return self.async_create_entry(
             return self.async_create_entry(
                 title=title, data={**self.data, **user_input}
                 title=title, data={**self.data, **user_input}
             )
             )
-        config = config_for_legacy_use(self.data[CONF_TYPE])
+        config = get_config(self.data[CONF_TYPE])
         schema = {vol.Required(CONF_NAME, default=config.name): str}
         schema = {vol.Required(CONF_NAME, default=config.name): str}
         e = config.primary_entity
         e = config.primary_entity
         schema[vol.Optional(e.entity, default=True)] = bool
         schema[vol.Optional(e.entity, default=True)] = bool
@@ -137,7 +137,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
             vol.Required(CONF_LOCAL_KEY, default=config.get(CONF_LOCAL_KEY, "")): str,
             vol.Required(CONF_LOCAL_KEY, default=config.get(CONF_LOCAL_KEY, "")): str,
             vol.Required(CONF_HOST, default=config.get(CONF_HOST, "")): str,
             vol.Required(CONF_HOST, default=config.get(CONF_HOST, "")): str,
         }
         }
-        cfg = config_for_legacy_use(config[CONF_TYPE])
+        cfg = get_config(config[CONF_TYPE])
         if cfg is None:
         if cfg is None:
             return self.async_abort(reason="not_supported")
             return self.async_abort(reason="not_supported")
         e = cfg.primary_entity
         e = cfg.primary_entity

+ 2 - 2
custom_components/tuya_local/fan.py

@@ -10,7 +10,7 @@ from .const import (
     CONF_TYPE,
     CONF_TYPE,
 )
 )
 from .generic.fan import TuyaLocalFan
 from .generic.fan import TuyaLocalFan
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -20,7 +20,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     device = data["device"]
     device = data["device"]
 
 
-    cfg = config_for_legacy_use(discovery_info[CONF_TYPE])
+    cfg = get_config(discovery_info[CONF_TYPE])
     if cfg is None:
     if cfg is None:
         raise ValueError(f"No device config found for {discovery_info}")
         raise ValueError(f"No device config found for {discovery_info}")
     ecfg = cfg.primary_entity
     ecfg = cfg.primary_entity

+ 14 - 1
custom_components/tuya_local/helpers/device_config.py

@@ -4,7 +4,7 @@ Config parser for Tuya Local devices.
 from fnmatch import fnmatch
 from fnmatch import fnmatch
 import logging
 import logging
 from os import walk
 from os import walk
-from os.path import join, dirname, splitext
+from os.path import join, dirname, splitext, exists
 from pydoc import locate
 from pydoc import locate
 
 
 from homeassistant.util.yaml import load_yaml
 from homeassistant.util.yaml import load_yaml
@@ -536,6 +536,19 @@ def possible_matches(dps):
             yield parsed
             yield parsed
 
 
 
 
+def get_config(conf_type):
+    """
+    Return a config to use with config_type.
+    """
+    _CONFIG_DIR = dirname(config_dir.__file__)
+    fname = conf_type + ".yaml"
+    fpath = join(_CONFIG_DIR, fname)
+    if exists(fpath):
+        return TuyaDeviceConfig(fname)
+    else:
+        return config_for_legacy_use(conf_type)
+
+
 def config_for_legacy_use(conf_type):
 def config_for_legacy_use(conf_type):
     """
     """
     Return a config to use with config_type for legacy transition.
     Return a config to use with config_type for legacy transition.

+ 2 - 2
custom_components/tuya_local/humidifier.py

@@ -10,7 +10,7 @@ from .const import (
     CONF_TYPE,
     CONF_TYPE,
 )
 )
 from .generic.humidifier import TuyaLocalHumidifier
 from .generic.humidifier import TuyaLocalHumidifier
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -20,7 +20,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     device = data["device"]
     device = data["device"]
 
 
-    cfg = config_for_legacy_use(discovery_info[CONF_TYPE])
+    cfg = get_config(discovery_info[CONF_TYPE])
     if cfg is None:
     if cfg is None:
         raise ValueError(f"No device config found for {discovery_info}")
         raise ValueError(f"No device config found for {discovery_info}")
     ecfg = cfg.primary_entity
     ecfg = cfg.primary_entity

+ 2 - 2
custom_components/tuya_local/light.py

@@ -10,7 +10,7 @@ from .const import (
     CONF_TYPE,
     CONF_TYPE,
 )
 )
 from .generic.light import TuyaLocalLight
 from .generic.light import TuyaLocalLight
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -20,7 +20,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     device = data["device"]
     device = data["device"]
 
 
-    cfg = config_for_legacy_use(discovery_info[CONF_TYPE])
+    cfg = get_config(discovery_info[CONF_TYPE])
     if cfg is None:
     if cfg is None:
         raise ValueError(f"No device config found for {discovery_info}")
         raise ValueError(f"No device config found for {discovery_info}")
     ecfg = cfg.primary_entity
     ecfg = cfg.primary_entity

+ 2 - 2
custom_components/tuya_local/lock.py

@@ -10,7 +10,7 @@ from .const import (
     CONF_TYPE,
     CONF_TYPE,
 )
 )
 from .generic.lock import TuyaLocalLock
 from .generic.lock import TuyaLocalLock
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -21,7 +21,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     device = data["device"]
     device = data["device"]
 
 
-    cfg = config_for_legacy_use(discovery_info[CONF_TYPE])
+    cfg = get_config(discovery_info[CONF_TYPE])
     if cfg is None:
     if cfg is None:
         raise ValueError(f"No device config found for {discovery_info}")
         raise ValueError(f"No device config found for {discovery_info}")
     ecfg = cfg.primary_entity
     ecfg = cfg.primary_entity

+ 2 - 2
custom_components/tuya_local/switch.py

@@ -10,7 +10,7 @@ from .const import (
     CONF_TYPE,
     CONF_TYPE,
 )
 )
 from .generic.switch import TuyaLocalSwitch
 from .generic.switch import TuyaLocalSwitch
-from .helpers.device_config import config_for_legacy_use
+from .helpers.device_config import get_config
 
 
 _LOGGER = logging.getLogger(__name__)
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -20,7 +20,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     data = hass.data[DOMAIN][discovery_info[CONF_DEVICE_ID]]
     device = data["device"]
     device = data["device"]
 
 
-    cfg = config_for_legacy_use(discovery_info[CONF_TYPE])
+    cfg = get_config(discovery_info[CONF_TYPE])
     if cfg is None:
     if cfg is None:
         raise ValueError(f"No device config found for {discovery_info}")
         raise ValueError(f"No device config found for {discovery_info}")
     ecfg = cfg.primary_entity
     ecfg = cfg.primary_entity

+ 9 - 9
tests/test_device_config.py

@@ -6,7 +6,7 @@ from warnings import warn
 
 
 from custom_components.tuya_local.helpers.device_config import (
 from custom_components.tuya_local.helpers.device_config import (
     available_configs,
     available_configs,
-    config_for_legacy_use,
+    get_config,
     possible_matches,
     possible_matches,
     TuyaDeviceConfig,
     TuyaDeviceConfig,
 )
 )
@@ -51,7 +51,7 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
 
 
     def test_match_quality(self):
     def test_match_quality(self):
         """Test the match_quality function."""
         """Test the match_quality function."""
-        cfg = config_for_legacy_use("deta_fan")
+        cfg = get_config("deta_fan")
         q = cfg.match_quality({**KOGAN_HEATER_PAYLOAD, "updated_at": 0})
         q = cfg.match_quality({**KOGAN_HEATER_PAYLOAD, "updated_at": 0})
         self.assertEqual(q, 0)
         self.assertEqual(q, 0)
         q = cfg.match_quality({**GPPH_HEATER_PAYLOAD})
         q = cfg.match_quality({**GPPH_HEATER_PAYLOAD})
@@ -59,14 +59,14 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
 
 
     def test_entity_find_unknown_dps_fails(self):
     def test_entity_find_unknown_dps_fails(self):
         """Test that finding a dps that doesn't exist fails."""
         """Test that finding a dps that doesn't exist fails."""
-        cfg = config_for_legacy_use("kogan_switch")
+        cfg = get_config("kogan_switch")
         non_existing = cfg.primary_entity.find_dps("missing")
         non_existing = cfg.primary_entity.find_dps("missing")
         self.assertIsNone(non_existing)
         self.assertIsNone(non_existing)
 
 
     async def test_dps_async_set_readonly_value_fails(self):
     async def test_dps_async_set_readonly_value_fails(self):
         """Test that setting a readonly dps fails."""
         """Test that setting a readonly dps fails."""
         mock_device = MagicMock()
         mock_device = MagicMock()
-        cfg = config_for_legacy_use("kogan_switch")
+        cfg = get_config("kogan_switch")
         voltage = cfg.primary_entity.find_dps("voltage_v")
         voltage = cfg.primary_entity.find_dps("voltage_v")
         with self.assertRaises(TypeError):
         with self.assertRaises(TypeError):
             await voltage.async_set_value(mock_device, 230)
             await voltage.async_set_value(mock_device, 230)
@@ -74,20 +74,20 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
     def test_dps_values_returns_none_with_no_mapping(self):
     def test_dps_values_returns_none_with_no_mapping(self):
         """Test that a dps with no mapping returns None as its possible values"""
         """Test that a dps with no mapping returns None as its possible values"""
         mock_device = MagicMock()
         mock_device = MagicMock()
-        cfg = config_for_legacy_use("kogan_switch")
+        cfg = get_config("kogan_switch")
         voltage = cfg.primary_entity.find_dps("voltage_v")
         voltage = cfg.primary_entity.find_dps("voltage_v")
         self.assertIsNone(voltage.values(mock_device))
         self.assertIsNone(voltage.values(mock_device))
 
 
     # Test detection of all devices.
     # Test detection of all devices.
 
 
-    def _test_detect(self, payload, legacy_type, legacy_class):
+    def _test_detect(self, payload, dev_type, legacy_class):
         """Test that payload is detected as the correct type and class."""
         """Test that payload is detected as the correct type and class."""
         matched = False
         matched = False
         false_matches = []
         false_matches = []
         quality = 0
         quality = 0
         for cfg in possible_matches(payload):
         for cfg in possible_matches(payload):
             self.assertTrue(cfg.matches(payload))
             self.assertTrue(cfg.matches(payload))
-            if cfg.legacy_type == legacy_type:
+            if cfg.legacy_type == dev_type:
                 self.assertFalse(matched)
                 self.assertFalse(matched)
                 matched = True
                 matched = True
                 quality = cfg.match_quality(payload)
                 quality = cfg.match_quality(payload)
@@ -108,7 +108,7 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
 
 
         self.assertTrue(matched)
         self.assertTrue(matched)
         if quality < 100:
         if quality < 100:
-            warn(f"{legacy_type} detected with imperfect quality {quality}%")
+            warn(f"{dev_type} detected with imperfect quality {quality}%")
 
 
         best_q = 0
         best_q = 0
         for cfg in false_matches:
         for cfg in false_matches:
@@ -119,7 +119,7 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
         self.assertGreater(quality, best_q)
         self.assertGreater(quality, best_q)
 
 
         # Ensure the same correct config is returned when looked up by type
         # Ensure the same correct config is returned when looked up by type
-        cfg = config_for_legacy_use(legacy_type)
+        cfg = get_config(dev_type)
         if legacy_class is not None:
         if legacy_class is not None:
             cfg_class = cfg.primary_entity.legacy_class
             cfg_class = cfg.primary_entity.legacy_class
             if cfg_class is None:
             if cfg_class is None: