[1/3] Refactor mqtt-vacuum in preparation for discovery and device registry (#19462)
* Refactor mqtt-vacuum in preparation for discovery and device registry
This commit is contained in:
parent
76c30aca38
commit
dee229152f
1 changed files with 117 additions and 155 deletions
|
@ -9,7 +9,8 @@ import logging
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import mqtt
|
||||
from homeassistant.components.mqtt import MqttAvailability
|
||||
from homeassistant.components.mqtt import (
|
||||
MqttAvailability, subscription)
|
||||
from homeassistant.components.vacuum import (
|
||||
SUPPORT_BATTERY, SUPPORT_CLEAN_SPOT, SUPPORT_FAN_SPEED,
|
||||
SUPPORT_LOCATE, SUPPORT_PAUSE, SUPPORT_RETURN_HOME, SUPPORT_SEND_COMMAND,
|
||||
|
@ -145,131 +146,14 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
|
|||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the vacuum."""
|
||||
name = config.get(CONF_NAME)
|
||||
supported_feature_strings = config.get(CONF_SUPPORTED_FEATURES)
|
||||
supported_features = strings_to_services(supported_feature_strings)
|
||||
|
||||
qos = config.get(mqtt.CONF_QOS)
|
||||
retain = config.get(mqtt.CONF_RETAIN)
|
||||
|
||||
command_topic = config.get(mqtt.CONF_COMMAND_TOPIC)
|
||||
payload_turn_on = config.get(CONF_PAYLOAD_TURN_ON)
|
||||
payload_turn_off = config.get(CONF_PAYLOAD_TURN_OFF)
|
||||
payload_return_to_base = config.get(CONF_PAYLOAD_RETURN_TO_BASE)
|
||||
payload_stop = config.get(CONF_PAYLOAD_STOP)
|
||||
payload_clean_spot = config.get(CONF_PAYLOAD_CLEAN_SPOT)
|
||||
payload_locate = config.get(CONF_PAYLOAD_LOCATE)
|
||||
payload_start_pause = config.get(CONF_PAYLOAD_START_PAUSE)
|
||||
|
||||
battery_level_topic = config.get(CONF_BATTERY_LEVEL_TOPIC)
|
||||
battery_level_template = config.get(CONF_BATTERY_LEVEL_TEMPLATE)
|
||||
if battery_level_template:
|
||||
battery_level_template.hass = hass
|
||||
|
||||
charging_topic = config.get(CONF_CHARGING_TOPIC)
|
||||
charging_template = config.get(CONF_CHARGING_TEMPLATE)
|
||||
if charging_template:
|
||||
charging_template.hass = hass
|
||||
|
||||
cleaning_topic = config.get(CONF_CLEANING_TOPIC)
|
||||
cleaning_template = config.get(CONF_CLEANING_TEMPLATE)
|
||||
if cleaning_template:
|
||||
cleaning_template.hass = hass
|
||||
|
||||
docked_topic = config.get(CONF_DOCKED_TOPIC)
|
||||
docked_template = config.get(CONF_DOCKED_TEMPLATE)
|
||||
if docked_template:
|
||||
docked_template.hass = hass
|
||||
|
||||
error_topic = config.get(CONF_ERROR_TOPIC)
|
||||
error_template = config.get(CONF_ERROR_TEMPLATE)
|
||||
if error_template:
|
||||
error_template.hass = hass
|
||||
|
||||
fan_speed_topic = config.get(CONF_FAN_SPEED_TOPIC)
|
||||
fan_speed_template = config.get(CONF_FAN_SPEED_TEMPLATE)
|
||||
if fan_speed_template:
|
||||
fan_speed_template.hass = hass
|
||||
|
||||
set_fan_speed_topic = config.get(CONF_SET_FAN_SPEED_TOPIC)
|
||||
fan_speed_list = config.get(CONF_FAN_SPEED_LIST)
|
||||
|
||||
send_command_topic = config.get(CONF_SEND_COMMAND_TOPIC)
|
||||
|
||||
availability_topic = config.get(mqtt.CONF_AVAILABILITY_TOPIC)
|
||||
payload_available = config.get(mqtt.CONF_PAYLOAD_AVAILABLE)
|
||||
payload_not_available = config.get(mqtt.CONF_PAYLOAD_NOT_AVAILABLE)
|
||||
|
||||
async_add_entities([
|
||||
MqttVacuum(
|
||||
name, supported_features, qos, retain, command_topic,
|
||||
payload_turn_on, payload_turn_off, payload_return_to_base,
|
||||
payload_stop, payload_clean_spot, payload_locate,
|
||||
payload_start_pause, battery_level_topic, battery_level_template,
|
||||
charging_topic, charging_template, cleaning_topic,
|
||||
cleaning_template, docked_topic, docked_template,
|
||||
error_topic, error_template, fan_speed_topic,
|
||||
fan_speed_template, set_fan_speed_topic, fan_speed_list,
|
||||
send_command_topic, availability_topic, payload_available,
|
||||
payload_not_available
|
||||
),
|
||||
])
|
||||
async_add_entities([MqttVacuum(config, discovery_info)])
|
||||
|
||||
|
||||
class MqttVacuum(MqttAvailability, VacuumDevice):
|
||||
"""Representation of a MQTT-controlled vacuum."""
|
||||
|
||||
def __init__(
|
||||
self, name, supported_features, qos, retain, command_topic,
|
||||
payload_turn_on, payload_turn_off, payload_return_to_base,
|
||||
payload_stop, payload_clean_spot, payload_locate,
|
||||
payload_start_pause, battery_level_topic, battery_level_template,
|
||||
charging_topic, charging_template, cleaning_topic,
|
||||
cleaning_template, docked_topic, docked_template,
|
||||
error_topic, error_template, fan_speed_topic,
|
||||
fan_speed_template, set_fan_speed_topic, fan_speed_list,
|
||||
send_command_topic, availability_topic, payload_available,
|
||||
payload_not_available):
|
||||
def __init__(self, config, discovery_info):
|
||||
"""Initialize the vacuum."""
|
||||
super().__init__(availability_topic, qos, payload_available,
|
||||
payload_not_available)
|
||||
|
||||
self._name = name
|
||||
self._supported_features = supported_features
|
||||
self._qos = qos
|
||||
self._retain = retain
|
||||
|
||||
self._command_topic = command_topic
|
||||
self._payload_turn_on = payload_turn_on
|
||||
self._payload_turn_off = payload_turn_off
|
||||
self._payload_return_to_base = payload_return_to_base
|
||||
self._payload_stop = payload_stop
|
||||
self._payload_clean_spot = payload_clean_spot
|
||||
self._payload_locate = payload_locate
|
||||
self._payload_start_pause = payload_start_pause
|
||||
|
||||
self._battery_level_topic = battery_level_topic
|
||||
self._battery_level_template = battery_level_template
|
||||
|
||||
self._charging_topic = charging_topic
|
||||
self._charging_template = charging_template
|
||||
|
||||
self._cleaning_topic = cleaning_topic
|
||||
self._cleaning_template = cleaning_template
|
||||
|
||||
self._docked_topic = docked_topic
|
||||
self._docked_template = docked_template
|
||||
|
||||
self._error_topic = error_topic
|
||||
self._error_template = error_template
|
||||
|
||||
self._fan_speed_topic = fan_speed_topic
|
||||
self._fan_speed_template = fan_speed_template
|
||||
|
||||
self._set_fan_speed_topic = set_fan_speed_topic
|
||||
self._fan_speed_list = fan_speed_list
|
||||
self._send_command_topic = send_command_topic
|
||||
|
||||
self._cleaning = False
|
||||
self._charging = False
|
||||
self._docked = False
|
||||
|
@ -277,45 +161,115 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
self._status = 'Unknown'
|
||||
self._battery_level = 0
|
||||
self._fan_speed = 'unknown'
|
||||
self._fan_speed_list = []
|
||||
self._sub_state = None
|
||||
|
||||
# Load config
|
||||
self._setup_from_config(config)
|
||||
|
||||
qos = config.get(mqtt.CONF_QOS)
|
||||
availability_topic = config.get(mqtt.CONF_AVAILABILITY_TOPIC)
|
||||
payload_available = config.get(mqtt.CONF_PAYLOAD_AVAILABLE)
|
||||
payload_not_available = config.get(mqtt.CONF_PAYLOAD_NOT_AVAILABLE)
|
||||
|
||||
MqttAvailability.__init__(self, availability_topic, qos,
|
||||
payload_available, payload_not_available)
|
||||
|
||||
def _setup_from_config(self, config):
|
||||
self._name = config.get(CONF_NAME)
|
||||
supported_feature_strings = config.get(CONF_SUPPORTED_FEATURES)
|
||||
self._supported_features = strings_to_services(
|
||||
supported_feature_strings
|
||||
)
|
||||
self._fan_speed_list = config.get(CONF_FAN_SPEED_LIST)
|
||||
self._qos = config.get(mqtt.CONF_QOS)
|
||||
self._retain = config.get(mqtt.CONF_RETAIN)
|
||||
|
||||
self._command_topic = config.get(mqtt.CONF_COMMAND_TOPIC)
|
||||
self._set_fan_speed_topic = config.get(CONF_SET_FAN_SPEED_TOPIC)
|
||||
self._send_command_topic = config.get(CONF_SEND_COMMAND_TOPIC)
|
||||
|
||||
self._payloads = {
|
||||
key: config.get(key) for key in (
|
||||
CONF_PAYLOAD_TURN_ON,
|
||||
CONF_PAYLOAD_TURN_OFF,
|
||||
CONF_PAYLOAD_RETURN_TO_BASE,
|
||||
CONF_PAYLOAD_STOP,
|
||||
CONF_PAYLOAD_CLEAN_SPOT,
|
||||
CONF_PAYLOAD_LOCATE,
|
||||
CONF_PAYLOAD_START_PAUSE
|
||||
)
|
||||
}
|
||||
self._state_topics = {
|
||||
key: config.get(key) for key in (
|
||||
CONF_BATTERY_LEVEL_TOPIC,
|
||||
CONF_CHARGING_TOPIC,
|
||||
CONF_CLEANING_TOPIC,
|
||||
CONF_DOCKED_TOPIC,
|
||||
CONF_ERROR_TOPIC,
|
||||
CONF_FAN_SPEED_TOPIC
|
||||
)
|
||||
}
|
||||
self._templates = {
|
||||
key: config.get(key) for key in (
|
||||
CONF_BATTERY_LEVEL_TEMPLATE,
|
||||
CONF_CHARGING_TEMPLATE,
|
||||
CONF_CLEANING_TEMPLATE,
|
||||
CONF_DOCKED_TEMPLATE,
|
||||
CONF_ERROR_TEMPLATE,
|
||||
CONF_FAN_SPEED_TEMPLATE
|
||||
)
|
||||
}
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Subscribe MQTT events."""
|
||||
await super().async_added_to_hass()
|
||||
await self._subscribe_topics()
|
||||
|
||||
async def _subscribe_topics(self):
|
||||
"""(Re)Subscribe to topics."""
|
||||
for tpl in self._templates.values():
|
||||
if tpl is not None:
|
||||
tpl.hass = self.hass
|
||||
|
||||
@callback
|
||||
def message_received(topic, payload, qos):
|
||||
"""Handle new MQTT message."""
|
||||
if topic == self._battery_level_topic and \
|
||||
self._battery_level_template:
|
||||
battery_level = self._battery_level_template\
|
||||
if topic == self._state_topics[CONF_BATTERY_LEVEL_TOPIC] and \
|
||||
self._templates[CONF_BATTERY_LEVEL_TEMPLATE]:
|
||||
battery_level = self._templates[CONF_BATTERY_LEVEL_TEMPLATE]\
|
||||
.async_render_with_possible_json_value(
|
||||
payload, error_value=None)
|
||||
if battery_level is not None:
|
||||
self._battery_level = int(battery_level)
|
||||
|
||||
if topic == self._charging_topic and self._charging_template:
|
||||
charging = self._charging_template\
|
||||
if topic == self._state_topics[CONF_CHARGING_TOPIC] and \
|
||||
self._templates[CONF_CHARGING_TEMPLATE]:
|
||||
charging = self._templates[CONF_CHARGING_TEMPLATE]\
|
||||
.async_render_with_possible_json_value(
|
||||
payload, error_value=None)
|
||||
if charging is not None:
|
||||
self._charging = cv.boolean(charging)
|
||||
|
||||
if topic == self._cleaning_topic and self._cleaning_template:
|
||||
cleaning = self._cleaning_template \
|
||||
if topic == self._state_topics[CONF_CLEANING_TOPIC] and \
|
||||
self._templates[CONF_CLEANING_TEMPLATE]:
|
||||
cleaning = self._templates[CONF_CLEANING_TEMPLATE]\
|
||||
.async_render_with_possible_json_value(
|
||||
payload, error_value=None)
|
||||
if cleaning is not None:
|
||||
self._cleaning = cv.boolean(cleaning)
|
||||
|
||||
if topic == self._docked_topic and self._docked_template:
|
||||
docked = self._docked_template \
|
||||
if topic == self._state_topics[CONF_DOCKED_TOPIC] and \
|
||||
self._templates[CONF_DOCKED_TEMPLATE]:
|
||||
docked = self._templates[CONF_DOCKED_TEMPLATE]\
|
||||
.async_render_with_possible_json_value(
|
||||
payload, error_value=None)
|
||||
if docked is not None:
|
||||
self._docked = cv.boolean(docked)
|
||||
|
||||
if topic == self._error_topic and self._error_template:
|
||||
error = self._error_template \
|
||||
if topic == self._state_topics[CONF_ERROR_TOPIC] and \
|
||||
self._templates[CONF_ERROR_TEMPLATE]:
|
||||
error = self._templates[CONF_ERROR_TEMPLATE]\
|
||||
.async_render_with_possible_json_value(
|
||||
payload, error_value=None)
|
||||
if error is not None:
|
||||
|
@ -333,8 +287,9 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
else:
|
||||
self._status = "Stopped"
|
||||
|
||||
if topic == self._fan_speed_topic and self._fan_speed_template:
|
||||
fan_speed = self._fan_speed_template\
|
||||
if topic == self._state_topics[CONF_FAN_SPEED_TOPIC] and \
|
||||
self._templates[CONF_FAN_SPEED_TEMPLATE]:
|
||||
fan_speed = self._templates[CONF_FAN_SPEED_TEMPLATE]\
|
||||
.async_render_with_possible_json_value(
|
||||
payload, error_value=None)
|
||||
if fan_speed is not None:
|
||||
|
@ -342,14 +297,17 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
topics_list = [topic for topic in (self._battery_level_topic,
|
||||
self._charging_topic,
|
||||
self._cleaning_topic,
|
||||
self._docked_topic,
|
||||
self._fan_speed_topic) if topic]
|
||||
for topic in set(topics_list):
|
||||
await self.hass.components.mqtt.async_subscribe(
|
||||
topic, message_received, self._qos)
|
||||
topics_list = {topic for topic in self._state_topics.values() if topic}
|
||||
self._sub_state = await subscription.async_subscribe_topics(
|
||||
self.hass, self._sub_state,
|
||||
{
|
||||
"topic{}".format(i): {
|
||||
"topic": topic,
|
||||
"msg_callback": message_received,
|
||||
"qos": self._qos
|
||||
} for i, topic in enumerate(topics_list)
|
||||
}
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -417,7 +375,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payload_turn_on, self._qos, self._retain)
|
||||
self._payloads[CONF_PAYLOAD_TURN_ON],
|
||||
self._qos, self._retain)
|
||||
self._status = 'Cleaning'
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -427,7 +386,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payload_turn_off, self._qos, self._retain)
|
||||
self._payloads[CONF_PAYLOAD_TURN_OFF],
|
||||
self._qos, self._retain)
|
||||
self._status = 'Turning Off'
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -436,7 +396,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
if self.supported_features & SUPPORT_STOP == 0:
|
||||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic, self._payload_stop,
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payloads[CONF_PAYLOAD_STOP],
|
||||
self._qos, self._retain)
|
||||
self._status = 'Stopping the current task'
|
||||
self.async_schedule_update_ha_state()
|
||||
|
@ -447,7 +408,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payload_clean_spot, self._qos, self._retain)
|
||||
self._payloads[CONF_PAYLOAD_CLEAN_SPOT],
|
||||
self._qos, self._retain)
|
||||
self._status = "Cleaning spot"
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -457,7 +419,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payload_locate, self._qos, self._retain)
|
||||
self._payloads[CONF_PAYLOAD_LOCATE],
|
||||
self._qos, self._retain)
|
||||
self._status = "Hi, I'm over here!"
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -467,7 +430,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payload_start_pause, self._qos, self._retain)
|
||||
self._payloads[CONF_PAYLOAD_START_PAUSE],
|
||||
self._qos, self._retain)
|
||||
self._status = 'Pausing/Resuming cleaning...'
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -477,8 +441,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
return
|
||||
|
||||
mqtt.async_publish(self.hass, self._command_topic,
|
||||
self._payload_return_to_base, self._qos,
|
||||
self._retain)
|
||||
self._payloads[CONF_PAYLOAD_RETURN_TO_BASE],
|
||||
self._qos, self._retain)
|
||||
self._status = 'Returning home...'
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -489,9 +453,8 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
if not self._fan_speed_list or fan_speed not in self._fan_speed_list:
|
||||
return
|
||||
|
||||
mqtt.async_publish(
|
||||
self.hass, self._set_fan_speed_topic, fan_speed, self._qos,
|
||||
self._retain)
|
||||
mqtt.async_publish(self.hass, self._set_fan_speed_topic,
|
||||
fan_speed, self._qos, self._retain)
|
||||
self._status = "Setting fan to {}...".format(fan_speed)
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
|
@ -500,8 +463,7 @@ class MqttVacuum(MqttAvailability, VacuumDevice):
|
|||
if self.supported_features & SUPPORT_SEND_COMMAND == 0:
|
||||
return
|
||||
|
||||
mqtt.async_publish(
|
||||
self.hass, self._send_command_topic, command, self._qos,
|
||||
self._retain)
|
||||
mqtt.async_publish(self.hass, self._send_command_topic,
|
||||
command, self._qos, self._retain)
|
||||
self._status = "Sending command {}...".format(command)
|
||||
self.async_schedule_update_ha_state()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue