50
50
CONF_PROTOCOL_VERSION ,
51
51
CONF_RESET_DPIDS ,
52
52
CONF_RESTORE_ON_RECONNECT ,
53
+ DATA_DISCOVERY ,
53
54
DOMAIN ,
54
55
DEFAULT_CATEGORIES ,
55
56
ENTITY_CATEGORY ,
58
59
CONF_DEVICE_SLEEP_TIME ,
59
60
CONF_DPS_STRINGS ,
60
61
CONF_MANUAL_DPS ,
62
+ CONF_TUYA_IP ,
61
63
)
62
64
63
65
_LOGGER = logging .getLogger (__name__ )
@@ -387,6 +389,8 @@ async def check_connection(self):
387
389
await self ._connect_task
388
390
if not self .connected and self ._gwateway and self ._gwateway ._connect_task :
389
391
await self ._gwateway ._connect_task
392
+ if not self ._interface :
393
+ self .error (f"Not connected to device { self ._device_config .name } " )
390
394
391
395
async def close (self ):
392
396
"""Close connection and stop re-connect loop."""
@@ -409,46 +413,67 @@ async def update_local_key(self):
409
413
dev_id = self ._device_config .id
410
414
cloud_api = self ._hass_entry .cloud_data
411
415
await cloud_api .async_get_devices_list ()
416
+ discovery = self ._hass .data [DOMAIN ].get (DATA_DISCOVERY )
417
+
412
418
cloud_devs = cloud_api .device_list
413
419
if dev_id in cloud_devs :
414
420
cloud_localkey = cloud_devs [dev_id ].get (CONF_LOCAL_KEY )
415
421
if not cloud_localkey or self ._local_key == cloud_localkey :
416
422
return
417
- self . _local_key = cloud_localkey
423
+
418
424
new_data = self ._config_entry .data .copy ()
425
+ self ._local_key = cloud_localkey
426
+
427
+ if self .is_subdevice :
428
+ from .core .helpers import get_gateway_by_deviceid
429
+
430
+ # Update Node ID.
431
+ if new_node_id := cloud_devs [dev_id ].get (CONF_NODE_ID ):
432
+ new_data [CONF_DEVICES ][dev_id ][CONF_NODE_ID ] = new_node_id
433
+
434
+ # Update Gateway ID and IP
435
+ new_gw = get_gateway_by_deviceid (dev_id , cloud_devs )
436
+ new_data [CONF_DEVICES ][dev_id ][CONF_GATEWAY_ID ] = new_gw .id
437
+ if discovery and (local_gw := discovery .devices .get (new_gw .id )):
438
+ new_ip = local_gw .get (CONF_TUYA_IP , self ._device_config .host )
439
+ new_data [CONF_DEVICES ][dev_id ][CONF_HOST ] = new_ip
440
+ self .info (f"Updated informations for sub-device { dev_id } ." )
441
+
419
442
new_data [CONF_DEVICES ][dev_id ][CONF_LOCAL_KEY ] = self ._local_key
420
443
new_data [ATTR_UPDATED_AT ] = str (int (time .time () * 1000 ))
421
444
self ._hass .config_entries .async_update_entry (
422
- self ._config_entry ,
423
- data = new_data ,
445
+ self ._config_entry , data = new_data
424
446
)
425
447
self .info (f"local_key updated for device { dev_id } ." )
426
448
427
- async def set_dp (self , state , dp_index ):
428
- """Change value of a DP of the Tuya device."""
449
+ async def set_values (self ):
450
+ """Send self._pending_status payload to device."""
429
451
await self .check_connection ()
430
- if self ._interface is not None :
452
+ if self ._interface and self ._pending_status :
453
+ payload , self ._pending_status = self ._pending_status .copy (), {}
431
454
try :
432
- await self ._interface .set_dp ( state , dp_index , cid = self ._node_id )
455
+ await self ._interface .set_dps ( payload , cid = self ._node_id )
433
456
except Exception : # pylint: disable=broad-except
434
- self .debug (f"Failed to set DP { dp_index } to { str (state )} " , force = True )
457
+ self .debug (f"Failed to set values { payload } " , force = True )
458
+
459
+ async def set_dp (self , state , dp_index ):
460
+ """Change value of a DP of the Tuya device."""
461
+ if self ._interface is not None :
462
+ self ._pending_status .update ({dp_index : state })
463
+ await asyncio .sleep (0.001 )
464
+ await self .set_values ()
435
465
else :
436
466
if self .is_sleep :
437
467
return self ._pending_status .update ({str (dp_index ): state })
438
- self .error (f"Not connected to device { self ._device_config .name } " )
439
468
440
469
async def set_dps (self , states ):
441
470
"""Change value of a DPs of the Tuya device."""
442
- await self .check_connection ()
443
471
if self ._interface is not None :
444
- try :
445
- await self ._interface .set_dps (states , cid = self ._node_id )
446
- except Exception : # pylint: disable=broad-except
447
- self .debug (f"Failed to set DPs { states } " )
472
+ self ._pending_status .update (states )
473
+ await self .set_values ()
448
474
else :
449
475
if self .is_sleep :
450
476
return self ._pending_status .update (states )
451
- self .error (f"Not connected to device { self ._device_config .name } " )
452
477
453
478
async def _async_refresh (self , _now ):
454
479
if self ._interface is not None :
@@ -588,11 +613,13 @@ def _update_handler(status):
588
613
"""Update entity state when status was updated."""
589
614
if status is None :
590
615
status = {}
616
+
617
+ if status == RESTORE_STATES and stored_data :
618
+ if stored_data .state not in (STATE_UNAVAILABLE , STATE_UNKNOWN ):
619
+ self .debug (f"{ self .name } : Restore state: { stored_data .state } " )
620
+ status [self ._dp_id ] = stored_data .state
621
+
591
622
if self ._status != status :
592
- if status == RESTORE_STATES :
593
- if stored_data and stored_data .state != STATE_UNAVAILABLE :
594
- self .debug (f"{ self .name } : restore state: { stored_data .state } " )
595
- status [self ._dp_id ] = stored_data .state
596
623
self ._status = status .copy ()
597
624
598
625
if status :
0 commit comments