Răsfoiți Sursa

Use tinytuya set_multiple_values API function to send.

When this was originally developed, the only way to set arbitrary dps
was to work with low level functions, generating the payload then
sending it.

Over time, tinytuya has evolved with a more complete API, so there is
a higher level function to do what we want.

Currently it looks like it basically does the same as what we were
doing, but with new Tuya protocol versions coming all the time, and
workarounds for device issues being built in to tinytuya, it may pick
up extra functionality at some point, which we would miss by rolling
our own using lower level functions.

There is a minor performance hit in the case where we need resends,
but actually it looks like resends are handled at a lower level in
tinytuya anyway.

Unlikely based on review of the code, but may help with #338 and #372.
Jason Rumney 3 ani în urmă
părinte
comite
8b35f43e09
2 a modificat fișierele cu 10 adăugiri și 12 ștergeri
  1. 4 8
      custom_components/tuya_local/device.py
  2. 6 4
      tests/test_device.py

+ 4 - 8
custom_components/tuya_local/device.py

@@ -370,29 +370,25 @@ class TuyaLocalDevice(object):
 
 
     async def _send_pending_updates(self):
     async def _send_pending_updates(self):
         pending_properties = self._get_unsent_properties()
         pending_properties = self._get_unsent_properties()
-        payload = self._api.generate_payload(
-            tinytuya.CONTROL,
-            pending_properties,
-        )
 
 
         _LOGGER.debug(
         _LOGGER.debug(
             f"{self.name} sending dps update: {json.dumps(pending_properties, default=non_json)}"
             f"{self.name} sending dps update: {json.dumps(pending_properties, default=non_json)}"
         )
         )
 
 
         await self._retry_on_failed_connection(
         await self._retry_on_failed_connection(
-            lambda: self._send_payload(payload),
+            lambda: self._set_values(pending_properties),
             "Failed to update device state.",
             "Failed to update device state.",
         )
         )
 
 
-    def _send_payload(self, payload):
+    def _set_values(self, properties):
         try:
         try:
             self._lock.acquire()
             self._lock.acquire()
-            self._api.send(payload)
+            self._api.set_multiple_values(properties, nowait=True)
             self._cached_state["updated_at"] = 0
             self._cached_state["updated_at"] = 0
             now = time()
             now = time()
             self._last_connection = now
             self._last_connection = now
             pending_updates = self._get_pending_updates()
             pending_updates = self._get_pending_updates()
-            for key in list(pending_updates):
+            for key in properties.keys():
                 pending_updates[key]["updated_at"] = now
                 pending_updates[key]["updated_at"] = now
                 pending_updates[key]["sent"] = True
                 pending_updates[key]["sent"] = True
         finally:
         finally:

+ 6 - 4
tests/test_device.py

@@ -277,7 +277,7 @@ class TestDevice(IsolatedAsyncioTestCase):
     async def test_async_set_property_sends_to_api(self):
     async def test_async_set_property_sends_to_api(self):
         await self.subject.async_set_property("1", False)
         await self.subject.async_set_property("1", False)
 
 
-        self.mock_api().send.assert_called_once()
+        self.mock_api().set_multiple_values.assert_called_once()
 
 
     async def test_set_property_immediately_stores_pending_updates(self):
     async def test_set_property_immediately_stores_pending_updates(self):
         self.subject._cached_state = {"1": True}
         self.subject._cached_state = {"1": True}
@@ -335,17 +335,19 @@ class TestDevice(IsolatedAsyncioTestCase):
             delta=2,
             delta=2,
         )
         )
 
 
-    def test_send_payload(self):
+    def test_set_values(self):
         # set up preconditions
         # set up preconditions
         self.subject._pending_updates = {
         self.subject._pending_updates = {
             "1": {"value": "sample", "updated_at": time() - 2, "sent": False},
             "1": {"value": "sample", "updated_at": time() - 2, "sent": False},
         }
         }
 
 
         # call the function under test
         # call the function under test
-        self.subject._send_payload("PAYLOAD")
+        self.subject._set_values({"1": "sample"})
 
 
         # did it send what it was asked?
         # did it send what it was asked?
-        self.mock_api().send.assert_called_once_with("PAYLOAD")
+        self.mock_api().set_multiple_values.assert_called_once_with(
+            {"1": "sample"}, nowait=True
+        )
         # did it mark the pending updates as sent?
         # did it mark the pending updates as sent?
         self.assertTrue(self.subject._pending_updates["1"]["sent"])
         self.assertTrue(self.subject._pending_updates["1"]["sent"])
         # did it update the time on the pending updates?
         # did it update the time on the pending updates?