From 33e0033b0a95003252779262e58a719a902c4d1e Mon Sep 17 00:00:00 2001 From: rospogrigio Date: Tue, 10 Jan 2023 18:18:35 +0100 Subject: [PATCH] Introduced the possibility to select which devices should have the pytuya debug enabled --- custom_components/localtuya/common.py | 2 + custom_components/localtuya/config_flow.py | 40 ++++++++----------- custom_components/localtuya/const.py | 1 + .../localtuya/pytuya/__init__.py | 26 ++++++++---- .../localtuya/translations/en.json | 1 + .../localtuya/translations/it.json | 1 + .../localtuya/translations/pt-BR.json | 1 + 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/custom_components/localtuya/common.py b/custom_components/localtuya/common.py index 76521eb..85ed21c 100644 --- a/custom_components/localtuya/common.py +++ b/custom_components/localtuya/common.py @@ -28,6 +28,7 @@ from .const import ( ATTR_STATE, ATTR_UPDATED_AT, CONF_DEFAULT_VALUE, + CONF_ENABLE_DEBUG, CONF_LOCAL_KEY, CONF_MODEL, CONF_PASSIVE_ENTITY, @@ -188,6 +189,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger): self._dev_config_entry[CONF_DEVICE_ID], self._local_key, float(self._dev_config_entry[CONF_PROTOCOL_VERSION]), + self._dev_config_entry.get(CONF_ENABLE_DEBUG, False), self, ) self._interface.add_dps_to_request(self.dps_to_request) diff --git a/custom_components/localtuya/config_flow.py b/custom_components/localtuya/config_flow.py index 0258a72..8f37be9 100644 --- a/custom_components/localtuya/config_flow.py +++ b/custom_components/localtuya/config_flow.py @@ -33,6 +33,7 @@ from .const import ( CONF_ADD_DEVICE, CONF_DPS_STRINGS, CONF_EDIT_DEVICE, + CONF_ENABLE_DEBUG, CONF_LOCAL_KEY, CONF_MANUAL_DPS, CONF_MODEL, @@ -82,30 +83,16 @@ CLOUD_SETUP_SCHEMA = vol.Schema( } ) -CONFIGURE_DEVICE_SCHEMA = vol.Schema( - { - vol.Required(CONF_FRIENDLY_NAME): str, - vol.Required(CONF_LOCAL_KEY): str, - vol.Required(CONF_HOST): str, - vol.Required(CONF_DEVICE_ID): str, - vol.Required(CONF_PROTOCOL_VERSION, default="3.3"): vol.In( - ["3.1", "3.2", "3.3", "3.4"] - ), - vol.Optional(CONF_SCAN_INTERVAL): int, - vol.Optional(CONF_MANUAL_DPS): str, - vol.Optional(CONF_RESET_DPIDS): str, - } -) - DEVICE_SCHEMA = vol.Schema( { + vol.Required(CONF_FRIENDLY_NAME): cv.string, vol.Required(CONF_HOST): cv.string, vol.Required(CONF_DEVICE_ID): cv.string, vol.Required(CONF_LOCAL_KEY): cv.string, - vol.Required(CONF_FRIENDLY_NAME): cv.string, vol.Required(CONF_PROTOCOL_VERSION, default="3.3"): vol.In( ["3.1", "3.2", "3.3", "3.4"] ), + vol.Required(CONF_ENABLE_DEBUG, default=False): bool, vol.Optional(CONF_SCAN_INTERVAL): int, vol.Optional(CONF_MANUAL_DPS): cv.string, vol.Optional(CONF_RESET_DPIDS): str, @@ -145,15 +132,16 @@ def options_schema(entities): ] return vol.Schema( { - vol.Required(CONF_FRIENDLY_NAME): str, - vol.Required(CONF_HOST): str, - vol.Required(CONF_LOCAL_KEY): str, + vol.Required(CONF_FRIENDLY_NAME): cv.string, + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_LOCAL_KEY): cv.string, vol.Required(CONF_PROTOCOL_VERSION, default="3.3"): vol.In( ["3.1", "3.2", "3.3", "3.4"] ), - vol.Optional(CONF_SCAN_INTERVAL): int, - vol.Optional(CONF_MANUAL_DPS): str, - vol.Optional(CONF_RESET_DPIDS): str, + vol.Required(CONF_ENABLE_DEBUG, default=False): bool, + vol.Optional(CONF_SCAN_INTERVAL): cv.string, + vol.Optional(CONF_MANUAL_DPS): cv.string, + vol.Optional(CONF_RESET_DPIDS): cv.string, vol.Required( CONF_ENTITIES, description={"suggested_value": entity_names} ): cv.multi_select(entity_names), @@ -253,6 +241,7 @@ async def validate_input(hass: core.HomeAssistant, data): data[CONF_DEVICE_ID], data[CONF_LOCAL_KEY], float(data[CONF_PROTOCOL_VERSION]), + data[CONF_ENABLE_DEBUG], ) if CONF_RESET_DPIDS in data: reset_ids_str = data[CONF_RESET_DPIDS].split(",") @@ -570,6 +559,11 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow): CONF_ENTITIES: [], } ) + if len(user_input[CONF_ENTITIES]) == 0: + return self.async_abort( + reason="no_entities", + description_placeholders={}, + ) if user_input[CONF_ENTITIES]: entity_ids = [ int(entity.split(":")[0]) @@ -617,7 +611,7 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow): if dev_id in cloud_devs: defaults[CONF_LOCAL_KEY] = cloud_devs[dev_id].get(CONF_LOCAL_KEY) defaults[CONF_FRIENDLY_NAME] = cloud_devs[dev_id].get(CONF_NAME) - schema = schema_defaults(CONFIGURE_DEVICE_SCHEMA, **defaults) + schema = schema_defaults(DEVICE_SCHEMA, **defaults) placeholders = {"for_device": ""} diff --git a/custom_components/localtuya/const.py b/custom_components/localtuya/const.py index 8010d18..3a6c252 100644 --- a/custom_components/localtuya/const.py +++ b/custom_components/localtuya/const.py @@ -28,6 +28,7 @@ ATTR_UPDATED_AT = "updated_at" # config flow CONF_LOCAL_KEY = "local_key" +CONF_ENABLE_DEBUG = "enable_debug" CONF_PROTOCOL_VERSION = "protocol_version" CONF_DPS_STRINGS = "dps_strings" CONF_MODEL = "model" diff --git a/custom_components/localtuya/pytuya/__init__.py b/custom_components/localtuya/pytuya/__init__.py index e6dbe27..df34c93 100644 --- a/custom_components/localtuya/pytuya/__init__.py +++ b/custom_components/localtuya/pytuya/__init__.py @@ -233,13 +233,17 @@ class ContextualLogger: def __init__(self): """Initialize a new ContextualLogger.""" self._logger = None + self._enable_debug = False - def set_logger(self, logger, device_id): + def set_logger(self, logger, device_id, enable_debug=False): """Set base logger to use.""" + self._enable_debug = enable_debug self._logger = TuyaLoggingAdapter(logger, {"device_id": device_id}) def debug(self, msg, *args): """Debug level log.""" + if not self._enable_debug: + return return self._logger.log(logging.DEBUG, msg, *args) def info(self, msg, *args): @@ -415,7 +419,7 @@ class MessageDispatcher(ContextualLogger): RESET_SEQNO = -101 SESS_KEY_SEQNO = -102 - def __init__(self, dev_id, listener, protocol_version, local_key): + def __init__(self, dev_id, listener, protocol_version, local_key, enable_debug): """Initialize a new MessageBuffer.""" super().__init__() self.buffer = b"" @@ -423,7 +427,7 @@ class MessageDispatcher(ContextualLogger): self.listener = listener self.version = protocol_version self.local_key = local_key - self.set_logger(_LOGGER, dev_id) + self.set_logger(_LOGGER, dev_id, enable_debug) def abort(self): """Abort all waiting clients.""" @@ -540,7 +544,9 @@ class EmptyListener(TuyaListener): class TuyaProtocol(asyncio.Protocol, ContextualLogger): """Implementation of the Tuya protocol.""" - def __init__(self, dev_id, local_key, protocol_version, on_connected, listener): + def __init__( + self, dev_id, local_key, protocol_version, enable_debug, on_connected, listener + ): """ Initialize a new TuyaInterface. @@ -554,7 +560,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger): """ super().__init__() self.loop = asyncio.get_running_loop() - self.set_logger(_LOGGER, dev_id) + self.set_logger(_LOGGER, dev_id, enable_debug) self.id = dev_id self.local_key = local_key.encode("latin1") self.real_local_key = self.local_key @@ -572,7 +578,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger): self.seqno = 1 self.transport = None self.listener = weakref.ref(listener) - self.dispatcher = self._setup_dispatcher() + self.dispatcher = self._setup_dispatcher(enable_debug) self.on_connected = on_connected self.heartbeater = None self.dps_cache = {} @@ -603,7 +609,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger): return json.loads('{ "Error":"%s", "Err":"%s", "Payload":%s }' % vals) - def _setup_dispatcher(self): + def _setup_dispatcher(self, enable_debug): def _status_update(msg): if msg.seqno > 0: self.seqno = msg.seqno + 1 @@ -615,7 +621,9 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger): if listener is not None: listener.status_updated(self.dps_cache) - return MessageDispatcher(self.id, _status_update, self.version, self.local_key) + return MessageDispatcher( + self.id, _status_update, self.version, self.local_key, enable_debug + ) def connection_made(self, transport): """Did connect to the device.""" @@ -1145,6 +1153,7 @@ async def connect( device_id, local_key, protocol_version, + enable_debug, listener=None, port=6668, timeout=5, @@ -1157,6 +1166,7 @@ async def connect( device_id, local_key, protocol_version, + enable_debug, on_connected, listener or EmptyListener(), ), diff --git a/custom_components/localtuya/translations/en.json b/custom_components/localtuya/translations/en.json index 4b3ddb0..157fdf9 100644 --- a/custom_components/localtuya/translations/en.json +++ b/custom_components/localtuya/translations/en.json @@ -95,6 +95,7 @@ "device_id": "Device ID", "local_key": "Local key", "protocol_version": "Protocol Version", + "enable_debug": "Enable debugging for this device (debug must be enabled also in configuration.yaml)", "scan_interval": "Scan interval (seconds, only when not updating automatically)", "entities": "Entities (uncheck an entity to remove it)", "manual_dps_strings": "Manual DPS to add (separated by commas ',') - used when detection is not working (optional)", diff --git a/custom_components/localtuya/translations/it.json b/custom_components/localtuya/translations/it.json index faf4afa..1cbd4c0 100644 --- a/custom_components/localtuya/translations/it.json +++ b/custom_components/localtuya/translations/it.json @@ -95,6 +95,7 @@ "device_id": "ID del dispositivo", "local_key": "Chiave locale", "protocol_version": "Versione del protocollo", + "enable_debug": "Abilita il debugging per questo device (il debug va abilitato anche in configuration.yaml)", "scan_interval": "Intervallo di scansione (secondi, solo quando non si aggiorna automaticamente)", "entities": "Entities (deseleziona un'entity per rimuoverla)" } diff --git a/custom_components/localtuya/translations/pt-BR.json b/custom_components/localtuya/translations/pt-BR.json index a2feed4..26f01ac 100644 --- a/custom_components/localtuya/translations/pt-BR.json +++ b/custom_components/localtuya/translations/pt-BR.json @@ -95,6 +95,7 @@ "device_id": "ID do dispositivo", "local_key": "Local key", "protocol_version": "Versão do protocolo", + "enable_debug": "Ative a depuração para este dispositivo (a depuração também deve ser ativada em configuration.yaml)", "scan_interval": "Intervalo de escaneamento (segundos, somente quando não estiver atualizando automaticamente)", "entities": "Entidades (desmarque uma entidade para removê-la)" }