Skip to content

Commit 1130950

Browse files
authored
Merge pull request #607 from uzlonewolf/invalid-json
Handle invalid binary data in the JSON from the device better
2 parents 3f16eb9 + 7f3f20f commit 1130950

File tree

3 files changed

+34
-11
lines changed

3 files changed

+34
-11
lines changed

RELEASE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# RELEASE NOTES
22

3+
## v1.16.2 - Invalid JSON Handling
4+
5+
* Handle invalid binary data in the JSON from the device better by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/607 re: #606
6+
37
## v1.16.1 - Scanner Error Handling
48

59
* Adds error handling for cases when the scanner broadcasts fails by @x011 in https://github.com/jasonacox/tinytuya/pull/585 and @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/587

tinytuya/core/XenonDevice.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ def _decode_payload(self, payload):
700700
payload = payload[len(H.PROTOCOL_VERSION_BYTES_31) :]
701701
# Decrypt payload
702702
# Remove 16-bytes of MD5 hexdigest of payload
703-
payload = cipher.decrypt(payload[16:])
703+
payload = cipher.decrypt(payload[16:], decode_text=False)
704704
elif self.version >= 3.2: # 3.2 or 3.3 or 3.4 or 3.5
705705
# Trim header for non-default device type
706706
if payload.startswith( self.version_bytes ):
@@ -713,7 +713,7 @@ def _decode_payload(self, payload):
713713
if self.version < 3.4:
714714
try:
715715
log.debug("decrypting=%r", payload)
716-
payload = cipher.decrypt(payload, False)
716+
payload = cipher.decrypt(payload, False, decode_text=False)
717717
except:
718718
log.debug("incomplete payload=%r (len:%d)", payload, len(payload), exc_info=True)
719719
return error_json(ERR_PAYLOAD)
@@ -722,13 +722,10 @@ def _decode_payload(self, payload):
722722
# Try to detect if device22 found
723723
log.debug("payload type = %s", type(payload))
724724

725-
if not isinstance(payload, str):
726-
try:
727-
payload = payload.decode()
728-
except:
729-
log.debug("payload was not string type and decoding failed")
730-
return error_json(ERR_JSON, payload)
731-
if not self.disabledetect and "data unvalid" in payload:
725+
if isinstance(payload, str):
726+
payload = payload.encode('utf-8')
727+
728+
if not self.disabledetect and b"data unvalid" in payload:
732729
self.dev_type = "device22"
733730
# set at least one DPS
734731
self.dps_to_request = {"1": None}
@@ -741,13 +738,35 @@ def _decode_payload(self, payload):
741738
log.debug("Unexpected payload=%r", payload)
742739
return error_json(ERR_PAYLOAD, payload)
743740

741+
invalid_json = None
744742
if not isinstance(payload, str):
745-
payload = payload.decode()
743+
try:
744+
payload = payload.decode()
745+
except UnicodeDecodeError:
746+
if (payload[:1] == b'{') and (payload[-1:] == b'}'):
747+
try:
748+
invalid_json = payload
749+
payload = payload.decode( errors='replace' )
750+
except:
751+
pass
752+
except:
753+
pass
754+
755+
# if .decode() threw an exception, `payload` will still be bytes
756+
if not isinstance(payload, str):
757+
log.debug("payload was not string type and decoding failed")
758+
return error_json(ERR_JSON, payload)
759+
746760
log.debug("decoded results=%r", payload)
747761
try:
748762
json_payload = json.loads(payload)
749763
except:
750764
json_payload = error_json(ERR_JSON, payload)
765+
json_payload['invalid_json'] = payload
766+
767+
if invalid_json and isinstance(json_payload, dict):
768+
# give it to the user so they can try to decode it if they want
769+
json_payload['invalid_json'] = invalid_json
751770

752771
# v3.4 stuffs it into {"data":{"dps":{"1":true}}, ...}
753772
if "dps" not in json_payload and "data" in json_payload and "dps" in json_payload['data']:

tinytuya/core/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
# Colorama terminal color capability for all platforms
8585
init()
8686

87-
version_tuple = (1, 16, 1)
87+
version_tuple = (1, 16, 2)
8888
version = __version__ = "%d.%d.%d" % version_tuple
8989
__author__ = "jasonacox"
9090

0 commit comments

Comments
 (0)