Skip to content

Commit

Permalink
Merge pull request #397 from uzlonewolf/misc
Browse files Browse the repository at this point in the history
Various updates inspired by recent issues
  • Loading branch information
jasonacox authored Aug 18, 2023
2 parents 38a193d + 0ac7597 commit fd65f9d
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 57 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,23 @@ Global Functions
set_debug(toggle, color) # Activate verbose debugging output
Classes
OutletDevice(dev_id, address, local_key=None, dev_type='default')
CoverDevice(dev_id, address, local_key=None, dev_type='default')
BulbDevice(dev_id, address, local_key=None, dev_type='default')
OutletDevice(args...)
CoverDevice(args...)
BulbDevice(args...)
Where args:
dev_id (str): Device ID e.g. 01234567891234567890
address (str): Device Network IP Address e.g. 10.0.1.99 or 0.0.0.0 to auto-find
local_key (str, optional): The encryption key. Defaults to None.
address (str): Device Network IP Address e.g. 10.0.1.99 or "Auto" to auto-find
local_key (str): The encryption key
dev_type (str): Device type for payload options (see below)
connection_timeout = 5 (int): Timeout in seconds
version = 3.1 (float): Tuya Protocol (e.g. 3.1, 3.2, 3.3, 3.4, 3.5)
persist = False (bool): Keep TCP link open
cid = None (str): Optional sub device id
node_id = None (str): Alias for cid
parent = None (object): Gateway device object this is a child of
connection_retry_limit = 5 (int)
connection_retry_delay = 5 (int)
Cloud(apiRegion, apiKey, apiSecret, apiDeviceID, new_sign_algorithm)
Expand Down Expand Up @@ -243,6 +253,7 @@ The "Err" number will be one of these:
* 911 (ERR_CLOUDTOKEN) - Unable to Get Cloud Token
* 912 (ERR_PARAMS) - Missing Function Parameters
* 913 (ERR_CLOUD) - Error Response from Tuya Cloud
* 914 (ERR_KEY_OR_VER) - Check device key or version
### Example Usage
Expand Down
6 changes: 6 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# RELEASE NOTES

## v1.12.10 - Various Updates

* PyPI 1.12.10
* Updates to scanner, added error code and helpful troubleshooting messages, make connection/key errors more descriptive.
* Added socketRetryLimit (`connection_retry_limit`) and socketRetryDelay (`connection_retry_limit`) to Device constructor args.

## v1.12.9 - Import Issue with urllib3

* PyPI 1.12.9
Expand Down
74 changes: 46 additions & 28 deletions examples/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,59 @@
"""
import tinytuya
import time

# tinytuya.set_debug(True)

d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
d.set_version(3.3)
d.set_socketPersistent(True)
# Setting the address to 'Auto' or None will trigger a scan which will auto-detect both the address and version, but this can take up to 8 seconds
d = tinytuya.OutletDevice('DEVICEID', 'Auto', 'DEVICEKEY', persist=True)
# If you know both the address and version then supplying them is a lot quicker
# d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY', version=DEVICEVERSION, persist=True)

STATUS_TIMER = 30
KEEPALIVE_TIMER = 12

print(" > Send Request for Status < ")
payload = d.generate_payload(tinytuya.DP_QUERY)
d.send(payload)
data = d.status()
print('Initial Status: %r' % data)
if data and 'Err' in data:
print("Status request returned an error, is version %r and local key %r correct?" % (d.version, d.local_key))

print(" > Begin Monitor Loop <")
heartbeat_time = time.time() + KEEPALIVE_TIMER
status_time = None

# Uncomment if you want the monitor to constantly request status - otherwise you
# will only get updates when state changes
#status_time = time.time() + STATUS_TIMER

while(True):
# See if any data is available
data = d.receive()
if status_time and time.time() >= status_time:
# Uncomment if your device provides power monitoring data but it is not updating
# Some devices require a UPDATEDPS command to force measurements of power.
# print(" > Send DPS Update Request < ")
# Most devices send power data on DPS indexes 18, 19 and 20
# d.updatedps(['18','19','20'], nowait=True)
# Some Tuya devices will not accept the DPS index values for UPDATEDPS - try:
# payload = d.generate_payload(tinytuya.UPDATEDPS)
# d.send(payload)

# poll for status
print(" > Send Request for Status < ")
data = d.status()
status_time = time.time() + STATUS_TIMER
heartbeat_time = time.time() + KEEPALIVE_TIMER
elif time.time() >= heartbeat_time:
# send a keep-alive
data = d.heartbeat(nowait=False)
heartbeat_time = time.time() + KEEPALIVE_TIMER
else:
# no need to send anything, just listen for an asynchronous update
data = d.receive()

print('Received Payload: %r' % data)

# Send keyalive heartbeat
print(" > Send Heartbeat Ping < ")
payload = d.generate_payload(tinytuya.HEART_BEAT)
d.send(payload)

# Uncomment if you want the monitor to constantly request status - otherwise you
# will only get updates when state changes
# print(" > Send Request for Status < ")
# payload = d.generate_payload(tinytuya.DP_QUERY)
# d.send(payload)

# Uncomment if your device provides power monitoring data but it is not updating
# Some devices require a UPDATEDPS command to force measurements of power.
# print(" > Send DPS Update Request < ")
# Most devices send power data on DPS indexes 18, 19 and 20
# payload = d.generate_payload(tinytuya.UPDATEDPS,['18','19','20'])
# Some Tuya devices will not accept the DPS index values for UPDATEDPS - try:
# payload = d.generate_payload(tinytuya.UPDATEDPS)
# d.send(payload)


if data and 'Err' in data:
print("Received error!")
# rate limit retries so we don't hammer the device
time.sleep(5)
5 changes: 5 additions & 0 deletions server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ def tuyalisten(port):
# Enable UDP listening broadcasting mode on UDP port
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
client.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
try:
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except AttributeError:
# SO_REUSEPORT not available
pass
client.bind(("", port))
client.settimeout(5)

Expand Down
Loading

0 comments on commit fd65f9d

Please sign in to comment.