Updating the status of TuyaDevice using the response of the set_dps() call
This commit is contained in:
@@ -89,13 +89,18 @@ class TuyaDevice:
|
||||
raise ConnectionError("Failed to update status .")
|
||||
|
||||
def set_dps(self, state, dps_index):
|
||||
# _LOGGER.info("running def set_dps from cover")
|
||||
"""Change the Tuya switch status and clear the cache."""
|
||||
self._cached_status = ""
|
||||
self._cached_status_time = 0
|
||||
# _LOGGER.info("running def set_dps from TuyaDevice")
|
||||
# No need to clear the cache here: let's just update the status of the changed dps as returned by the interface (see 5 lines below)
|
||||
# self._cached_status = ""
|
||||
# self._cached_status_time = 0
|
||||
for i in range(5):
|
||||
try:
|
||||
return self._interface.set_dps(state, dps_index)
|
||||
result = self._interface.set_dps(state, dps_index)
|
||||
self._cached_status["dps"].update(result["dps"])
|
||||
# NOW WE SHOULD TRIGGER status_updated FOR ALL ENTITIES INVOLVED IN result["dps"] :
|
||||
#for dp in result["dps"]:
|
||||
# have status_updated() called....
|
||||
return
|
||||
except Exception:
|
||||
print(
|
||||
"Failed to set status of device [{}]".format(
|
||||
@@ -116,7 +121,7 @@ class TuyaDevice:
|
||||
self._lock.acquire()
|
||||
try:
|
||||
now = time()
|
||||
if not self._cached_status or now - self._cached_status_time > 15:
|
||||
if not self._cached_status or now - self._cached_status_time > 10:
|
||||
sleep(0.5)
|
||||
self._cached_status = self.__get_status()
|
||||
self._cached_status_time = time()
|
||||
|
@@ -253,6 +253,62 @@ class TuyaInterface:
|
||||
"""
|
||||
return self.exchange(SET, {str(dps_index): value})
|
||||
|
||||
|
||||
def _decode_received_data(self, data, is_status):
|
||||
"""Return device status."""
|
||||
"""is_status may be True (result of a status request) or False (result of a set_dps request)"""
|
||||
result = data[20:-8] # hard coded offsets
|
||||
if self.dev_type != "type_0a":
|
||||
result = result[15:]
|
||||
elif not is_status:
|
||||
result = result[15:]
|
||||
|
||||
log.debug("Decrypting %r :", result)
|
||||
# result = data[data.find('{'):data.rfind('}')+1] # naive marker search,
|
||||
# hope neither { nor } occur in header/footer
|
||||
# print('result %r' % result)
|
||||
if result.startswith(b"{"):
|
||||
# this is the regular expected code path
|
||||
if not isinstance(result, str):
|
||||
result = result.decode()
|
||||
result = json.loads(result)
|
||||
elif result.startswith(PROTOCOL_VERSION_BYTES_31):
|
||||
# got an encrypted payload, happens occasionally
|
||||
# expect resulting json to look similar to:
|
||||
# {"devId":"ID","dps":{"1":true,"2":0},"t":EPOCH_SECS,"s":3_DIGIT_NUM}
|
||||
# NOTE dps.2 may or may not be present
|
||||
result = result[len(PROTOCOL_VERSION_BYTES_31) :] # remove version header
|
||||
# remove (what I'm guessing, but not confirmed is) 16-bytes of MD5
|
||||
# hexdigest of payload
|
||||
result = result[16:]
|
||||
cipher = AESCipher(self.local_key)
|
||||
result = cipher.decrypt(result)
|
||||
#print("decrypted result=[{}]".format(result))
|
||||
log.info("decrypted result=%r", result)
|
||||
if not isinstance(result, str):
|
||||
result = result.decode()
|
||||
result = json.loads(result)
|
||||
elif self.version == 3.3:
|
||||
# results of a set_dps request must have a further offset
|
||||
cipher = AESCipher(self.local_key)
|
||||
result = cipher.decrypt(result, False)
|
||||
log.debug("decrypted result=%r", result)
|
||||
if "data unvalid" in result:
|
||||
self.dev_type = "type_0d"
|
||||
log.info(
|
||||
"'data unvalid' error detected: switching to dev_type %r",
|
||||
self.dev_type,
|
||||
)
|
||||
return self.status()
|
||||
if not isinstance(result, str):
|
||||
result = result.decode()
|
||||
result = json.loads(result)
|
||||
else:
|
||||
log.error("Unexpected status() payload=%r", result)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def detect_available_dps(self):
|
||||
"""Return which datapoints are supported by the device."""
|
||||
# type_0d devices need a sort of bruteforce querying in order to detect the
|
||||
|
Reference in New Issue
Block a user