Mastering Custom MQTT Sensors and Switches: Bridging External Scripts to Home Assistant
NGC 224
DIY Smart Home Creator
Intro
Are you a tinkerer looking to pull data from a unique sensor connected to your Raspberry Pi, or perhaps trigger a custom script on your server directly from Home Assistant? Many powerful devices and custom solutions lack direct, pre-built Home Assistant integrations. This is where MQTT (Message Queuing Telemetry Transport) shines. Acting as a lightweight, publish-subscribe messaging protocol, MQTT provides an incredibly flexible bridge, allowing virtually anything that can execute a script to communicate seamlessly with Home Assistant. This guide will walk you through setting up custom MQTT sensors and switches, transforming your shell scripts and external programs into first-class Home Assistant entities.
Setting Up an MQTT Broker (If Needed)
Before diving into custom sensors and switches, ensure you have an MQTT broker running and configured. The Mosquitto broker add-on is highly recommended for Home Assistant OS/Supervised users due to its ease of setup. For other installations (Docker, Core), you can install Mosquitto independently on your network. Make sure Home Assistant's MQTT integration is configured to connect to your broker.
Publishing Custom Sensor Data from a Shell Script
Let's create a custom sensor that reports your Raspberry Pi's CPU temperature. This can be adapted for any script that outputs a single value.
1. Create Your Script
On your Raspberry Pi or host system, create a script (e.g., /config/scripts/get_cpu_temp.sh):
#!/bin/bash
CPU_TEMP=$(vcgencmd measure_temp | egrep -o '[0-9]*\.[0-9]*')
mosquitto_pub -h your_mqtt_broker_ip -p 1883 -u your_mqtt_user -P your_mqtt_password -t 'homeassistant/rpi_cpu/temperature' -m "$CPU_TEMP" -rReplace your_mqtt_broker_ip, your_mqtt_user, and your_mqtt_password with your MQTT broker details. The -r flag (retain) is crucial, ensuring the last reported value persists even if the broker restarts, so Home Assistant always has a state.
Make the script executable: chmod +x /config/scripts/get_cpu_temp.sh
2. Automate Script Execution
Use Home Assistant's command_line sensor or a cron job to periodically run this script. For simplicity and Home Assistant's awareness, using a command_line sensor is often preferred.
# configuration.yaml
sensor:
- platform: command_line
name: RPi CPU Temp Script Runner
command: "/config/scripts/get_cpu_temp.sh"
scan_interval: 30 # Run every 30 seconds (adjust as needed)
unit_of_measurement: '°C' # Optional, for the sensor in HA
value_template: "{{ value }}" # Required, even if not used directlyNote: The command_line sensor itself isn't directly displaying the temperature; it's merely triggering the script that publishes to MQTT. We still need the MQTT sensor.
3. Configure Home Assistant MQTT Sensor
# configuration.yaml
mqtt:
sensor:
- name: "Raspberry Pi CPU Temperature"
state_topic: "homeassistant/rpi_cpu/temperature"
unit_of_measurement: "°C"
value_template: "{{ value | float }}"
device_class: "temperature"
state_class: "measurement"Restart Home Assistant. You should now see a new sensor entity (e.g., sensor.raspberry_pi_cpu_temperature) reporting your CPU temperature.
Controlling a Custom Switch via MQTT and a Shell Script
Now let's create an MQTT switch in Home Assistant that triggers a script on an external system, such as restarting a service or toggling a power outlet controlled by a custom script.
1. Create Your Control Script
On your target system, create a script (e.g., /config/scripts/control_custom_device.sh). This script will subscribe to MQTT and listen for commands.
#!/bin/bash
TOPIC="homeassistant/custom_device/set"
ACTION_ON="ON"
ACTION_OFF="OFF"
# Function to execute when 'ON' command is received
function do_on_action() {
echo "Custom device ON action triggered."
# Example: Execute another script or command
# /path/to/your/on_script.sh
}
# Function to execute when 'OFF' command is received
function do_off_action() {
echo "Custom device OFF action triggered."
# Example: Execute another script or command
# /path/to/your/off_script.sh
}
# Subscribe to the topic and act on messages
mosquitto_sub -h your_mqtt_broker_ip -p 1883 -u your_mqtt_user -P your_mqtt_password -t "$TOPIC" | while read line
do
if [ "$line" = "$ACTION_ON" ]; then
do_on_action
# Publish state back to HA
mosquitto_pub -h your_mqtt_broker_ip -p 1883 -u your_mqtt_user -P your_mqtt_password -t 'homeassistant/custom_device/state' -m 'ON' -r
elif [ "$line" = "$ACTION_OFF" ]; then
do_off_action
# Publish state back to HA
mosquitto_pub -h your_mqtt_broker_ip -p 1883 -u your_mqtt_user -P your_mqtt_password -t 'homeassistant/custom_device/state' -m 'OFF' -r
else
echo "Received unknown command: $line"
fi
doneMake it executable: chmod +x /config/scripts/control_custom_device.sh. You'll want to run this script continuously, perhaps using systemd (see Advanced Config).
2. Configure Home Assistant MQTT Switch
# configuration.yaml
mqtt:
switch:
- name: "Custom Device Toggle"
command_topic: "homeassistant/custom_device/set"
state_topic: "homeassistant/custom_device/state"
payload_on: "ON"
payload_off: "OFF"
# Optional: optimistic: true if you don't receive state feedback immediately
# initial_state: 'off' # If you want to ensure it starts off
retain: true # Keep the last state on the brokerRestart Home Assistant. You'll find a new switch entity (e.g., switch.custom_device_toggle). When you toggle it in Home Assistant, your script will receive the 'ON' or 'OFF' command.
Troubleshooting Common Issues
MQTT Connection Errors
Ensure your MQTT broker IP, port, username, and password are correct in all scripts and Home Assistant configurations. Test connectivity directly:
mosquitto_pub -h your_mqtt_broker_ip -t 'test/topic' -m 'hello'
mosquitto_sub -h your_mqtt_broker_ip -t 'test/topic'If mosquitto_sub doesn't show 'hello', check broker logs and firewall rules.
Script Permissions and Paths
Verify your scripts are executable (chmod +x) and that the paths in Home Assistant's command_line sensor or systemd units are correct.
Payload Mismatches
Ensure the value_template for sensors correctly extracts the value (e.g., float conversion). For switches, payload_on and payload_off must exactly match what your script publishes/subscribes to.
Entity Not Appearing/Updating
Check Home Assistant logs for MQTT-related errors. If using retain: true, try publishing a dummy message to clear an old retained message if unexpected behavior occurs. Verify topics in scripts and HA config match precisely.
Advanced Configuration and Optimization
Using Python for Enhanced Logic
For more complex data processing or device control, replace shell scripts with Python. Python's Paho-MQTT client library offers robust MQTT interaction.
# publish_temp.py
import paho.mqtt.publish as publish
import subprocess
import time
MQTT_BROKER = "your_mqtt_broker_ip"
MQTT_USER = "your_mqtt_user"
MQTT_PASS = "your_mqtt_password"
TOPIC = "homeassistant/rpi_cpu/temperature"
def get_cpu_temperature():
cmd = "vcgencmd measure_temp"
output = subprocess.check_output(cmd, shell=True).decode('utf-8')
temp = float(output.split('=')[1].split("'')[0])
return temp
if __name__ == "__main__":
temp = get_cpu_temperature()
publish.single(TOPIC, str(temp), hostname=MQTT_BROKER, port=1883,
auth={'username': MQTT_USER, 'password': MQTT_PASS}, retain=True)
print(f"Published CPU temperature: {temp}°C")MQTT Discovery for Automatic Configuration
For a cleaner configuration.yaml, use MQTT Discovery. Your scripts publish a special "discovery" message to a topic like homeassistant/sensor/mydevice/temperature/config, containing the entity's configuration in JSON.
{
"name": "RPi CPU Temp Discovery",
"state_topic": "homeassistant/rpi_cpu/temperature",
"unit_of_measurement": "°C",
"device_class": "temperature",
"state_class": "measurement",
"unique_id": "rpi_cpu_temp_001"
}Publish this JSON to homeassistant/sensor/mydevice/temperature/config with the -r (retain) flag. Then, your sensor script only needs to publish to homeassistant/rpi_cpu/temperature.
Managing Scripts with Systemd
For daemonized scripts (like the MQTT switch listener), use systemd for robust background execution, automatic restarts, and logging. Create a service file (e.g., /etc/systemd/system/custom_device_control.service):
[Unit]
Description=Custom Device MQTT Control Script
After=network.target
[Service]
ExecStart=/usr/bin/bash /config/scripts/control_custom_device.sh
WorkingDirectory=/config/scripts
StandardOutput=inherit
StandardError=inherit
Restart=always
User=your_user # e.g., pi or ha
Group=your_group # e.g., pi or ha
[Install]
WantedBy=multi-user.targetThen: sudo systemctl enable custom_device_control.service and sudo systemctl start custom_device_control.service.
Real-World Example: Smart Home Server Status Monitor
Imagine you run several services on a dedicated server (Plex, Nextcloud, etc.). You can create a script that checks the status of these services using systemctl is-active <service_name> and publishes "running" or "stopped" to separate MQTT topics. Home Assistant then picks these up as MQTT binary sensors, allowing you to quickly see server health and even automate notifications if a critical service goes down. You could extend this with an MQTT switch to remotely restart a service.
Best Practices and Wrap-up
Security
Always use a dedicated MQTT user with a strong password for Home Assistant and your publishing/subscribing scripts. Consider TLS/SSL encryption for MQTT traffic, especially if your broker is accessible from outside your local network.
Error Handling and Logging
Include error handling in your scripts (e.g., try-except blocks in Python, checking exit codes in bash) and log any issues. systemd will capture script output, making debugging easier.
Resource Efficiency
Avoid excessively frequent updates for sensors unless absolutely necessary. Too many MQTT messages can overwhelm your broker and Home Assistant. Use the scan_interval in command_line sensors judiciously.
Reliability with Retain Flag
Utilize the -r (retain) flag with mosquitto_pub for sensor states and discovery messages. This ensures that Home Assistant receives the last known state immediately upon startup or reconnection, preventing 'unknown' states.
Mastering custom MQTT integrations opens up a world of possibilities for tailoring Home Assistant to your precise needs. Whether it's integrating an obscure device, monitoring a server, or creating unique controls, MQTT provides the robust, flexible backbone for your most innovative smart home projects.
NGC 224
Author bio: DIY Smart Home Creator
