Skip to content

Commit 3d0a22d

Browse files
committed
* Groups set dp values is now set values together instead of set dp on it's own. * Sub-devices updated localkey also update the node_id and gateway id.
1 parent e49b1fb commit 3d0a22d

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

custom_components/localtuya/common.py

+46-19
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
CONF_PROTOCOL_VERSION,
5151
CONF_RESET_DPIDS,
5252
CONF_RESTORE_ON_RECONNECT,
53+
DATA_DISCOVERY,
5354
DOMAIN,
5455
DEFAULT_CATEGORIES,
5556
ENTITY_CATEGORY,
@@ -58,6 +59,7 @@
5859
CONF_DEVICE_SLEEP_TIME,
5960
CONF_DPS_STRINGS,
6061
CONF_MANUAL_DPS,
62+
CONF_TUYA_IP,
6163
)
6264

6365
_LOGGER = logging.getLogger(__name__)
@@ -387,6 +389,8 @@ async def check_connection(self):
387389
await self._connect_task
388390
if not self.connected and self._gwateway and self._gwateway._connect_task:
389391
await self._gwateway._connect_task
392+
if not self._interface:
393+
self.error(f"Not connected to device {self._device_config.name}")
390394

391395
async def close(self):
392396
"""Close connection and stop re-connect loop."""
@@ -409,46 +413,67 @@ async def update_local_key(self):
409413
dev_id = self._device_config.id
410414
cloud_api = self._hass_entry.cloud_data
411415
await cloud_api.async_get_devices_list()
416+
discovery = self._hass.data[DOMAIN].get(DATA_DISCOVERY)
417+
412418
cloud_devs = cloud_api.device_list
413419
if dev_id in cloud_devs:
414420
cloud_localkey = cloud_devs[dev_id].get(CONF_LOCAL_KEY)
415421
if not cloud_localkey or self._local_key == cloud_localkey:
416422
return
417-
self._local_key = cloud_localkey
423+
418424
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+
419442
new_data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY] = self._local_key
420443
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
421444
self._hass.config_entries.async_update_entry(
422-
self._config_entry,
423-
data=new_data,
445+
self._config_entry, data=new_data
424446
)
425447
self.info(f"local_key updated for device {dev_id}.")
426448

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."""
429451
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(), {}
431454
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)
433456
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()
435465
else:
436466
if self.is_sleep:
437467
return self._pending_status.update({str(dp_index): state})
438-
self.error(f"Not connected to device {self._device_config.name}")
439468

440469
async def set_dps(self, states):
441470
"""Change value of a DPs of the Tuya device."""
442-
await self.check_connection()
443471
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()
448474
else:
449475
if self.is_sleep:
450476
return self._pending_status.update(states)
451-
self.error(f"Not connected to device {self._device_config.name}")
452477

453478
async def _async_refresh(self, _now):
454479
if self._interface is not None:
@@ -588,11 +613,13 @@ def _update_handler(status):
588613
"""Update entity state when status was updated."""
589614
if status is None:
590615
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+
591622
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
596623
self._status = status.copy()
597624

598625
if status:

0 commit comments

Comments
 (0)