Supervision complète d’un Raspberry Pi 3 via MQTT et Home Assistant
Ce script Bash permet de superviser un Raspberry Pi 3 et de publier ses métriques dans MQTT, afin qu’elles soient automatiquement intégrées dans Home Assistant grâce au mécanisme de MQTT Discovery.
L’objectif est d’obtenir une télémétrie complète du système :
-
état des feeders ADS-B
-
charge CPU
-
température
-
mémoire
-
disque
-
réseau
-
connectivité
-
alimentation du Raspberry Pi
-
nombre d’avions détectés
Toutes ces informations sont publiées automatiquement dans MQTT et deviennent immédiatement visibles dans Home Assistant sans configuration manuelle.
Principe de fonctionnement
Le script repose sur trois mécanismes principaux :
-
Création automatique des capteurs Home Assistant via MQTT Discovery
-
Collecte des métriques système
-
Publication des données et des attributs dans MQTT
Chaque métrique devient un capteur Home Assistant associé à un topic MQTT spécifique.
Architecture des topics MQTT
Les données sont publiées dans une arborescence simple :
rpi3/<categorie>/<metrique>/state
rpi3/<categorie>/<metrique>/attributes
Exemples :
rpi3/system/cpu_temp/state
rpi3/system/cpu_temp/attributes
rpi3/system/ram_used/state
rpi3/system/ram_used/attributes
rpi3/feeders/fr24feed/state
state
contient la valeur brute du capteur
exemple :
54.2
attributes
contient des informations complémentaires au format JSON
exemple :
{
"label": "54.2",
"updated": "2026-01-30 20:15:10"
}
Cela permet dans Home Assistant d’afficher par exemple :
-
l’heure de dernière mise à jour
-
une étiquette lisible
-
d’autres métadonnées.
Création automatique des capteurs (MQTT Discovery)
La fonction :
publish_discovery()
crée automatiquement les capteurs dans Home Assistant en publiant un message dans :
homeassistant/sensor/<unique_id>/config
Exemple :
homeassistant/sensor/rpi3_system_cpu_temp/config
Le message publié contient un JSON décrivant le capteur, par exemple :
-
nom du capteur
-
topic MQTT
-
unité
-
icône
-
type de donnée
-
identifiant unique
Exemple simplifié :
{
"name": "CPU Temp",
"state_topic": "rpi3/system/cpu_temp/state",
"unit_of_measurement": "°C",
"device_class": "temperature",
"icon": "mdi:thermometer"
}
Grâce à cela :
-
Home Assistant détecte automatiquement le capteur
-
aucune configuration YAML n’est nécessaire
-
les capteurs apparaissent immédiatement dans l’interface.
Publication des données
La fonction :
publish_value()
publie les informations dans MQTT.
Elle envoie deux messages :
1. valeur du capteur
rpi3/system/cpu_temp/state
2. attributs du capteur
rpi3/system/cpu_temp/attributes
Les attributs incluent :
-
un label lisible
-
la date de mise à jour.
Supervision des feeders ADS-B
Le script vérifie l’état de plusieurs services ADS-B :
-
ADSBExchange
-
FlightRadar24
-
Planefinder
-
FlightAware
-
AirNav
-
OpenSky
-
Dump1090
-
ADSBHub
Pour chaque feeder :
-
le script vérifie si le service est actif via systemctl
-
il publie :
1 = actif
0 = inactif
Exemple :
rpi3/feeders/fr24feed/state
Cela permet de voir immédiatement dans Home Assistant si un feeder est arrêté.
Métriques système collectées
Le script récupère différentes informations du Raspberry Pi.
CPU
-
charge 1 minute
-
charge 5 minutes
-
charge 15 minutes
source :
/proc/loadavg
Température
-
température CPU
-
température GPU
commande utilisée :
vcgencmd measure_temp
Fréquence GPU
vcgencmd measure_clock core
Mémoire
RAM utilisée et RAM totale via :
free -m
Disque
espace utilisé et libre via :
df -h /
Réseau
trafic réseau total :
/sys/class/net/<interface>/statistics/
-
rx_bytes
-
tx_bytes
Connectivité
Deux tests de connectivité sont effectués :
-
ping du routeur local
-
ping de Google DNS (8.8.8.8)
Cela permet de distinguer :
-
un problème réseau local
-
un problème Internet.
Adresse IP
Le script publie l’adresse IP actuelle du Raspberry Pi :
hostname -I
Détection du nombre d’avions ADS-B
Le script interroge l’API locale de dump1090 :
http://localhost:8080/data/aircraft.json
Il compte les avions vus dans les 60 dernières secondes.
Commande utilisée :
jq '[.aircraft[] | select(.seen < 60)] | length'
Cela donne une estimation du trafic aérien actif.
Surveillance de l’alimentation du Raspberry Pi
Le script utilise :
vcgencmd get_throttled
Si le Raspberry Pi manque de puissance électrique, un flag est activé.
Le capteur renvoie :
1 = alimentation OK
0 = sous-alimentation détectée
Organisation des capteurs dans Home Assistant
Tous les capteurs sont regroupés sous un device unique :
Raspberry Pi 3
avec les métadonnées :
-
modèle
-
fabricant
-
version du script.
Avantages de cette approche
-
configuration automatique dans Home Assistant
-
architecture MQTT simple et lisible
-
script léger et portable
-
supervision complète du Raspberry Pi
-
idéal pour les stations ADS-B
Exemple de résultat dans Home Assistant
Une fois le script exécuté, on obtient par exemple :
-
CPU Temp
-
GPU Temp
-
RAM Used
-
Disk Free
-
Net In / Net Out
-
Ping Router
-
Ping Google
-
Aircraft Active
-
état des feeders ADS-B
Le tout regroupé dans un seul appareil Raspberry Pi 3.
Aadapter selon vos besoins ![]()
#!/bin/bash
# ============================================
# status3_full.sh - Supervision complète RPi3 via MQTT HA
# ADS-B + métriques système + réseau + GPU + I/O
# ============================================
GREEN="\033[0;32m"
RED="\033[0;31m"
RESET="\033[0m"
BROKER="192.168.1.87"
USER="mqtt-user"
PASS="mqtt-pass"
echo "=== Supervision RPi3 complète ==="
# --------------------------------------------
# MQTT Discovery
# --------------------------------------------
publish_discovery() {
local name="$1"
local service="$2"
local topic_base="$3"
local unique_id="rpi3_${topic_base}_${service}"
local discovery_topic="homeassistant/sensor/${unique_id}/config"
# Définition des unités, device_class, state_class et icône selon le service
local unit="" icon="" device_class="" state_class=""
case "$service" in
cpu_temp|gpu_temp)
unit="°C"
state_class="measurement"
device_class="temperature"
icon="mdi:thermometer"
;;
cpu_load1|cpu_load5|cpu_load15)
state_class="measurement"
# device_class="none"
icon="mdi:cpu-64-bit"
state_class="measurement"
;;
ram_used|ram_total)
unit="MB"
icon="mdi:memory"
state_class="measurement"
;;
disk_used|disk_free)
unit="GB"
icon="mdi:harddisk"
state_class="measurement"
;;
net_in|net_out)
unit="Bytes"
state_class="total_increasing"
icon="mdi:network"
# state_class="measurement"
;;
pi_power)
icon="mdi:flash"
state_class="measurement"
;;
ping_router|ping_google)
icon="mdi:network-pos"
state_class="measurement"
;;
aircraft_active|adsb_aircraft_count)
unit="aircraft"
icon="mdi:airplane"
state_class="measurement"
;;
ip_address)
icon="mdi:lan"
;;
*)
icon="mdi:help-circle"
state_class="measurement"
;;
esac
# Construction du payload JSON
local payload="{\"name\":\"$name\",\"state_topic\":\"rpi3/$topic_base/$service/state\",\"unique_id\":\"$unique_id\",\"object_id\":\"$unique_id\""
# Ajouter unit_of_measurement seulement si définie
[[ -n "$unit" ]] && payload+=",\"unit_of_measurement\":\"$unit\""
# Ajouter device_class seulement si défini
[[ -n "$device_class" ]] && payload+=",\"device_class\":\"$device_class\""
# Ajouter state_class seulement si défini
[[ -n "$state_class" ]] && payload+=",\"state_class\":\"$state_class\""
# Champs fixes
payload+=",\"icon\":\"$icon\",\"json_attributes_topic\":\"rpi3/$topic_base/$service/attributes\",\"value_template\":\"{{ value }}\",\"device\":{\"identifiers\":[\"rpi3\"],\"name\":\"Raspberry Pi 3\",\"model\":\"Raspberry Pi 3 B+\",\"manufacturer\":\"Raspberry Pi Foundation\",\"sw_version\":\"status.sh v0.0.1 20260130\"}}"
# Debug
#echo "DEBUG: Publishing to $discovery_topic"
#echo "DEBUG: Payload -> $payload"
# Publication MQTT
mosquitto_pub -h "$BROKER" -u "$USER" -P "$PASS" -t "$discovery_topic" -m "$payload" -r
}
# --------------------------------------------
# Publier valeurs MQTT
# --------------------------------------------
publish_value() {
local topic_base="$1"
local service="$2"
local value="$3"
local label="$4"
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
# Publier la valeur simple dans state_topic
mosquitto_pub -h "$BROKER" -u "$USER" -P "$PASS" \
-t "rpi3/$topic_base/$service/state" -m "$value"
# Publier les attributs dans un topic séparé
payload=$(jq -n \
--arg lbl "$label" \
--arg ts "$timestamp" \
'{label: $lbl, updated: $ts}')
mosquitto_pub -h "$BROKER" -u "$USER" -P "$PASS" \
-t "rpi3/$topic_base/$service/attributes" -m "$payload"
}
# --------------------------------------------
# ADS-B Feeders
# --------------------------------------------
feeders=(
"adsbexchange-feed:ADSBExchange Feed"
"adsbexchange-mlat:ADSBExchange MLAT"
"adsbexchange-stats:ADSBExchange Stats"
"fr24feed:FR24"
"pfclient:Planefinder"
"piaware:FlightAware Piaware"
"rbfeeder:AirNav RBFeeder"
"dump1090-fa:Dump1090-fa"
"opensky-feeder:OpenSky"
"adsbhub.sh:ADSBhub Script"
)
for f in "${feeders[@]}"; do
service="${f%%:*}"
name="${f##*:}"
publish_discovery "$name" "$service" "feeders" "$service"
# Vérification service ou script
if [ "$service" == "adsbhub.sh" ]; then
pgrep -f /usr/bin/adsbhub.sh >/dev/null && status="active" || status="inactive"
else
status=$(sudo systemctl is-active "$service" 2>/dev/null || echo "inactive")
fi
value=$([ "$status" == "active" ] && echo 1 || echo 0)
label=$([ "$status" == "active" ] && echo "OK" || echo "KO")
publish_value "feeders" "$service" "$value" "$label"
done
# --------------------------------------------
# Pi System métriques
# --------------------------------------------
system_metrics=(
"pi_power:Pi Power"
"cpu_load1:CPU Load 1min"
"cpu_load5:CPU Load 5min"
"cpu_load15:CPU Load 15min"
"cpu_temp:CPU Temp"
"gpu_temp:GPU Temp"
"gpu_freq:GPU Freq"
"ram_used:RAM Used"
"ram_total:RAM Total"
"disk_used:Disk Used"
"disk_free:Disk Free"
"ip_address:IP Address"
"ping_router:Ping Router"
"ping_google:Ping Google"
"net_in:Net In"
"net_out:Net Out"
"aircraft_active:Aircraft Active (<60s)"
)
ROUTER="192.168.1.1"
NET_IF="enxb827ebc51e31"
for s in "${system_metrics[@]}"; do
service="${s%%:*}"
name="${s##*:}"
publish_discovery "$name" "$service" "system" "$service"
case "$service" in
pi_power)
output=$(/usr/bin/vcgencmd get_throttled)
if [ "$output" == "throttled=0x0" ]; then value=1; label="OK"; else value=0; label="Under powered"; fi
;;
cpu_load1)
value=$(cut -d ' ' -f1 /proc/loadavg)
label="$value"
;;
cpu_load5)
value=$(cut -d ' ' -f2 /proc/loadavg)
label="$value"
;;
cpu_load15)
value=$(cut -d ' ' -f3 /proc/loadavg)
label="$value"
;;
cpu_temp)
value=$(/usr/bin/vcgencmd measure_temp | cut -d '=' -f2 | tr -d "'C")
label="${value}"
;;
gpu_temp)
value=$(/usr/bin/vcgencmd measure_temp | cut -d '=' -f2 | tr -d "'C")
label="${value}"
;;
gpu_freq)
value=$(/usr/bin/vcgencmd measure_clock core | cut -d '=' -f2 | awk '{print $1/1000000}')
label="${value} MHz"
;;
ram_used)
value=$(free -m | awk '/Mem:/ {print $3}')
label="${value} MB"
;;
ram_total)
value=$(free -m | awk '/Mem:/ {print $2}')
label="${value} MB"
;;
disk_used)
value=$(df -h / | awk 'NR==2 {print $3}' | sed 's/G//')
label="$value GB"
;;
disk_free)
value=$(df -h / | awk 'NR==2 {print $4}' | sed 's/G//')
label="$value GB"
;;
ip_address)
value=$(hostname -I | awk '{print $1}')
label="$value"
;;
ping_router)
ping -c 1 $ROUTER >/dev/null 2>&1 && value=1 && label="OK" || value=0 && label="KO"
;;
ping_google)
ping -c 1 8.8.8.8 >/dev/null 2>&1 && value=1 && label="OK" || value=0 && label="KO"
;;
net_in)
value=$(cat /sys/class/net/$NET_IF/statistics/rx_bytes)
label="$value Bytes"
;;
net_out)
value=$(cat /sys/class/net/$NET_IF/statistics/tx_bytes)
label="$value Bytes"
;;
aircraft_active)
value=$(curl -s http://localhost:8080/data/aircraft.json | jq '[.aircraft[] | select(.seen < 60)] | length' 2>/dev/null || echo 0)
label="$value aircraft"
;;
esac
publish_value "system" "$service" "$value" "$label"
done
# --------------------------------------------
# Services critiques (seul SSH)
# --------------------------------------------
critical_services=(
"ssh:SSH"
)
for c in "${critical_services[@]}"; do
service="${c%%:*}"
name="${c##*:}"
publish_discovery "$name" "$service" "system" "$service"
status=$(sudo systemctl is-active "$service" 2>/dev/null || echo "inactive")
value=$([ "$status" == "active" ] && echo 1 || echo 0)
label=$([ "$status" == "active" ] && echo "OK" || echo "KO")
publish_value "system" "$service" "$value" "$label"
done
echo "=== Fin supervision complète RPi3 ==="