Revert "Revert "Rebase from upstream""

This commit is contained in:
sibowler
2022-05-29 07:20:19 +10:00
committed by GitHub
parent 4f722a00df
commit 01a9fb6a48
23 changed files with 1316 additions and 116 deletions

View File

@@ -21,6 +21,7 @@ Functions
json = status() # returns json payload
set_version(version) # 3.1 [default] or 3.3
detect_available_dps() # returns a list of available dps provided by the device
update_dps(dps) # sends update dps command
add_dps_to_request(dp_index) # adds dp_index to the list of dps used by the
# device (to be queried in the payload)
set_dp(on, dp_index) # Set value of any dps index.
@@ -61,6 +62,7 @@ TuyaMessage = namedtuple("TuyaMessage", "seqno cmd retcode payload crc")
SET = "set"
STATUS = "status"
HEARTBEAT = "heartbeat"
UPDATEDPS = "updatedps" # Request refresh of DPS
PROTOCOL_VERSION_BYTES_31 = b"3.1"
PROTOCOL_VERSION_BYTES_33 = b"3.3"
@@ -76,6 +78,9 @@ SUFFIX_VALUE = 0x0000AA55
HEARTBEAT_INTERVAL = 10
# DPS that are known to be safe to use with update_dps (0x12) command
UPDATE_DPS_WHITELIST = [18, 19, 20] # Socket (Wi-Fi)
# This is intended to match requests.json payload at
# https://github.com/codetheweb/tuyapi :
# type_0a devices require the 0a command as the status request
@@ -90,11 +95,13 @@ PAYLOAD_DICT = {
STATUS: {"hexByte": 0x0A, "command": {"gwId": "", "devId": ""}},
SET: {"hexByte": 0x07, "command": {"devId": "", "uid": "", "t": ""}},
HEARTBEAT: {"hexByte": 0x09, "command": {}},
UPDATEDPS: {"hexByte": 0x12, "command": {"dpId": [18, 19, 20]}},
},
"type_0d": {
STATUS: {"hexByte": 0x0D, "command": {"devId": "", "uid": "", "t": ""}},
SET: {"hexByte": 0x07, "command": {"devId": "", "uid": "", "t": ""}},
HEARTBEAT: {"hexByte": 0x09, "command": {}},
UPDATEDPS: {"hexByte": 0x12, "command": {"dpId": [18, 19, 20]}},
},
}
@@ -292,6 +299,8 @@ class MessageDispatcher(ContextualLogger):
sem = self.listeners[self.HEARTBEAT_SEQNO]
self.listeners[self.HEARTBEAT_SEQNO] = msg
sem.release()
elif msg.cmd == 0x12:
self.debug("Got normal updatedps response")
elif msg.cmd == 0x08:
self.debug("Got status update")
self.listener(msg)
@@ -478,6 +487,26 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
"""Send a heartbeat message."""
return await self.exchange(HEARTBEAT)
async def update_dps(self, dps=None):
"""
Request device to update index.
Args:
dps([int]): list of dps to update, default=detected&whitelisted
"""
if self.version == 3.3:
if dps is None:
if not self.dps_cache:
await self.detect_available_dps()
if self.dps_cache:
dps = [int(dp) for dp in self.dps_cache]
# filter non whitelisted dps
dps = list(set(dps).intersection(set(UPDATE_DPS_WHITELIST)))
self.debug("updatedps() entry (dps %s, dps_cache %s)", dps, self.dps_cache)
payload = self._generate_payload(UPDATEDPS, dps)
self.transport.write(payload)
return True
async def set_dp(self, value, dp_index):
"""
Set value (may be any type: bool, int or string) of any dps index.
@@ -582,7 +611,10 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
json_data["t"] = str(int(time.time()))
if data is not None:
json_data["dps"] = data
if "dpId" in json_data:
json_data["dpId"] = data
else:
json_data["dps"] = data
elif command_hb == 0x0D:
json_data["dps"] = self.dps_to_request
@@ -591,7 +623,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
if self.version == 3.3:
payload = self.cipher.encrypt(payload, False)
if command_hb != 0x0A:
if command_hb not in [0x0A, 0x12]:
# add the 3.3 header
payload = PROTOCOL_33_HEADER + payload
elif command == SET: