Skip to content

Commit

Permalink
Protocol 3.4 and 3.5 support
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonacox committed Apr 8, 2023
1 parent 3a713d6 commit 775ba05
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 21 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Pulling data from Tuya devices on your network requires that you have the Device
1. Download the "Smart Life" - Smart Living app for iPhone or Android. Pair with your smart plug (this is important as you cannot monitor a plug that has not been paired).
* https://itunes.apple.com/us/app/smart-life-smart-living/id1115101477?mt=8
* https://play.google.com/store/apps/details?id=com.tuya.smartlife&hl=en
2. For Device IP, ID and VERSION: Run the tuyapower scan to get a list of Tuya devices on your network along with their device IP, ID and VERSION number (3.1 or 3.3):
2. For Device IP, ID and VERSION: Run the tuyapower scan to get a list of Tuya devices on your network along with their device IP, ID and VERSION number (3.1 to 3.5 - most are 3.3):
```bash
python3 -m tuyapower
```
Expand Down Expand Up @@ -100,7 +100,7 @@ Notes:
* PLUGID = Device ID e.g. 01234567891234567890
* PLUGIP = Device IP Address e.g. 10.0.1.99
* PLUGKEY = Device Key e.g. 0123456789abcdef
* PLUGVERS = Version of Protocol 3.1 or 3.3
* PLUGVERS = Version of Protocol 3.1, 3.2, 3.3, 3.4 or 3.5
* verbose = Print more details - True or False (default is False)
* max_retries = Number of times to retry scan of new devices (default is 15)
Expand Down
49 changes: 49 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# RELEASE NOTES

## v0.2.0 - New Tuya Device Support

* PyPI 0.2.0
* Add support for Tuya protocols 3.2, 3.4 and 3.5 devices

## v0.1.0

* PyPI 0.1.0
* Added support for multi-switch devices
* Update to use tinytuya in Docker by @stevoh6 in #16
* Added err variable to output by @gamuama in #23

## v0.0.25

* Bug fix in deviceRaw() not honoring timeout settings
* Set sw response variable to False as default

## v0.0.24

* deviceInfo() - Added better error handling for devices without expect outlet/power data in their dps response.
* deviceRaw() - Added new function to return raw device data response.
* test.py & plugpower.py - Updated to add device raw data to output.

## v0.0.23 - TinyTuya

* Added support to use tinytuya, replacing pytuya:
* dds support for Device IDs that are 22 characters long (pytuya only supports 20)
* Removed misleading productKey (product SKU identity, not local Key) from scan() output
* Attempts to import tinytuya but falls back to pytuya if unavailable

## v0.0.22 - Scan Max Retry Option

* Added option to allow users to specify maximum retries for scan functions:

```bash
# specify 50 retries via command line
python3 -m tuyapower 50
```

```python
# invoke verbose interactive scan
tuyapower.scan(50)

# return payload of devices
devices = tuyapower.deviceScan(false, 50)
```

4 changes: 2 additions & 2 deletions plugjson.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
print("Usage: %s <PLUGID> <PLUGIP> <PLUGKEY> <PLUGVERS>\n" % sys.argv[0])
print(" Required: <PLUGID> is the Device ID e.g. 01234567891234567890")
print(" <PLUGIP> is the IP address of the smart plug e.g. 10.0.1.99")
print(" Optional: <PLUGKEY> is the Device Keyy (default 0123456789abcdef)")
print(" <PLUGVERS> is the Firmware Version 3.1 (defualt) or 3.3\n")
print(" Optional: <PLUGKEY> is the Device Key (default 0123456789abcdef)")
print(" <PLUGVERS> is the Firmware Version 3.1 (default), 3.2, 3.3, 3.4 or 3.5\n")
print(" Note: You may also send values via Environmental variables: ")
print(" PLUGID, PLUGIP, PLUGKEY, PLUGVERS\n")
exit()
Expand Down
2 changes: 1 addition & 1 deletion plugpower.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
print(" Required: <PLUGID> is the Device ID e.g. 01234567891234567890")
print(" <PLUGIP> is the IP address of the smart plug e.g. 10.0.1.99")
print(" Optional: <PLUGKEY> is the Device Key (default 0123456789abcdef)")
print(" <PLUGVERS> is the Firmware Version 3.1 (default) or 3.3\n")
print(" <PLUGVERS> is the Firmware Version 3.1 (default), 3.2, 3.3, 3.4 or 3.5\n")
print(" Note: You may also send values via Environmental variables: ")
print(" PLUGID, PLUGIP, PLUGKEY, PLUGVERS\n")
exit()
Expand Down
4 changes: 2 additions & 2 deletions test-json.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
print("Usage: %s <PLUGID> <PLUGIP> <PLUGKEY> <PLUGVERS>\n" % sys.argv[0])
print(" Required: <PLUGID> is the Device ID e.g. 01234567891234567890")
print(" <PLUGIP> is the IP address of the smart plug e.g. 10.0.1.99")
print(" Optional: <PLUGKEY> is the Device Keyy (default 0123456789abcdef)")
print(" <PLUGVERS> is the Firmware Version 3.1 (defualt) or 3.3\n")
print(" Optional: <PLUGKEY> is the Device Key (default 0123456789abcdef)")
print(" <PLUGVERS> is the Firmware Version (default), 3.2, 3.3, 3.4 or 3.5\n")
print(" Note: You may also send values via Environmental variables: ")
print(" PLUGID, PLUGIP, PLUGKEY, PLUGVERS\n")
exit()
Expand Down
2 changes: 1 addition & 1 deletion test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
print(" Required: <PLUGID> is the Device ID e.g. 01234567891234567890")
print(" <PLUGIP> is the IP address of the smart plug e.g. 10.0.1.99")
print(" Optional: <PLUGKEY> is the Device Key (default 0123456789abcdef)")
print(" <PLUGVERS> is the Firmware Version 3.1 (default) or 3.3\n")
print(" <PLUGVERS> is the Firmware Version 3.1 (default), 3.2, 3.3, 3.4 or 3.5\n")
print(" Note: You may also send values via Environmental variables: ")
print(" PLUGID, PLUGIP, PLUGKEY, PLUGVERS\n")
exit()
Expand Down
28 changes: 15 additions & 13 deletions tuyapower/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
id = Device ID e.g. 01234567891234567890
ip = Device IP Address e.g. 10.0.1.99
key = Device Key e.g. 0123456789abcdef
vers = Version of Protocol 3.1 or 3.3
vers = Version of Protocol 3.1, 3.2, 3.3, 3.4 and 3.5
verbose = True or False (print output)
port = UDP port to scan (default 6666)
Expand Down Expand Up @@ -55,7 +55,7 @@
api_ver = "unknown"

name = "tuyapower"
version_tuple = (0, 1, 0)
version_tuple = (0, 2, 0)
version = version_string = __version__ = "%d.%d.%d" % version_tuple
__author__ = "jasonacox"

Expand Down Expand Up @@ -88,7 +88,7 @@ def deviceInfo(deviceid, ip, key, vers):
id = Device ID e.g. 01234567891234567890
ip = Device IP Address e.g. 10.0.1.99
key = Device Key e.g. 0123456789abcdef
vers = Version of Protocol 3.1 or 3.3
vers = Version of Protocol 3.1, 3.2, 3.3, 3.4 and 3.5
Response :
on = Switch state - true or false
Expand All @@ -107,8 +107,9 @@ def deviceInfo(deviceid, ip, key, vers):
d = tinytuya.OutletDevice(deviceid, ip, key)
else:
d = pytuya.OutletDevice(deviceid, ip, key)
if vers == "3.3":
d.set_version(3.3)
if float(vers) > 3.3:
return (sw, w, mA, V, "Unsupported Version: Use tinytuya")
d.set_version(float(vers))

try:
data = d.status()
Expand Down Expand Up @@ -151,7 +152,7 @@ def deviceInfo(deviceid, ip, key, vers):
if e in dps.keys():
swDict[e] = dps[e]
sw = swDict
# Check for power data - DP 19 on some 3.1/3.3 devices
# Check for power data - DP 19 on some devices
if "19" in dps.keys():
w = float(dps["19"]) / 10.0
mA = float(dps["18"])
Expand Down Expand Up @@ -202,7 +203,7 @@ def deviceRaw(deviceid, ip, key, vers):
id = Device ID e.g. 01234567891234567890
ip = Device IP Address e.g. 10.0.1.99
key = Device Key e.g. 0123456789abcdef
vers = Version of Protocol 3.1 or 3.3
vers = Version of Protocol 3.1, 3.2, 3.3, 3.4 and 3.5
Response :
rawData = Data response from device
Expand All @@ -214,9 +215,10 @@ def deviceRaw(deviceid, ip, key, vers):
d = tinytuya.OutletDevice(deviceid, ip, key)
else:
d = pytuya.OutletDevice(deviceid, ip, key)
if float(vers) > 3.3:
return ("ERROR: Unsupported Version: Use tinytuya")

if vers == "3.3":
d.set_version(3.3)
d.set_version(float(vers))

try:
data = d.status()
Expand Down Expand Up @@ -256,7 +258,7 @@ def devicePrint(deviceid, ip, key='0123456789abcdef', vers='3.1'):
id = Device ID e.g. 01234567891234567890
ip = Device IP Address e.g. 10.0.1.99
key = Device Key e.g. 0123456789abcdef
vers = Version of Protocol 3.1 or 3.3
vers = Version of Protocol 3.1, 3.2, 3.3, 3.4 and 3.5
"""
# Poll Smart Switch for Power Data
Expand Down Expand Up @@ -295,7 +297,7 @@ def deviceJSON(deviceid, ip, key='0123456789abcdef', vers='3.1'):
id = Device ID e.g. 01234567891234567890
ip = Device IP Address e.g. 10.0.1.99
key = Device Key e.g. 0123456789abcdef
vers = Version of Protocol 3.1 or 3.3
vers = Version of Protocol 3.1, 3.2, 3.3, 3.4 and 3.5
Response:
JSON String
Expand All @@ -319,7 +321,7 @@ def deviceJSON(deviceid, ip, key='0123456789abcdef', vers='3.1'):
MAXCOUNT = 15 # How many tries before stopping
DEBUG = False # Additional details beyond verbose
UDPPORT = 6666 # Tuya 3.1 UDP Port
UDPPORTS = 6667 # Tuya 3.3 encrypted UDP Port
UDPPORTS = 6667 # Tuya 3.3+ encrypted UDP Port
TIMEOUT = 3.0 # Seconds to wait for a broadcast

# Return positive number or zero
Expand Down Expand Up @@ -374,7 +376,7 @@ def deviceScan(verbose = False,maxretry = MAXCOUNT):
client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
client.bind(("", UDPPORT))
client.settimeout(TIMEOUT)
# Enable UDP lisenting broadcasting mode on encrypted UDP port 6667 - 3.3 Devices
# Enable UDP lisenting broadcasting mode on encrypted UDP port 6667 - 3.3+ Devices
clients = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
clients.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
clients.bind(("", UDPPORTS))
Expand Down

0 comments on commit 775ba05

Please sign in to comment.