Skip to content

Commit

Permalink
Add debug mode to config flow
Browse files Browse the repository at this point in the history
  • Loading branch information
postlund committed Oct 13, 2020
1 parent 084b3a7 commit 38f4b6e
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 4 deletions.
89 changes: 88 additions & 1 deletion custom_components/localtuya/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,37 @@

DISCOVER_TIMEOUT = 6.0

ACTION_SET_DPS = "set_dp"
ACTION_RELOAD_DPS = "reload_dps"
ACTION_EXIT_DEBUG = "exit_debug"

CONF_ACTION = "action"
CONF_DATAPOINT = "datapoint"
CONF_DATA_TYPE = "data_type"
CONF_VALUE = "value"
CONF_DEBUG = "debug"

PLATFORM_TO_ADD = "platform_to_add"
NO_ADDITIONAL_PLATFORMS = "no_additional_platforms"
DISCOVERED_DEVICE = "discovered_device"

CUSTOM_DEVICE = "..."

DEBUG_TYPES_CONVERSIONS = {
"int": int,
"str": str,
"bool": lambda x: x.lower() == "true",
"float": float,
}

BASIC_INFO_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.3"]),
vol.Optional(CONF_DEBUG, default=False): bool,
}
)

Expand Down Expand Up @@ -70,6 +88,20 @@
)


def debug_schema(dps):
"""Create schema for debug mode."""
return vol.Schema(
{
vol.Required(CONF_ACTION, default=ACTION_SET_DPS): vol.In(
[ACTION_SET_DPS, ACTION_RELOAD_DPS, ACTION_EXIT_DEBUG]
),
vol.Optional(CONF_DATAPOINT): vol.In(dps),
vol.Optional(CONF_DATA_TYPE): vol.In(["int", "float", "str", "bool"]),
vol.Optional(CONF_VALUE): str,
}
)


def user_schema(devices):
"""Create schema for user step."""
devices = [f"{ip} ({dev['gwId']})" for ip, dev in devices.items()]
Expand Down Expand Up @@ -157,8 +189,27 @@ def config_schema():
)


async def _tuya_command(hass: core.HomeAssistant, data, func, *args):
"""Execute a Tuya command.."""
tuyainterface = pytuya.TuyaInterface(
data[CONF_DEVICE_ID],
data[CONF_HOST],
data[CONF_LOCAL_KEY],
float(data[CONF_PROTOCOL_VERSION]),
)
try:
return await hass.async_add_executor_job(getattr(tuyainterface, func), *args)
except (ConnectionRefusedError, ConnectionResetError):
raise CannotConnect
except ValueError:
raise InvalidAuth


async def validate_input(hass: core.HomeAssistant, data):
"""Validate the user input allows us to connect."""
detected_dps = await _tuya_command(hass, data, "detect_available_dps")
return dps_string_list(detected_dps)

tuyainterface = pytuya.TuyaInterface(
data[CONF_DEVICE_ID],
data[CONF_HOST],
Expand Down Expand Up @@ -230,9 +281,11 @@ async def async_step_basic_info(self, user_input=None):
await self.async_set_unique_id(user_input[CONF_DEVICE_ID])
self._abort_if_unique_id_configured()

self.basic_info = user_input
try:
self.basic_info = user_input
self.dps_strings = await validate_input(self.hass, user_input)
if user_input.get(CONF_DEBUG):
return await self.async_step_debug()
return await self.async_step_pick_entity_type()
except CannotConnect:
errors["base"] = "cannot_connect"
Expand Down Expand Up @@ -311,6 +364,40 @@ async def async_step_import(self, user_input):
title=f"{user_input[CONF_FRIENDLY_NAME]} (YAML)", data=user_input
)

async def async_step_debug(self, user_input=None):
"""Handle debug mode."""
errors = {}
if user_input is not None:
action = user_input[CONF_ACTION]
if action == ACTION_SET_DPS:
try:
type_convert = DEBUG_TYPES_CONVERSIONS[user_input[CONF_DATA_TYPE]]
value = type_convert(user_input[CONF_VALUE])
dp = user_input[CONF_DATAPOINT].split(" ")[0]
await _tuya_command(
self.hass, self.basic_info, "set_dps", value, dp
)
except Exception: # pylint: disable=broad-except
_LOGGER.exception(f"failed to set datapoint {dp}={value}")
errors["base"] = "set_dp_failed"

elif action == ACTION_EXIT_DEBUG:
return self.async_abort(reason="exit_debug")

# Always try to refresh datapoints after doing something
try:
self.dps_strings = await validate_input(self.hass, self.basic_info)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("failed to fetch datapoints")
errors["base"] = "fetch_dps_failed"

return self.async_show_form(
step_id="debug",
data_schema=debug_schema(self.dps_strings),
errors=errors,
description_placeholders={"dps": ", ".join(self.dps_strings)},
)


class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle options flow for LocalTuya integration."""
Expand Down
20 changes: 17 additions & 3 deletions custom_components/localtuya/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
{
"config": {
"abort": {
"already_configured": "Device has already been configured."
"already_configured": "Device has already been configured.",
"exit_debug": "Leaving debug mode."
},
"error": {
"cannot_connect": "Cannot connect to device. Verify that address is correct and try again.",
"invalid_auth": "Failed to authenticate with device. Verify that device id and local key are correct.",
"unknown": "An unknown error occurred. See log for details.",
"entity_already_configured": "Entity with this ID has already been configured.",
"discovery_failed": "Failed to discover devices. You can still add a device manually."
"discovery_failed": "Failed to discover devices. You can still add a device manually.",
"fetch_dps_failed": "Failed to fetch datapoints. See log for details.",
"set_dp_failed": "Failed to set datapoint. See log for details."
},
"step": {
"user": {
Expand All @@ -26,7 +29,8 @@
"host": "Host",
"device_id": "Device ID",
"local_key": "Local key",
"protocol_version": "Protocol Version"
"protocol_version": "Protocol Version",
"debug": "Enable debug mode"
}
},
"pick_entity_type": {
Expand Down Expand Up @@ -59,6 +63,16 @@
"brightness": "Brightness",
"color_temp": "Color Temperature"
}
},
"debug": {
"title": "Debug",
"description": "You can manually alter the value of a datapoint here. Current values for all datapoints:\n\n{dps}",
"data": {
"action": "Action",
"datapoint": "Datapoint",
"data_type": "Data Type",
"value": "Value"
}
}
}
},
Expand Down

0 comments on commit 38f4b6e

Please sign in to comment.