Introduced checkbox to choose whether to setup Cloud API account
This commit is contained in:
@@ -29,9 +29,10 @@ from homeassistant.helpers.event import async_track_time_interval
|
|||||||
|
|
||||||
from .cloud_api import TuyaCloudApi
|
from .cloud_api import TuyaCloudApi
|
||||||
from .common import TuyaDevice, async_config_entry_by_device_id
|
from .common import TuyaDevice, async_config_entry_by_device_id
|
||||||
from .config_flow import config_schema
|
from .config_flow import config_schema, ENTRIES_VERSION
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_UPDATED_AT,
|
ATTR_UPDATED_AT,
|
||||||
|
CONF_NO_CLOUD,
|
||||||
CONF_PRODUCT_KEY,
|
CONF_PRODUCT_KEY,
|
||||||
CONF_USER_ID,
|
CONF_USER_ID,
|
||||||
DATA_CLOUD,
|
DATA_CLOUD,
|
||||||
@@ -183,10 +184,10 @@ async def async_setup(hass: HomeAssistant, config: dict):
|
|||||||
|
|
||||||
async def async_migrate_entry(hass, config_entry: ConfigEntry):
|
async def async_migrate_entry(hass, config_entry: ConfigEntry):
|
||||||
"""Migrate old entries merging all of them in one."""
|
"""Migrate old entries merging all of them in one."""
|
||||||
new_version = 2
|
new_version = ENTRIES_VERSION
|
||||||
|
stored_entries = hass.config_entries.async_entries(DOMAIN)
|
||||||
if config_entry.version == 1:
|
if config_entry.version == 1:
|
||||||
_LOGGER.debug("Migrating config entry from version %s", config_entry.version)
|
_LOGGER.debug("Migrating config entry from version %s", config_entry.version)
|
||||||
stored_entries = hass.config_entries.async_entries(DOMAIN)
|
|
||||||
|
|
||||||
if config_entry.entry_id == stored_entries[0].entry_id:
|
if config_entry.entry_id == stored_entries[0].entry_id:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
@@ -198,6 +199,7 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
|
|||||||
new_data[CONF_CLIENT_SECRET] = ""
|
new_data[CONF_CLIENT_SECRET] = ""
|
||||||
new_data[CONF_USER_ID] = ""
|
new_data[CONF_USER_ID] = ""
|
||||||
new_data[CONF_USERNAME] = DOMAIN
|
new_data[CONF_USERNAME] = DOMAIN
|
||||||
|
new_data[CONF_NO_CLOUD] = True
|
||||||
new_data[CONF_DEVICES] = {
|
new_data[CONF_DEVICES] = {
|
||||||
config_entry.data[CONF_DEVICE_ID]: config_entry.data.copy()
|
config_entry.data[CONF_DEVICE_ID]: config_entry.data.copy()
|
||||||
}
|
}
|
||||||
@@ -223,24 +225,41 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
|
|||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
new_version,
|
new_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
"""Set up LocalTuya integration from a config entry."""
|
"""Set up LocalTuya integration from a config entry."""
|
||||||
unsub_listener = entry.add_update_listener(update_listener)
|
if entry.version < ENTRIES_VERSION:
|
||||||
hass.data[DOMAIN][UNSUB_LISTENER] = unsub_listener
|
_LOGGER.debug(
|
||||||
|
"Skipping setup for entry %s since its version (%s) is old",
|
||||||
|
entry.entry_id,
|
||||||
|
entry.version,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
_LOGGER.debug("ASE: %s %s", entry.entry_id, entry.data)
|
||||||
|
|
||||||
region = entry.data[CONF_REGION]
|
region = entry.data[CONF_REGION]
|
||||||
client_id = entry.data[CONF_CLIENT_ID]
|
client_id = entry.data[CONF_CLIENT_ID]
|
||||||
secret = entry.data[CONF_CLIENT_SECRET]
|
secret = entry.data[CONF_CLIENT_SECRET]
|
||||||
user_id = entry.data[CONF_USER_ID]
|
user_id = entry.data[CONF_USER_ID]
|
||||||
tuya_api = TuyaCloudApi(hass, region, client_id, secret, user_id)
|
tuya_api = TuyaCloudApi(hass, region, client_id, secret, user_id)
|
||||||
res = await tuya_api.async_get_access_token()
|
no_cloud = True
|
||||||
if res != "ok":
|
if CONF_NO_CLOUD in entry.data:
|
||||||
_LOGGER.error("Cloud API connection failed: %s", res)
|
no_cloud = entry.data.get(CONF_NO_CLOUD)
|
||||||
_LOGGER.info("Cloud API connection succeeded.")
|
_LOGGER.debug("ASE DC: %s", no_cloud)
|
||||||
res = await tuya_api.async_get_devices_list()
|
if no_cloud:
|
||||||
|
_LOGGER.info("Cloud API account not configured.")
|
||||||
|
# wait 1 second to make sure possible migration has finished
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
else:
|
||||||
|
res = await tuya_api.async_get_access_token()
|
||||||
|
if res != "ok":
|
||||||
|
_LOGGER.error("Cloud API connection failed: %s", res)
|
||||||
|
_LOGGER.info("Cloud API connection succeeded.")
|
||||||
|
res = await tuya_api.async_get_devices_list()
|
||||||
hass.data[DOMAIN][DATA_CLOUD] = tuya_api
|
hass.data[DOMAIN][DATA_CLOUD] = tuya_api
|
||||||
|
|
||||||
async def setup_entities(dev_id):
|
async def setup_entities(dev_id):
|
||||||
@@ -262,6 +281,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
for dev_id in entry.data[CONF_DEVICES]:
|
for dev_id in entry.data[CONF_DEVICES]:
|
||||||
hass.async_create_task(setup_entities(dev_id))
|
hass.async_create_task(setup_entities(dev_id))
|
||||||
|
|
||||||
|
unsub_listener = entry.add_update_listener(update_listener)
|
||||||
|
hass.data[DOMAIN][entry.entry_id] = {UNSUB_LISTENER: unsub_listener}
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -269,7 +291,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
platforms = {}
|
platforms = {}
|
||||||
|
|
||||||
hass.data[DOMAIN][UNSUB_LISTENER]()
|
hass.data[DOMAIN][entry.entry_id][UNSUB_LISTENER]()
|
||||||
for dev_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
|
for dev_id, device in hass.data[DOMAIN][TUYA_DEVICES].items():
|
||||||
if device.connected:
|
if device.connected:
|
||||||
await device.close()
|
await device.close()
|
||||||
|
@@ -38,6 +38,7 @@ from .const import (
|
|||||||
CONF_PRODUCT_NAME,
|
CONF_PRODUCT_NAME,
|
||||||
CONF_PROTOCOL_VERSION,
|
CONF_PROTOCOL_VERSION,
|
||||||
CONF_SETUP_CLOUD,
|
CONF_SETUP_CLOUD,
|
||||||
|
CONF_NO_CLOUD,
|
||||||
CONF_USER_ID,
|
CONF_USER_ID,
|
||||||
DATA_CLOUD,
|
DATA_CLOUD,
|
||||||
DATA_DISCOVERY,
|
DATA_DISCOVERY,
|
||||||
@@ -48,6 +49,8 @@ from .discovery import discover
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ENTRIES_VERSION = 2
|
||||||
|
|
||||||
PLATFORM_TO_ADD = "platform_to_add"
|
PLATFORM_TO_ADD = "platform_to_add"
|
||||||
NO_ADDITIONAL_ENTITIES = "no_additional_entities"
|
NO_ADDITIONAL_ENTITIES = "no_additional_entities"
|
||||||
SELECTED_DEVICE = "selected_device"
|
SELECTED_DEVICE = "selected_device"
|
||||||
@@ -69,10 +72,11 @@ CONFIGURE_SCHEMA = vol.Schema(
|
|||||||
CLOUD_SETUP_SCHEMA = vol.Schema(
|
CLOUD_SETUP_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_REGION, default="eu"): vol.In(["eu", "us", "cn", "in"]),
|
vol.Required(CONF_REGION, default="eu"): vol.In(["eu", "us", "cn", "in"]),
|
||||||
vol.Required(CONF_CLIENT_ID): cv.string,
|
vol.Optional(CONF_CLIENT_ID): cv.string,
|
||||||
vol.Required(CONF_CLIENT_SECRET): cv.string,
|
vol.Optional(CONF_CLIENT_SECRET): cv.string,
|
||||||
vol.Required(CONF_USER_ID): cv.string,
|
vol.Optional(CONF_USER_ID): cv.string,
|
||||||
vol.Optional(CONF_USERNAME, default=DOMAIN): cv.string,
|
vol.Optional(CONF_USERNAME, default=DOMAIN): cv.string,
|
||||||
|
vol.Required(CONF_NO_CLOUD, default=False): bool,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -279,7 +283,7 @@ async def attempt_cloud_connection(hass, user_input):
|
|||||||
class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
"""Handle a config flow for LocalTuya integration."""
|
"""Handle a config flow for LocalTuya integration."""
|
||||||
|
|
||||||
VERSION = 2
|
VERSION = ENTRIES_VERSION
|
||||||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -296,9 +300,14 @@ class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
errors = {}
|
errors = {}
|
||||||
placeholders = {}
|
placeholders = {}
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
|
if user_input.get(CONF_NO_CLOUD):
|
||||||
|
for i in [CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_USER_ID]:
|
||||||
|
user_input[i] = ""
|
||||||
|
return await self._create_entry(user_input)
|
||||||
|
|
||||||
cloud_api, res = await attempt_cloud_connection(self.hass, user_input)
|
cloud_api, res = await attempt_cloud_connection(self.hass, user_input)
|
||||||
|
|
||||||
if len(res) == 0:
|
if not res:
|
||||||
return await self._create_entry(user_input)
|
return await self._create_entry(user_input)
|
||||||
errors["base"] = res["reason"]
|
errors["base"] = res["reason"]
|
||||||
placeholders = {"msg": res["msg"]}
|
placeholders = {"msg": res["msg"]}
|
||||||
@@ -315,8 +324,8 @@ class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def _create_entry(self, user_input):
|
async def _create_entry(self, user_input):
|
||||||
"""Register new entry."""
|
"""Register new entry."""
|
||||||
if self._async_current_entries():
|
# if self._async_current_entries():
|
||||||
return self.async_abort(reason="already_configured")
|
# return self.async_abort(reason="already_configured")
|
||||||
|
|
||||||
await self.async_set_unique_id(user_input.get(CONF_USER_ID))
|
await self.async_set_unique_id(user_input.get(CONF_USER_ID))
|
||||||
user_input[CONF_DEVICES] = {}
|
user_input[CONF_DEVICES] = {}
|
||||||
@@ -370,9 +379,22 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
errors = {}
|
errors = {}
|
||||||
placeholders = {}
|
placeholders = {}
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
|
if user_input.get(CONF_NO_CLOUD):
|
||||||
|
new_data = self.config_entry.data.copy()
|
||||||
|
new_data.update(user_input)
|
||||||
|
for i in [CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_USER_ID]:
|
||||||
|
new_data[i] = ""
|
||||||
|
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={}
|
||||||
|
)
|
||||||
|
|
||||||
cloud_api, res = await attempt_cloud_connection(self.hass, user_input)
|
cloud_api, res = await attempt_cloud_connection(self.hass, user_input)
|
||||||
|
|
||||||
if len(res) == 0:
|
if not res:
|
||||||
new_data = self.config_entry.data.copy()
|
new_data = self.config_entry.data.copy()
|
||||||
new_data.update(user_input)
|
new_data.update(user_input)
|
||||||
cloud_devs = cloud_api.device_list
|
cloud_devs = cloud_api.device_list
|
||||||
@@ -394,6 +416,7 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
|
|
||||||
defaults = self.config_entry.data.copy()
|
defaults = self.config_entry.data.copy()
|
||||||
defaults.update(user_input or {})
|
defaults.update(user_input or {})
|
||||||
|
defaults[CONF_NO_CLOUD] = False
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="cloud_setup",
|
step_id="cloud_setup",
|
||||||
@@ -490,12 +513,11 @@ class LocalTuyaOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
self.device_data.update(
|
self.device_data.update(
|
||||||
{
|
{
|
||||||
CONF_DEVICE_ID: dev_id,
|
CONF_DEVICE_ID: dev_id,
|
||||||
CONF_MODEL: self.device_data[CONF_MODEL],
|
|
||||||
CONF_DPS_STRINGS: self.dps_strings,
|
CONF_DPS_STRINGS: self.dps_strings,
|
||||||
CONF_ENTITIES: [],
|
CONF_ENTITIES: [],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if len(user_input[CONF_ENTITIES]) > 0:
|
if user_input[CONF_ENTITIES]:
|
||||||
entity_ids = [
|
entity_ids = [
|
||||||
int(entity.split(":")[0])
|
int(entity.split(":")[0])
|
||||||
for entity in user_input[CONF_ENTITIES]
|
for entity in user_input[CONF_ENTITIES]
|
||||||
|
Reference in New Issue
Block a user