1 """Support for MQTT lawn mowers."""
3 from __future__
import annotations
5 from collections.abc
import Callable
9 import voluptuous
as vol
15 LawnMowerEntityFeature,
26 from .
import subscription
27 from .config
import MQTT_BASE_SCHEMA
28 from .const
import CONF_RETAIN, DEFAULT_OPTIMISTIC, DEFAULT_RETAIN
29 from .entity
import MqttEntity, async_setup_entity_entry_helper
36 from .schemas
import MQTT_ENTITY_COMMON_SCHEMA
37 from .util
import valid_publish_topic, valid_subscribe_topic
39 _LOGGER = logging.getLogger(__name__)
43 CONF_ACTIVITY_STATE_TOPIC =
"activity_state_topic"
44 CONF_ACTIVITY_VALUE_TEMPLATE =
"activity_value_template"
45 CONF_DOCK_COMMAND_TOPIC =
"dock_command_topic"
46 CONF_DOCK_COMMAND_TEMPLATE =
"dock_command_template"
47 CONF_PAUSE_COMMAND_TOPIC =
"pause_command_topic"
48 CONF_PAUSE_COMMAND_TEMPLATE =
"pause_command_template"
49 CONF_START_MOWING_COMMAND_TOPIC =
"start_mowing_command_topic"
50 CONF_START_MOWING_COMMAND_TEMPLATE =
"start_mowing_command_template"
52 DEFAULT_NAME =
"MQTT Lawn Mower"
53 ENTITY_ID_FORMAT = lawn_mower.DOMAIN +
".{}"
55 MQTT_LAWN_MOWER_ATTRIBUTES_BLOCKED: frozenset[str] = frozenset()
58 FEATURE_PAUSE =
"pause"
59 FEATURE_START_MOWING =
"start_mowing"
61 PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
63 vol.Optional(CONF_ACTIVITY_VALUE_TEMPLATE): cv.template,
64 vol.Optional(CONF_ACTIVITY_STATE_TOPIC): valid_subscribe_topic,
65 vol.Optional(CONF_DOCK_COMMAND_TEMPLATE): cv.template,
66 vol.Optional(CONF_DOCK_COMMAND_TOPIC): valid_publish_topic,
67 vol.Optional(CONF_NAME): vol.Any(cv.string,
None),
68 vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
69 vol.Optional(CONF_PAUSE_COMMAND_TEMPLATE): cv.template,
70 vol.Optional(CONF_PAUSE_COMMAND_TOPIC): valid_publish_topic,
71 vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
72 vol.Optional(CONF_START_MOWING_COMMAND_TEMPLATE): cv.template,
73 vol.Optional(CONF_START_MOWING_COMMAND_TOPIC): valid_publish_topic,
75 ).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
77 DISCOVERY_SCHEMA = vol.All(PLATFORM_SCHEMA_MODERN.extend({}, extra=vol.REMOVE_EXTRA))
82 config_entry: ConfigEntry,
83 async_add_entities: AddEntitiesCallback,
85 """Set up MQTT lawn mower through YAML and through MQTT discovery."""
93 PLATFORM_SCHEMA_MODERN,
98 """Representation of an MQTT lawn mower."""
100 _default_name = DEFAULT_NAME
101 _entity_id_format = ENTITY_ID_FORMAT
102 _attributes_extra_blocked = MQTT_LAWN_MOWER_ATTRIBUTES_BLOCKED
103 _command_templates: dict[str, Callable[[PublishPayloadType], PublishPayloadType]]
104 _command_topics: dict[str, str]
105 _value_template: Callable[[ReceivePayloadType], ReceivePayloadType]
109 """Return the config schema."""
110 return DISCOVERY_SCHEMA
113 """(Re)Setup the entity."""
117 config.get(CONF_ACTIVITY_VALUE_TEMPLATE), entity=self
118 ).async_render_with_possible_json_value
121 if CONF_DOCK_COMMAND_TOPIC
in config:
122 self.
_command_topics_command_topics[FEATURE_DOCK] = config[CONF_DOCK_COMMAND_TOPIC]
123 supported_features |= LawnMowerEntityFeature.DOCK
124 if CONF_PAUSE_COMMAND_TOPIC
in config:
125 self.
_command_topics_command_topics[FEATURE_PAUSE] = config[CONF_PAUSE_COMMAND_TOPIC]
126 supported_features |= LawnMowerEntityFeature.PAUSE
127 if CONF_START_MOWING_COMMAND_TOPIC
in config:
129 CONF_START_MOWING_COMMAND_TOPIC
131 supported_features |= LawnMowerEntityFeature.START_MOWING
135 config.get(CONF_DOCK_COMMAND_TEMPLATE), entity=self
138 config.get(CONF_PAUSE_COMMAND_TEMPLATE), entity=self
141 config.get(CONF_START_MOWING_COMMAND_TEMPLATE), entity=self
146 """Handle new MQTT messages."""
150 "Invalid empty activity payload from topic %s, for entity %s",
155 if payload.lower() ==
"none":
163 "Invalid activity for %s: '%s' (valid activities: %s)",
166 [option.value
for option
in LawnMowerActivity],
172 """(Re)Subscribe to topics."""
174 CONF_ACTIVITY_STATE_TOPIC, self.
_message_received_message_received, {
"_attr_activity"}
181 """(Re)Subscribe to topics."""
182 subscription.async_subscribe_topics_internal(self.
hasshasshass, self.
_sub_state_sub_state)
187 with contextlib.suppress(ValueError):
190 async
def _async_operate(self, option: str, activity: LawnMowerActivity) ->
None:
191 """Execute operation."""
199 """Start or resume mowing."""
200 await self.
_async_operate_async_operate(
"start_mowing", LawnMowerActivity.MOWING)
203 """Dock the mower."""
204 await self.
_async_operate_async_operate(
"dock", LawnMowerActivity.DOCKED)
207 """Pause the lawn mower."""
208 await self.
_async_operate_async_operate(
"pause", LawnMowerActivity.PAUSED)
None async_publish_with_config(self, str topic, PublishPayloadType payload)
bool add_subscription(self, str state_topic_config_key, Callable[[ReceiveMessage], None] msg_callback, set[str]|None tracked_attributes, bool disable_encoding=False)
None _message_received(self, ReceiveMessage msg)
None _setup_from_config(self, ConfigType config)
None _prepare_subscribe_topics(self)
None _async_operate(self, str option, LawnMowerActivity activity)
None _subscribe_topics(self)
VolSchemaType config_schema()
None async_start_mowing(self)
None async_write_ha_state(self)
State|None async_get_last_state(self)
None async_setup_entity_entry_helper(HomeAssistant hass, ConfigEntry entry, type[MqttEntity]|None entity_class, str domain, AddEntitiesCallback async_add_entities, VolSchemaType discovery_schema, VolSchemaType platform_schema_modern, dict[str, type[MqttEntity]]|None schema_class_mapping=None)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)