mirror of
https://github.com/home-assistant/core.git
synced 2025-09-10 23:31:37 +02:00
Add MQTT alarm control panel subentry support (#150395)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
This commit is contained in:
@@ -7,10 +7,7 @@ import logging
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import alarm_control_panel as alarm
|
||||
from homeassistant.components.alarm_control_panel import (
|
||||
AlarmControlPanelEntityFeature,
|
||||
AlarmControlPanelState,
|
||||
)
|
||||
from homeassistant.components.alarm_control_panel import AlarmControlPanelState
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_CODE, CONF_NAME, CONF_VALUE_TEMPLATE
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@@ -21,12 +18,33 @@ from homeassistant.helpers.typing import ConfigType
|
||||
from . import subscription
|
||||
from .config import DEFAULT_RETAIN, MQTT_BASE_SCHEMA
|
||||
from .const import (
|
||||
ALARM_CONTROL_PANEL_SUPPORTED_FEATURES,
|
||||
CONF_CODE_ARM_REQUIRED,
|
||||
CONF_CODE_DISARM_REQUIRED,
|
||||
CONF_CODE_TRIGGER_REQUIRED,
|
||||
CONF_COMMAND_TEMPLATE,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_PAYLOAD_ARM_AWAY,
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS,
|
||||
CONF_PAYLOAD_ARM_HOME,
|
||||
CONF_PAYLOAD_ARM_NIGHT,
|
||||
CONF_PAYLOAD_ARM_VACATION,
|
||||
CONF_PAYLOAD_DISARM,
|
||||
CONF_PAYLOAD_TRIGGER,
|
||||
CONF_RETAIN,
|
||||
CONF_STATE_TOPIC,
|
||||
CONF_SUPPORTED_FEATURES,
|
||||
DEFAULT_ALARM_CONTROL_PANEL_COMMAND_TEMPLATE,
|
||||
DEFAULT_PAYLOAD_ARM_AWAY,
|
||||
DEFAULT_PAYLOAD_ARM_CUSTOM_BYPASS,
|
||||
DEFAULT_PAYLOAD_ARM_HOME,
|
||||
DEFAULT_PAYLOAD_ARM_NIGHT,
|
||||
DEFAULT_PAYLOAD_ARM_VACATION,
|
||||
DEFAULT_PAYLOAD_DISARM,
|
||||
DEFAULT_PAYLOAD_TRIGGER,
|
||||
PAYLOAD_NONE,
|
||||
REMOTE_CODE,
|
||||
REMOTE_CODE_TEXT,
|
||||
)
|
||||
from .entity import MqttEntity, async_setup_entity_entry_helper
|
||||
from .models import MqttCommandTemplate, MqttValueTemplate, ReceiveMessage
|
||||
@@ -37,26 +55,6 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
_SUPPORTED_FEATURES = {
|
||||
"arm_home": AlarmControlPanelEntityFeature.ARM_HOME,
|
||||
"arm_away": AlarmControlPanelEntityFeature.ARM_AWAY,
|
||||
"arm_night": AlarmControlPanelEntityFeature.ARM_NIGHT,
|
||||
"arm_vacation": AlarmControlPanelEntityFeature.ARM_VACATION,
|
||||
"arm_custom_bypass": AlarmControlPanelEntityFeature.ARM_CUSTOM_BYPASS,
|
||||
"trigger": AlarmControlPanelEntityFeature.TRIGGER,
|
||||
}
|
||||
|
||||
CONF_CODE_ARM_REQUIRED = "code_arm_required"
|
||||
CONF_CODE_DISARM_REQUIRED = "code_disarm_required"
|
||||
CONF_CODE_TRIGGER_REQUIRED = "code_trigger_required"
|
||||
CONF_PAYLOAD_DISARM = "payload_disarm"
|
||||
CONF_PAYLOAD_ARM_HOME = "payload_arm_home"
|
||||
CONF_PAYLOAD_ARM_AWAY = "payload_arm_away"
|
||||
CONF_PAYLOAD_ARM_NIGHT = "payload_arm_night"
|
||||
CONF_PAYLOAD_ARM_VACATION = "payload_arm_vacation"
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS = "payload_arm_custom_bypass"
|
||||
CONF_PAYLOAD_TRIGGER = "payload_trigger"
|
||||
|
||||
MQTT_ALARM_ATTRIBUTES_BLOCKED = frozenset(
|
||||
{
|
||||
alarm.ATTR_CHANGED_BY,
|
||||
@@ -65,44 +63,40 @@ MQTT_ALARM_ATTRIBUTES_BLOCKED = frozenset(
|
||||
}
|
||||
)
|
||||
|
||||
DEFAULT_COMMAND_TEMPLATE = "{{action}}"
|
||||
DEFAULT_ARM_NIGHT = "ARM_NIGHT"
|
||||
DEFAULT_ARM_VACATION = "ARM_VACATION"
|
||||
DEFAULT_ARM_AWAY = "ARM_AWAY"
|
||||
DEFAULT_ARM_HOME = "ARM_HOME"
|
||||
DEFAULT_ARM_CUSTOM_BYPASS = "ARM_CUSTOM_BYPASS"
|
||||
DEFAULT_DISARM = "DISARM"
|
||||
DEFAULT_TRIGGER = "TRIGGER"
|
||||
DEFAULT_NAME = "MQTT Alarm"
|
||||
|
||||
REMOTE_CODE = "REMOTE_CODE"
|
||||
REMOTE_CODE_TEXT = "REMOTE_CODE_TEXT"
|
||||
|
||||
PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(CONF_SUPPORTED_FEATURES, default=list(_SUPPORTED_FEATURES)): [
|
||||
vol.In(_SUPPORTED_FEATURES)
|
||||
],
|
||||
vol.Optional(
|
||||
CONF_SUPPORTED_FEATURES,
|
||||
default=list(ALARM_CONTROL_PANEL_SUPPORTED_FEATURES),
|
||||
): [vol.In(ALARM_CONTROL_PANEL_SUPPORTED_FEATURES)],
|
||||
vol.Optional(CONF_CODE): cv.string,
|
||||
vol.Optional(CONF_CODE_ARM_REQUIRED, default=True): cv.boolean,
|
||||
vol.Optional(CONF_CODE_DISARM_REQUIRED, default=True): cv.boolean,
|
||||
vol.Optional(CONF_CODE_TRIGGER_REQUIRED, default=True): cv.boolean,
|
||||
vol.Optional(
|
||||
CONF_COMMAND_TEMPLATE, default=DEFAULT_COMMAND_TEMPLATE
|
||||
CONF_COMMAND_TEMPLATE, default=DEFAULT_ALARM_CONTROL_PANEL_COMMAND_TEMPLATE
|
||||
): cv.template,
|
||||
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
||||
vol.Optional(CONF_NAME): vol.Any(cv.string, None),
|
||||
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_ARM_NIGHT, default=DEFAULT_ARM_NIGHT): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_VACATION, default=DEFAULT_ARM_VACATION
|
||||
CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_PAYLOAD_ARM_AWAY
|
||||
): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS, default=DEFAULT_ARM_CUSTOM_BYPASS
|
||||
CONF_PAYLOAD_ARM_HOME, default=DEFAULT_PAYLOAD_ARM_HOME
|
||||
): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_TRIGGER, default=DEFAULT_TRIGGER): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_NIGHT, default=DEFAULT_PAYLOAD_ARM_NIGHT
|
||||
): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_VACATION, default=DEFAULT_PAYLOAD_ARM_VACATION
|
||||
): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS, default=DEFAULT_PAYLOAD_ARM_CUSTOM_BYPASS
|
||||
): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_PAYLOAD_DISARM): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_TRIGGER, default=DEFAULT_PAYLOAD_TRIGGER): cv.string,
|
||||
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||
vol.Required(CONF_STATE_TOPIC): valid_subscribe_topic,
|
||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||
@@ -152,7 +146,9 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
||||
).async_render
|
||||
|
||||
for feature in self._config[CONF_SUPPORTED_FEATURES]:
|
||||
self._attr_supported_features |= _SUPPORTED_FEATURES[feature]
|
||||
self._attr_supported_features |= ALARM_CONTROL_PANEL_SUPPORTED_FEATURES[
|
||||
feature
|
||||
]
|
||||
|
||||
if (code := self._config.get(CONF_CODE)) is None:
|
||||
self._attr_code_format = None
|
||||
|
@@ -71,6 +71,7 @@ from homeassistant.const import (
|
||||
ATTR_SW_VERSION,
|
||||
CONF_BRIGHTNESS,
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CODE,
|
||||
CONF_DEVICE,
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_DISCOVERY,
|
||||
@@ -129,6 +130,7 @@ from homeassistant.util.unit_conversion import TemperatureConverter
|
||||
from .addon import get_addon_manager
|
||||
from .client import MqttClientSetup
|
||||
from .const import (
|
||||
ALARM_CONTROL_PANEL_SUPPORTED_FEATURES,
|
||||
ATTR_PAYLOAD,
|
||||
ATTR_QOS,
|
||||
ATTR_RETAIN,
|
||||
@@ -149,7 +151,10 @@ from .const import (
|
||||
CONF_CERTIFICATE,
|
||||
CONF_CLIENT_CERT,
|
||||
CONF_CLIENT_KEY,
|
||||
CONF_CODE_ARM_REQUIRED,
|
||||
CONF_CODE_DISARM_REQUIRED,
|
||||
CONF_CODE_FORMAT,
|
||||
CONF_CODE_TRIGGER_REQUIRED,
|
||||
CONF_COLOR_MODE_STATE_TOPIC,
|
||||
CONF_COLOR_MODE_VALUE_TEMPLATE,
|
||||
CONF_COLOR_TEMP_COMMAND_TEMPLATE,
|
||||
@@ -216,6 +221,11 @@ from .const import (
|
||||
CONF_OSCILLATION_COMMAND_TOPIC,
|
||||
CONF_OSCILLATION_STATE_TOPIC,
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE,
|
||||
CONF_PAYLOAD_ARM_AWAY,
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS,
|
||||
CONF_PAYLOAD_ARM_HOME,
|
||||
CONF_PAYLOAD_ARM_NIGHT,
|
||||
CONF_PAYLOAD_ARM_VACATION,
|
||||
CONF_PAYLOAD_AVAILABLE,
|
||||
CONF_PAYLOAD_CLOSE,
|
||||
CONF_PAYLOAD_LOCK,
|
||||
@@ -229,6 +239,7 @@ from .const import (
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE,
|
||||
CONF_PAYLOAD_STOP,
|
||||
CONF_PAYLOAD_STOP_TILT,
|
||||
CONF_PAYLOAD_TRIGGER,
|
||||
CONF_PAYLOAD_UNLOCK,
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE,
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC,
|
||||
@@ -280,6 +291,7 @@ from .const import (
|
||||
CONF_STATE_VALUE_TEMPLATE,
|
||||
CONF_SUGGESTED_DISPLAY_PRECISION,
|
||||
CONF_SUPPORTED_COLOR_MODES,
|
||||
CONF_SUPPORTED_FEATURES,
|
||||
CONF_SWING_HORIZONTAL_MODE_COMMAND_TEMPLATE,
|
||||
CONF_SWING_HORIZONTAL_MODE_COMMAND_TOPIC,
|
||||
CONF_SWING_HORIZONTAL_MODE_LIST,
|
||||
@@ -329,12 +341,18 @@ from .const import (
|
||||
CONF_XY_VALUE_TEMPLATE,
|
||||
CONFIG_ENTRY_MINOR_VERSION,
|
||||
CONFIG_ENTRY_VERSION,
|
||||
DEFAULT_ALARM_CONTROL_PANEL_COMMAND_TEMPLATE,
|
||||
DEFAULT_BIRTH,
|
||||
DEFAULT_CLIMATE_INITIAL_TEMPERATURE,
|
||||
DEFAULT_DISCOVERY,
|
||||
DEFAULT_ENCODING,
|
||||
DEFAULT_KEEPALIVE,
|
||||
DEFAULT_ON_COMMAND_TYPE,
|
||||
DEFAULT_PAYLOAD_ARM_AWAY,
|
||||
DEFAULT_PAYLOAD_ARM_CUSTOM_BYPASS,
|
||||
DEFAULT_PAYLOAD_ARM_HOME,
|
||||
DEFAULT_PAYLOAD_ARM_NIGHT,
|
||||
DEFAULT_PAYLOAD_ARM_VACATION,
|
||||
DEFAULT_PAYLOAD_AVAILABLE,
|
||||
DEFAULT_PAYLOAD_CLOSE,
|
||||
DEFAULT_PAYLOAD_LOCK,
|
||||
@@ -347,6 +365,7 @@ from .const import (
|
||||
DEFAULT_PAYLOAD_PRESS,
|
||||
DEFAULT_PAYLOAD_RESET,
|
||||
DEFAULT_PAYLOAD_STOP,
|
||||
DEFAULT_PAYLOAD_TRIGGER,
|
||||
DEFAULT_PAYLOAD_UNLOCK,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_POSITION_CLOSED,
|
||||
@@ -370,6 +389,8 @@ from .const import (
|
||||
DEFAULT_WILL,
|
||||
DEFAULT_WS_PATH,
|
||||
DOMAIN,
|
||||
REMOTE_CODE,
|
||||
REMOTE_CODE_TEXT,
|
||||
SUPPORTED_PROTOCOLS,
|
||||
TRANSPORT_TCP,
|
||||
TRANSPORT_WEBSOCKETS,
|
||||
@@ -468,6 +489,7 @@ KEY_UPLOAD_SELECTOR = FileSelector(
|
||||
|
||||
# Subentry selectors
|
||||
SUBENTRY_PLATFORMS = [
|
||||
Platform.ALARM_CONTROL_PANEL,
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.BUTTON,
|
||||
Platform.CLIMATE,
|
||||
@@ -573,6 +595,21 @@ TIMEOUT_SELECTOR = NumberSelector(
|
||||
NumberSelectorConfig(mode=NumberSelectorMode.BOX, min=0)
|
||||
)
|
||||
|
||||
# Alarm control panel selectors
|
||||
ALARM_CONTROL_PANEL_FEATURES_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=list(ALARM_CONTROL_PANEL_SUPPORTED_FEATURES),
|
||||
multiple=True,
|
||||
translation_key="alarm_control_panel_features",
|
||||
)
|
||||
)
|
||||
ALARM_CONTROL_PANEL_CODE_MODE = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=["local_code", "remote_code", "remote_code_text"],
|
||||
translation_key="alarm_control_panel_code_mode",
|
||||
)
|
||||
)
|
||||
|
||||
# Climate specific selectors
|
||||
CLIMATE_MODE_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
@@ -729,6 +766,25 @@ HUMIDITY_SELECTOR = vol.All(
|
||||
vol.Coerce(int),
|
||||
)
|
||||
|
||||
_CODE_VALIDATION_MODE = {
|
||||
"remote_code": REMOTE_CODE,
|
||||
"remote_code_text": REMOTE_CODE_TEXT,
|
||||
}
|
||||
|
||||
|
||||
@callback
|
||||
def default_alarm_control_panel_code(config: dict[str, Any]) -> str:
|
||||
"""Return alarm control panel code based on the stored code and code mode."""
|
||||
code: str
|
||||
if config["alarm_control_panel_code_mode"] in _CODE_VALIDATION_MODE:
|
||||
# Return magic value for remote code validation
|
||||
return _CODE_VALIDATION_MODE[config["alarm_control_panel_code_mode"]]
|
||||
if (code := config.get(CONF_CODE, "")) in _CODE_VALIDATION_MODE.values():
|
||||
# Remove magic value for remote code validation
|
||||
return ""
|
||||
|
||||
return code
|
||||
|
||||
|
||||
@callback
|
||||
def temperature_default_from_celsius_to_system_default(
|
||||
@@ -925,6 +981,7 @@ class PlatformField:
|
||||
vol.UNDEFINED
|
||||
)
|
||||
is_schema_default: bool = False
|
||||
include_in_config: bool = False
|
||||
exclude_from_reconfig: bool = False
|
||||
exclude_from_config: bool = False
|
||||
conditions: tuple[dict[str, Any], ...] | None = None
|
||||
@@ -995,6 +1052,23 @@ SHARED_PLATFORM_ENTITY_FIELDS: dict[str, PlatformField] = {
|
||||
}
|
||||
|
||||
PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = {
|
||||
Platform.ALARM_CONTROL_PANEL.value: {
|
||||
CONF_SUPPORTED_FEATURES: PlatformField(
|
||||
selector=ALARM_CONTROL_PANEL_FEATURES_SELECTOR,
|
||||
required=True,
|
||||
default=lambda config: config.get(
|
||||
CONF_SUPPORTED_FEATURES, list(ALARM_CONTROL_PANEL_SUPPORTED_FEATURES)
|
||||
),
|
||||
),
|
||||
"alarm_control_panel_code_mode": PlatformField(
|
||||
selector=ALARM_CONTROL_PANEL_CODE_MODE,
|
||||
required=True,
|
||||
exclude_from_config=True,
|
||||
default=lambda config: config[CONF_CODE].lower()
|
||||
if config.get(CONF_CODE) in (REMOTE_CODE, REMOTE_CODE_TEXT)
|
||||
else "local_code",
|
||||
),
|
||||
},
|
||||
Platform.BINARY_SENSOR.value: {
|
||||
CONF_DEVICE_CLASS: PlatformField(
|
||||
selector=BINARY_SENSOR_DEVICE_CLASS_SELECTOR,
|
||||
@@ -1168,6 +1242,92 @@ PLATFORM_ENTITY_FIELDS: dict[str, dict[str, PlatformField]] = {
|
||||
Platform.LOCK.value: {},
|
||||
}
|
||||
PLATFORM_MQTT_FIELDS: dict[str, dict[str, PlatformField]] = {
|
||||
Platform.ALARM_CONTROL_PANEL: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_publish_topic,
|
||||
error="invalid_publish_topic",
|
||||
),
|
||||
CONF_COMMAND_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_ALARM_CONTROL_PANEL_COMMAND_TEMPLATE,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=True,
|
||||
validator=valid_subscribe_topic,
|
||||
error="invalid_subscribe_topic",
|
||||
),
|
||||
CONF_VALUE_TEMPLATE: PlatformField(
|
||||
selector=TEMPLATE_SELECTOR,
|
||||
required=False,
|
||||
validator=validate(cv.template),
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_CODE: PlatformField(
|
||||
selector=PASSWORD_SELECTOR,
|
||||
required=True,
|
||||
include_in_config=True,
|
||||
default=default_alarm_control_panel_code,
|
||||
conditions=({"alarm_control_panel_code_mode": "local_code"},),
|
||||
),
|
||||
CONF_CODE_ARM_REQUIRED: PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=True,
|
||||
default=True,
|
||||
),
|
||||
CONF_CODE_DISARM_REQUIRED: PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=True,
|
||||
default=True,
|
||||
),
|
||||
CONF_CODE_TRIGGER_REQUIRED: PlatformField(
|
||||
selector=BOOLEAN_SELECTOR,
|
||||
required=True,
|
||||
default=True,
|
||||
),
|
||||
CONF_RETAIN: PlatformField(selector=BOOLEAN_SELECTOR, required=False),
|
||||
CONF_PAYLOAD_ARM_HOME: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_ARM_HOME,
|
||||
section="alarm_control_panel_payload_settings",
|
||||
),
|
||||
CONF_PAYLOAD_ARM_AWAY: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_ARM_AWAY,
|
||||
section="alarm_control_panel_payload_settings",
|
||||
),
|
||||
CONF_PAYLOAD_ARM_NIGHT: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_ARM_NIGHT,
|
||||
section="alarm_control_panel_payload_settings",
|
||||
),
|
||||
CONF_PAYLOAD_ARM_VACATION: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_ARM_VACATION,
|
||||
section="alarm_control_panel_payload_settings",
|
||||
),
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_ARM_CUSTOM_BYPASS,
|
||||
section="alarm_control_panel_payload_settings",
|
||||
),
|
||||
CONF_PAYLOAD_TRIGGER: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
default=DEFAULT_PAYLOAD_TRIGGER,
|
||||
section="alarm_control_panel_payload_settings",
|
||||
),
|
||||
},
|
||||
Platform.BINARY_SENSOR.value: {
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
@@ -2774,6 +2934,7 @@ ENTITY_CONFIG_VALIDATOR: dict[
|
||||
str,
|
||||
Callable[[dict[str, Any]], dict[str, str]] | None,
|
||||
] = {
|
||||
Platform.ALARM_CONTROL_PANEL: None,
|
||||
Platform.BINARY_SENSOR.value: None,
|
||||
Platform.BUTTON.value: None,
|
||||
Platform.CLIMATE.value: validate_climate_platform_config,
|
||||
@@ -2969,13 +3130,24 @@ def data_schema_from_fields(
|
||||
data_schema: dict[Any, Any] = {}
|
||||
all_data_element_options: set[Any] = set()
|
||||
no_reconfig_options: set[Any] = set()
|
||||
|
||||
defaults: dict[str, Any] = {}
|
||||
for field_name, field_details in data_schema_fields.items():
|
||||
default = defaults[field_name] = get_default(field_details)
|
||||
if not field_details.include_in_config or component_data is None:
|
||||
continue
|
||||
component_data[field_name] = default
|
||||
|
||||
for schema_section in sections:
|
||||
# Always calculate the default values
|
||||
# Getting the default value may update the subentry data,
|
||||
# even when and option is filtered out
|
||||
data_schema_element = {
|
||||
vol.Required(field_name, default=get_default(field_details))
|
||||
vol.Required(field_name, default=defaults[field_name])
|
||||
if field_details.required
|
||||
else vol.Optional(
|
||||
field_name,
|
||||
default=get_default(field_details)
|
||||
default=defaults[field_name]
|
||||
if field_details.default is not None
|
||||
else vol.UNDEFINED,
|
||||
): field_details.selector(component_data_with_user_input or {})
|
||||
@@ -3024,12 +3196,16 @@ def data_schema_from_fields(
|
||||
)
|
||||
|
||||
# Reset all fields from the component_data not in the schema
|
||||
# except for options that should stay included
|
||||
if component_data:
|
||||
filtered_fields = (
|
||||
set(data_schema_fields) - all_data_element_options - no_reconfig_options
|
||||
)
|
||||
for field in filtered_fields:
|
||||
if field in component_data:
|
||||
if (
|
||||
field in component_data
|
||||
and not data_schema_fields[field].include_in_config
|
||||
):
|
||||
del component_data[field]
|
||||
return vol.Schema(data_schema)
|
||||
|
||||
@@ -3591,6 +3767,7 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow):
|
||||
for field, platform_field in data_schema_fields.items()
|
||||
if field in (set(component_data) - set(config))
|
||||
and not platform_field.exclude_from_reconfig
|
||||
and not platform_field.include_in_config
|
||||
):
|
||||
component_data.pop(field)
|
||||
component_data.update(merged_user_input)
|
||||
@@ -3906,7 +4083,10 @@ class MQTTSubentryFlowHandler(ConfigSubentryFlow):
|
||||
)
|
||||
component_data.update(subentry_default_data)
|
||||
for key, platform_field in platform_fields.items():
|
||||
if not platform_field.exclude_from_config:
|
||||
if (
|
||||
not platform_field.exclude_from_config
|
||||
or platform_field.include_in_config
|
||||
):
|
||||
continue
|
||||
if key in component_data:
|
||||
component_data.pop(key)
|
||||
|
@@ -4,6 +4,7 @@ import logging
|
||||
|
||||
import jinja2
|
||||
|
||||
from homeassistant.components.alarm_control_panel import AlarmControlPanelEntityFeature
|
||||
from homeassistant.const import CONF_DISCOVERY, CONF_PAYLOAD, Platform
|
||||
from homeassistant.exceptions import TemplateError
|
||||
|
||||
@@ -31,7 +32,10 @@ CONF_AVAILABILITY_TEMPLATE = "availability_template"
|
||||
CONF_AVAILABILITY_TOPIC = "availability_topic"
|
||||
CONF_BROKER = "broker"
|
||||
CONF_BIRTH_MESSAGE = "birth_message"
|
||||
CONF_CODE_ARM_REQUIRED = "code_arm_required"
|
||||
CONF_CODE_DISARM_REQUIRED = "code_disarm_required"
|
||||
CONF_CODE_FORMAT = "code_format"
|
||||
CONF_CODE_TRIGGER_REQUIRED = "code_trigger_required"
|
||||
CONF_COMMAND_TEMPLATE = "command_template"
|
||||
CONF_COMMAND_TOPIC = "command_topic"
|
||||
CONF_DISCOVERY_PREFIX = "discovery_prefix"
|
||||
@@ -127,7 +131,13 @@ CONF_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic"
|
||||
CONF_OSCILLATION_COMMAND_TEMPLATE = "oscillation_command_template"
|
||||
CONF_OSCILLATION_STATE_TOPIC = "oscillation_state_topic"
|
||||
CONF_OSCILLATION_VALUE_TEMPLATE = "oscillation_value_template"
|
||||
CONF_PAYLOAD_ARM_AWAY = "payload_arm_away"
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS = "payload_arm_custom_bypass"
|
||||
CONF_PAYLOAD_ARM_HOME = "payload_arm_home"
|
||||
CONF_PAYLOAD_ARM_NIGHT = "payload_arm_night"
|
||||
CONF_PAYLOAD_ARM_VACATION = "payload_arm_vacation"
|
||||
CONF_PAYLOAD_CLOSE = "payload_close"
|
||||
CONF_PAYLOAD_DISARM = "payload_disarm"
|
||||
CONF_PAYLOAD_LOCK = "payload_lock"
|
||||
CONF_PAYLOAD_OPEN = "payload_open"
|
||||
CONF_PAYLOAD_OSCILLATION_OFF = "payload_oscillation_off"
|
||||
@@ -137,6 +147,7 @@ CONF_PAYLOAD_RESET_PERCENTAGE = "payload_reset_percentage"
|
||||
CONF_PAYLOAD_RESET_PRESET_MODE = "payload_reset_preset_mode"
|
||||
CONF_PAYLOAD_STOP = "payload_stop"
|
||||
CONF_PAYLOAD_STOP_TILT = "payload_stop_tilt"
|
||||
CONF_PAYLOAD_TRIGGER = "payload_trigger"
|
||||
CONF_PAYLOAD_UNLOCK = "payload_unlock"
|
||||
CONF_PERCENTAGE_COMMAND_TEMPLATE = "percentage_command_template"
|
||||
CONF_PERCENTAGE_COMMAND_TOPIC = "percentage_command_topic"
|
||||
@@ -247,6 +258,7 @@ CONF_CONFIGURATION_URL = "configuration_url"
|
||||
CONF_OBJECT_ID = "object_id"
|
||||
CONF_SUPPORT_URL = "support_url"
|
||||
|
||||
DEFAULT_ALARM_CONTROL_PANEL_COMMAND_TEMPLATE = "{{action}}"
|
||||
DEFAULT_BRIGHTNESS = False
|
||||
DEFAULT_BRIGHTNESS_SCALE = 255
|
||||
DEFAULT_CLIMATE_INITIAL_TEMPERATURE = 21.0
|
||||
@@ -260,8 +272,15 @@ DEFAULT_FLASH_TIME_SHORT = 2
|
||||
DEFAULT_OPTIMISTIC = False
|
||||
DEFAULT_ON_COMMAND_TYPE = "last"
|
||||
DEFAULT_QOS = 0
|
||||
|
||||
DEFAULT_PAYLOAD_ARM_AWAY = "ARM_AWAY"
|
||||
DEFAULT_PAYLOAD_ARM_CUSTOM_BYPASS = "ARM_CUSTOM_BYPASS"
|
||||
DEFAULT_PAYLOAD_ARM_HOME = "ARM_HOME"
|
||||
DEFAULT_PAYLOAD_ARM_NIGHT = "ARM_NIGHT"
|
||||
DEFAULT_PAYLOAD_ARM_VACATION = "ARM_VACATION"
|
||||
DEFAULT_PAYLOAD_AVAILABLE = "online"
|
||||
DEFAULT_PAYLOAD_CLOSE = "CLOSE"
|
||||
DEFAULT_PAYLOAD_DISARM = "DISARM"
|
||||
DEFAULT_PAYLOAD_LOCK = "LOCK"
|
||||
DEFAULT_PAYLOAD_NOT_AVAILABLE = "offline"
|
||||
DEFAULT_PAYLOAD_OFF = "OFF"
|
||||
@@ -270,10 +289,10 @@ DEFAULT_PAYLOAD_OPEN = "OPEN"
|
||||
DEFAULT_PAYLOAD_OSCILLATE_OFF = "oscillate_off"
|
||||
DEFAULT_PAYLOAD_OSCILLATE_ON = "oscillate_on"
|
||||
DEFAULT_PAYLOAD_PRESS = "PRESS"
|
||||
DEFAULT_PAYLOAD_STOP = "STOP"
|
||||
DEFAULT_PAYLOAD_RESET = "None"
|
||||
DEFAULT_PAYLOAD_STOP = "STOP"
|
||||
DEFAULT_PAYLOAD_TRIGGER = "TRIGGER"
|
||||
DEFAULT_PAYLOAD_UNLOCK = "UNLOCK"
|
||||
|
||||
DEFAULT_PORT = 1883
|
||||
DEFAULT_RETAIN = False
|
||||
DEFAULT_TILT_CLOSED_POSITION = 0
|
||||
@@ -303,6 +322,17 @@ TILT_PAYLOAD = "tilt"
|
||||
|
||||
VALUES_ON_COMMAND_TYPE = ["first", "last", "brightness"]
|
||||
|
||||
ALARM_CONTROL_PANEL_SUPPORTED_FEATURES = {
|
||||
"arm_home": AlarmControlPanelEntityFeature.ARM_HOME,
|
||||
"arm_away": AlarmControlPanelEntityFeature.ARM_AWAY,
|
||||
"arm_night": AlarmControlPanelEntityFeature.ARM_NIGHT,
|
||||
"arm_vacation": AlarmControlPanelEntityFeature.ARM_VACATION,
|
||||
"arm_custom_bypass": AlarmControlPanelEntityFeature.ARM_CUSTOM_BYPASS,
|
||||
"trigger": AlarmControlPanelEntityFeature.TRIGGER,
|
||||
}
|
||||
REMOTE_CODE = "REMOTE_CODE"
|
||||
REMOTE_CODE_TEXT = "REMOTE_CODE_TEXT"
|
||||
|
||||
PROTOCOL_31 = "3.1"
|
||||
PROTOCOL_311 = "3.1.1"
|
||||
PROTOCOL_5 = "5"
|
||||
|
@@ -243,6 +243,7 @@
|
||||
"title": "Configure MQTT device \"{mqtt_device}\"",
|
||||
"description": "Please configure specific details for {platform} entity \"{entity}\":",
|
||||
"data": {
|
||||
"alarm_control_panel_code_mode": "Alarm code validation mode",
|
||||
"climate_feature_action": "Current action support",
|
||||
"climate_feature_current_humidity": "Current humidity support",
|
||||
"climate_feature_current_temperature": "Current temperature support",
|
||||
@@ -263,10 +264,12 @@
|
||||
"schema": "Schema",
|
||||
"state_class": "State class",
|
||||
"suggested_display_precision": "Suggested display precision",
|
||||
"supported_features": "Supported features",
|
||||
"temperature_unit": "Temperature unit",
|
||||
"unit_of_measurement": "Unit of measurement"
|
||||
},
|
||||
"data_description": {
|
||||
"alarm_control_panel_code_mode": "Configures how the alarm control panel validates the code. A local code is configured with the entity and is validated by Home Assistant. A remote code is sent to the device and validated remotely. [Learn more.]({url}#code)",
|
||||
"climate_feature_action": "The climate supports reporting the current action.",
|
||||
"climate_feature_current_humidity": "The climate supports reporting the current humidity.",
|
||||
"climate_feature_current_temperature": "The climate supports reporting the current temperature.",
|
||||
@@ -287,6 +290,7 @@
|
||||
"schema": "The schema to use. [Learn more.]({url}#comparison-of-light-mqtt-schemas)",
|
||||
"state_class": "The [State class](https://developers.home-assistant.io/docs/core/entity/sensor/#available-state-classes) of the sensor. [Learn more.]({url}#state_class)",
|
||||
"suggested_display_precision": "The number of decimals which should be used in the {platform} entity state after rounding. [Learn more.]({url}#suggested_display_precision)",
|
||||
"supported_features": "The features that the entity supports.",
|
||||
"temperature_unit": "This determines the native unit of measurement the MQTT climate device works with.",
|
||||
"unit_of_measurement": "Defines the unit of measurement of the sensor, if any."
|
||||
},
|
||||
@@ -308,7 +312,11 @@
|
||||
"data": {
|
||||
"blue_template": "Blue template",
|
||||
"brightness_template": "Brightness template",
|
||||
"code": "Alarm code",
|
||||
"code_format": "Code format",
|
||||
"code_arm_required": "Code arm required",
|
||||
"code_disarm_required": "Code disarm required",
|
||||
"code_trigger_required": "Code trigger required",
|
||||
"command_template": "Command template",
|
||||
"command_topic": "Command topic",
|
||||
"command_off_template": "Command \"off\" template",
|
||||
@@ -341,10 +349,14 @@
|
||||
"data_description": {
|
||||
"blue_template": "[Template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract blue color from the state payload value. Expected result of the template is an integer from 0-255 range.",
|
||||
"brightness_template": "[Template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract brightness from the state payload value. Expected result of the template is an integer from 0-255 range.",
|
||||
"code": "Specifies a code to enable or disable the alarm in the frontend. Note that this blocks sending MQTT message commands to the remote device if the code validation fails. [Learn more.]({url}#code)",
|
||||
"code_format": "A regular expression to validate a supplied code when it is set during the action to open, lock or unlock the MQTT lock. [Learn more.]({url}#code_format)",
|
||||
"code_arm_required": "If set, the code is required to arm the alarm. If not set, the code is not validated.",
|
||||
"code_disarm_required": "If set, the code is required to disarm the alarm. If not set, the code is not validated.",
|
||||
"code_trigger_required": "If set, the code is required to manually trigger the alarm. If not set, the code is not validated.",
|
||||
"command_off_template": "The [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) for \"off\" state changes. Available variables are: `state` and `transition`.",
|
||||
"command_on_template": "The [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) for \"on\" state changes. Available variables: `state`, `brightness`, `color_temp`, `red`, `green`, `blue`, `hue`, `sat`, `flash`, `transition` and `effect`. Values `red`, `green`, `blue` and `brightness` are provided as integers from range 0-255. Value of `hue` is provided as float from range 0-360. Value of `sat` is provided as float from range 0-100. Value of `color_temp` is provided as integer representing Kelvin units.",
|
||||
"command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to render the payload to be published at the command topic.",
|
||||
"command_template": "A [template](https://www.home-assistant.io/docs/configuration/templating/#using-command-templates-with-mqtt) to render the payload to be published at the command topic. [Learn more.]({url}#command_template)",
|
||||
"command_topic": "The publishing topic that will be used to control the {platform} entity. [Learn more.]({url}#command_topic)",
|
||||
"color_temp_template": "[Template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract color temperature in Kelvin from the state payload value. Expected result of the template is an integer.",
|
||||
"force_update": "Sends update events even if the value hasn’t changed. Useful if you want to have meaningful value graphs in history. [Learn more.]({url}#force_update)",
|
||||
@@ -394,6 +406,27 @@
|
||||
"transition": "Enable the transition feature for this light"
|
||||
}
|
||||
},
|
||||
"alarm_control_panel_payload_settings": {
|
||||
"name": "Alarm control panel payload settings",
|
||||
"data": {
|
||||
"payload_arm_away": "Payload \"arm away\"",
|
||||
"payload_arm_custom_bypass": "Payload \"arm custom bypass\"",
|
||||
"payload_arm_disarm": "Payload \"disarm\"",
|
||||
"payload_arm_home": "Payload \"arm home\"",
|
||||
"payload_arm_night": "Payload \"arm night\"",
|
||||
"payload_arm_vacation": "Payload \"arm vacation\"",
|
||||
"payload_trigger": "Payload \"trigger alarm\""
|
||||
},
|
||||
"data_description": {
|
||||
"payload_arm_away": "The payload sent when an \"arm away\" command is issued.",
|
||||
"payload_arm_custom_bypass": "The payload sent when an \"arm custom bypass\" command is issued.",
|
||||
"payload_arm_disarm": "The payload sent when a \"disarm\" command is issued.",
|
||||
"payload_arm_home": "The payload sent when an \"arm home\" command is issued.",
|
||||
"payload_arm_night": "The payload sent when an \"arm night\" command is issued.",
|
||||
"payload_arm_vacation": "The payload sent when an \"arm vacation\" command is issued.",
|
||||
"payload_trigger": "The payload sent when a \"trigger alarm\" command is issued."
|
||||
}
|
||||
},
|
||||
"climate_action_settings": {
|
||||
"name": "Current action settings",
|
||||
"data": {
|
||||
@@ -1070,6 +1103,23 @@
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
"alarm_control_panel_code_mode": {
|
||||
"options": {
|
||||
"local_code": "Local code validation",
|
||||
"remote_code": "Numeric remote code validation",
|
||||
"remote_code_text": "Text remote code validation"
|
||||
}
|
||||
},
|
||||
"alarm_control_panel_features": {
|
||||
"options": {
|
||||
"arm_away": "[%key:component::alarm_control_panel::services::alarm_arm_away::name%]",
|
||||
"arm_custom_bypass": "[%key:component::alarm_control_panel::services::alarm_arm_custom_bypass::name%]",
|
||||
"arm_home": "[%key:component::alarm_control_panel::services::alarm_arm_home::name%]",
|
||||
"arm_night": "[%key:component::alarm_control_panel::services::alarm_arm_night::name%]",
|
||||
"arm_vacation": "[%key:component::alarm_control_panel::services::alarm_arm_vacation::name%]",
|
||||
"trigger": "[%key:component::alarm_control_panel::services::alarm_trigger::name%]"
|
||||
}
|
||||
},
|
||||
"climate_modes": {
|
||||
"options": {
|
||||
"off": "[%key:common::state::off%]",
|
||||
@@ -1223,6 +1273,7 @@
|
||||
},
|
||||
"platform": {
|
||||
"options": {
|
||||
"alarm_control_panel": "[%key:component::alarm_control_panel::title%]",
|
||||
"binary_sensor": "[%key:component::binary_sensor::title%]",
|
||||
"button": "[%key:component::button::title%]",
|
||||
"climate": "[%key:component::climate::title%]",
|
||||
|
@@ -70,6 +70,78 @@ DEFAULT_CONFIG_DEVICE_INFO_MAC = {
|
||||
"configuration_url": "http://example.com",
|
||||
}
|
||||
|
||||
MOCK_SUBENTRY_ALARM_CONTROL_PANEL_COMPONENT_LOCAL_CODE = {
|
||||
"4b06357ef8654e8d9c54cee5bb0e9391": {
|
||||
"platform": "alarm_control_panel",
|
||||
"name": "Alarm",
|
||||
"entity_category": "config",
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{action}}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"code": "1234",
|
||||
"code_arm_required": True,
|
||||
"code_disarm_required": True,
|
||||
"code_trigger_required": True,
|
||||
"payload_arm_away": "ARM_AWAY",
|
||||
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS",
|
||||
"payload_arm_home": "ARM_HOME",
|
||||
"payload_arm_night": "ARM_NIGHT",
|
||||
"payload_arm_vacation": "ARM_VACATION",
|
||||
"payload_trigger": "TRIGGER",
|
||||
"supported_features": ["arm_home", "arm_away", "trigger"],
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/4b06357ef8654e8d9c54cee5bb0e9391",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_ALARM_CONTROL_PANEL_COMPONENT_REMOTE_CODE = {
|
||||
"4b06357ef8654e8d9c54cee5bb0e9392": {
|
||||
"platform": "alarm_control_panel",
|
||||
"name": "Alarm",
|
||||
"entity_category": None,
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{action}}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"code": "REMOTE_CODE",
|
||||
"code_arm_required": True,
|
||||
"code_disarm_required": True,
|
||||
"code_trigger_required": True,
|
||||
"payload_arm_away": "ARM_AWAY",
|
||||
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS",
|
||||
"payload_arm_home": "ARM_HOME",
|
||||
"payload_arm_night": "ARM_NIGHT",
|
||||
"payload_arm_vacation": "ARM_VACATION",
|
||||
"payload_trigger": "TRIGGER",
|
||||
"supported_features": ["arm_home", "arm_away", "arm_custom_bypass"],
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/4b06357ef8654e8d9c54cee5bb0e9392",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_ALARM_CONTROL_PANEL_COMPONENT_REMOTE_CODE_TEXT = {
|
||||
"4b06357ef8654e8d9c54cee5bb0e9393": {
|
||||
"platform": "alarm_control_panel",
|
||||
"name": "Alarm",
|
||||
"entity_category": None,
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{action}}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"code": "REMOTE_CODE_TEXT",
|
||||
"code_arm_required": True,
|
||||
"code_disarm_required": True,
|
||||
"code_trigger_required": True,
|
||||
"payload_arm_away": "ARM_AWAY",
|
||||
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS",
|
||||
"payload_arm_home": "ARM_HOME",
|
||||
"payload_arm_night": "ARM_NIGHT",
|
||||
"payload_arm_vacation": "ARM_VACATION",
|
||||
"payload_trigger": "TRIGGER",
|
||||
"supported_features": ["arm_home", "arm_away", "arm_vacation"],
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/4b06357ef8654e8d9c54cee5bb0e9393",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_BINARY_SENSOR_COMPONENT = {
|
||||
"5b06357ef8654e8d9c54cee5bb0e939b": {
|
||||
"platform": "binary_sensor",
|
||||
@@ -444,6 +516,18 @@ MOCK_NOTIFY_SUBENTRY_DATA_MULTI = {
|
||||
"components": MOCK_SUBENTRY_NOTIFY_COMPONENT1 | MOCK_SUBENTRY_NOTIFY_COMPONENT2,
|
||||
} | MOCK_SUBENTRY_AVAILABILITY_DATA
|
||||
|
||||
MOCK_ALARM_CONTROL_PANEL_LOCAL_CODE_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 0}},
|
||||
"components": MOCK_SUBENTRY_ALARM_CONTROL_PANEL_COMPONENT_LOCAL_CODE,
|
||||
}
|
||||
MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_TEXT_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 1}},
|
||||
"components": MOCK_SUBENTRY_ALARM_CONTROL_PANEL_COMPONENT_REMOTE_CODE_TEXT,
|
||||
}
|
||||
MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 1}},
|
||||
"components": MOCK_SUBENTRY_ALARM_CONTROL_PANEL_COMPONENT_REMOTE_CODE,
|
||||
}
|
||||
MOCK_BINARY_SENSOR_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 2}},
|
||||
"components": MOCK_SUBENTRY_BINARY_SENSOR_COMPONENT,
|
||||
|
@@ -33,6 +33,9 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.service_info.hassio import HassioServiceInfo
|
||||
|
||||
from .common import (
|
||||
MOCK_ALARM_CONTROL_PANEL_LOCAL_CODE_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_TEXT_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_BINARY_SENSOR_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_BUTTON_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_CLIMATE_HIGH_LOW_SUBENTRY_DATA_SINGLE,
|
||||
@@ -2665,6 +2668,113 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
"entity_name",
|
||||
),
|
||||
[
|
||||
(
|
||||
MOCK_ALARM_CONTROL_PANEL_LOCAL_CODE_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 0}},
|
||||
{"name": "Alarm"},
|
||||
{
|
||||
"entity_category": "config",
|
||||
"supported_features": ["arm_home", "arm_away", "trigger"],
|
||||
"alarm_control_panel_code_mode": "local_code",
|
||||
},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{action}}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"code": "1234",
|
||||
"code_arm_required": True,
|
||||
"code_disarm_required": True,
|
||||
"code_trigger_required": True,
|
||||
"retain": False,
|
||||
"alarm_control_panel_payload_settings": {
|
||||
"payload_arm_away": "ARM_AWAY",
|
||||
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS",
|
||||
"payload_arm_home": "ARM_HOME",
|
||||
"payload_arm_night": "ARM_NIGHT",
|
||||
"payload_arm_vacation": "ARM_VACATION",
|
||||
"payload_trigger": "TRIGGER",
|
||||
},
|
||||
},
|
||||
(
|
||||
(
|
||||
{
|
||||
"state_topic": "test-topic",
|
||||
"command_topic": "test-topic#invalid",
|
||||
},
|
||||
{"command_topic": "invalid_publish_topic"},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic#invalid",
|
||||
},
|
||||
{"state_topic": "invalid_subscribe_topic"},
|
||||
),
|
||||
),
|
||||
"Milk notifier Alarm",
|
||||
),
|
||||
(
|
||||
MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 1}},
|
||||
{"name": "Alarm"},
|
||||
{
|
||||
"supported_features": ["arm_home", "arm_away", "arm_custom_bypass"],
|
||||
"alarm_control_panel_code_mode": "remote_code",
|
||||
},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{action}}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"code_arm_required": True,
|
||||
"code_disarm_required": True,
|
||||
"code_trigger_required": True,
|
||||
"retain": False,
|
||||
"alarm_control_panel_payload_settings": {
|
||||
"payload_arm_away": "ARM_AWAY",
|
||||
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS",
|
||||
"payload_arm_home": "ARM_HOME",
|
||||
"payload_arm_night": "ARM_NIGHT",
|
||||
"payload_arm_vacation": "ARM_VACATION",
|
||||
"payload_trigger": "TRIGGER",
|
||||
},
|
||||
},
|
||||
(),
|
||||
"Milk notifier Alarm",
|
||||
),
|
||||
(
|
||||
MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_TEXT_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 2}},
|
||||
{"name": "Alarm"},
|
||||
{
|
||||
"supported_features": ["arm_home", "arm_away", "arm_vacation"],
|
||||
"alarm_control_panel_code_mode": "remote_code_text",
|
||||
},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{action}}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"code_arm_required": True,
|
||||
"code_disarm_required": True,
|
||||
"code_trigger_required": True,
|
||||
"retain": False,
|
||||
"alarm_control_panel_payload_settings": {
|
||||
"payload_arm_away": "ARM_AWAY",
|
||||
"payload_arm_custom_bypass": "ARM_CUSTOM_BYPASS",
|
||||
"payload_arm_home": "ARM_HOME",
|
||||
"payload_arm_night": "ARM_NIGHT",
|
||||
"payload_arm_vacation": "ARM_VACATION",
|
||||
"payload_trigger": "TRIGGER",
|
||||
},
|
||||
},
|
||||
(),
|
||||
"Milk notifier Alarm",
|
||||
),
|
||||
(
|
||||
MOCK_BINARY_SENSOR_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 2}},
|
||||
@@ -3399,6 +3509,9 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
# MOCK_LOCK_SUBENTRY_DATA_SINGLE
|
||||
],
|
||||
ids=[
|
||||
"alarm_control_panel_local_code",
|
||||
"alarm_control_panel_remote_code",
|
||||
"alarm_control_panel_remote_code_text",
|
||||
"binary_sensor",
|
||||
"button",
|
||||
"climate_single",
|
||||
@@ -3830,6 +3943,67 @@ async def test_subentry_reconfigure_edit_entity_multi_entitites(
|
||||
"removed_options",
|
||||
),
|
||||
[
|
||||
(
|
||||
(
|
||||
ConfigSubentryData(
|
||||
data=MOCK_ALARM_CONTROL_PANEL_LOCAL_CODE_SUBENTRY_DATA_SINGLE,
|
||||
subentry_type="device",
|
||||
title="Mock subentry",
|
||||
),
|
||||
),
|
||||
(),
|
||||
{
|
||||
"alarm_control_panel_code_mode": "remote_code",
|
||||
"supported_features": ["arm_home", "arm_away", "arm_custom_bypass"],
|
||||
},
|
||||
{
|
||||
"command_topic": "test-topic1-updated",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic1-updated",
|
||||
"value_template": "{{ value }}",
|
||||
"retain": True,
|
||||
},
|
||||
{
|
||||
"command_topic": "test-topic1-updated",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic1-updated",
|
||||
"value_template": "{{ value }}",
|
||||
"retain": True,
|
||||
"code": "REMOTE_CODE",
|
||||
},
|
||||
{"entity_picture"},
|
||||
),
|
||||
(
|
||||
(
|
||||
ConfigSubentryData(
|
||||
data=MOCK_ALARM_CONTROL_PANEL_REMOTE_CODE_SUBENTRY_DATA_SINGLE,
|
||||
subentry_type="device",
|
||||
title="Mock subentry",
|
||||
),
|
||||
),
|
||||
(),
|
||||
{
|
||||
"alarm_control_panel_code_mode": "local_code",
|
||||
"supported_features": ["arm_home", "arm_away", "arm_custom_bypass"],
|
||||
},
|
||||
{
|
||||
"command_topic": "test-topic1-updated",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic1-updated",
|
||||
"value_template": "{{ value }}",
|
||||
"code": "1234",
|
||||
"retain": True,
|
||||
},
|
||||
{
|
||||
"command_topic": "test-topic1-updated",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic1-updated",
|
||||
"value_template": "{{ value }}",
|
||||
"code": "1234",
|
||||
"retain": True,
|
||||
},
|
||||
{"entity_picture"},
|
||||
),
|
||||
(
|
||||
(
|
||||
ConfigSubentryData(
|
||||
@@ -4053,7 +4227,15 @@ async def test_subentry_reconfigure_edit_entity_multi_entitites(
|
||||
{"entity_picture"},
|
||||
),
|
||||
],
|
||||
ids=["notify", "sensor", "light_basic", "climate_single", "climate_high_low"],
|
||||
ids=[
|
||||
"alarm_control_panel_local_code",
|
||||
"alarm_control_panel_remote_code",
|
||||
"notify",
|
||||
"sensor",
|
||||
"light_basic",
|
||||
"climate_single",
|
||||
"climate_high_low",
|
||||
],
|
||||
)
|
||||
async def test_subentry_reconfigure_edit_entity_single_entity(
|
||||
hass: HomeAssistant,
|
||||
@@ -4123,7 +4305,6 @@ async def test_subentry_reconfigure_edit_entity_single_entity(
|
||||
user_input={},
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "entity_platform_config"
|
||||
|
||||
# entity platform config flow step
|
||||
assert result["step_id"] == "entity_platform_config"
|
||||
|
Reference in New Issue
Block a user