MQTT, short for Message Queue Telemetry Transport, is a lightweight and scalable messaging protocol used for establishing communication between multiple devices in the context of the Internet of Things (IoT).
- It operates on a publish-subscribe model and is particularly suitable for resource-constrained devices with low bandwidth and power requirements, such as an RV.
- MQTT enables seamless machine-to-machine communication. With MQTT, smart sensors and other IoT devices within the RV can easily transmit and receive data. Sensors can talk to each other (without Home Assistant) and can also communicate with HA.
- MQTT is not the most secure protocol, but, in our case, it is running on Beastie’s local and secure LAN; so not much of a concern to us.
We are using MQTT as our standard messaging protocol for (almost) all internal communication. The publish-subscribe model allows us to replace wiring with WiFi. For example, we implemented two-way switches (for floor lighting and for the water pump) without physically connecting the switches together. It also allows us to program automations in a completely decentralized way. Home Assistant doesn’t need to run for any of the automations to work (as long as the MQTT broker runs and WiFi is up and running).
Installing MQTT brokers
We run two MQTT brokers. See design principles. One is running on our Odroid N2+ server and acts as the main MQTT broker. The second one is running inside the Victron Cerbo CX and handles all Victron-related communication.
1. Mosquitto Add-on for Home Assistant
Mosquitto is the most popular open source implementation of the MQTT protocol. It can be installed quite easily from within the Home Assistant UI. Simply go to Settings->Devices&Services
and click on Add Integration
. Search for MQTT
and follow the prompts to install. Done.
2. Enable MQTT broker for Victron
In order to control the Victron system through MQTT, you need to have either the Cerbo GX or Venus GX (now deprecated) appliance installed. They are the brains of the entire Victron system and enable things such as smart panels, and remote configuration and monitoring.
MQTT is turned off by default. To turn it on, go to your Victron Remote Console. Click on Settings -> Services -> enable MQTT on LAN
. Enable both entries. Done.
Both MQTT brokers are now running.
MQTT Tools
1. Command line interface
One way to monitor MQTT traffic and test for correct behavior is to use Mosquitto’s command line interface to subscribe to topics or publish to certain topics. The format is very straightforward:
mosquitto_pub -h localhost -t waterpump -m "on"
mosquitto_sub - h localhost -t waterpump
2. MQTT Explorer
A much better and easier way is to use MQTT Explorer. The app will visualize the entire topic tree and make it easy to navigate the tree, look up values, but also publish values.
Configuring MQTT brokers
Now that both brokers are running and MQTT Explorer is installed, we have to configure the brokers to ensure they are connected/bridged, so that all information flows from one to the other.
1. Bridging MQTT brokers
Login to your HA server (using SSH) and change directories to share->mosquitto
. Create a new file mosquitto.conf
and add following entries:
# enable bridging with Victron Mosquitto Broker
connection venus-home
address 192.168.xx.xx
topic # both 0 venus-home/
Make sure to replace 192.168.xx.xx
with the IP address of our Cerbo GX. Restart your MQTT add-on and venus-home should now show up as a topic in your MQTT hierarchy tree (check with MQTT Explorer). Learn more about MQTT bridging.
2. Victron MQTT keepalive
Victron will stop sending data after about 1 minute unless prompted to continue. So, the next step is to create a Home Assistant automation that will ensure Victron keeps updating the data over MQTT.
To do so, add following entry to your automation.yaml
file:
- id: 'PICK_A_NUMBER'
alias: Refresh MQTT Victron
description: Request data on the MQTT Server
trigger:
- platform: time_pattern
seconds: '30'
condition: []
action:
- service: mqtt.publish
data:
topic: venus-home/R/YOUR_VENUS_ID/system/0/Serial
mode: single
Replace PICK_A_NUMBER
with a unique number. And replace YOUR_VENUS_ID
with the system ID of your Venus install. You can find the system ID in the MQTT hierarchy under path /venus-home/system/0/Serial
MQTT and Home Assistant Entities
How do sensors that communicate over MQTT show up as entities in Home Assistant? There are 3 ways:
1. Auto-discovery
This is obviously the easiest way. Connect the sensor, configure the MQTT connection details, and the sensor will show up automatically in Home Assistant. Any sensor that is powered by ESPHome will fall into that category. Besides that, a number of other products and sensors have auto-discovery built in. Here’s a list of products that support auto-discovery over MQTT.
2. DIY Auto-discovery
If your product doesn’t fall into the first category, but you have full access to how that product works, you can get Home Assistant to auto-discover it. The way to do this is to have the product send out a ‘discovery’ message over MQTT every time it boots up and periodically after that. The discovery message is a specially formatted message that will tell Home Assistant everything it needs to know in order to create the proper entities with the right actions associated with them. The format of the discovery message is discussed here.
Even if you don’t have full access to the device’s software, you might still be able to generate the correct discovery message in a roundabout way. To do so, we will create a Home Assistant automation that will listen for incoming MQTT messages that match a certain format and based on the format and details of the incoming message, the automation will construct an outgoing discovery message that will then trigger auto-discovery by Home Assistant. This Github repository, implementing auto-discovery for Shelly devices running Shelly proprietary software, is a good example of this method. Note: although we use Shelly devices extensively, we decided to flash them with ESPhome, so they get auto-discovered automatically (case 1 above).
3. Manual configuration
The third option is to bypass the auto-discovery system and instead manually define every entity. This is what we’re doing for entities that are based on Victron data. The Victron system does not support Home Assistant auto-discovery, and does not give the user the ability to construct discovery messages and send them from the Cerbo GX system. So instead, we will manually configure them.
Here’s an example of a Victron sensor (read-only):
- name: "VICTRON - AC Output Power"
state_topic: "venus-home/N/YOUR_VENUS_ID/vebus/276/Ac/Out/L1/P"
unit_of_measurement: "W"
unique_id: "279_10"
Or here’s an example of a Mopeca propane sensor, connected over BLE, to the Victron Cerbo GX:
- name: "VICTRON - Propane"
state_topic: "venus-home/N/YOUR_VENUS_ID/tank/32/Level"
unit_of_measurement: "%"
unique_id: "280-04"
value_template: "{{ value_json.value | round(0) }}"
Here’s an example of a pressure reading for the front left (FL) tire of our TPMS system:
- name: "TPMS - FL psi"
state_topic: "pressurepro/tpms/status"
unique_id: "300_12"
unit_of_measurement: "psi"
value_template: "{{ value_json.fl is defined | iif(value_json.fl.psi, states(entity_id)) }}"
These are all examples of read-only entities. What if we want to make changes and push those changes over MQTT to the proper device? How is that getting configured manually? This is more involved. Let’s take a look at a concrete example: how to control the Victron inverter mode (on/off/charge only/invert only) from Home Assistant?
First we create an input_select entity to make it easy for the user to select the right mode. Add these lines to your configuration.yaml
:
input_select:
victron_inverter_mode:
name: Inverter Mode
options:
- "Off"
- "Charger Only"
- "Inverter Only"
- "On"
Second, we read the incoming values from Victron (numbers 0 – 4), and map them to the proper input_select options. This is done through an automation stored in automation.yaml
:
- id: '1631292806794'
alias: Victron - Read Inverter Mode
description: ''
trigger:
- platform: mqtt
topic: venus-home/N/YOUR_VENUS_ID/vebus/276/Mode
condition: []
action:
- service: input_select.select_option
target:
entity_id: input_select.victron_inverter_mode
data:
option: "{% set obj = trigger.payload_json %}\n{% if obj.value == 1 %}\n Charger\
\ Only\n{%-elif obj.value == 2 %}\n Inverter Only\n{%-elif obj.value == 3\
\ %}\n On\n{%-else %}\n Off\n{% endif %}\n"
mode: single
Third, we do the reverse translation when we want to push a change back to the Victron system (another automation in automation.yaml
):
- id: '1631493142727'
alias: Victron - Input Select Push Inverter Mode Change
description: ''
trigger:
- platform: state
entity_id: input_select.victron_inverter_mode
condition: []
action:
- service: mqtt.publish
data:
topic: venus-home/W/YOUR_VENUS_ID/vebus/276/Mode
payload_template: "{% if trigger.to_state.state == \"On\" %}\n {% set obj =\
\ {\"value\": 3} %}\n{%-elif trigger.to_state.state == \"Charger Only\" %}\n\
\ {% set obj = {\"value\": 1} %}\n{%-elif trigger.to_state.state == \"Inverter\
\ Only\" %}\n {% set obj = {\"value\": 2} %}\n{%-else %}\n {% set obj =\
\ {\"value\": 4} %}\n{%endif %}\n{{ obj|to_json }} \n"
mode: single