Jelajahi Sumber

Add a persist option for persistent device connections.

Althoough upstream moved away from persistent connections to improve
co-existence with the official manufacturers apps, they do seem to
solve some stability issues, see the following discussion for analysis:
 https://github.com/jasonacox/tinytuya/issues/13
Jason Rumney 4 tahun lalu
induk
melakukan
825465d156

+ 5 - 0
README.md

@@ -78,6 +78,11 @@ You can easily configure your devices using the Integrations UI at `Home Assista
     _(string) (Required)_ Local key retrieved
 [as per the instructions below](#finding-your-device-id-and-local-key).
 
+#### persist
+
+    _(boolean) (Optional)_ Whether to use persistent connections to the device.
+Persistent connections may improve stability and performance, particularly to some older devices using protocol version 3.1.  But using persistent connections, it will not be possible to use the official manufacturer's mobile app to control some devices, as only one local connection is possible at a time.  Without this checked, the device will be polled, leaving opportunities for the mobile app to connect temporarily.
+
 #### type
 
     _(string) (Optional)_ The type of Tuya device. `auto` to automatically detect the device type, or if that doesn't work, select from the available options `heater`, `geco_heater` `gpcv_heater`, `dehumidifier`, `fan`, `kogan_heater`, `gsh_heater`, `eurom_heater`, `gardenpac_heatpump`, `purline_m100_heater`, `remora_heatpump`,  or `kogan_switch`.  Note that the type is likely to change in future to be a configuration file name or product id, as the hardcoded list is a maintenance burden.

+ 6 - 1
custom_components/tuya_local/config_flow.py

@@ -104,7 +104,12 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
 
 async def async_test_connection(config: dict, hass: HomeAssistant):
     device = TuyaLocalDevice(
-        "Test", config[CONF_DEVICE_ID], config[CONF_HOST], config[CONF_LOCAL_KEY], hass
+        "Test",
+        config[CONF_DEVICE_ID],
+        config[CONF_HOST],
+        config[CONF_LOCAL_KEY],
+        False,
+        hass,
     )
     await device.async_refresh()
     return device.has_returned_state

+ 7 - 0
custom_components/tuya_local/configuration.py

@@ -9,6 +9,7 @@ from .const import (
     CONF_FAN,
     CONF_HUMIDIFIER,
     CONF_LOCAL_KEY,
+    CONF_PERSIST,
     CONF_SWITCH,
     CONF_TYPE,
     CONF_TYPE_AUTO,
@@ -100,6 +101,12 @@ INDIVIDUAL_CONFIG_SCHEMA_TEMPLATE = [
         "default": False,
         "option": True,
     },
+    {
+        "key": CONF_PERSIST,
+        "type": bool,
+        "required": False,
+        "option": True,
+    },
 ]
 
 

+ 1 - 0
custom_components/tuya_local/const.py

@@ -4,6 +4,7 @@ DOMAIN = "tuya_local"
 
 CONF_DEVICE_ID = "device_id"
 CONF_LOCAL_KEY = "local_key"
+CONF_PERSIST = "persist"
 CONF_TYPE = "type"
 CONF_TYPE_AUTO = "auto"
 CONF_TYPE_GPPH_HEATER = "heater"

+ 7 - 1
custom_components/tuya_local/device.py

@@ -16,6 +16,7 @@ from .const import (
     API_PROTOCOL_VERSIONS,
     CONF_DEVICE_ID,
     CONF_LOCAL_KEY,
+    CONF_PERSIST,
     DOMAIN,
 )
 from .helpers.device_config import possible_matches
@@ -25,7 +26,7 @@ _LOGGER = logging.getLogger(__name__)
 
 
 class TuyaLocalDevice(object):
-    def __init__(self, name, dev_id, address, local_key, hass: HomeAssistant):
+    def __init__(self, name, dev_id, address, local_key, persist, hass: HomeAssistant):
         """
         Represents a Tuya-based device.
 
@@ -38,6 +39,9 @@ class TuyaLocalDevice(object):
         self._api_protocol_version_index = None
         self._api_protocol_working = False
         self._api = tinytuya.Device(dev_id, address, local_key)
+        if persist:
+            self._api.set_socketPersistent(True)
+
         self._refresh_task = None
         self._rotate_api_protocol_version()
 
@@ -283,8 +287,10 @@ def setup_device(hass: HomeAssistant, config: dict):
         config[CONF_DEVICE_ID],
         config[CONF_HOST],
         config[CONF_LOCAL_KEY],
+        config[CONF_PERSIST],
         hass,
     )
+
     hass.data[DOMAIN][config[CONF_DEVICE_ID]] = {"device": device}
 
     return device

+ 1 - 1
custom_components/tuya_local/manifest.json

@@ -2,7 +2,7 @@
     "domain": "tuya_local",
     "iot_class": "local_polling",
     "name": "Tuya based devices local control",
-    "version": "0.7.2", 
+    "version": "0.8.0", 
     "documentation": "https://github.com/make-all/tuya-local",
     "issue_tracker": "https://github.com/make-all/tuya-local/issues",
     "dependencies": [],

+ 3 - 1
custom_components/tuya_local/translations/en.json

@@ -16,7 +16,8 @@
           "child_lock": "Include child lock as a lock entity (unsupported on fans and switches)",
           "switch": "Include a switch entity (switches only)",
           "humidifier": "Include a humidifier entity (humidifiers and dehumidifiers only)",
-	  "fan": "Include a fan entitiy (fans, humidifiers and dehumidifiers)"
+	  "fan": "Include a fan entitiy (fans, humidifiers and dehumidifiers)",
+	  "persist": "Use persistent connections (see docs)"
         }
       }
     },
@@ -43,6 +44,7 @@
 	    "switch": "Include device as a switch entity (switches only)",
           "humidifier": "Include a humidifier entity (humidifiers and dehumidifiers only)",
 	  "fan": "Include a fan entitiy (fans, humidifiers and dehumidifiers)"
+	  "persist": "Use persistent connections (see docs)"
         }
       },
       "imported": {

+ 6 - 1
tests/test_device.py

@@ -47,7 +47,12 @@ class TestDevice(IsolatedAsyncioTestCase):
         self.hass = hass_patcher.start()
 
         self.subject = TuyaLocalDevice(
-            "Some name", "some_dev_id", "some.ip.address", "some_local_key", self.hass()
+            "Some name",
+            "some_dev_id",
+            "some.ip.address",
+            "some_local_key",
+            False,
+            self.hass(),
         )
 
     def test_configures_tinytuya_correctly(self):