mirror of
https://github.com/home-assistant/core.git
synced 2026-09-25 17:04:04 -04:00
Add stop action to MQTT lawn mower (#181192)
This commit is contained in:
@@ -215,6 +215,8 @@ ABBREVIATIONS = {
|
||||
"stat_tpl": "state_template",
|
||||
"stat_val_tpl": "state_value_template",
|
||||
"step": "step",
|
||||
"stop_cmd_t": "stop_command_topic",
|
||||
"stop_cmd_tpl": "stop_command_template",
|
||||
"strt_mw_cmd_t": "start_mowing_command_topic",
|
||||
"strt_mw_cmd_tpl": "start_mowing_command_template",
|
||||
"stype": "subtype",
|
||||
|
||||
@@ -48,6 +48,8 @@ CONF_PAUSE_COMMAND_TOPIC = "pause_command_topic"
|
||||
CONF_PAUSE_COMMAND_TEMPLATE = "pause_command_template"
|
||||
CONF_START_MOWING_COMMAND_TOPIC = "start_mowing_command_topic"
|
||||
CONF_START_MOWING_COMMAND_TEMPLATE = "start_mowing_command_template"
|
||||
CONF_STOP_COMMAND_TOPIC = "stop_command_topic"
|
||||
CONF_STOP_COMMAND_TEMPLATE = "stop_command_template"
|
||||
|
||||
DEFAULT_NAME = "MQTT Lawn Mower"
|
||||
|
||||
@@ -56,6 +58,7 @@ MQTT_LAWN_MOWER_ATTRIBUTES_BLOCKED: frozenset[str] = frozenset()
|
||||
FEATURE_DOCK = "dock"
|
||||
FEATURE_PAUSE = "pause"
|
||||
FEATURE_START_MOWING = "start_mowing"
|
||||
FEATURE_STOP = "stop"
|
||||
|
||||
PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||
{
|
||||
@@ -70,6 +73,8 @@ PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
||||
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||
vol.Optional(CONF_START_MOWING_COMMAND_TEMPLATE): cv.template,
|
||||
vol.Optional(CONF_START_MOWING_COMMAND_TOPIC): valid_publish_topic,
|
||||
vol.Optional(CONF_STOP_COMMAND_TEMPLATE): cv.template,
|
||||
vol.Optional(CONF_STOP_COMMAND_TOPIC): valid_publish_topic,
|
||||
},
|
||||
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
||||
|
||||
@@ -130,6 +135,9 @@ class MqttLawnMower(MqttEntity, LawnMowerEntity, RestoreEntity):
|
||||
CONF_START_MOWING_COMMAND_TOPIC
|
||||
]
|
||||
supported_features |= LawnMowerEntityFeature.START_MOWING
|
||||
if CONF_STOP_COMMAND_TOPIC in config:
|
||||
self._command_topics[FEATURE_STOP] = config[CONF_STOP_COMMAND_TOPIC]
|
||||
supported_features |= LawnMowerEntityFeature.STOP
|
||||
self._attr_supported_features = supported_features
|
||||
self._command_templates = {}
|
||||
self._command_templates[FEATURE_DOCK] = MqttCommandTemplate(
|
||||
@@ -141,6 +149,9 @@ class MqttLawnMower(MqttEntity, LawnMowerEntity, RestoreEntity):
|
||||
self._command_templates[FEATURE_START_MOWING] = MqttCommandTemplate(
|
||||
config.get(CONF_START_MOWING_COMMAND_TEMPLATE), entity=self
|
||||
).async_render
|
||||
self._command_templates[FEATURE_STOP] = MqttCommandTemplate(
|
||||
config.get(CONF_STOP_COMMAND_TEMPLATE), entity=self
|
||||
).async_render
|
||||
|
||||
@callback
|
||||
def _message_received(self, msg: ReceiveMessage) -> None:
|
||||
@@ -212,3 +223,8 @@ class MqttLawnMower(MqttEntity, LawnMowerEntity, RestoreEntity):
|
||||
async def async_pause(self) -> None:
|
||||
"""Pause the lawn mower."""
|
||||
await self._async_operate("pause", LawnMowerActivity.PAUSED)
|
||||
|
||||
@override
|
||||
async def async_stop(self) -> None:
|
||||
"""Stop the lawn mower."""
|
||||
await self._async_operate("stop", LawnMowerActivity.IDLE)
|
||||
|
||||
@@ -13,6 +13,7 @@ from homeassistant.components.lawn_mower import (
|
||||
SERVICE_DOCK,
|
||||
SERVICE_PAUSE,
|
||||
SERVICE_START_MOWING,
|
||||
SERVICE_STOP,
|
||||
LawnMowerEntityFeature,
|
||||
)
|
||||
from homeassistant.components.mqtt.const import DOMAIN
|
||||
@@ -61,6 +62,7 @@ DEFAULT_FEATURES = (
|
||||
LawnMowerEntityFeature.START_MOWING
|
||||
| LawnMowerEntityFeature.PAUSE
|
||||
| LawnMowerEntityFeature.DOCK
|
||||
| LawnMowerEntityFeature.STOP
|
||||
)
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
@@ -70,6 +72,7 @@ DEFAULT_CONFIG = {
|
||||
"dock_command_topic": "dock-test-topic",
|
||||
"pause_command_topic": "pause-test-topic",
|
||||
"start_mowing_command_topic": "start_mowing-test-topic",
|
||||
"stop_command_topic": "stop-test-topic",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +114,13 @@ async def test_run_lawn_mower_setup_and_state_updates(
|
||||
state = hass.states.get("lawn_mower.test_lawn_mower")
|
||||
assert state.state == "returning"
|
||||
|
||||
async_fire_mqtt_message(hass, "test/lawn_mower_stat", "idle")
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("lawn_mower.test_lawn_mower")
|
||||
assert state.state == "idle"
|
||||
|
||||
async_fire_mqtt_message(hass, "test/lawn_mower_stat", "docked")
|
||||
|
||||
await hass.async_block_till_done()
|
||||
@@ -157,6 +167,17 @@ async def test_run_lawn_mower_setup_and_state_updates(
|
||||
},
|
||||
LawnMowerEntityFeature.START_MOWING | LawnMowerEntityFeature.DOCK,
|
||||
),
|
||||
(
|
||||
{
|
||||
DOMAIN: {
|
||||
lawn_mower.DOMAIN: {
|
||||
"stop_command_topic": "stop-test-topic",
|
||||
"name": "test",
|
||||
}
|
||||
}
|
||||
},
|
||||
LawnMowerEntityFeature.STOP,
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_supported_features(
|
||||
@@ -285,6 +306,20 @@ async def test_run_lawn_mower_service_optimistic(
|
||||
state = hass.states.get("lawn_mower.test")
|
||||
assert state.state == "docked"
|
||||
|
||||
await hass.services.async_call(
|
||||
lawn_mower.DOMAIN,
|
||||
SERVICE_STOP,
|
||||
{ATTR_ENTITY_ID: "lawn_mower.test"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
"stop-test-topic", "stop", 0, False, message_expiry_interval=None
|
||||
)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
state = hass.states.get("lawn_mower.test")
|
||||
assert state.state == "idle"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"hass_config",
|
||||
@@ -325,6 +360,8 @@ async def test_restore_lawn_mower_from_invalid_state(
|
||||
"pause_command_template": '{"action": "{{ value }}"}',
|
||||
"start_mowing_command_topic": "test/lawn_mower_start_mowing_cmd",
|
||||
"start_mowing_command_template": '{"action": "{{ value }}"}',
|
||||
"stop_command_topic": "test/lawn_mower_stop_cmd",
|
||||
"stop_command_template": '{"action": "{{ value }}"}',
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,6 +434,24 @@ async def test_run_lawn_mower_service_optimistic_with_command_templates(
|
||||
state = hass.states.get("lawn_mower.test_lawn_mower")
|
||||
assert state.state == "docked"
|
||||
|
||||
await hass.services.async_call(
|
||||
lawn_mower.DOMAIN,
|
||||
SERVICE_STOP,
|
||||
{ATTR_ENTITY_ID: "lawn_mower.test_lawn_mower"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
"test/lawn_mower_stop_cmd",
|
||||
'{"action": "stop"}',
|
||||
0,
|
||||
False,
|
||||
message_expiry_interval=None,
|
||||
)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
state = hass.states.get("lawn_mower.test_lawn_mower")
|
||||
assert state.state == "idle"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
|
||||
async def test_availability_when_connection_lost(
|
||||
@@ -675,6 +730,13 @@ async def test_entity_id_update_discovery_update(
|
||||
"test/lawn_mower_stat",
|
||||
"dock-test-topic",
|
||||
),
|
||||
(
|
||||
SERVICE_STOP,
|
||||
"stop",
|
||||
"idle",
|
||||
"test/lawn_mower_stat",
|
||||
"stop-test-topic",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_entity_debug_info_message(
|
||||
@@ -694,6 +756,7 @@ async def test_entity_debug_info_message(
|
||||
"dock_command_topic": "dock-test-topic",
|
||||
"pause_command_topic": "pause-test-topic",
|
||||
"start_mowing_command_topic": "start_mowing-test-topic",
|
||||
"stop_command_topic": "stop-test-topic",
|
||||
"name": "test",
|
||||
}
|
||||
}
|
||||
@@ -770,6 +833,13 @@ async def test_mqtt_payload_not_a_valid_activity_warning(
|
||||
"dock",
|
||||
"dock_command_template",
|
||||
),
|
||||
(
|
||||
SERVICE_STOP,
|
||||
"stop_command_topic",
|
||||
{},
|
||||
"stop",
|
||||
"stop_command_template",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_publishing_with_custom_encoding(
|
||||
@@ -816,6 +886,7 @@ async def test_reloadable(
|
||||
("activity_state_topic", "docked", None, "docked"),
|
||||
("activity_state_topic", "returning", None, "returning"),
|
||||
("activity_state_topic", "mowing", None, "mowing"),
|
||||
("activity_state_topic", "idle", None, "idle"),
|
||||
],
|
||||
)
|
||||
async def test_encoding_subscribable_topics(
|
||||
|
||||
Reference in New Issue
Block a user