MQTT

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

Leave a Reply

Your email address will not be published. Required fields are marked *