Valetudo supports publishing status data and receiving commands from MQTT.
The following autodiscovery protocols are supported:
They are both optional and mutually compatible: you can enable both at the same time or none at all.
Since the MQTT code is heavily based on the capabilities system you may want to first give a look to how capabilities, status attributes, and the robot object work.
The MQTT OOP structure is heavily influenced by the Homie convention. This page will also contain lots of references to it, so make sure you grasp the fundamental concepts of the convention before proceeding further:
To keep the codebase maintainable and prevent entire classes of potential issues, the code tries to define and restrict the responsibilities of each component as follows:
Handles are subclasses of
MqttHandle. They are designed to map exactly to the levels of the Homie convention topology.
RobotMqttHandle⇒ Homie device
NodeMqttHandle⇒ Homie node
PropertyMqttHandle⇒ Homie property
Two more classes are present that further extend from these and bridge the handles to Valetudo’s internals:
Handles are assigned into a tree structure:
RobotMqttHandle, being the root handle, registers to the
NodeMqttHandles register to
PropertyMqttHandles register to
This structure simplifies and unifies publication to the MQTT broker, Instead of publishing data directly, any handle may “refresh” itself.
When a handle is refreshed it will ask the
MqttController to retrieve a fresh payload from it and publish it to its
Refreshing is recursive: whenever a handle is refreshed all children are refreshed as well. Attached Home Assistant components will also be refreshed, but we will discuss this later.
RobotMqttHandle is special since it is the root handle. It maps to a Homie device. It is mainly responsible for
checking which capabilities the robot supports and registering the corresponding handles.
It will also subscribe to the robot status and register matching handles as soon as the corresponding attributes are added (therefore it’s normal if they don’t show up until the robot is fully connected and the status is polled).
Finally, it handles the registration of
MapNodeMqttHandle, which as the name suggests provides map data.
RobotStateNodeMqttHandle children all map to Homie nodes. Their peculiarity is that they provide infrastructure to
subscribe to the robot state.
This is accomplished by providing a list of status attribute matchers, which the handle will subscribe to.
When a status event occurs, the handle and all its children are refreshed.
CapabilityMqttHAndle children also map to Homie nodes. The class itself inherits from
therefore it is as well able to subscribe to robot status events.
It is encouraged, whenever possible, to handle status data in a capability handle as opposed to a status handle whenever actions performed on the capability will be reflected into and match exactly to a status attribute event.
This is true, for example, for both
PresetSelectionCapabilitys, since setting a preset will usually result in the same
value being reflected back to the status attribute: you send
low and you get back
This is NOT true, for example, for
BasicControlCapability. While actions performed on it will directly affect
StatusStateAttribute, the status event won’t match exactly: you perform
START but you get back
PropertyMqttHandle, as the name suggests, maps to Homie properties. However, unlike the previously discussed handles,
property handles do not have subclasses and should not be subclassed.
Property handles are in fact defined and registered in-line in the capability/status handle constructors. All data is provided as parameters to the constructor.
These handles handle the actual data to be published and receive commands. However, they never interact directly with
the MQTT client. They instead must be provided with at least one of the following callbacks: a
getter to retrieve
fresh data to be published; a
setter to perform operations with the data received from MQTT.
setter callback is provided, property handles will be subscribed to a
setter is provided but a
getter is not provided, the property will act as a command property according to
the Homie convention: the data received in the
/set topic will automatically be reflected back to the main topic to
acknowledge the command.
Home Assistant uses a very different workflow. Instead of defining a structure, it defines components which may or may not map to some capabilities’ behavior.
In some instances it will try to adapt to an existing MQTT structure and allow you to provide topics and payloads for accomplishing different tasks. In some other cases it will try to impose its own structure.
This makes it difficult to share data with the previously defined structure. However, Valetudo provides enough
abstraction to make this easier:
Home Assistant components may subscribe to topics. However, this should be avoided when possible: most features can and should be implemented by providing Hass with the handle topics.
Components are not handles, they are a separate entity. However, in order to share data with handles, they are attached to and managed by the handle they share information with.
Components may be attached to any type of handle, from the robot handle to the property handle. For instance, the map component is attached to the map handle.
Whenever an handle is refreshed, the attached Hass components are refreshed as well.
Some components are trickier. For example, the
VacuumHassComponent is attached to the robot handle since that’s what
it shares most data with. However, it also needs access to the fan speed and a reference to the
command topic in order to send cleaning control commands.
This is accomplished using
HassAnchor is a utility to share data from the handle that manages some type of information to the hass component that
There are two types of
HassAnchor: plain anchors and topic references. The implementation is exactly the same, the
distinction has been put in place, once again, to separate responsibilities: “plain” anchors may only be used in
payloads, topic references may only be used in autoconfiguration payloads.
HassAnchors can be thought of as fancy “template variables”. Hass component payloads are in fact provided as regular
HassAnchor may be retrieved and used in its
Of course, the value isn’t going to jump into existence on its own: some other component needs to provide it. This is a
responsibility of handles: whenever they share some value with a hass component, they should also
post() it into the
anchor every time they retrieve it for their own needs.
HassAnchors are eventful: whenever a handle posts a value into an anchor, the hass component that uses it is
automatically refreshed and its payload published to MQTT.
If for whatever reason an anchor doesn’t hold any value when the hass component payload is requested for publication, the publication will be delayed. This means that you should only use anchors if you are sure they will be populated, otherwise the hass component will stay in a limbo forever.
Here’s a bunch of things to keep in mind when adding new MQTT handles and Home Assistant components.
$attributes- they won’t be available if Homie is disabled
This section does not describe general MQTT troubleshooting, but rather troubleshooting of problems that can occur when writing new code.
Status handles are only published once the
StatusAttribute they subscribe to first appears. If it does appear, but the
handle isn’t published, you may have an incorrect attribute matcher.
Both status and capability handles have to be registered into the designated lists inside the
for them to be loaded.
You can enable
debug.debugHassAnchors in the configuration and set the log level to
trace. It will print a report
whenever an anchor is blocking publication for a Hass component.
Open source cloud replacement for vacuum robots enabling local-only operation