Skip to content

Commit 74c0b19

Browse files
committed
Fetch the device list a 2nd time to make sure we have the local key
1 parent 54d650f commit 74c0b19

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

tinytuya/Cloud.py

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ def _tuyaplatform(self, uri, action='GET', post=None, ver='v1.0', recursive=Fals
213213
"POST: URL=%s HEADERS=%s DATA=%s", url, headers, body,
214214
)
215215
response = requests.post(url, headers=headers, data=body)
216+
log.debug(
217+
"POST RESPONSE: code=%d text=%s token=%s", response.status_code, response.text, self.token
218+
)
216219

217220
# Check to see if token is expired
218221
if "token invalid" in response.text:
@@ -307,17 +310,48 @@ def cloudrequest(self, url, action=None, post=None, query=None):
307310
action = 'POST' if post else 'GET'
308311
return self._tuyaplatform(url, action=action, post=post, ver=None, query=query)
309312

310-
def _get_all_devices(self):
313+
# merge device list 'result2' into 'result1'
314+
# if result2 has a device which is not in result1 then it will be added
315+
# if result2 has a key which does not exist or is empty in result1 then that key will be copied over
316+
def _update_device_list( self, result1, result2 ):
317+
for new_device in result2:
318+
if 'id' not in new_device or not new_device['id']:
319+
continue
320+
found = False
321+
for existing_device in result1:
322+
if 'id' in existing_device and existing_device['id'] == new_device['id']:
323+
found = True
324+
for k in new_device:
325+
if k not in existing_device or not existing_device[k]:
326+
existing_device[k] = new_device[k]
327+
if not found:
328+
result1.append( new_device )
329+
330+
def _get_all_devices( self, uid=None, device_ids=None ):
311331
fetches = 0
312332
our_result = { 'result': [] }
313333
last_row_key = None
314334
has_more = True
315335
total = 0
316-
query = {'size':'50'}
317336

318-
while has_more:
337+
if uid:
338+
# get device list for specified user id
339+
query = {'page_size':'75', 'source_type': 'tuyaUser', 'source_id': uid}
340+
# API docu: https://developer.tuya.com/en/docs/cloud/dc413408fe?id=Kc09y2ons2i3b
341+
uri = '/v1.3/iot-03/devices'
342+
if device_ids:
343+
if isinstance( device_ids, tuple ) or isinstance( device_ids, list ):
344+
query['device_ids'] = ','.join(device_ids)
345+
else:
346+
query['device_ids'] = device_ids
347+
else:
348+
# get all devices
349+
query = {'size':'50'}
319350
# API docu: https://developer.tuya.com/en/docs/cloud/fc19523d18?id=Kakr4p8nq5xsc
320-
result = self.cloudrequest( '/v1.0/iot-01/associated-users/devices', query=query )
351+
uri = '/v1.0/iot-01/associated-users/devices'
352+
353+
while has_more:
354+
result = self.cloudrequest( uri, query=query )
321355
fetches += 1
322356
has_more = False
323357

@@ -330,7 +364,12 @@ def _get_all_devices(self):
330364
# format it the same as before, basically just moves result->devices into result
331365
for i in result:
332366
if i == 'result':
333-
our_result[i] += result[i]['devices']
367+
# by-user-id has the result in 'list' while all-devices has it in 'devices'
368+
if 'list' in result[i] and 'devices' not in result[i]:
369+
our_result[i] += result[i]['list']
370+
elif 'devices' in result[i]:
371+
our_result[i] += result[i]['devices']
372+
334373
if 'total' in result[i]: total = result[i]['total']
335374
if 'last_row_key' in result[i]:
336375
has_more = result[i]['has_more']
@@ -364,6 +403,17 @@ def getdevices(self, verbose=False):
364403
json_data = self._tuyaplatform(uri)
365404
else:
366405
json_data = self._get_all_devices()
406+
users = {}
407+
# loop through all devices and build a list of user IDs
408+
for dev in json_data['result']:
409+
if 'uid' in dev:
410+
users[dev['uid']] = True
411+
if users:
412+
# we have at least 1 user id, so fetch the device list again to make sure we have the local key
413+
# this also gets us the gateway_id for child devices
414+
for uid in users.keys():
415+
json_data2 = self._get_all_devices( uid=uid )
416+
self._update_device_list( json_data['result'], json_data2['result'] )
367417

368418
if verbose:
369419
return json_data

tinytuya/wizard.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,20 @@ def wizard(color=True, retries=None, forcescan=False, nocloud=False):
157157
# Filter to only Name, ID and Key, IP and mac-address
158158
tuyadevices = cloud.filter_devices( json_data['result'] )
159159

160-
# The device list does not tell us which device is the parent for a sub-device, so we need to try and figure it out
160+
# The device list does not (always) tell us which device is the parent for a sub-device, so we need to try and figure it out
161161
# The only link between parent and child appears to be the local key
162+
163+
# Result:
162164
# if 'parent' not in device: device is not a sub-device
163165
# if 'parent' in device: device is a sub-device
164166
# if device['parent'] == '': device is a sub-device with an unknown parent
165167
# else: device['parent'] == device_id of parent
166168
for dev in tuyadevices:
167-
if 'sub' in dev and dev['sub']:
169+
if 'gateway_id' in dev and dev['gateway_id']:
170+
# if the Cloud gave us the parent then just use that
171+
dev['parent'] = dev['gateway_id']
172+
elif 'sub' in dev and dev['sub']:
173+
# no parent from cloud, try to find it via the local key
168174
if 'parent' not in dev:
169175
# Set 'parent' to an empty string in case we can't find it
170176
dev['parent'] = ''

0 commit comments

Comments
 (0)