Merge pull request #1227 from rospogrigio/device_debugging_option
Device debugging option
This commit is contained in:
@@ -164,8 +164,11 @@ logger:
|
|||||||
default: warning
|
default: warning
|
||||||
logs:
|
logs:
|
||||||
custom_components.localtuya: debug
|
custom_components.localtuya: debug
|
||||||
|
custom_components.localtuya.pytuya: debug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Then, edit the device that is showing problems and check the "Enable debugging for this device" button.
|
||||||
|
|
||||||
# Notes:
|
# Notes:
|
||||||
|
|
||||||
* Do not declare anything as "tuya", such as by initiating a "switch.tuya". Using "tuya" launches Home Assistant's built-in, cloud-based Tuya integration in lieu of localtuya.
|
* Do not declare anything as "tuya", such as by initiating a "switch.tuya". Using "tuya" launches Home Assistant's built-in, cloud-based Tuya integration in lieu of localtuya.
|
||||||
|
@@ -28,6 +28,7 @@ from .const import (
|
|||||||
ATTR_STATE,
|
ATTR_STATE,
|
||||||
ATTR_UPDATED_AT,
|
ATTR_UPDATED_AT,
|
||||||
CONF_DEFAULT_VALUE,
|
CONF_DEFAULT_VALUE,
|
||||||
|
CONF_ENABLE_DEBUG,
|
||||||
CONF_LOCAL_KEY,
|
CONF_LOCAL_KEY,
|
||||||
CONF_MODEL,
|
CONF_MODEL,
|
||||||
CONF_PASSIVE_ENTITY,
|
CONF_PASSIVE_ENTITY,
|
||||||
@@ -188,6 +189,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
|||||||
self._dev_config_entry[CONF_DEVICE_ID],
|
self._dev_config_entry[CONF_DEVICE_ID],
|
||||||
self._local_key,
|
self._local_key,
|
||||||
float(self._dev_config_entry[CONF_PROTOCOL_VERSION]),
|
float(self._dev_config_entry[CONF_PROTOCOL_VERSION]),
|
||||||
|
self._dev_config_entry.get(CONF_ENABLE_DEBUG, False),
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
self._interface.add_dps_to_request(self.dps_to_request)
|
self._interface.add_dps_to_request(self.dps_to_request)
|
||||||
|
@@ -33,6 +33,7 @@ from .const import (
|
|||||||
CONF_ADD_DEVICE,
|
CONF_ADD_DEVICE,
|
||||||
CONF_DPS_STRINGS,
|
CONF_DPS_STRINGS,
|
||||||
CONF_EDIT_DEVICE,
|
CONF_EDIT_DEVICE,
|
||||||
|
CONF_ENABLE_DEBUG,
|
||||||
CONF_LOCAL_KEY,
|
CONF_LOCAL_KEY,
|
||||||
CONF_MANUAL_DPS,
|
CONF_MANUAL_DPS,
|
||||||
CONF_MODEL,
|
CONF_MODEL,
|
||||||
@@ -82,30 +83,17 @@ 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(
|
DEVICE_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
|
vol.Required(CONF_FRIENDLY_NAME): cv.string,
|
||||||
vol.Required(CONF_HOST): cv.string,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
vol.Required(CONF_DEVICE_ID): cv.string,
|
vol.Required(CONF_DEVICE_ID): cv.string,
|
||||||
vol.Required(CONF_LOCAL_KEY): 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(
|
vol.Required(CONF_PROTOCOL_VERSION, default="3.3"): vol.In(
|
||||||
["3.1", "3.2", "3.3", "3.4"]
|
["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_SCAN_INTERVAL): int,
|
||||||
vol.Optional(CONF_MANUAL_DPS): cv.string,
|
vol.Optional(CONF_MANUAL_DPS): cv.string,
|
||||||
vol.Optional(CONF_RESET_DPIDS): str,
|
vol.Optional(CONF_RESET_DPIDS): str,
|
||||||
@@ -145,15 +133,16 @@ def options_schema(entities):
|
|||||||
]
|
]
|
||||||
return vol.Schema(
|
return vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_FRIENDLY_NAME): str,
|
vol.Required(CONF_FRIENDLY_NAME): cv.string,
|
||||||
vol.Required(CONF_HOST): str,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
vol.Required(CONF_LOCAL_KEY): str,
|
vol.Required(CONF_LOCAL_KEY): cv.string,
|
||||||
vol.Required(CONF_PROTOCOL_VERSION, default="3.3"): vol.In(
|
vol.Required(CONF_PROTOCOL_VERSION, default="3.3"): vol.In(
|
||||||
["3.1", "3.2", "3.3", "3.4"]
|
["3.1", "3.2", "3.3", "3.4"]
|
||||||
),
|
),
|
||||||
vol.Optional(CONF_SCAN_INTERVAL): int,
|
vol.Required(CONF_ENABLE_DEBUG, default=False): bool,
|
||||||
vol.Optional(CONF_MANUAL_DPS): str,
|
vol.Optional(CONF_SCAN_INTERVAL): cv.string,
|
||||||
vol.Optional(CONF_RESET_DPIDS): str,
|
vol.Optional(CONF_MANUAL_DPS): cv.string,
|
||||||
|
vol.Optional(CONF_RESET_DPIDS): cv.string,
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_ENTITIES, description={"suggested_value": entity_names}
|
CONF_ENTITIES, description={"suggested_value": entity_names}
|
||||||
): cv.multi_select(entity_names),
|
): cv.multi_select(entity_names),
|
||||||
@@ -253,6 +242,7 @@ async def validate_input(hass: core.HomeAssistant, data):
|
|||||||
data[CONF_DEVICE_ID],
|
data[CONF_DEVICE_ID],
|
||||||
data[CONF_LOCAL_KEY],
|
data[CONF_LOCAL_KEY],
|
||||||
float(data[CONF_PROTOCOL_VERSION]),
|
float(data[CONF_PROTOCOL_VERSION]),
|
||||||
|
data[CONF_ENABLE_DEBUG],
|
||||||
)
|
)
|
||||||
if CONF_RESET_DPIDS in data:
|
if CONF_RESET_DPIDS in data:
|
||||||
reset_ids_str = data[CONF_RESET_DPIDS].split(",")
|
reset_ids_str = data[CONF_RESET_DPIDS].split(",")
|
||||||
@@ -622,7 +612,7 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
if dev_id in cloud_devs:
|
if dev_id in cloud_devs:
|
||||||
defaults[CONF_LOCAL_KEY] = cloud_devs[dev_id].get(CONF_LOCAL_KEY)
|
defaults[CONF_LOCAL_KEY] = cloud_devs[dev_id].get(CONF_LOCAL_KEY)
|
||||||
defaults[CONF_FRIENDLY_NAME] = cloud_devs[dev_id].get(CONF_NAME)
|
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": ""}
|
placeholders = {"for_device": ""}
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@ ATTR_UPDATED_AT = "updated_at"
|
|||||||
|
|
||||||
# config flow
|
# config flow
|
||||||
CONF_LOCAL_KEY = "local_key"
|
CONF_LOCAL_KEY = "local_key"
|
||||||
|
CONF_ENABLE_DEBUG = "enable_debug"
|
||||||
CONF_PROTOCOL_VERSION = "protocol_version"
|
CONF_PROTOCOL_VERSION = "protocol_version"
|
||||||
CONF_DPS_STRINGS = "dps_strings"
|
CONF_DPS_STRINGS = "dps_strings"
|
||||||
CONF_MODEL = "model"
|
CONF_MODEL = "model"
|
||||||
|
@@ -233,13 +233,17 @@ class ContextualLogger:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize a new ContextualLogger."""
|
"""Initialize a new ContextualLogger."""
|
||||||
self._logger = None
|
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."""
|
"""Set base logger to use."""
|
||||||
|
self._enable_debug = enable_debug
|
||||||
self._logger = TuyaLoggingAdapter(logger, {"device_id": device_id})
|
self._logger = TuyaLoggingAdapter(logger, {"device_id": device_id})
|
||||||
|
|
||||||
def debug(self, msg, *args):
|
def debug(self, msg, *args):
|
||||||
"""Debug level log."""
|
"""Debug level log."""
|
||||||
|
if not self._enable_debug:
|
||||||
|
return
|
||||||
return self._logger.log(logging.DEBUG, msg, *args)
|
return self._logger.log(logging.DEBUG, msg, *args)
|
||||||
|
|
||||||
def info(self, msg, *args):
|
def info(self, msg, *args):
|
||||||
@@ -415,7 +419,7 @@ class MessageDispatcher(ContextualLogger):
|
|||||||
RESET_SEQNO = -101
|
RESET_SEQNO = -101
|
||||||
SESS_KEY_SEQNO = -102
|
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."""
|
"""Initialize a new MessageBuffer."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.buffer = b""
|
self.buffer = b""
|
||||||
@@ -423,7 +427,7 @@ class MessageDispatcher(ContextualLogger):
|
|||||||
self.listener = listener
|
self.listener = listener
|
||||||
self.version = protocol_version
|
self.version = protocol_version
|
||||||
self.local_key = local_key
|
self.local_key = local_key
|
||||||
self.set_logger(_LOGGER, dev_id)
|
self.set_logger(_LOGGER, dev_id, enable_debug)
|
||||||
|
|
||||||
def abort(self):
|
def abort(self):
|
||||||
"""Abort all waiting clients."""
|
"""Abort all waiting clients."""
|
||||||
@@ -540,7 +544,9 @@ class EmptyListener(TuyaListener):
|
|||||||
class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
||||||
"""Implementation of the Tuya protocol."""
|
"""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.
|
Initialize a new TuyaInterface.
|
||||||
|
|
||||||
@@ -554,7 +560,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
|||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.loop = asyncio.get_running_loop()
|
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.id = dev_id
|
||||||
self.local_key = local_key.encode("latin1")
|
self.local_key = local_key.encode("latin1")
|
||||||
self.real_local_key = self.local_key
|
self.real_local_key = self.local_key
|
||||||
@@ -572,7 +578,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
|||||||
self.seqno = 1
|
self.seqno = 1
|
||||||
self.transport = None
|
self.transport = None
|
||||||
self.listener = weakref.ref(listener)
|
self.listener = weakref.ref(listener)
|
||||||
self.dispatcher = self._setup_dispatcher()
|
self.dispatcher = self._setup_dispatcher(enable_debug)
|
||||||
self.on_connected = on_connected
|
self.on_connected = on_connected
|
||||||
self.heartbeater = None
|
self.heartbeater = None
|
||||||
self.dps_cache = {}
|
self.dps_cache = {}
|
||||||
@@ -603,7 +609,7 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
|||||||
|
|
||||||
return json.loads('{ "Error":"%s", "Err":"%s", "Payload":%s }' % vals)
|
return json.loads('{ "Error":"%s", "Err":"%s", "Payload":%s }' % vals)
|
||||||
|
|
||||||
def _setup_dispatcher(self):
|
def _setup_dispatcher(self, enable_debug):
|
||||||
def _status_update(msg):
|
def _status_update(msg):
|
||||||
if msg.seqno > 0:
|
if msg.seqno > 0:
|
||||||
self.seqno = msg.seqno + 1
|
self.seqno = msg.seqno + 1
|
||||||
@@ -615,7 +621,9 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
|||||||
if listener is not None:
|
if listener is not None:
|
||||||
listener.status_updated(self.dps_cache)
|
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):
|
def connection_made(self, transport):
|
||||||
"""Did connect to the device."""
|
"""Did connect to the device."""
|
||||||
@@ -988,7 +996,6 @@ class TuyaProtocol(asyncio.Protocol, ContextualLogger):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# self.debug("session local nonce: %r remote nonce: %r", self.local_nonce, self.remote_nonce)
|
# self.debug("session local nonce: %r remote nonce: %r", self.local_nonce, self.remote_nonce)
|
||||||
|
|
||||||
rkey_hmac = hmac.new(self.local_key, self.remote_nonce, sha256).digest()
|
rkey_hmac = hmac.new(self.local_key, self.remote_nonce, sha256).digest()
|
||||||
await self.exchange_quick(MessagePayload(SESS_KEY_NEG_FINISH, rkey_hmac), None)
|
await self.exchange_quick(MessagePayload(SESS_KEY_NEG_FINISH, rkey_hmac), None)
|
||||||
|
|
||||||
@@ -1145,6 +1152,7 @@ async def connect(
|
|||||||
device_id,
|
device_id,
|
||||||
local_key,
|
local_key,
|
||||||
protocol_version,
|
protocol_version,
|
||||||
|
enable_debug,
|
||||||
listener=None,
|
listener=None,
|
||||||
port=6668,
|
port=6668,
|
||||||
timeout=5,
|
timeout=5,
|
||||||
@@ -1157,6 +1165,7 @@ async def connect(
|
|||||||
device_id,
|
device_id,
|
||||||
local_key,
|
local_key,
|
||||||
protocol_version,
|
protocol_version,
|
||||||
|
enable_debug,
|
||||||
on_connected,
|
on_connected,
|
||||||
listener or EmptyListener(),
|
listener or EmptyListener(),
|
||||||
),
|
),
|
||||||
|
@@ -96,6 +96,7 @@
|
|||||||
"device_id": "Device ID",
|
"device_id": "Device ID",
|
||||||
"local_key": "Local key",
|
"local_key": "Local key",
|
||||||
"protocol_version": "Protocol Version",
|
"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)",
|
"scan_interval": "Scan interval (seconds, only when not updating automatically)",
|
||||||
"entities": "Entities (uncheck an entity to remove it)",
|
"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)",
|
"manual_dps_strings": "Manual DPS to add (separated by commas ',') - used when detection is not working (optional)",
|
||||||
|
@@ -96,6 +96,7 @@
|
|||||||
"device_id": "ID del dispositivo",
|
"device_id": "ID del dispositivo",
|
||||||
"local_key": "Chiave locale",
|
"local_key": "Chiave locale",
|
||||||
"protocol_version": "Versione del protocollo",
|
"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)",
|
"scan_interval": "Intervallo di scansione (secondi, solo quando non si aggiorna automaticamente)",
|
||||||
"entities": "Entities (deseleziona un'entity per rimuoverla)"
|
"entities": "Entities (deseleziona un'entity per rimuoverla)"
|
||||||
}
|
}
|
||||||
|
@@ -96,6 +96,7 @@
|
|||||||
"device_id": "ID do dispositivo",
|
"device_id": "ID do dispositivo",
|
||||||
"local_key": "Local key",
|
"local_key": "Local key",
|
||||||
"protocol_version": "Versão do protocolo",
|
"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)",
|
"scan_interval": "Intervalo de escaneamento (segundos, somente quando não estiver atualizando automaticamente)",
|
||||||
"entities": "Entidades (desmarque uma entidade para removê-la)"
|
"entities": "Entidades (desmarque uma entidade para removê-la)"
|
||||||
}
|
}
|
||||||
|
3
info.md
3
info.md
@@ -164,8 +164,11 @@ logger:
|
|||||||
default: warning
|
default: warning
|
||||||
logs:
|
logs:
|
||||||
custom_components.localtuya: debug
|
custom_components.localtuya: debug
|
||||||
|
custom_components.localtuya.pytuya: debug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Then, edit the device that is showing problems and check the "Enable debugging for this device" button.
|
||||||
|
|
||||||
# Notes:
|
# Notes:
|
||||||
|
|
||||||
* Do not declare anything as "tuya", such as by initiating a "switch.tuya". Using "tuya" launches Home Assistant's built-in, cloud-based Tuya integration in lieu of localtuya.
|
* Do not declare anything as "tuya", such as by initiating a "switch.tuya". Using "tuya" launches Home Assistant's built-in, cloud-based Tuya integration in lieu of localtuya.
|
||||||
|
Reference in New Issue
Block a user