Home Assistant
Home Assistant Integrations for Meshtastic
Due to a known issue with nRF52 devices and JSON, nRF52 devices are not supported for use with Home Assistant at this time.
Integrating Meshtastic into Home Assistant brings a new level of control and monitoring to your mesh network. On this page, we'll guide you through the process of creating Meshtastic MQTT sensor entities within Home Assistant. Whether you want to keep an eye on battery levels, environmental conditions, or even receive notifications from your mesh network, these integrations provide you with the tools to make it happen.
It is highly recommended to download MQTT Explorer for analyzing the JSON threads that come across the broker. This can be downloaded here http://mqtt-explorer.com/.
Create Meshtastic MQTT Sensor Entities
-
Ensure your mesh unit is connected to your MQTT broker and using JSON as an output.
-
Open configuration.yaml and include the following line:
mqtt: !include mqtt.yaml
-
Create a new text file called
mqtt.yaml
in the root directory of home assistant (the same folder as configuration.yaml). -
Copy the following code to the mqtt.yaml file.
Default Node Telemetry Example
sensor:
# Node #1
- name: "Node 1 Battery Voltage"
unique_id: "node_1_battery_voltage"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and
value_json.payload.voltage is defined and
value_json.payload.temperature is not defined %}
{{ (value_json.payload.voltage | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
unit_of_measurement: "Volts"
# Telemetry packets come in two flavors: The default node telemetry, and the I2C sensor data.
# Both packets contain "voltage" so we check for temperature to ignore the sensor packet here.
- name: "Node 1 Battery Percent"
unique_id: "node_1_battery_percent"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.battery_level is defined %}
{{ (value_json.payload.battery_level | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
device_class: "battery"
unit_of_measurement: "%"
- name: "Node 1 ChUtil"
unique_id: "node_1_chutil"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.channel_utilization is defined %}
{{ (value_json.payload.channel_utilization | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
unit_of_measurement: "%"
- name: "Node 1 AirUtilTX"
unique_id: "node_1_airutiltx"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.air_util_tx is defined %}
{{ (value_json.payload.air_util_tx | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
unit_of_measurement: "%"
Telemetry Module Entities
- If you have environmental sensors installed, create entities for these by including some or all of the following blocks:
- name: "Node 1 Temperature"
unique_id: "node_1_temperature"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.temperature is defined %}
{{ (((value_json.payload.temperature | float) * 1.8) +32) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
device_class: "temperature"
unit_of_measurement: "°F"
# With device_class: "temperature" set, make sure to use the configured unit for temperature in your HA instance.
# If you don't, then non-temperature messages will change the value of this sensor by reinterpreting the current state with the wrong unit, unless you account for it.
# For Celsius use: {{ (value_json.payload.temperature | float) | round(1) }}
# For Fahrenheit use: {{ (((value_json.payload.temperature | float) * 1.8) +32) | round(2) }}
- name: "Node 1 Humidity"
unique_id: "node_1_humidity"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.relative_humidity is defined %}
{{ (value_json.payload.relative_humidity | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
device_class: "humidity"
unit_of_measurement: "%"
- name: "Node 1 Pressure"
unique_id: "node_1_pressure"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.barometric_pressure is defined %}
{{ (value_json.payload.barometric_pressure | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
device_class: "pressure"
unit_of_measurement: "hPa"
# With device_class: "pressure" set, make sure to use the configured unit for pressure in your HA instance.
# For psi use: {{ ((value_json.payload.barometric_pressure | float) / 68.9475729) | round(2) }}
- name: "Node 1 Gas Resistance"
unique_id: "node_1_gas_resistance"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
state_class: measurement
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.gas_resistance is defined %}
{{ (value_json.payload.gas_resistance | float) | round(2) }}
{% else %}
{{ this.state }}
{% endif %}
unit_of_measurement: "MOhms"
Message Entities
- For added functionality you can create an entity for messages received from a node:
- name: "Node 1 Messages"
unique_id: "node_1_messages"
state_topic: "msh/US/2/json/LongFast/!67ea9400"
value_template: >-
{% if value_json.from == 4038675309 and value_json.payload.text is defined %}
{{ value_json.payload.text }}
{% else %}
{{ this.state }}
{% endif %}
Maps & Device Tracker
To make it possible for your nodes to appear in maps within Home Assistant, you will need to set up a device_tracker entity. Luckily, Home Assistant allows them to be created ad-hoc, simply by calling the device_tracker.see
service from a script or automation.
To do this, create a new automation and use the three-dots menu to change to the "Edit in YAML" mode, and set it up like the following:
alias: Update Node 1 location
description: Update Meshtastic node when corresponding MQTT messages are seen.
trigger:
- platform: mqtt
topic: msh/US/2/json/LongFast/!67ea9400
payload: "on"
value_template: |-
{% if value_json.from == 4038675309 and
value_json.payload.latitude_i is defined and
value_json.payload.longitude_i is defined %}on{% endif %}
condition: []
action:
- service: device_tracker.see
metadata: {}
data:
dev_id: node_1
gps:
- "{{ (trigger.payload | from_json).payload.latitude_i | int * 1e-7 }}"
- "{{ (trigger.payload | from_json).payload.longitude_i | int * 1e-7 }}"
battery: "{{ states('sensor.node_1_battery_percent')|float(0) }}"
mode: single
The dev_id
within the service call determines what the device_tracker
entity will be called, for example device_tracker.node_1
for the above. Make sure that you have different names in this field for your different nodes, or they will all show up under the same tracker! Meshtastic represents latitude and longitude in integers, which is why they must be multiplied by 1e-7
to produce the real location.
Device trackers can also support a few different additional fields, but the one most relevant to Meshtastic usage is the battery level, which can be pulled in from the previously-created sensors as shown.
Additional Entities
Home Assistant entities can be created for any data type that is published to MQTT. For example: altitude, latitude_i, longitude_i, time, current, and neighbors. Use the templates above as a guide to create additional entities if desired.
Configure With Your Topic & Node ID's
-
In every entity, replace
msh/US/2/json/LongFast/!67ea9400
with the topic your node publishes to. In this example,!67ea9400
refers to the node that has mqtt enabled on the mesh and is publishing to the broker. -
In every entity replace
4038675309
with the node number of the radio you wish to monitor. In this example4038675309
is the node on the mesh with environment sensors and telemetry that I wish to observe. Node numbers can be found by monitoring the output in MQTT Explorer, listening with the MQTT addon or by using the Python CLI withmeshtastic --info
.