Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various updates inspired by recent issues #397

Merged
merged 12 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading