瀏覽代碼

device (subdevice sync): be fault tolerant getting cached lock

At startup I am seeing failures in the log due to missing tuyadevicelock
I can't immediately spot where, but there must be a path where this is
not getting initialised after a restart. Use get() instead of directly
accessing, with a default of a new Lock.

Also clean up the sleep calls so the lock does not need to be released
mid loop.

PR #3929
Jason Rumney 3 月之前
父節點
當前提交
05e39de69e
共有 1 個文件被更改,包括 14 次插入9 次删除
  1. 14 9
      custom_components/tuya_local/device.py

+ 14 - 9
custom_components/tuya_local/device.py

@@ -78,7 +78,9 @@ class TuyaLocalDevice(object):
             if dev_cid:
                 if hass.data[DOMAIN].get(dev_id) and name != "Test":
                     parent = hass.data[DOMAIN][dev_id]["tuyadevice"]
-                    parent_lock = hass.data[DOMAIN][dev_id]["tuyadevicelock"]
+                    parent_lock = hass.data[DOMAIN][dev_id].get(
+                        "tuyadevicelock", asyncio.Lock()
+                    )
                 else:
                     parent = tinytuya.Device(dev_id, address, local_key)
                     parent_lock = asyncio.Lock()
@@ -96,7 +98,9 @@ class TuyaLocalDevice(object):
             else:
                 if hass.data[DOMAIN].get(dev_id) and name != "Test":
                     self._api = hass.data[DOMAIN][dev_id]["tuyadevice"]
-                    self._api_lock = hass.data[DOMAIN][dev_id]["tuyadevicelock"]
+                    self._api_lock = hass.data[DOMAIN][dev_id].get(
+                        "tuyadevicelock", asyncio.Lock()
+                    )
                 else:
                     self._api = tinytuya.Device(dev_id, address, local_key)
                     self._api_lock = asyncio.Lock()
@@ -299,8 +303,9 @@ class TuyaLocalDevice(object):
 
         while self._running:
             error_count = self._api_working_protocol_failures
-            await self._api_lock.acquire()
+            force_backoff = False
             try:
+                await self._api_lock.acquire()
                 last_cache = self._cached_state.get("updated_at", 0)
                 now = time()
                 full_poll = False
@@ -344,8 +349,7 @@ class TuyaLocalDevice(object):
                         self._api.receive,
                     )
                 else:
-                    self._api_lock.release()
-                    await asyncio.sleep(5)
+                    force_backoff = True
                     poll = None
 
                 if poll:
@@ -390,13 +394,13 @@ class TuyaLocalDevice(object):
                 self._api.set_socketPersistent(False)
                 if self._api.parent:
                     self._api.parent.set_socketPersistent(False)
-                self._api_lock.release()
-                await asyncio.sleep(5)
+                force_backoff = True
             finally:
                 if self._api_lock.locked():
                     self._api_lock.release()
-
-            await asyncio.sleep(0.1 if self.has_returned_state else 5)
+            if not self.has_returned_state:
+                force_backoff = True
+            await asyncio.sleep(5 if force_backoff else 0.1)
 
         # Close the persistent connection when exiting the loop
         self._api.set_socketPersistent(False)
@@ -746,6 +750,7 @@ def setup_device(hass: HomeAssistant, config: dict):
     hass.data[DOMAIN][get_device_id(config)] = {
         "device": device,
         "tuyadevice": device._api,
+        "tuyadevicelock": device._api_lock,
     }
 
     return device