Second part of one_device_only big merge

This commit is contained in:
rospogrigio
2020-09-22 11:31:04 +02:00
committed by rospogrigio
parent 0048ce6d5e
commit 3259a4f654
10 changed files with 76 additions and 181 deletions

View File

@@ -9,8 +9,9 @@ from homeassistant.const import (
CONF_ENTITIES,
)
from .const import DOMAIN
from .const import DOMAIN, TUYA_DEVICE
from .config_flow import config_schema
from .common import TuyaDevice
_LOGGER = logging.getLogger(__name__)
@@ -19,23 +20,17 @@ UNSUB_LISTENER = "unsub_listener"
CONFIG_SCHEMA = config_schema()
def import_from_yaml(hass, config, platform):
"""Import configuration from YAML."""
config[CONF_PLATFORM] = platform
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=config
)
)
return True
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the LocalTuya integration component."""
hass.data.setdefault(DOMAIN, {})
print("setup:", config.get(DOMAIN))
for host_config in config.get(DOMAIN, []):
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_IMPORT}, data=host_config
)
)
return True
@@ -45,12 +40,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
hass.data[DOMAIN][entry.entry_id] = {
UNSUB_LISTENER: unsub_listener,
TUYA_DEVICE: TuyaDevice(entry.data),
}
for platform in set(entity[CONF_PLATFORM] for entity in entry.data[CONF_ENTITIES]):
for entity in entry.data[CONF_ENTITIES]:
platform = entity[CONF_PLATFORM]
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, platform)
)
return True

View File

@@ -16,8 +16,6 @@ sensor:
device_class: current
"""
import logging
from time import time, sleep
from threading import Lock
import voluptuous as vol
@@ -26,11 +24,7 @@ from homeassistant.components.binary_sensor import (
DEVICE_CLASSES_SCHEMA,
BinarySensorEntity,
)
from homeassistant.const import (
CONF_ID,
CONF_DEVICE_CLASS,
CONF_FRIENDLY_NAME,
)
from homeassistant.const import CONF_ID, CONF_DEVICE_CLASS
from .common import LocalTuyaEntity, prepare_setup_entities
@@ -51,7 +45,9 @@ def flow_schema(dps):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Tuya sensor based on a config entry."""
device, entities_to_setup = prepare_setup_entities(config_entry, DOMAIN)
tuyainterface, entities_to_setup = prepare_setup_entities(
hass, config_entry, DOMAIN
)
if not entities_to_setup:
return
@@ -59,7 +55,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for device_config in entities_to_setup:
sensors.append(
LocaltuyaBinarySensor(
TuyaCache(device, config_entry.data[CONF_FRIENDLY_NAME]),
tuyainterface,
config_entry,
device_config[CONF_ID],
)
@@ -68,74 +64,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(sensors, True)
class TuyaCache:
"""Cache wrapper for pytuya.TuyaDevice."""
def __init__(self, device, friendly_name):
"""Initialize the cache."""
self._cached_status = ""
self._cached_status_time = 0
self._device = device
self._friendly_name = friendly_name
self._lock = Lock()
@property
def unique_id(self):
"""Return unique device identifier."""
return self._device.id
def __get_status(self):
for i in range(5):
try:
status = self._device.status()
return status
except Exception:
print(
"Failed to update status of device [{}]".format(
self._device.address
)
)
sleep(1.0)
if i + 1 == 3:
_LOGGER.error(
"Failed to update status of device %s", self._device.address
)
# return None
raise ConnectionError("Failed to update status .")
def set_dps(self, state, dps_index):
"""Change the Tuya sensor status and clear the cache."""
self._cached_status = ""
self._cached_status_time = 0
for i in range(5):
try:
return self._device.set_dps(state, dps_index)
except Exception:
print(
"Failed to set status of device [{}]".format(self._device.address)
)
if i + 1 == 3:
_LOGGER.error(
"Failed to set status of device %s", self._device.address
)
return
# raise ConnectionError("Failed to set status.")
def status(self):
"""Get state of Tuya sensor and cache the results."""
self._lock.acquire()
try:
now = time()
if not self._cached_status or now - self._cached_status_time > 15:
sleep(0.5)
self._cached_status = self.__get_status()
self._cached_status_time = time()
return self._cached_status
finally:
self._lock.release()
class LocaltuyaBinarySensor(LocalTuyaEntity, BinarySensorEntity):
"""Representation of a Tuya binary sensor."""

View File

@@ -15,12 +15,12 @@ from homeassistant.const import (
)
from . import pytuya
from .const import CONF_LOCAL_KEY, CONF_PROTOCOL_VERSION, DOMAIN
from .const import CONF_LOCAL_KEY, CONF_PROTOCOL_VERSION, DOMAIN, TUYA_DEVICE
_LOGGER = logging.getLogger(__name__)
def prepare_setup_entities(config_entry, platform):
def prepare_setup_entities(hass, config_entry, platform):
"""Prepare ro setup entities for a platform."""
entities_to_setup = [
entity
@@ -30,16 +30,7 @@ def prepare_setup_entities(config_entry, platform):
if not entities_to_setup:
return None, None
tuyainterface = pytuya.TuyaInterface(
config_entry.data[CONF_DEVICE_ID],
config_entry.data[CONF_HOST],
config_entry.data[CONF_LOCAL_KEY],
float(config_entry.data[CONF_PROTOCOL_VERSION]),
)
for entity_config in entities_to_setup:
# this has to be done in case the device type is type_0d
tuyainterface.add_dps_to_request(entity_config[CONF_ID])
tuyainterface = hass.data[DOMAIN][config_entry.entry_id][TUYA_DEVICE]
return tuyainterface, entities_to_setup
@@ -55,12 +46,20 @@ def get_entity_config(config_entry, dps_id):
class TuyaDevice:
"""Cache wrapper for pytuya.TuyaInterface."""
def __init__(self, interface, friendly_name):
def __init__(self, config_entry):
"""Initialize the cache."""
self._cached_status = ""
self._cached_status_time = 0
self._interface = interface
self._friendly_name = friendly_name
self._interface = pytuya.TuyaInterface(
config_entry[CONF_DEVICE_ID],
config_entry[CONF_HOST],
config_entry[CONF_LOCAL_KEY],
config_entry[CONF_PROTOCOL_VERSION],
)
for entity in config_entry[CONF_ENTITIES]:
# this has to be done in case the device type is type_0d
self._interface.add_dps_to_request(entity[CONF_ID])
self._friendly_name = config_entry[CONF_FRIENDLY_NAME]
self._lock = Lock()
@property
@@ -90,7 +89,7 @@ class TuyaDevice:
def set_dps(self, state, dps_index):
# _LOGGER.info("running def set_dps from cover")
"""Change the Tuya device status and clear the cache."""
"""Change the Tuya switch status and clear the cache."""
self._cached_status = ""
self._cached_status_time = 0
for i in range(5):
@@ -111,7 +110,7 @@ class TuyaDevice:
# raise ConnectionError("Failed to set status.")
def status(self):
"""Get state of Tuya device and cache the results."""
"""Get state of Tuya switch and cache the results."""
_LOGGER.debug("running def status(self) from TuyaDevice")
self._lock.acquire()
try:

View File

@@ -13,7 +13,6 @@ from homeassistant.const import (
CONF_DEVICE_ID,
CONF_FRIENDLY_NAME,
CONF_PLATFORM,
CONF_SWITCHES,
)
import homeassistant.helpers.config_validation as cv
@@ -97,7 +96,6 @@ def schema_defaults(schema, dps_list=None, **defaults):
if field.schema in defaults:
field.default = vol.default_factory(defaults[field])
return copy
@@ -310,37 +308,21 @@ class LocaltuyaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle import from YAML."""
def _convert_entity(conf):
converted = {
CONF_ID: conf[CONF_ID],
CONF_FRIENDLY_NAME: conf[CONF_FRIENDLY_NAME],
CONF_PLATFORM: self.platform,
}
for field in flow_schema(self.platform, self.dps_strings).keys():
converted[str(field)] = conf[field]
return converted
for field in flow_schema(conf[CONF_PLATFORM], self.dps_strings).keys():
if str(field) in conf:
conf[str(field)] = str(conf[field])
await self.async_set_unique_id(user_input[CONF_DEVICE_ID])
self.platform = user_input[CONF_PLATFORM]
if len(user_input.get(CONF_SWITCHES, [])) > 0:
for switch_conf in user_input[CONF_SWITCHES].values():
self.entities.append(_convert_entity(switch_conf))
else:
self.entities.append(_convert_entity(user_input))
for entity_conf in user_input[CONF_ENTITIES]:
entity_conf[CONF_ID] = str(entity_conf[CONF_ID])
_convert_entity(entity_conf)
# print('ENTITIES: [{}] '.format(self.entities))
config = {
CONF_FRIENDLY_NAME: f"{user_input[CONF_FRIENDLY_NAME]}",
CONF_HOST: user_input[CONF_HOST],
CONF_DEVICE_ID: user_input[CONF_DEVICE_ID],
CONF_LOCAL_KEY: user_input[CONF_LOCAL_KEY],
CONF_PROTOCOL_VERSION: user_input[CONF_PROTOCOL_VERSION],
CONF_YAML_IMPORT: True,
CONF_ENTITIES: self.entities,
}
self._abort_if_unique_id_configured(updates=config)
user_input[CONF_YAML_IMPORT] = True
self._abort_if_unique_id_configured(updates=user_input)
return self.async_create_entry(
title=f"{config[CONF_FRIENDLY_NAME]} (YAML)", data=config
title=f"{user_input[CONF_FRIENDLY_NAME]} (YAML)", data=user_input
)

View File

@@ -26,3 +26,5 @@ DOMAIN = "localtuya"
# Platforms in this list must support config flows
PLATFORMS = ["binary_sensor", "cover", "fan", "light", "sensor", "switch"]
TUYA_DEVICE = "tuya_device"

View File

@@ -31,17 +31,14 @@ from homeassistant.components.cover import (
SUPPORT_STOP,
SUPPORT_SET_POSITION,
)
from homeassistant.const import (
CONF_ID,
CONF_FRIENDLY_NAME,
)
from homeassistant.const import CONF_ID
from .const import (
CONF_OPEN_CMD,
CONF_CLOSE_CMD,
CONF_STOP_CMD,
)
from .common import LocalTuyaEntity, TuyaDevice, prepare_setup_entities
from .common import LocalTuyaEntity, prepare_setup_entities
_LOGGER = logging.getLogger(__name__)
@@ -61,7 +58,9 @@ def flow_schema(dps):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Tuya cover based on a config entry."""
tuyainterface, entities_to_setup = prepare_setup_entities(config_entry, DOMAIN)
tuyainterface, entities_to_setup = prepare_setup_entities(
hass, config_entry, DOMAIN
)
if not entities_to_setup:
return
@@ -69,7 +68,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for device_config in entities_to_setup:
covers.append(
LocaltuyaCover(
TuyaDevice(tuyainterface, config_entry.data[CONF_FRIENDLY_NAME]),
tuyainterface,
config_entry,
device_config[CONF_ID],
)
@@ -185,7 +184,7 @@ class LocaltuyaCover(LocalTuyaEntity, CoverEntity):
def stop_cover(self, **kwargs):
"""Stop the cover."""
_LOGGER.debug("Laudebugching command %s to cover ", self._config[CONF_STOP_CMD])
_LOGGER.debug("Launching command %s to cover ", self._config[CONF_STOP_CMD])
self._device.set_dps(self._config[CONF_STOP_CMD], self._dps_id)
def status_updated(self):

View File

@@ -26,9 +26,9 @@ from homeassistant.components.fan import (
SUPPORT_SET_SPEED,
SUPPORT_OSCILLATE,
)
from homeassistant.const import CONF_ID, CONF_FRIENDLY_NAME
from homeassistant.const import CONF_ID
from .common import LocalTuyaEntity, TuyaDevice, prepare_setup_entities
from .common import LocalTuyaEntity, prepare_setup_entities
_LOGGER = logging.getLogger(__name__)
@@ -40,7 +40,9 @@ def flow_schema(dps):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Tuya fan based on a config entry."""
tuyainterface, entities_to_setup = prepare_setup_entities(config_entry, DOMAIN)
tuyainterface, entities_to_setup = prepare_setup_entities(
hass, config_entry, DOMAIN
)
if not entities_to_setup:
return
@@ -49,7 +51,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for device_config in entities_to_setup:
fans.append(
LocaltuyaFan(
TuyaDevice(tuyainterface, config_entry.data[CONF_FRIENDLY_NAME]),
tuyainterface,
config_entry,
device_config[CONF_ID],
)

View File

@@ -13,10 +13,7 @@ light:
"""
import logging
from homeassistant.const import (
CONF_ID,
CONF_FRIENDLY_NAME,
)
from homeassistant.const import CONF_ID
from homeassistant.components.light import (
LightEntity,
DOMAIN,
@@ -27,7 +24,7 @@ from homeassistant.components.light import (
SUPPORT_COLOR,
)
from .common import LocalTuyaEntity, TuyaDevice, prepare_setup_entities
from .common import LocalTuyaEntity, prepare_setup_entities
_LOGGER = logging.getLogger(__name__)
@@ -49,18 +46,17 @@ def flow_schema(dps):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Tuya light based on a config entry."""
tuyainterface, entities_to_setup = prepare_setup_entities(config_entry, DOMAIN)
tuyainterface, entities_to_setup = prepare_setup_entities(
hass, config_entry, DOMAIN
)
if not entities_to_setup:
return
lights = []
for device_config in entities_to_setup:
# this has to be done in case the device type is type_0d
tuyainterface.add_dps_to_request(device_config[CONF_ID])
lights.append(
LocaltuyaLight(
TuyaDevice(tuyainterface, config_entry.data[CONF_FRIENDLY_NAME]),
tuyainterface,
config_entry,
device_config[CONF_ID],
)

View File

@@ -22,13 +22,12 @@ from homeassistant.components.sensor import DOMAIN, DEVICE_CLASSES
from homeassistant.const import (
CONF_ID,
CONF_DEVICE_CLASS,
CONF_FRIENDLY_NAME,
CONF_UNIT_OF_MEASUREMENT,
STATE_UNKNOWN,
)
from .const import CONF_SCALING
from .common import LocalTuyaEntity, TuyaDevice, prepare_setup_entities
from .common import LocalTuyaEntity, prepare_setup_entities
_LOGGER = logging.getLogger(__name__)
@@ -48,7 +47,9 @@ def flow_schema(dps):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Tuya sensor based on a config entry."""
tuyainterface, entities_to_setup = prepare_setup_entities(config_entry, DOMAIN)
tuyainterface, entities_to_setup = prepare_setup_entities(
hass, config_entry, DOMAIN
)
if not entities_to_setup:
return
@@ -56,7 +57,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for device_config in entities_to_setup:
sensors.append(
LocaltuyaSensor(
TuyaDevice(tuyainterface, config_entry.data[CONF_FRIENDLY_NAME]),
tuyainterface,
config_entry,
device_config[CONF_ID],
)

View File

@@ -32,10 +32,7 @@ from homeassistant.components.switch import (
SwitchEntity,
DOMAIN,
)
from homeassistant.const import (
CONF_ID,
CONF_FRIENDLY_NAME,
)
from homeassistant.const import CONF_ID
from .const import (
ATTR_CURRENT,
@@ -45,12 +42,10 @@ from .const import (
CONF_CURRENT_CONSUMPTION,
CONF_VOLTAGE,
)
from .common import LocalTuyaEntity, TuyaDevice, prepare_setup_entities
from .common import LocalTuyaEntity, prepare_setup_entities
_LOGGER = logging.getLogger(__name__)
DEFAULT_ID = "1"
def flow_schema(dps):
"""Return schema used in config flow."""
@@ -63,24 +58,17 @@ def flow_schema(dps):
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up a Tuya switch based on a config entry."""
tuyainterface, entities_to_setup = prepare_setup_entities(config_entry, DOMAIN)
tuyainterface, entities_to_setup = prepare_setup_entities(
hass, config_entry, DOMAIN
)
if not entities_to_setup:
return
switches = []
for device_config in entities_to_setup:
if device_config.get(CONF_CURRENT, "-1") != "-1":
tuyainterface.add_dps_to_request(device_config.get(CONF_CURRENT))
if device_config.get(CONF_CURRENT_CONSUMPTION, "-1") != "-1":
tuyainterface.add_dps_to_request(
device_config.get(CONF_CURRENT_CONSUMPTION)
)
if device_config.get(CONF_VOLTAGE, "-1") != "-1":
tuyainterface.add_dps_to_request(device_config.get(CONF_VOLTAGE))
switches.append(
LocaltuyaSwitch(
TuyaDevice(tuyainterface, config_entry.data[CONF_FRIENDLY_NAME]),
tuyainterface,
config_entry,
device_config[CONF_ID],
)