mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add switch as entity platform on MQTT subentries (#140658)
This commit is contained in:
parent
57f65c205e
commit
febc455bc5
@ -33,6 +33,7 @@ from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.components.switch import SwitchDeviceClass
|
||||
from homeassistant.config_entries import (
|
||||
SOURCE_RECONFIGURE,
|
||||
ConfigEntry,
|
||||
@ -55,6 +56,7 @@ from homeassistant.const import (
|
||||
CONF_DISCOVERY,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_OPTIMISTIC,
|
||||
CONF_PASSWORD,
|
||||
CONF_PAYLOAD,
|
||||
CONF_PLATFORM,
|
||||
@ -233,7 +235,7 @@ KEY_UPLOAD_SELECTOR = FileSelector(
|
||||
)
|
||||
|
||||
# Subentry selectors
|
||||
SUBENTRY_PLATFORMS = [Platform.NOTIFY, Platform.SENSOR]
|
||||
SUBENTRY_PLATFORMS = [Platform.NOTIFY, Platform.SENSOR, Platform.SWITCH]
|
||||
SUBENTRY_PLATFORM_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=[platform.value for platform in SUBENTRY_PLATFORMS],
|
||||
@ -286,6 +288,15 @@ EXPIRE_AFTER_SELECTOR = NumberSelector(
|
||||
NumberSelectorConfig(mode=NumberSelectorMode.BOX, min=0)
|
||||
)
|
||||
|
||||
# Switch specific selectors
|
||||
SWITCH_DEVICE_CLASS_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=[device_class.value for device_class in SwitchDeviceClass],
|
||||
mode=SelectSelectorMode.DROPDOWN,
|
||||
translation_key="device_class_switch",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def validate_sensor_platform_config(
|
||||
@ -390,6 +401,9 @@ PLATFORM_ENTITY_FIELDS = {
|
||||
conditions=({"device_class": "enum"},),
|
||||
),
|
||||
},
|
||||
Platform.SWITCH.value: {
|
||||
CONF_DEVICE_CLASS: PlatformField(SWITCH_DEVICE_CLASS_SELECTOR, False, str),
|
||||
},
|
||||
}
|
||||
PLATFORM_MQTT_FIELDS = {
|
||||
Platform.NOTIFY.value: {
|
||||
@ -419,6 +433,22 @@ PLATFORM_MQTT_FIELDS = {
|
||||
EXPIRE_AFTER_SELECTOR, False, cv.positive_int, section="advanced_settings"
|
||||
),
|
||||
},
|
||||
Platform.SWITCH.value: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
TEXT_SELECTOR, True, valid_publish_topic, "invalid_publish_topic"
|
||||
),
|
||||
CONF_COMMAND_TEMPLATE: PlatformField(
|
||||
TEMPLATE_SELECTOR, False, cv.template, "invalid_template"
|
||||
),
|
||||
CONF_STATE_TOPIC: PlatformField(
|
||||
TEXT_SELECTOR, False, valid_subscribe_topic, "invalid_subscribe_topic"
|
||||
),
|
||||
CONF_VALUE_TEMPLATE: PlatformField(
|
||||
TEMPLATE_SELECTOR, False, cv.template, "invalid_template"
|
||||
),
|
||||
CONF_RETAIN: PlatformField(BOOLEAN_SELECTOR, False, bool),
|
||||
CONF_OPTIMISTIC: PlatformField(BOOLEAN_SELECTOR, False, bool),
|
||||
},
|
||||
}
|
||||
ENTITY_CONFIG_VALIDATOR: dict[
|
||||
str,
|
||||
@ -426,6 +456,7 @@ ENTITY_CONFIG_VALIDATOR: dict[
|
||||
] = {
|
||||
Platform.NOTIFY.value: None,
|
||||
Platform.SENSOR.value: validate_sensor_platform_config,
|
||||
Platform.SWITCH.value: None,
|
||||
}
|
||||
|
||||
MQTT_DEVICE_PLATFORM_FIELDS = {
|
||||
|
@ -246,7 +246,9 @@
|
||||
"value_template": "Value template",
|
||||
"last_reset_value_template": "Last reset value template",
|
||||
"force_update": "Force update",
|
||||
"retain": "Retain"
|
||||
"optimistic": "Optimistic",
|
||||
"retain": "Retain",
|
||||
"qos": "QoS"
|
||||
},
|
||||
"data_description": {
|
||||
"command_topic": "The publishing topic that will be used to control the {platform} entity. [Learn more.]({url}#command_topic)",
|
||||
@ -255,7 +257,9 @@
|
||||
"value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract the {platform} entity value.",
|
||||
"last_reset_value_template": "Defines a [template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract the last reset. When Last reset template is set, the State class option must be Total. [Learn more.]({url}#last_reset_value_template)",
|
||||
"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)",
|
||||
"retain": "Select if values published by the {platform} entity should be retained at the MQTT broker."
|
||||
"optimistic": "Flag that defines if the {platform} entity works in optimistic mode. [Learn more.]({url}#optimistic)",
|
||||
"retain": "Select if values published by the {platform} entity should be retained at the MQTT broker.",
|
||||
"qos": "The QoS value {platform} entity should use."
|
||||
},
|
||||
"sections": {
|
||||
"advanced_settings": {
|
||||
@ -462,10 +466,17 @@
|
||||
"wind_speed": "[%key:component::sensor::entity_component::wind_speed::name%]"
|
||||
}
|
||||
},
|
||||
"device_class_switch": {
|
||||
"options": {
|
||||
"outlet": "[%key:component::switch::entity_component::outlet::name%]",
|
||||
"switch": "[%key:component::switch::title%]"
|
||||
}
|
||||
},
|
||||
"platform": {
|
||||
"options": {
|
||||
"notify": "Notify",
|
||||
"sensor": "Sensor"
|
||||
"sensor": "Sensor",
|
||||
"switch": "Switch"
|
||||
}
|
||||
},
|
||||
"set_ca_cert": {
|
||||
|
@ -125,6 +125,19 @@ MOCK_SUBENTRY_SENSOR_COMPONENT_LAST_RESET = {
|
||||
"entity_picture": "https://example.com/e9261f6feed443e7b7d5f3fbe2a47412",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_SWITCH_COMPONENT = {
|
||||
"3faf1318016c46c5aea26707eeb6f12e": {
|
||||
"platform": "switch",
|
||||
"name": "Outlet",
|
||||
"device_class": "outlet",
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"entity_picture": "https://example.com/3faf1318016c46c5aea26707eeb6f12e",
|
||||
"optimistic": True,
|
||||
},
|
||||
}
|
||||
|
||||
# Bogus light component just for code coverage
|
||||
# Note that light cannot be setup through the UI yet
|
||||
@ -223,7 +236,17 @@ MOCK_SENSOR_SUBENTRY_DATA_SINGLE_LAST_RESET_TEMPLATE = {
|
||||
},
|
||||
"components": MOCK_SUBENTRY_SENSOR_COMPONENT_LAST_RESET,
|
||||
}
|
||||
|
||||
MOCK_SWITCH_SUBENTRY_DATA_SINGLE_STATE_CLASS = {
|
||||
"device": {
|
||||
"name": "Test switch",
|
||||
"sw_version": "1.0",
|
||||
"hw_version": "2.1 rev a",
|
||||
"model": "Model XL",
|
||||
"model_id": "mn002",
|
||||
"configuration_url": "https://example.com",
|
||||
},
|
||||
"components": MOCK_SUBENTRY_SWITCH_COMPONENT,
|
||||
}
|
||||
MOCK_SUBENTRY_DATA_BAD_COMPONENT_SCHEMA = {
|
||||
"device": {
|
||||
"name": "Milk notifier",
|
||||
@ -246,7 +269,8 @@ MOCK_SUBENTRY_DATA_SET_MIX = {
|
||||
},
|
||||
"components": MOCK_SUBENTRY_NOTIFY_COMPONENT1
|
||||
| MOCK_SUBENTRY_NOTIFY_COMPONENT2
|
||||
| MOCK_SUBENTRY_LIGHT_COMPONENT,
|
||||
| MOCK_SUBENTRY_LIGHT_COMPONENT
|
||||
| MOCK_SUBENTRY_SWITCH_COMPONENT,
|
||||
} | MOCK_SUBENTRY_AVAILABILITY_DATA
|
||||
_SENTINEL = object()
|
||||
|
||||
|
@ -39,6 +39,7 @@ from .common import (
|
||||
MOCK_SENSOR_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_SENSOR_SUBENTRY_DATA_SINGLE_LAST_RESET_TEMPLATE,
|
||||
MOCK_SENSOR_SUBENTRY_DATA_SINGLE_STATE_CLASS,
|
||||
MOCK_SWITCH_SUBENTRY_DATA_SINGLE_STATE_CLASS,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry, MockMqttReasonCode
|
||||
@ -2733,12 +2734,41 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
(),
|
||||
"Test sensor Energy",
|
||||
),
|
||||
(
|
||||
MOCK_SWITCH_SUBENTRY_DATA_SINGLE_STATE_CLASS,
|
||||
{"name": "Test switch", "mqtt_settings": {"qos": 0}},
|
||||
{"name": "Outlet"},
|
||||
{"device_class": "outlet"},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"state_topic": "test-topic",
|
||||
"value_template": "{{ value_json.value }}",
|
||||
"optimistic": True,
|
||||
},
|
||||
(
|
||||
(
|
||||
{"command_topic": "test-topic#invalid"},
|
||||
{"command_topic": "invalid_publish_topic"},
|
||||
),
|
||||
(
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"state_topic": "test-topic#invalid",
|
||||
},
|
||||
{"state_topic": "invalid_subscribe_topic"},
|
||||
),
|
||||
),
|
||||
"Test switch Outlet",
|
||||
),
|
||||
],
|
||||
ids=[
|
||||
"notify_with_entity_name",
|
||||
"notify_no_entity_name",
|
||||
"sensor_options",
|
||||
"sensor_total",
|
||||
"switch",
|
||||
],
|
||||
)
|
||||
async def test_subentry_configflow(
|
||||
|
Loading…
x
Reference in New Issue
Block a user