mirror of
https://github.com/home-assistant/core.git
synced 2025-06-24 17:11:53 +02:00
Add MQTT button as entity platform on MQTT subentries (#144204)
This commit is contained in:
@ -14,7 +14,13 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .config import DEFAULT_RETAIN, MQTT_BASE_SCHEMA
|
||||
from .const import CONF_COMMAND_TEMPLATE, CONF_COMMAND_TOPIC, CONF_RETAIN
|
||||
from .const import (
|
||||
CONF_COMMAND_TEMPLATE,
|
||||
CONF_COMMAND_TOPIC,
|
||||
CONF_PAYLOAD_PRESS,
|
||||
CONF_RETAIN,
|
||||
DEFAULT_PAYLOAD_PRESS,
|
||||
)
|
||||
from .entity import MqttEntity, async_setup_entity_entry_helper
|
||||
from .models import MqttCommandTemplate
|
||||
from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
||||
@ -22,9 +28,7 @@ from .util import valid_publish_topic
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
CONF_PAYLOAD_PRESS = "payload_press"
|
||||
DEFAULT_NAME = "MQTT Button"
|
||||
DEFAULT_PAYLOAD_PRESS = "PRESS"
|
||||
|
||||
PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||
{
|
||||
|
@ -26,6 +26,7 @@ from cryptography.x509 import load_der_x509_certificate, load_pem_x509_certifica
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.components.button import ButtonDeviceClass
|
||||
from homeassistant.components.file_upload import process_uploaded_file
|
||||
from homeassistant.components.hassio import AddonError, AddonManager, AddonState
|
||||
from homeassistant.components.light import (
|
||||
@ -163,6 +164,7 @@ from .const import (
|
||||
CONF_OPTIONS,
|
||||
CONF_PAYLOAD_AVAILABLE,
|
||||
CONF_PAYLOAD_NOT_AVAILABLE,
|
||||
CONF_PAYLOAD_PRESS,
|
||||
CONF_QOS,
|
||||
CONF_RED_TEMPLATE,
|
||||
CONF_RETAIN,
|
||||
@ -206,6 +208,7 @@ from .const import (
|
||||
DEFAULT_PAYLOAD_NOT_AVAILABLE,
|
||||
DEFAULT_PAYLOAD_OFF,
|
||||
DEFAULT_PAYLOAD_ON,
|
||||
DEFAULT_PAYLOAD_PRESS,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_PREFIX,
|
||||
DEFAULT_PROTOCOL,
|
||||
@ -309,6 +312,7 @@ KEY_UPLOAD_SELECTOR = FileSelector(
|
||||
# Subentry selectors
|
||||
SUBENTRY_PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.BUTTON,
|
||||
Platform.LIGHT,
|
||||
Platform.NOTIFY,
|
||||
Platform.SENSOR,
|
||||
@ -353,6 +357,14 @@ BINARY_SENSOR_DEVICE_CLASS_SELECTOR = SelectSelector(
|
||||
sort=True,
|
||||
)
|
||||
)
|
||||
BUTTON_DEVICE_CLASS_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=[device_class.value for device_class in ButtonDeviceClass],
|
||||
mode=SelectSelectorMode.DROPDOWN,
|
||||
translation_key="device_class_button",
|
||||
sort=True,
|
||||
)
|
||||
)
|
||||
SENSOR_STATE_CLASS_SELECTOR = SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=[device_class.value for device_class in SensorStateClass],
|
||||
@ -546,6 +558,13 @@ PLATFORM_ENTITY_FIELDS = {
|
||||
validator=str,
|
||||
),
|
||||
},
|
||||
Platform.BUTTON.value: {
|
||||
CONF_DEVICE_CLASS: PlatformField(
|
||||
selector=BUTTON_DEVICE_CLASS_SELECTOR,
|
||||
required=False,
|
||||
validator=str,
|
||||
),
|
||||
},
|
||||
Platform.NOTIFY.value: {},
|
||||
Platform.SENSOR.value: {
|
||||
CONF_DEVICE_CLASS: PlatformField(
|
||||
@ -634,6 +653,29 @@ PLATFORM_MQTT_FIELDS = {
|
||||
section="advanced_settings",
|
||||
),
|
||||
},
|
||||
Platform.BUTTON.value: {
|
||||
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,
|
||||
validator=cv.template,
|
||||
error="invalid_template",
|
||||
),
|
||||
CONF_PAYLOAD_PRESS: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
required=False,
|
||||
validator=str,
|
||||
default=DEFAULT_PAYLOAD_PRESS,
|
||||
),
|
||||
CONF_RETAIN: PlatformField(
|
||||
selector=BOOLEAN_SELECTOR, required=False, validator=bool
|
||||
),
|
||||
},
|
||||
Platform.NOTIFY.value: {
|
||||
CONF_COMMAND_TOPIC: PlatformField(
|
||||
selector=TEXT_SELECTOR,
|
||||
@ -1206,6 +1248,7 @@ ENTITY_CONFIG_VALIDATOR: dict[
|
||||
Callable[[dict[str, Any]], dict[str, str]] | None,
|
||||
] = {
|
||||
Platform.BINARY_SENSOR.value: None,
|
||||
Platform.BUTTON.value: None,
|
||||
Platform.LIGHT.value: validate_light_platform_config,
|
||||
Platform.NOTIFY.value: None,
|
||||
Platform.SENSOR.value: validate_sensor_platform_config,
|
||||
|
@ -109,6 +109,7 @@ CONF_OFF_DELAY = "off_delay"
|
||||
CONF_ON_COMMAND_TYPE = "on_command_type"
|
||||
CONF_PAYLOAD_CLOSE = "payload_close"
|
||||
CONF_PAYLOAD_OPEN = "payload_open"
|
||||
CONF_PAYLOAD_PRESS = "payload_press"
|
||||
CONF_PAYLOAD_STOP = "payload_stop"
|
||||
CONF_POSITION_CLOSED = "position_closed"
|
||||
CONF_POSITION_OPEN = "position_open"
|
||||
@ -188,6 +189,7 @@ DEFAULT_PAYLOAD_NOT_AVAILABLE = "offline"
|
||||
DEFAULT_PAYLOAD_OFF = "OFF"
|
||||
DEFAULT_PAYLOAD_ON = "ON"
|
||||
DEFAULT_PAYLOAD_OPEN = "OPEN"
|
||||
DEFAULT_PAYLOAD_PRESS = "PRESS"
|
||||
DEFAULT_PORT = 1883
|
||||
DEFAULT_RETAIN = False
|
||||
DEFAULT_WS_HEADERS: dict[str, str] = {}
|
||||
|
@ -258,6 +258,7 @@
|
||||
"optimistic": "Optimistic",
|
||||
"payload_off": "Payload \"off\"",
|
||||
"payload_on": "Payload \"on\"",
|
||||
"payload_press": "Payload \"press\"",
|
||||
"qos": "QoS",
|
||||
"red_template": "Red template",
|
||||
"retain": "Retain",
|
||||
@ -282,6 +283,7 @@
|
||||
"optimistic": "Flag that defines if the {platform} entity works in optimistic mode. [Learn more.]({url}#optimistic)",
|
||||
"payload_off": "The payload that represents the \"off\" state.",
|
||||
"payload_on": "The payload that represents the \"on\" state.",
|
||||
"payload_press": "The payload to send when the button is triggered.",
|
||||
"qos": "The QoS value a {platform} entity should use.",
|
||||
"red_template": "[Template](https://www.home-assistant.io/docs/configuration/templating/#using-value-templates-with-mqtt) to extract red color from the state payload value. Expected result of the template is an integer from 0-255 range.",
|
||||
"retain": "Select if values published by the {platform} entity should be retained at the MQTT broker.",
|
||||
@ -634,6 +636,13 @@
|
||||
"window": "[%key:component::binary_sensor::entity_component::window::name%]"
|
||||
}
|
||||
},
|
||||
"device_class_button": {
|
||||
"options": {
|
||||
"identify": "[%key:component::button::entity_component::identify::name%]",
|
||||
"restart": "[%key:common::action::restart%]",
|
||||
"update": "[%key:component::button::entity_component::update::name%]"
|
||||
}
|
||||
},
|
||||
"device_class_sensor": {
|
||||
"options": {
|
||||
"apparent_power": "[%key:component::sensor::entity_component::apparent_power::name%]",
|
||||
@ -717,6 +726,7 @@
|
||||
"platform": {
|
||||
"options": {
|
||||
"binary_sensor": "[%key:component::binary_sensor::title%]",
|
||||
"button": "[%key:component::button::title%]",
|
||||
"light": "[%key:component::light::title%]",
|
||||
"notify": "[%key:component::notify::title%]",
|
||||
"sensor": "[%key:component::sensor::title%]",
|
||||
|
@ -80,6 +80,18 @@ MOCK_SUBENTRY_BINARY_SENSOR_COMPONENT = {
|
||||
"entity_picture": "https://example.com/5b06357ef8654e8d9c54cee5bb0e939b",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_BUTTON_COMPONENT = {
|
||||
"365d05e6607c4dfb8ae915cff71a954b": {
|
||||
"platform": "button",
|
||||
"name": "Restart",
|
||||
"device_class": "restart",
|
||||
"command_topic": "test-topic",
|
||||
"payload_press": "PRESS",
|
||||
"command_template": "{{ value }}",
|
||||
"retain": False,
|
||||
"entity_picture": "https://example.com/365d05e6607c4dfb8ae915cff71a954b",
|
||||
},
|
||||
}
|
||||
MOCK_SUBENTRY_NOTIFY_COMPONENT1 = {
|
||||
"363a7ecad6be4a19b939a016ea93e994": {
|
||||
"platform": "notify",
|
||||
@ -205,6 +217,10 @@ MOCK_BINARY_SENSOR_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 2}},
|
||||
"components": MOCK_SUBENTRY_BINARY_SENSOR_COMPONENT,
|
||||
}
|
||||
MOCK_BUTTON_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 2}},
|
||||
"components": MOCK_SUBENTRY_BUTTON_COMPONENT,
|
||||
}
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_SINGLE = {
|
||||
"device": MOCK_SUBENTRY_DEVICE_DATA | {"mqtt_settings": {"qos": 1}},
|
||||
"components": MOCK_SUBENTRY_NOTIFY_COMPONENT1,
|
||||
|
@ -34,6 +34,7 @@ from homeassistant.helpers.service_info.hassio import HassioServiceInfo
|
||||
|
||||
from .common import (
|
||||
MOCK_BINARY_SENSOR_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_BUTTON_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_LIGHT_BASIC_KELVIN_SUBENTRY_DATA_SINGLE,
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_MULTI,
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_NO_NAME,
|
||||
@ -2677,6 +2678,26 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
),
|
||||
"Milk notifier Hatch",
|
||||
),
|
||||
(
|
||||
MOCK_BUTTON_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 2}},
|
||||
{"name": "Restart"},
|
||||
{"device_class": "restart"},
|
||||
(),
|
||||
{
|
||||
"command_topic": "test-topic",
|
||||
"command_template": "{{ value }}",
|
||||
"payload_press": "PRESS",
|
||||
"retain": False,
|
||||
},
|
||||
(
|
||||
(
|
||||
{"command_topic": "test-topic#invalid"},
|
||||
{"command_topic": "invalid_publish_topic"},
|
||||
),
|
||||
),
|
||||
"Milk notifier Restart",
|
||||
),
|
||||
(
|
||||
MOCK_NOTIFY_SUBENTRY_DATA_SINGLE,
|
||||
{"name": "Milk notifier", "mqtt_settings": {"qos": 1}},
|
||||
@ -2853,6 +2874,7 @@ async def test_migrate_of_incompatible_config_entry(
|
||||
],
|
||||
ids=[
|
||||
"binary_sensor",
|
||||
"button",
|
||||
"notify_with_entity_name",
|
||||
"notify_no_entity_name",
|
||||
"sensor_options",
|
||||
|
Reference in New Issue
Block a user