Obfuscated diagnostics; fixed IP auto-update; cleaned logs

This commit is contained in:
rospogrigio
2022-05-23 12:31:15 +02:00
parent cdfe8e4906
commit ef50285c33
4 changed files with 75 additions and 75 deletions

View File

@@ -66,7 +66,6 @@ SERVICE_SET_DP_SCHEMA = vol.Schema(
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the LocalTuya integration component."""
hass.data.setdefault(DOMAIN, {})
print("SETUP")
device_cache = {}
@@ -134,6 +133,9 @@ async def async_setup(hass: HomeAssistant, config: dict):
# settings triggers a reload of the config entry, which tears down the device
# so no need to connect in that case.
if updated:
_LOGGER.debug("Updating keys for device %s: %s %s",
device_id, device_ip, product_key
)
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
hass.config_entries.async_update_entry(
entry, data=new_data
@@ -148,26 +150,17 @@ async def async_setup(hass: HomeAssistant, config: dict):
if not device.connected:
device.async_connect()
discovery = TuyaDiscovery(_device_discovered)
def _shutdown(event):
"""Clean up resources when shutting down."""
discovery.close()
try:
await discovery.start()
hass.data[DOMAIN][DATA_DISCOVERY] = discovery
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("failed to set up discovery")
async def _async_reconnect(now):
"""Try connecting to devices not already connected to."""
for device_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
if not device.connected:
device.async_connect()
# async_track_time_interval(hass, _async_reconnect, RECONNECT_INTERVAL)
async_track_time_interval(hass, _async_reconnect, RECONNECT_INTERVAL)
hass.helpers.service.async_register_admin_service(
DOMAIN,
@@ -179,6 +172,14 @@ async def async_setup(hass: HomeAssistant, config: dict):
DOMAIN, SERVICE_SET_DP, _handle_set_dp, schema=SERVICE_SET_DP_SCHEMA
)
discovery = TuyaDiscovery(_device_discovered)
try:
await discovery.start()
hass.data[DOMAIN][DATA_DISCOVERY] = discovery
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("failed to set up discovery")
return True
@@ -228,7 +229,6 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
print("SETUP ENTRY STARTED!")
"""Set up LocalTuya integration from a config entry."""
unsub_listener = entry.add_update_listener(update_listener)
hass.data[DOMAIN][UNSUB_LISTENER] = unsub_listener
@@ -244,19 +244,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
_LOGGER.error("Cloud API connection failed: %s", res)
_LOGGER.info("Cloud API connection succeeded.")
res = await tuya_api.async_get_devices_list()
for dev_id, dev in tuya_api._device_list.items():
_LOGGER.debug(
"Cloud device: %s \t dev_id %s \t key %s", dev["name"], dev["id"], dev["local_key"]
)
hass.data[DOMAIN][DATA_CLOUD] = tuya_api
# device = TuyaDevice(hass, entry.data)
#
# hass.data[DOMAIN][entry.entry_id] = {
# UNSUB_LISTENER: unsub_listener,
# TUYA_DEVICE: device,
# }
#
async def setup_entities(dev_id):
dev_entry = entry.data[CONF_DEVICES][dev_id]
device = TuyaDevice(hass, entry, dev_id)
@@ -272,19 +261,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
device.async_connect()
await async_remove_orphan_entities(hass, entry)
print("SETUP_ENTITIES for {} ENDED".format(dev_id))
for dev_id in entry.data[CONF_DEVICES]:
hass.async_create_task(setup_entities(dev_id))
print("SETUP ENTRY ENDED!")
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
# print("ASYNC_UNLOAD_ENTRY INVOKED...")
platforms = {}
for dev_id, dev_entry in entry.data[CONF_DEVICES].items():
for entity in dev_entry[CONF_ENTITIES]:
@@ -301,20 +286,18 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
hass.data[DOMAIN][UNSUB_LISTENER]()
for dev_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
await device.close()
if device.connected:
await device.close()
if unload_ok:
hass.data[DOMAIN][TUYA_DEVICES] = {}
# print("ASYNC_UNLOAD_ENTRY ENDED")
return True
async def update_listener(hass, config_entry):
"""Update listener."""
print("UPDATE_LISTENER INVOKED")
await hass.config_entries.async_reload(config_entry.entry_id)
print("UPDATE_LISTENER RELOADED {}".format(config_entry.entry_id))
async def async_remove_config_entry_device(
@@ -323,9 +306,18 @@ async def async_remove_config_entry_device(
"""Remove a config entry from a device."""
dev_id = list(device_entry.identifiers)[0][1].split("_")[-1]
ent_reg = await er.async_get_registry(hass)
entities = {
ent.unique_id: ent.entity_id
for ent in er.async_entries_for_config_entry(ent_reg, config_entry.entry_id)
if dev_id in ent.unique_id
}
for entity_id in entities.values():
ent_reg.async_remove(entity_id)
if dev_id not in config_entry.data[CONF_DEVICES]:
_LOGGER.debug(
"Device ID %s not found in config entry: finalizing device removal", dev_id
_LOGGER.info(
"Device %s not found in config entry: finalizing device removal", dev_id
)
return True
@@ -340,15 +332,7 @@ async def async_remove_config_entry_device(
data=new_data,
)
ent_reg = await er.async_get_registry(hass)
entities = {
ent.unique_id: ent.entity_id
for ent in er.async_entries_for_config_entry(ent_reg, config_entry.entry_id)
if dev_id in ent.unique_id
}
for entity_id in entities.values():
ent_reg.async_remove(entity_id)
print("REMOVED {}".format(entity_id))
_LOGGER.info("Device %s removed.", dev_id)
return True
@@ -361,11 +345,8 @@ async def async_remove_orphan_entities(hass, entry):
ent.unique_id: ent.entity_id
for ent in er.async_entries_for_config_entry(ent_reg, entry.entry_id)
}
print("ENTITIES ORPHAN {}".format(entities))
_LOGGER.info("ENTITIES ORPHAN %s", entities)
return
res = ent_reg.async_remove("switch.aa")
print("RESULT ORPHAN {}".format(res))
# del entities[101]
for entity in entry.data[CONF_ENTITIES]:
if entity[CONF_ID] in entities:

View File

@@ -74,6 +74,10 @@ async def async_setup_entry(
if len(entities_to_setup) > 0:
if dev_id not in hass.data[DOMAIN][TUYA_DEVICES]:
print("STRANO: {}".format(hass.data[DOMAIN][TUYA_DEVICES]))
return
tuyainterface = hass.data[DOMAIN][TUYA_DEVICES][dev_id]
dps_config_fields = list(get_dps_for_platform(flow_schema))
@@ -127,7 +131,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
super().__init__()
self._hass = hass
self._config_entry = config_entry
self._dev_config_entry = config_entry.data[CONF_DEVICES][dev_id]
self._dev_config_entry = config_entry.data[CONF_DEVICES][dev_id].copy()
self._interface = None
self._status = {}
self.dps_to_request = {}
@@ -205,9 +209,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
except Exception as e: # pylint: disable=broad-except
self.exception(f"Connect to {self._dev_config_entry[CONF_HOST]} failed")
self.error("BBBB: %s", type(type(e)))
if 'json.decode' in str(type(e)):
self.error("BBBB2")
await self.update_local_key()
if self._interface is not None:
@@ -220,7 +222,6 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
await self._hass.data[DOMAIN][DATA_CLOUD].async_get_devices_list()
cloud_devs = self._hass.data[DOMAIN][DATA_CLOUD]._device_list
if dev_id in cloud_devs:
old_key = self._local_key
self._local_key = cloud_devs[dev_id].get(CONF_LOCAL_KEY)
new_data = self._config_entry.data.copy()
new_data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY] = self._local_key
@@ -229,10 +230,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
self._config_entry,
data=new_data,
)
self.debug(
"New local key for %s: from %s to %s",
dev_id, old_key, self._local_key
)
self.info("local_key updated for device %s.", dev_id)
async def _async_refresh(self, _now):
if self._interface is not None:

View File

@@ -27,7 +27,7 @@ from homeassistant.const import (
from homeassistant.core import callback
from .cloud_api import TuyaCloudApi
from .common import async_config_entry_by_device_id, pytuya
from .common import pytuya
from .const import (
CONF_ACTION,
CONF_ADD_DEVICE,
@@ -304,11 +304,6 @@ class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
placeholders = {"msg": res["msg"]}
defaults = {}
defaults[CONF_REGION] = "eu"
defaults[CONF_CLIENT_ID] = "xxx"
defaults[CONF_CLIENT_SECRET] = "xxx"
defaults[CONF_USER_ID] = "xxx"
defaults[CONF_USERNAME] = "xxx"
defaults.update(user_input or {})
return self.async_show_form(
@@ -383,16 +378,17 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
cloud_devs = cloud_api._device_list
for dev_id, dev in new_data[CONF_DEVICES].items():
if CONF_MODEL not in dev and dev_id in cloud_devs:
new_data[CONF_DEVICES][dev_id][CONF_MODEL] = cloud_devs[dev_id].get(
CONF_PRODUCT_NAME
)
model = cloud_devs[dev_id].get(CONF_PRODUCT_NAME)
new_data[CONF_DEVICES][dev_id][CONF_MODEL] = model
new_data[ATTR_UPDATED_AT] = str(int(time.time() * 1000))
self.hass.config_entries.async_update_entry(
self.config_entry,
data=new_data,
)
return self.async_create_entry(title=new_data.get(CONF_USERNAME), data={})
return self.async_create_entry(
title=new_data.get(CONF_USERNAME), data={}
)
errors["base"] = res["reason"]
placeholders = {"msg": res["msg"]}
@@ -559,7 +555,6 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
CONF_ENTITIES: self.entities,
}
# entry = async_config_entry_by_device_id(self.hass, self.unique_id)
dev_id = self.device_data.get(CONF_DEVICE_ID)
if dev_id in self.config_entry.data[CONF_DEVICES]:
self.hass.config_entries.async_update_entry(

View File

@@ -3,11 +3,26 @@ from __future__ import annotations
from typing import Any
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICES
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntry
from .const import DOMAIN, DATA_CLOUD
from homeassistant.const import (
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
CONF_DEVICES,
)
from .const import (
DOMAIN,
DATA_CLOUD,
CONF_USER_ID,
CONF_LOCAL_KEY,
)
CLOUD_DEVICES = "cloud_devices"
DEVICE_CONFIG = "device_config"
DEVICE_CLOUD_INFO = "device_cloud_info"
async def async_get_config_entry_diagnostics(
@@ -15,14 +30,20 @@ async def async_get_config_entry_diagnostics(
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
data = {}
data = {**entry.data}
# print("DATA is {}".format(data))
data = entry.data.copy()
tuya_api = hass.data[DOMAIN][DATA_CLOUD]
data["cloud_devices"] = tuya_api._device_list
# censoring private information
# data["token"] = re.sub(r"[^\-]", "*", data["token"])
# data["userId"] = re.sub(r"[^\-]", "*", data["userId"])
for field in [CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_USER_ID]:
data[field] = f"{data[field][0:3]}...{data[field][-3:]}"
for dev_id, dev in data[CONF_DEVICES].items():
local_key = data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY]
local_key_obfuscated = f"{local_key[0:3]}...{local_key[-3:]}"
data[CONF_DEVICES][dev_id][CONF_LOCAL_KEY] = local_key_obfuscated
data[CLOUD_DEVICES] = tuya_api._device_list
for dev_id, dev in data[CLOUD_DEVICES].items():
local_key = data[CLOUD_DEVICES][dev_id][CONF_LOCAL_KEY]
local_key_obfuscated = f"{local_key[0:3]}...{local_key[-3:]}"
data[CLOUD_DEVICES][dev_id][CONF_LOCAL_KEY] = local_key_obfuscated
return data
@@ -32,9 +53,14 @@ async def async_get_device_diagnostics(
"""Return diagnostics for a device entry."""
data = {}
dev_id = list(device.identifiers)[0][1].split("_")[-1]
data["device_config"] = entry.data[CONF_DEVICES][dev_id]
data[DEVICE_CONFIG] = entry.data[CONF_DEVICES][dev_id]
local_key = data[DEVICE_CONFIG][CONF_LOCAL_KEY]
data[DEVICE_CONFIG][CONF_LOCAL_KEY] = f"{local_key[0:3]}...{local_key[-3:]}"
tuya_api = hass.data[DOMAIN][DATA_CLOUD]
if dev_id in tuya_api._device_list:
data["device_cloud_info"] = tuya_api._device_list[dev_id]
data[DEVICE_CLOUD_INFO] = tuya_api._device_list[dev_id]
local_key = data[DEVICE_CLOUD_INFO][CONF_LOCAL_KEY]
data[DEVICE_CLOUD_INFO][CONF_LOCAL_KEY] = f"{local_key[0:3]}...{local_key[-3:]}"
# data["log"] = hass.data[DOMAIN][CONF_DEVICES][dev_id].logger.retrieve_log()
return data