Skip to content

Commit 565e578

Browse files
committed
Refactor threading.py to add error handling and heartbeat keepalive
1 parent f15cecc commit 565e578

File tree

1 file changed

+68
-22
lines changed

1 file changed

+68
-22
lines changed

examples/threading.py

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
]
5151
}
5252

53+
54+
# Settings
55+
TTL_HEARTBEAT = 12 # Time in seconds between heartbeats
56+
5357
# Create array, devices, that is an array of tinytuya.Device objects
5458
devices = []
5559
for i in config["TuyaDevices"]:
@@ -62,33 +66,75 @@ def getDeviceStatuses():
6266
global statuses
6367

6468
def listen_for_status_updates(device, index):
69+
"""
70+
Thread function to continuously listen for status updates and send heartbeats.
71+
"""
6572
# Enable persistent connection to the device
66-
device.set_socketPersistent(True)
67-
68-
# Call status() once to establish connection and get initial status
69-
initial_status = device.status()
70-
print(f"INITIAL status from {device.id}: {initial_status}")
71-
statuses[index] = {"id": device.id, "status": initial_status["dps"]}
72-
73+
def reconnect():
74+
time.sleep(5) # Cool-down before reconnecting
75+
try:
76+
print(f"Reconnecting to {device.id}...")
77+
device.set_socketPersistent(True)
78+
initial_status = device.status()
79+
print(f"Reconnected and got status from {device.id}: {initial_status}")
80+
statuses[index] = {"id": device.id, "status": initial_status["dps"]}
81+
return True
82+
except Exception as e:
83+
print(f"Failed to reconnect to {device.id}: {e}")
84+
return False
85+
86+
try:
87+
# Call status() once to establish connection and get initial status
88+
device.set_socketPersistent(True)
89+
initial_status = device.status()
90+
print(f"INITIAL status from {device.id}: {initial_status}")
91+
statuses[index] = {"id": device.id, "status": initial_status["dps"]}
92+
except Exception as e:
93+
print(f"Error getting initial status from {device.id}: {e}")
94+
statuses[index] = {"id": device.id, "status": "Disconnected"}
95+
return
96+
97+
# Variables to track the last heartbeat
98+
last_heartbeat_time = time.time()
99+
73100
# Infinite loop to listen for status updates
74101
while True:
75-
# Listen for updates from the device (TinyTuya handles receiving updates)
76-
updated_status = device.receive()
77-
78-
if updated_status:
79-
print(f"UPDATE status from {device.id}: {updated_status}")
80-
# We may only get one DPS, so just update that one item
81-
if "dps" in updated_status:
82-
for key in updated_status["dps"]:
83-
statuses[index]["status"][key] = updated_status["dps"][key]
84-
print(f" - Updated status for {device.id} DPS {key} to {updated_status['dps'][key]}")
85-
# This would be a good place to push a socket.io update to a web client
86-
87-
# Add a small delay to avoid overwhelming the system
88-
time.sleep(0.1) # 100ms
102+
try:
103+
# Send a heartbeat every 5 seconds
104+
if time.time() - last_heartbeat_time >= TTL_HEARTBEAT:
105+
try:
106+
device.heartbeat()
107+
print(f"Heartbeat sent to {device.id}")
108+
last_heartbeat_time = time.time()
109+
except Exception as hb_error:
110+
print(f"Failed to send heartbeat to {device.id}: {hb_error}")
111+
# Try to reconnect if the heartbeat fails
112+
if not reconnect():
113+
statuses[index]["status"] = "Disconnected"
114+
break # Exit the loop if reconnection fails
115+
116+
# Listen for updates from the device
117+
updated_status = device.receive()
118+
119+
if updated_status:
120+
print(f"UPDATE status from {device.id}: {updated_status}")
121+
# We may only get one DPS, so just update that one item
122+
if "dps" in updated_status:
123+
for key in updated_status["dps"]:
124+
statuses[index]["status"][key] = updated_status["dps"][key]
125+
print(f" - Updated status for {device.id} DPS {key} to {updated_status['dps'][key]}")
126+
127+
# Small delay to avoid tight loops
128+
time.sleep(0.1)
129+
130+
except Exception as e:
131+
print(f"Error receiving status from {device.id}: {e}")
132+
statuses[index]["status"] = "Disconnected"
133+
if not reconnect():
134+
break # Exit the loop if reconnection fails
89135

90136
threads = []
91-
137+
92138
# Create and start a thread for each device
93139
for index, device in enumerate(devices):
94140
print(f"Starting thread for device {device.id}")

0 commit comments

Comments
 (0)