Merge remote-tracking branch 'upstream/master' into climate
This commit is contained in:
@@ -71,6 +71,7 @@ localtuya:
|
||||
color_mode: 21 # Optional, usually 2 or 21, default: "none"
|
||||
brightness: 22 # Optional, usually 3 or 22, default: "none"
|
||||
color_temp: 23 # Optional, usually 4 or 23, default: "none"
|
||||
color_temp_reverse: false # Optional, default: false
|
||||
color: 24 # Optional, usually 5 (RGB_HSV) or 24 (HSV), default: "none"
|
||||
brightness_lower: 29 # Optional, usually 0 or 29, default: 29
|
||||
brightness_upper: 1000 # Optional, usually 255 or 1000, default: 1000
|
||||
@@ -79,7 +80,6 @@ localtuya:
|
||||
scene: 25 # Optional, usually 6 (RGB_HSV) or 25 (HSV), default: "none"
|
||||
music_mode: False # Optional, some use internal mic, others, phone mic. Only internal mic is supported, default: "False"
|
||||
|
||||
|
||||
- platform: sensor
|
||||
friendly_name: Plug Voltage
|
||||
id: 20
|
||||
@@ -107,6 +107,8 @@ Start by going to Configuration - Integration and pressing the "+" button to cre
|
||||
Wait for 6 seconds for the scanning of the devices in your LAN. Then, a drop-down menu will appear containing the list of detected devices: you can
|
||||
select one of these, or manually input all the parameters.
|
||||
|
||||
> **Note: The tuya app on your device must be closed for the following steps to work reliably.**
|
||||
|
||||

|
||||
|
||||
If you have selected one entry, you only need to input the device's Friendly Name and the localKey.
|
||||
|
@@ -116,6 +116,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
||||
self.dps_to_request = {}
|
||||
self._is_closing = False
|
||||
self._connect_task = None
|
||||
self._disconnect_task = None
|
||||
self.set_logger(_LOGGER, config_entry[CONF_DEVICE_ID])
|
||||
|
||||
# This has to be done in case the device type is type_0d
|
||||
@@ -133,6 +134,7 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
||||
self._connect_task = asyncio.create_task(self._make_connection())
|
||||
|
||||
async def _make_connection(self):
|
||||
"""Subscribe localtuya entity events."""
|
||||
self.debug("Connecting to %s", self._config_entry[CONF_HOST])
|
||||
|
||||
try:
|
||||
@@ -151,6 +153,19 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
||||
raise Exception("Failed to retrieve status")
|
||||
|
||||
self.status_updated(status)
|
||||
|
||||
def _new_entity_handler(entity_id):
|
||||
self.debug(
|
||||
"New entity %s was added to %s",
|
||||
entity_id,
|
||||
self._config_entry[CONF_HOST],
|
||||
)
|
||||
self._dispatch_status()
|
||||
|
||||
signal = f"localtuya_entity_{self._config_entry[CONF_DEVICE_ID]}"
|
||||
self._disconnect_task = async_dispatcher_connect(
|
||||
self._hass, signal, _new_entity_handler
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
self.exception(f"Connect to {self._config_entry[CONF_HOST]} failed")
|
||||
if self._interface is not None:
|
||||
@@ -166,6 +181,8 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
||||
await self._connect_task
|
||||
if self._interface is not None:
|
||||
await self._interface.close()
|
||||
if self._disconnect_task is not None:
|
||||
self._disconnect_task()
|
||||
|
||||
async def set_dp(self, state, dp_index):
|
||||
"""Change value of a DP of the Tuya device."""
|
||||
@@ -195,7 +212,9 @@ class TuyaDevice(pytuya.TuyaListener, pytuya.ContextualLogger):
|
||||
def status_updated(self, status):
|
||||
"""Device updated status."""
|
||||
self._status.update(status)
|
||||
self._dispatch_status()
|
||||
|
||||
def _dispatch_status(self):
|
||||
signal = f"localtuya_{self._config_entry[CONF_DEVICE_ID]}"
|
||||
async_dispatcher_send(self._hass, signal, self._status)
|
||||
|
||||
@@ -243,10 +262,14 @@ class LocalTuyaEntity(RestoreEntity, pytuya.ContextualLogger):
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
signal = f"localtuya_{self._config_entry.data[CONF_DEVICE_ID]}"
|
||||
|
||||
self.async_on_remove(
|
||||
async_dispatcher_connect(self.hass, signal, _update_handler)
|
||||
)
|
||||
|
||||
signal = f"localtuya_entity_{self._config_entry.data[CONF_DEVICE_ID]}"
|
||||
async_dispatcher_send(self.hass, signal, self.entity_id)
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return device information for the device registry."""
|
||||
|
@@ -16,6 +16,7 @@ CONF_COLOR = "color"
|
||||
CONF_COLOR_MODE = "color_mode"
|
||||
CONF_COLOR_TEMP_MIN_KELVIN = "color_temp_min_kelvin"
|
||||
CONF_COLOR_TEMP_MAX_KELVIN = "color_temp_max_kelvin"
|
||||
CONF_COLOR_TEMP_REVERSE = "color_temp_reverse"
|
||||
CONF_MUSIC_MODE = "music_mode"
|
||||
|
||||
# switch
|
||||
@@ -64,6 +65,16 @@ DATA_DISCOVERY = "discovery"
|
||||
DOMAIN = "localtuya"
|
||||
|
||||
# Platforms in this list must support config flows
|
||||
PLATFORMS = ["binary_sensor", "cover", "climate", "fan", "light", "sensor", "switch"]
|
||||
PLATFORMS = [
|
||||
"binary_sensor",
|
||||
"climate",
|
||||
"cover",
|
||||
"fan",
|
||||
"light",
|
||||
"number",
|
||||
"select",
|
||||
"sensor",
|
||||
"switch",
|
||||
]
|
||||
|
||||
TUYA_DEVICE = "tuya_device"
|
||||
|
@@ -79,7 +79,13 @@ class LocaltuyaFan(LocalTuyaEntity, FanEntity):
|
||||
"""Get the list of available speeds."""
|
||||
return [SPEED_OFF, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
|
||||
|
||||
async def async_turn_on(self, speed: str = None, **kwargs) -> None:
|
||||
async def async_turn_on(
|
||||
self,
|
||||
speed: str = None,
|
||||
percentage: int = None,
|
||||
preset_mode: str = None,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Turn on the entity."""
|
||||
await self._device.set_dp(True, self._dp_id)
|
||||
if speed is not None:
|
||||
|
@@ -27,6 +27,7 @@ from .const import (
|
||||
CONF_COLOR_MODE,
|
||||
CONF_COLOR_TEMP_MAX_KELVIN,
|
||||
CONF_COLOR_TEMP_MIN_KELVIN,
|
||||
CONF_COLOR_TEMP_REVERSE,
|
||||
CONF_MUSIC_MODE,
|
||||
)
|
||||
|
||||
@@ -36,6 +37,8 @@ MIRED_TO_KELVIN_CONST = 1000000
|
||||
DEFAULT_MIN_KELVIN = 2700 # MIRED 370
|
||||
DEFAULT_MAX_KELVIN = 6500 # MIRED 153
|
||||
|
||||
DEFAULT_COLOR_TEMP_REVERSE = False
|
||||
|
||||
DEFAULT_LOWER_BRIGHTNESS = 29
|
||||
DEFAULT_UPPER_BRIGHTNESS = 1000
|
||||
|
||||
@@ -117,6 +120,11 @@ def flow_schema(dps):
|
||||
vol.Optional(CONF_COLOR_TEMP_MAX_KELVIN, default=DEFAULT_MAX_KELVIN): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1500, max=8000)
|
||||
),
|
||||
vol.Optional(
|
||||
CONF_COLOR_TEMP_REVERSE,
|
||||
default=DEFAULT_COLOR_TEMP_REVERSE,
|
||||
description={"suggested_value": DEFAULT_COLOR_TEMP_REVERSE},
|
||||
): bool,
|
||||
vol.Optional(CONF_SCENE): vol.In(dps),
|
||||
vol.Optional(
|
||||
CONF_MUSIC_MODE, default=False, description={"suggested_value": False}
|
||||
@@ -154,6 +162,9 @@ class LocaltuyaLight(LocalTuyaEntity, LightEntity):
|
||||
MIRED_TO_KELVIN_CONST
|
||||
/ self._config.get(CONF_COLOR_TEMP_MAX_KELVIN, DEFAULT_MAX_KELVIN)
|
||||
)
|
||||
self._color_temp_reverse = self._config.get(
|
||||
CONF_COLOR_TEMP_REVERSE, DEFAULT_COLOR_TEMP_REVERSE
|
||||
)
|
||||
self._hs = None
|
||||
self._effect = None
|
||||
self._effect_list = []
|
||||
@@ -199,11 +210,16 @@ class LocaltuyaLight(LocalTuyaEntity, LightEntity):
|
||||
def color_temp(self):
|
||||
"""Return the color_temp of the light."""
|
||||
if self.has_config(CONF_COLOR_TEMP) and self.is_white_mode:
|
||||
color_temp_value = (
|
||||
self._upper_color_temp - self._color_temp
|
||||
if self._color_temp_reverse
|
||||
else self._color_temp
|
||||
)
|
||||
return int(
|
||||
self._max_mired
|
||||
- (
|
||||
((self._max_mired - self._min_mired) / self._upper_color_temp)
|
||||
* self._color_temp
|
||||
* color_temp_value
|
||||
)
|
||||
)
|
||||
return None
|
||||
@@ -364,10 +380,16 @@ class LocaltuyaLight(LocalTuyaEntity, LightEntity):
|
||||
if ATTR_COLOR_TEMP in kwargs and (features & SUPPORT_COLOR_TEMP):
|
||||
if brightness is None:
|
||||
brightness = self._brightness
|
||||
color_temp_value = (
|
||||
(self._max_mired - self._min_mired)
|
||||
- (int(kwargs[ATTR_COLOR_TEMP]) - self._min_mired)
|
||||
if self._color_temp_reverse
|
||||
else (int(kwargs[ATTR_COLOR_TEMP]) - self._min_mired)
|
||||
)
|
||||
color_temp = int(
|
||||
self._upper_color_temp
|
||||
- (self._upper_color_temp / (self._max_mired - self._min_mired))
|
||||
* (int(kwargs[ATTR_COLOR_TEMP]) - self._min_mired)
|
||||
* color_temp_value
|
||||
)
|
||||
states[self._config.get(CONF_COLOR_MODE)] = MODE_WHITE
|
||||
states[self._config.get(CONF_BRIGHTNESS)] = brightness
|
||||
|
87
custom_components/localtuya/number.py
Normal file
87
custom_components/localtuya/number.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""Platform to present any Tuya DP as a number."""
|
||||
import logging
|
||||
from functools import partial
|
||||
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.number import DOMAIN, NumberEntity
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_CLASS,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
|
||||
from .common import LocalTuyaEntity, async_setup_entry
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_MIN_VALUE = "min_value"
|
||||
CONF_MAX_VALUE = "max_value"
|
||||
|
||||
DEFAULT_MIN = 0
|
||||
DEFAULT_MAX = 100000
|
||||
|
||||
|
||||
def flow_schema(dps):
|
||||
"""Return schema used in config flow."""
|
||||
return {
|
||||
vol.Optional(CONF_MIN_VALUE, default=DEFAULT_MIN): vol.All(
|
||||
vol.Coerce(float),
|
||||
vol.Range(min=-1000000.0, max=1000000.0),
|
||||
),
|
||||
vol.Required(CONF_MAX_VALUE, default=DEFAULT_MAX): vol.All(
|
||||
vol.Coerce(float),
|
||||
vol.Range(min=-1000000.0, max=1000000.0),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
class LocaltuyaNumber(LocalTuyaEntity, NumberEntity):
|
||||
"""Representation of a Tuya Number."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device,
|
||||
config_entry,
|
||||
sensorid,
|
||||
**kwargs,
|
||||
):
|
||||
"""Initialize the Tuya sensor."""
|
||||
super().__init__(device, config_entry, sensorid, _LOGGER, **kwargs)
|
||||
self._state = STATE_UNKNOWN
|
||||
|
||||
self._min_value = DEFAULT_MIN
|
||||
if CONF_MIN_VALUE in self._config:
|
||||
self._min_value = self._config.get(CONF_MIN_VALUE)
|
||||
|
||||
self._max_value = self._config.get(CONF_MAX_VALUE)
|
||||
|
||||
@property
|
||||
def value(self) -> float:
|
||||
"""Return sensor state."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def min_value(self) -> float:
|
||||
"""Return the minimum value."""
|
||||
return self._min_value
|
||||
|
||||
@property
|
||||
def max_value(self) -> float:
|
||||
"""Return the maximum value."""
|
||||
return self._max_value
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the class of this device."""
|
||||
return self._config.get(CONF_DEVICE_CLASS)
|
||||
|
||||
async def async_set_value(self, value: float) -> None:
|
||||
"""Update the current value."""
|
||||
await self._device.set_dp(value, self._dp_id)
|
||||
|
||||
def status_updated(self):
|
||||
"""Device status was updated."""
|
||||
state = self.dps(self._dp_id)
|
||||
self._state = state
|
||||
|
||||
|
||||
async_setup_entry = partial(async_setup_entry, DOMAIN, LocaltuyaNumber, flow_schema)
|
103
custom_components/localtuya/select.py
Normal file
103
custom_components/localtuya/select.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""Platform to present any Tuya DP as an enumeration."""
|
||||
import logging
|
||||
from functools import partial
|
||||
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.select import DOMAIN, SelectEntity
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_CLASS,
|
||||
STATE_UNKNOWN,
|
||||
)
|
||||
|
||||
from .common import LocalTuyaEntity, async_setup_entry
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_OPTIONS = "select_options"
|
||||
CONF_OPTIONS_FRIENDLY = "select_options_friendly"
|
||||
|
||||
|
||||
def flow_schema(dps):
|
||||
"""Return schema used in config flow."""
|
||||
return {
|
||||
vol.Required(CONF_OPTIONS): str,
|
||||
vol.Optional(CONF_OPTIONS_FRIENDLY): str,
|
||||
}
|
||||
|
||||
|
||||
class LocaltuyaSelect(LocalTuyaEntity, SelectEntity):
|
||||
"""Representation of a Tuya Enumeration."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
device,
|
||||
config_entry,
|
||||
sensorid,
|
||||
**kwargs,
|
||||
):
|
||||
"""Initialize the Tuya sensor."""
|
||||
super().__init__(device, config_entry, sensorid, _LOGGER, **kwargs)
|
||||
self._state = STATE_UNKNOWN
|
||||
self._state_friendly = ""
|
||||
self._valid_options = self._config.get(CONF_OPTIONS).split(";")
|
||||
|
||||
# Set Display options
|
||||
self._display_options = []
|
||||
display_options_str = ""
|
||||
if CONF_OPTIONS_FRIENDLY in self._config:
|
||||
display_options_str = self._config.get(CONF_OPTIONS_FRIENDLY).strip()
|
||||
_LOGGER.debug("Display Options Configured: %s", display_options_str)
|
||||
|
||||
if display_options_str.find(";") >= 0:
|
||||
self._display_options = display_options_str.split(";")
|
||||
elif len(display_options_str.strip()) > 0:
|
||||
self._display_options.append(display_options_str)
|
||||
else:
|
||||
# Default display string to raw string
|
||||
_LOGGER.debug("No Display options configured - defaulting to raw values")
|
||||
self._display_options = self._valid_options
|
||||
|
||||
_LOGGER.debug(
|
||||
"Total Raw Options: %s - Total Display Options: %s",
|
||||
str(len(self._valid_options)),
|
||||
str(len(self._display_options)),
|
||||
)
|
||||
if len(self._valid_options) > len(self._display_options):
|
||||
# If list of display items smaller than list of valid items,
|
||||
# then default remaining items to be the raw value
|
||||
_LOGGER.debug(
|
||||
"Valid options is larger than display options - \
|
||||
filling up with raw values"
|
||||
)
|
||||
for i in range(len(self._display_options), len(self._valid_options)):
|
||||
self._display_options.append(self._valid_options[i])
|
||||
|
||||
@property
|
||||
def current_option(self) -> str:
|
||||
"""Return the current value."""
|
||||
return self._state_friendly
|
||||
|
||||
@property
|
||||
def options(self) -> list:
|
||||
"""Return the list of values."""
|
||||
return self._display_options
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the class of this device."""
|
||||
return self._config.get(CONF_DEVICE_CLASS)
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Update the current value."""
|
||||
option_value = self._valid_options[self._display_options.index(option)]
|
||||
_LOGGER.debug("Sending Option: " + option + " -> " + option_value)
|
||||
await self._device.set_dp(option_value, self._dp_id)
|
||||
|
||||
def status_updated(self):
|
||||
"""Device status was updated."""
|
||||
state = self.dps(self._dp_id)
|
||||
self._state_friendly = self._display_options[self._valid_options.index(state)]
|
||||
self._state = state
|
||||
|
||||
|
||||
async_setup_entry = partial(async_setup_entry, DOMAIN, LocaltuyaSelect, flow_schema)
|
@@ -75,6 +75,10 @@
|
||||
"fan_speed_low": "Fan Low Speed Setting",
|
||||
"fan_speed_medium": "Fan Medium Speed Setting",
|
||||
"fan_speed_high": "Fan High Speed Setting",
|
||||
"max_value": "Maximum Value",
|
||||
"min_value": "Minimum Value",
|
||||
"select_options": "Valid entries, separate entries by a ;",
|
||||
"select_options_friendly": "User Friendly options, separate entries by a ;",
|
||||
"current_temperature_dp": "Current Temperature",
|
||||
"target_temperature_dp": "Target Temperature",
|
||||
"temperature_step": "Temperature Step (optional)",
|
||||
@@ -144,6 +148,10 @@
|
||||
"fan_speed_low": "Fan Low Speed Setting",
|
||||
"fan_speed_medium": "Fan Medium Speed Setting",
|
||||
"fan_speed_high": "Fan High Speed Setting",
|
||||
"max_value": "Maximum Value",
|
||||
"min_value": "Minimum Value",
|
||||
"select_options": "Valid entries, separate entries by a ;",
|
||||
"select_options_friendly": "User Friendly options, separate entries by a ;",
|
||||
"current_temperature_dp": "Current Temperature",
|
||||
"target_temperature_dp": "Target Temperature",
|
||||
"temperature_step": "Temperature Step (optional)",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Local Tuya",
|
||||
"domains": ["climate", "cover", "fan", "light", "sensor", "switch"],
|
||||
"domains": ["climate", "cover", "fan", "light", "number", "select", "sensor", "switch"],
|
||||
"homeassistant": "0.116.0",
|
||||
"iot_class": ["Local Push"]
|
||||
}
|
||||
|
13
info.md
13
info.md
@@ -66,7 +66,18 @@ localtuya:
|
||||
|
||||
- platform: light
|
||||
friendly_name: Device Light
|
||||
id: 4
|
||||
id: 4 # Usually 1 or 20
|
||||
color_mode: 21 # Optional, usually 2 or 21, default: "none"
|
||||
brightness: 22 # Optional, usually 3 or 22, default: "none"
|
||||
color_temp: 23 # Optional, usually 4 or 23, default: "none"
|
||||
color_temp_reverse: false # Optional, default: false
|
||||
color: 24 # Optional, usually 5 (RGB_HSV) or 24 (HSV), default: "none"
|
||||
brightness_lower: 29 # Optional, usually 0 or 29, default: 29
|
||||
brightness_upper: 1000 # Optional, usually 255 or 1000, default: 1000
|
||||
color_temp_min_kelvin: 2700 # Optional, default: 2700
|
||||
color_temp_max_kelvin: 6500 # Optional, default: 6500
|
||||
scene: 25 # Optional, usually 6 (RGB_HSV) or 25 (HSV), default: "none"
|
||||
music_mode: False # Optional, some use internal mic, others, phone mic. Only internal mic is supported, default: "False"
|
||||
|
||||
- platform: sensor
|
||||
friendly_name: Plug Voltage
|
||||
|
@@ -3,7 +3,7 @@ codespell==2.0.0
|
||||
flake8==3.9.2
|
||||
mypy==0.901
|
||||
pydocstyle==6.1.1
|
||||
cryptography==3.2
|
||||
cryptography==3.3.2
|
||||
pylint==2.8.2
|
||||
pylint-strict-informational==0.1
|
||||
homeassistant==2021.1.4
|
||||
homeassistant==2021.7.1
|
||||
|
@@ -12,7 +12,7 @@ warn_incomplete_stub = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_configs = true
|
||||
|
||||
[mypy-homeassistant.block_async_io,homeassistant.bootstrap,homeassistant.components,homeassistant.config_entries,homeassistant.config,homeassistant.const,homeassistant.core,homeassistant.data_entry_flow,homeassistant.exceptions,homeassistant.__init__,homeassistant.loader,homeassistant.__main__,homeassistant.requirements,homeassistant.runner,homeassistant.setup,homeassistant.util,homeassistant.auth.*,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.calendar.*,homeassistant.components.cover.*,homeassistant.components.device_automation.*,homeassistant.components.frontend.*,homeassistant.components.geo_location.*,homeassistant.components.group.*,homeassistant.components.history.*,homeassistant.components.http.*,homeassistant.components.image_processing.*,homeassistant.components.integration.*,homeassistant.components.light.*,homeassistant.components.lock.*,homeassistant.components.mailbox.*,homeassistant.components.media_player.*,homeassistant.components.notify.*,homeassistant.components.persistent_notification.*,homeassistant.components.proximity.*,homeassistant.components.remote.*,homeassistant.components.scene.*,homeassistant.components.sensor.*,homeassistant.components.sun.*,homeassistant.components.switch.*,homeassistant.components.systemmonitor.*,homeassistant.components.tts.*,homeassistant.components.vacuum.*,homeassistant.components.water_heater.*,homeassistant.components.weather.*,homeassistant.components.websocket_api.*,homeassistant.components.zone.*,homeassistant.helpers.*,homeassistant.scripts.*,homeassistant.util.*]
|
||||
[mypy-homeassistant.block_async_io,homeassistant.bootstrap,homeassistant.components,homeassistant.config_entries,homeassistant.config,homeassistant.const,homeassistant.core,homeassistant.data_entry_flow,homeassistant.exceptions,homeassistant.__init__,homeassistant.loader,homeassistant.__main__,homeassistant.requirements,homeassistant.runner,homeassistant.setup,homeassistant.util,homeassistant.auth.*,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.calendar.*,homeassistant.components.cover.*,homeassistant.components.device_automation.*,homeassistant.components.frontend.*,homeassistant.components.geo_location.*,homeassistant.components.group.*,homeassistant.components.history.*,homeassistant.components.http.*,homeassistant.components.image_processing.*,homeassistant.components.integration.*,homeassistant.components.light.*,homeassistant.components.lock.*,homeassistant.components.mailbox.*,homeassistant.components.media_player.*,homeassistant.components.notify.*,homeassistant.components.persistent_notification.*,homeassistant.components.proximity.*,homeassistant.components.remote.*,homeassistant.components.scene.*,homeassistant.components.sensor.*,homeassistant.components.sun.*,homeassistant.components.switch.*,homeassistant.components.systemmonitor.*,homeassistant.components.tts.*,homeassistant.components.vacuum.*,homeassistant.components.water_heater.*,homeassistant.components.weather.*,homeassistant.components.websocket_api.*,homeassistant.components.zone.*,homeassistant.helpers.*,homeassistant.scripts.*,homeassistant.util.*,homeassistant.components.select.*,homeassistant.components.number.*]
|
||||
strict = true
|
||||
ignore_errors = false
|
||||
warn_unreachable = true
|
||||
|
Reference in New Issue
Block a user