Sommaire
Vous voulez créer votre propre capteur, capable en un seul objet connecté de faire différentes mesures, et en particulier de la détection de présence ? Ce tutoriel est fait pour vous.
Nous allons apprendre à configurer un ESP32 comme plateforme multi-capteurs : détection de présence via un ou deux radars LD2410, mesure de température avec un DHT22, luminosité avec un capteur BH1750, et même Bluetooth Proxy.
Le tout est réalisé sans multiplier les microcontrôleurs, en utilisant un seul ESP comme centre de données local.
L’objectif : comprendre comment connecter plusieurs capteurs, optimiser les connexions, et intégrer proprement le tout dans Home Assistant.
Que vous soyez débutant ou bricoleur curieux, ce guide vous accompagne pas à pas dans la mise en place d’un système de capteurs domotique simple, évolutif et intelligent.
Introduction
Prérequis
- Ce qu'il faut maîtriser avant / pendant la réalisation.

- Un réseau Wi-Fi qui tient la route ou ESP lan/POE (non documentés ici).
- Bien différencier les capteurs ayant besoin d'une tension d'alimentation de 3.3V ou 5V (certains supporteront éventuellement les 2 tensions).
Objectif
- Créer une base stable et réutilisable pour d'autres projets domotiques.
- Économique : Un seul ESP au lieu de plusieurs modules commerciaux.
- Personnalisable : Ajout/suppression facile de capteurs.
- Évolutif : Architecture modulaire pour futurs ajouts.
- Local : Traitement des données en local, sans cloud.
Technologies utilisées
- ESP32 : Microcontrôleur WiFi/Bluetooth.
- ESPHome : Firmware personnalisé.
- Home Assistant : Plateforme domotique.
Matériel requis
- Matériel et électronique de base, fer à souder, étain, plaque de prototypage perforée ou breadboard et connexions Dupont, multimètre (recommandé).
- ESP32.
- Capteur DHT22 (température/humidité) (BMP280, DHT 11 ...).
- Capteur BH1750 (luminosité).
- Radar(s) LD2410 (détection présence) (LD2420, LD2450 ...).

Matériel utilisé dans mon installation
Esp32 Wroom 30 broches CP2102 micro USB type B principalement pour utiliser tous les blocs secteurs de Raspberry pi à ma disposition et inutilisés, car mes pi sont en POE. Ils deviennent compliqués à trouver (je peux difficilement vous les recommander) et passent au type C ou carrément en 38 pins.
Ma dernière commande vient de là : CP2102 WROOM ESP32. Comptez une dizaine de jours pour la livraison, les tarifs sont attractifs. Profitez-en pour en prendre plusieurs, ainsi que les capteurs dont vous avez besoin.
Utilisation d'un ESP32
Schéma de câblage
L'avantage de ce projet est sa modularité totale et son évolutivité. Vous pouvez :
- Commencer avec un seul capteur.
- Ajouter progressivement d'autres capteurs.
- Supprimer ceux dont vous n'avez pas besoin.

Capteurs additionnels compatibles
- Capteur de gaz (MQ-2, MQ-135).
- Capteur de flamme (détection infrarouge).
- Capteur de qualité d'air.
- Capteur de vibration (accéléromètre).
...la liste n'est pas exhaustive.
N'hésitez pas à jeter un oeil sur la documentation ESPHome, c'est une mine d'informations.


GPIO (General Purpose Input/Output) sur un ESP
Les GPIO sont des broches (ou "pins") sur un ESP (comme l’ESP32 ou l’ESP8266) qui permettent de connecter et contrôler des composants électroniques.
Chaque GPIO peut être utilisée pour :
- lire un capteur (comme un bouton, une sonde…),
- envoyer un signal (comme allumer une LED, activer un relais…).
Implémenter un radar de présence
Maintenant que nous avons abordé les fondamentaux, intéressons-nous à un capteur très puissant : le radar de présence LD2410.
Choix du capteur
Le 2450 sera recommandé pour un tracking de plusieurs personnes en simultané contrairement au 2410 et 2420. Ce dernier est une version plus évoluée, capable de suivre plusieurs "cibles" et de fournir des coordonnées précises dans l’espace (X, Y), ce qui ouvre la porte à des scénarios complexes comme le suivi de déplacement dans une pièce ou la détection d’intrusion avec discrimination.
Pour information, voici différents autres capteurs de présence du marché et leurs caractéristiques :

À la différence des détecteurs PIR classiques, il détecte non seulement les mouvements, mais aussi la présence immobile, ce qui le rend très utile en domotique. Il reste par contre sensible aux éléments extérieurs comme le vent ou, en intérieur, le lave-linge et malheureusement aussi aux animaux domestiques. Il faudra prendre un soin particulier dans son placement.
Pourquoi un radar LD2410 ?
- Détection fine (présence immobile).
- Angle de 120°.
- Précis, rapide, insensible à la lumière ou à la chaleur.
- Communication série UART.
- Traverse certains matériaux comme le bois, le placo ou même les murs fins, ce qui peut être un avantage (installation discrète ou dans un faux plafond), mais aussi un inconvénient si vous détectez par erreur des mouvements dans une pièce voisine.
- Coût raisonnable.
Limites d’un seul radar
- Angle de détection limité à environ 120°.
- portée maximale entre 5 et 6m (de mon expérience).
Multiplier les radars sur un seul ESP
- Pourquoi c’est possible : UART logiciel (software serial).
- Connecter 2 radars LD2410 avec des UART séparés.
- Explication sur les GPIO utilisés (attention à ceux compatibles UART).
Bonnes pratiques
- Placer les radars en angle pour couvrir des zones complémentaires.
- Tester la portée réelle et l’interférence éventuelle.
- Utiliser les logs ESPHome pour affiner la sensibilité.
Configuration 1 : ESP32 + 1 Radar LD2410
Schéma de câblage


Il suffit ensuite de relier électriquement les éléments ensemble en suivant strictement le schéma, soit via une plaque prototype percée et en soudant, soit via une breadboard et en faisant les liaisons avec des dupont.


Conseil personnel : après avoir monté plusieurs dizaines d'ESP, fini de souder directement sur celui-ci, pour quelques centimes, vous trouverez des supports 15 / 18 pins, qui permettront d'interchanger rapidement un ESP défaillant (ça arrive).

Ils s’intercaleront entre le circuit ( et donc les connexions électriques ) et l'ESP.

Configuration 2 : ESP32 + 2 Radar LD2410
Si besoin on pourra ajouter un second radar (potentiellement 120° + 120° de détection, mais on préfèrera une zone de recouvrement).
Schéma de câblage


Une fois toutes les connexions réalisées, on pourra tester que l'ESP s'allume, en connectant le bloc secteur (ou l'USB) si la led rouge s'allume, la première étape est franchie. Reste la configuration.
Configuration de l'ESP via ESPHome
Une mise au point sur les fondamentaux s’impose — cet article en propose une excellente approche de ce qu'il faut faire pour avoir un ESP remontant dans HA.

On a donc un ESP opérationnel et qui remonte dans Home Assistant.
Reste le plus simple, éditer le code et l'installer dans ESPHome Builder en cliquant sur EDIT sur l'ESP dont on veut modifier le code. Là encore la documentation ESPHome est une mine d'informations.

Je colle ici un exemple de configuration complet avec 2 radars, thermomètre luxmètre et Bluetooth Proxy dont nous n'avons pas encore parlé, tous les xxx sont à remplacer.
substitutions:
name: esp-xxx
friendly_name: esp-xxx
packages:
esphome.bluetooth-proxy: github://esphome/bluetooth-proxies/esp32-generic/esp32-generic.yaml@main
esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
api:
encryption:
key: xxx
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Optional manual IP
manual_ip:
static_ip: xxx
gateway: xxx
subnet: xxx
i2c:
sda: 21
scl: 22
scan: true
id: bus_a
text_sensor:
- platform: wifi_info
ip_address:
name: "IP Address"
mac_address:
name: "MAC Address"
- platform: version
name: "${name}_version"
- platform: template
name: "Uptime (Jours, Heures et Minutes)"
lambda: |-
int seconds = id(uptime_sensor).state;
int days = seconds / 86400;
seconds = seconds % 86400;
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
// Renvoie la chaîne formatée
return (days > 0 ? std::to_string(days) + " jours " : "") +
(hours > 0 ? std::to_string(hours) + " h " : "") +
(minutes > 0 ? std::to_string(minutes) + " min" : "0 min");
update_interval: 60s
entity_category: "diagnostic"
switch:
- platform: restart
name: "Restart"
logger:
level: VERY_VERBOSE
esp32_ble_tracker:
scan_parameters:
duration: 60s
active: true
bluetooth_proxy:
active: true
binary_sensor:
- platform: ble_presence
mac_address: xxx
name: "xxx"
timeout: 45s # le temps avant que ca passe en absent
min_rssi: -80dB # permet de regler la distance de detection
id: Mi_band_laurent
- platform: ble_presence
mac_address: xxx
name: "xxx"
timeout: 45s # le temps avant que ca passe en absent
min_rssi: -80dB # permet de regler la distance de detection
id: Mi_band_papa
- platform: status
name: "Status_g"
- platform: ld2410
ld2410_id: ld2410_g
has_target:
name: "Radar Target G"
id: radar_has_target_xxx_g
has_moving_target:
name: "Radar Moving Target G"
id: radar_moving_target_xxx_g
has_still_target:
name: "Radar Still Target G"
id: radar_still_target_xxx_g
- platform: status
name: "Status_d"
- platform: ld2410
ld2410_id: ld2410_d
has_target:
name: "Radar Target D"
id: radar_has_target_xxx_d
has_moving_target:
name: "Radar Moving Target D"
id: radar_moving_target_xxx_d
has_still_target:
name: "Radar Still Target D"
id: radar_still_target_xxx_d
uart:
- id: ld2410_uart_g
tx_pin: 17
rx_pin: 16
baud_rate: 256000
parity: NONE
stop_bits: 1
- id: ld2410_uart_d
tx_pin: 1
rx_pin: 3
baud_rate: 256000
parity: NONE
stop_bits: 1
ld2410:
- id: ld2410_g
uart_id: ld2410_uart_g
throttle: 1500ms
- id: ld2410_d
uart_id: ld2410_uart_d
throttle: 1500ms
number:
# Configuration pour le capteur gauche (G)
- platform: ld2410
ld2410_id: ld2410_g
timeout:
name: Radar Timeout G
max_move_distance_gate:
name: Radar Max Move Distance G
max_still_distance_gate:
name: Radar Max Still Distance G
g0:
move_threshold:
name: g0 move threshold G
still_threshold:
name: g0 still threshold G
g1:
move_threshold:
name: g1 move threshold G
still_threshold:
name: g1 still threshold G
g2:
move_threshold:
name: g2 move threshold G
still_threshold:
name: g2 still threshold G
g3:
move_threshold:
name: g3 move threshold G
still_threshold:
name: g3 still threshold G
g4:
move_threshold:
name: g4 move threshold G
still_threshold:
name: g4 still threshold G
g5:
move_threshold:
name: g5 move threshold G
still_threshold:
name: g5 still threshold G
g6:
move_threshold:
name: g6 move threshold G
still_threshold:
name: g6 still threshold G
g7:
move_threshold:
name: g7 move threshold G
still_threshold:
name: g7 still threshold G
g8:
move_threshold:
name: g8 move threshold G
still_threshold:
name: g8 still threshold G
# Configuration pour le capteur droit (D)
- platform: ld2410
ld2410_id: ld2410_d
timeout:
name: "Radar Timeout D"
max_move_distance_gate:
name: "Radar Max Move Distance D"
max_still_distance_gate:
name: "Radar Max Still Distance D"
g0:
move_threshold:
name: g0 move threshold D
still_threshold:
name: g0 still threshold D
g1:
move_threshold:
name: g1 move threshold D
still_threshold:
name: g1 still threshold D
g2:
move_threshold:
name: g2 move threshold D
still_threshold:
name: g2 still threshold D
g3:
move_threshold:
name: g3 move threshold D
still_threshold:
name: g3 still threshold D
g4:
move_threshold:
name: g4 move threshold D
still_threshold:
name: g4 still threshold D
g5:
move_threshold:
name: g5 move threshold D
still_threshold:
name: g5 still threshold D
g6:
move_threshold:
name: g6 move threshold D
still_threshold:
name: g6 still threshold D
g7:
move_threshold:
name: g7 move threshold D
still_threshold:
name: g7 still threshold D
g8:
move_threshold:
name: g8 move threshold D
still_threshold:
name: g8 still threshold D
sensor:
- platform: ld2410
ld2410_id: ld2410_g
moving_distance:
name: "Radar Moving Distance G"
id: moving_distance_g
still_distance:
name: "Radar Still Distance G"
id: still_distance_g
moving_energy:
name: "Radar Move Energy G"
still_energy:
name: "Radar Still Energy G"
detection_distance:
name: "Radar Detection Distance G"
id: radar_detection_distance_g
g0:
move_energy:
name: "g0 Move Energy G"
still_energy:
name: "g0 Still Energy G"
g1:
move_energy:
name: "g1 Move Energy G"
still_energy:
name: "g1 Still Energy G"
g2:
move_energy:
name: "g2 Move Energy G"
still_energy:
name: "g2 Still Energy G"
g3:
move_energy:
name: "g3 Move Energy G"
still_energy:
name: "g3 Still Energy G"
g4:
move_energy:
name: "g4 Move Energy G"
still_energy:
name: "g4 Still Energy G"
g5:
move_energy:
name: "g5 Move Energy G"
still_energy:
name: "g5 Still Energy G"
g6:
move_energy:
name: "g6 Move Energy G"
still_energy:
name: "g6 Still Energy G"
g7:
move_energy:
name: "g7 Move Energy G"
still_energy:
name: "g7 Still Energy G"
g8:
move_energy:
name: "g8 Move Energy G"
still_energy:
name: "g8 Still Energy G"
- platform: ld2410
ld2410_id: ld2410_d
moving_distance:
name: "Radar Moving Distance D"
id: moving_distance_d
still_distance:
name: "Radar Still Distance D"
id: still_distance_d
moving_energy:
name: "Radar Move Energy D"
still_energy:
name: "Radar Still Energy D"
detection_distance:
name: "Radar Detection Distance D"
id: radar_detection_distance_d
g0:
move_energy:
name: "g0 Move Energy D"
still_energy:
name: "g0 Still Energy D"
g1:
move_energy:
name: "g1 Move Energy D"
still_energy:
name: "g1 Still Energy D"
g2:
move_energy:
name: "g2 Move Energy D"
still_energy:
name: "g2 Still Energy D"
g3:
move_energy:
name: "g3 Move Energy D"
still_energy:
name: "g3 Still Energy D"
g4:
move_energy:
name: "g4 Move Energy D"
still_energy:
name: "g4 Still Energy D"
g5:
move_energy:
name: "g5 Move Energy D"
still_energy:
name: "g5 Still Energy D"
g6:
move_energy:
name: "g6 Move Energy D"
still_energy:
name: "g6 Still Energy D"
g7:
move_energy:
name: "g7 Move Energy D"
still_energy:
name: "g7 Still Energy D"
g8:
move_energy:
name: "g8 Move Energy D"
still_energy:
name: "g8 Still Energy D"
- platform: template
id: esp_memory
icon: mdi:memory
name: ESP Free Memory
lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024;
unit_of_measurement: 'kB'
state_class: measurement
entity_category: "diagnostic"
- platform: internal_temperature
name: "intern_temp"
- platform: uptime
name: "Uptime Raw"
id: uptime_sensor
- platform: wifi_signal
name: "WiFi Signal Strength"
update_interval: 60s
- platform: dht
pin: 27
temperature:
name: "Temperature"
accuracy_decimals: 2
device_class: "temperature"
filters:
- offset: -3.0
humidity:
name: "Humidite"
accuracy_decimals: 2
device_class: "humidity"
update_interval: 20s
- platform: bh1750
name: "Lumiere"
device_class: "illuminance"
address: 0x23
update_interval: 60s
substitutions:
name: esp-xxx
friendly_name: esp-xxx
Définir des variables réutilisables (${name}
, ${friendly_name}
) pour éviter les répétitions. Ici, elles servent à nommer l'appareil de façon cohérente.
packages:
esphome.bluetooth-proxy: github://esphome/bluetooth-proxies/esp32-generic/esp32-generic.yaml@main
Charger un template préconfiguré (via GitHub) pour transformer l’ESP32 en proxy Bluetooth, facilitant la détection d’appareils BLE par Home Assistant.
esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
name
: Nom réseau de l'appareil.name_add_mac_suffix
:false
= ne pas ajouter les 4 derniers caractères de l’adresse MAC au nom.friendly_name
: Nom lisible pour l’interface utilisateur.
api:
encryption:
key: xxx
Activer l’API sécurisée entre ESPHome et Home Assistant. La clé xxx
est utilisée pour chiffrer les communications.
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: xxx
gateway: xxx
subnet: xxx
ssid
etpassword
sont masqués avec!secret
.manual_ip
: IP statique + passerelle + masque de sous-réseau, pour éviter les conflits DHCP.
i2c:
sda: 21
scl: 22
scan: true
id: bus_a
Déclaration du bus I²C :
sda
,scl
: broches utilisées.scan: true
: détecte automatiquement les périphériques I²C.id
: identifiant interne du bus.
- platform: wifi_info / version / template
- platform: restart
name: "Restart"
Définit des capteurs de texte :
wifi_info
: IP et MAC.version
: version d’ESPHome.template
: formatage de l’uptime en jours/heures/minutes à partir d’un autre capteur nomméuptime_sensor
.- Un simple bouton de redémarrage de l’ESP via Home Assistant.
logger:
level: VERY_VERBOSE
Active la journalisation ultra détaillée (utile pour déboguer, mais très verbeux). On le repassera sur plus léger après le debug (level: INFO) par exemple.
esp32_ble_tracker:
scan_parameters:
duration: 60s
active: true
bluetooth_proxy:
active: true
- Permet à l’ESP de scanner les périphériques BLE environnants.
duration
: durée du scan.active
: mode actif = envoie des requêtes Bluetooth.- Active le rôle de proxy BLE, pour relayer les appareils Bluetooth vers Home Assistant.
- platform: ble_presence
mac_address: xxx
timeout: 45s
min_rssi: -80dB
- Détecte la présence de périphériques BLE (ex. Mi Band).
timeout
: temps avant de passer à "absent".min_rssi
: seuil de puissance de détection, -81dB > -90dB ne sera pas pris en compte ( de toute façon "au dessus" de -90dB c'est inutilisable).
Vient ensuite la partie purement radar / présence
- platform: ld2410
ld2410_id: ...
has_target / has_moving_target / has_still_target
uart:
- id: ld2410_uart_g / ld2410_uart_d
- id: ld2410_g / ld2410_d
uart_id: ...
throttle: 1500ms
Détection de cibles :
has_target
: détecte n'importe quelle cible.has_moving_target
: détecte les cibles en mouvement.has_still_target
: cibles immobiles détectées par le radar.
Configuration des ports série pour communiquer avec les radars LD2410 (gauche et droite).
tx_pin
,rx_pin
: broches de communication.baud_rate
: 256000 bps (exigé par les LD2410).parity
,stop_bits
: paramètres de communication.
Déclaration des capteurs radar LD2410, un pour chaque UART.
throttle
: fréquence d’actualisation (1.5 secondes).
number:
# Configuration pour le capteur gauche (G)
- platform: ld2410
ld2410_id: ld2410_g
# Configuration pour le capteur droit (D)
- platform: ld2410
ld2410_id: ld2410_d
Déclaration de paramètres configurables du radar (par Home Assistant) :
timeout
,max_move_distance_gate
, etc. : seuils de détection, distances, etc.g0
àg8
: 9 "gates" (zones de distance du radar), chaque gate peut avoir :move_threshold
: seuil de détection de mouvement.still_threshold
: seuil de détection d'immobile.
Cela permet un réglage très fin de la sensibilité du radar dans chaque zone.
sensor:
- platform: ld2410
ld2410_id: ld2410_g
- platform: ld2410
ld2410_id: ld2410_d
Deux grands blocs, un pour chaque radar :
Données générales :
moving_distance
: distance d’une cible en mouvement.still_distance
: distance d’une cible immobile.detection_distance
: distance maximale de détection.moving_energy
/still_energy
: intensité du signal.
Par zone (g0
à g8
) :
move_energy
: énergie détectée en mouvement.still_energy
: énergie d’un objet immobile.
- platform: template
id: esp_memory
icon: mdi:memory
name: ESP Free Memory
lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024;
unit_of_measurement: 'kB'
state_class: measurement
entity_category: "diagnostic"
- platform: internal_temperature
name: "intern_temp"
- platform: uptime
name: "Uptime Raw"
id: uptime_sensor
- platform: wifi_signal
name: "WiFi Signal Strength"
update_interval: 60s
- platform: dht
pin: 27
temperature:
name: "Temperature"
accuracy_decimals: 2
device_class: "temperature"
filters:
- offset: -3.0
humidity:
name: "Humidite"
accuracy_decimals: 2
device_class: "humidity"
update_interval: 20s
- platform: bh1750
name: "Lumiere"
device_class: "illuminance"
address: 0x23
update_interval: 60s
On peut aussi configurer plusieurs autres capteurs :
- Mémoire libre interne.
- Température interne.
- Puissance du signal Wifi toutes les 60 secondes (à définir).
- DHT pour la température, à noter qu'il faudra calibrer le capteur ( un offset est possible).
- Humidité toutes les 20s (à définir).
- Intensité lumineuse toutes les 60s (à définir).
Ce qui au final donnera quelque chose comme ça pour la partie info.

Calibrage de détection
Le radar LD2410 divise la zone de détection en 9 zones de distance appelées gates (de g0
pour la plus proche à g8
pour la plus éloignée).
Pour chacune de ces gates, on peut régler deux seuils indépendants :
move_threshold
: sensibilité à un mouvement dans cette zone.still_threshold
: sensibilité à une présence immobile dans cette zone.
Ces réglages permettent d’adapter la détection selon la distance et le comportement attendu dans chaque portion de la pièce.
Notez que vous pouvez désactiver une ou plusieurs gates si vous en avez le besoin (passer les seuils de détection à 100), chaque gates à un pas de 0.75m si vous voulez désactiver par exemple la détection au delà de 3m.


Méthode de réglage recommandée
Voici une démarche typique pour bien ajuster les seuils :
- Relever les valeurs typiques
- Note les valeurs en présence (avec quelqu’un immobile ou en mouvement).
- Note les valeurs en absence.
- Choisir un seuil juste au-dessus du bruit de fond
- Définis le
move_threshold
et lestill_threshold
à 10-20 % au-dessus du maximum observé sans personne. - Ajuste en fonction de la distance : plus on s’éloigne, plus les énergies sont faibles, donc les seuils aussi.
- Définis le
- Tester en conditions réelles
- Bouge dans différentes zones et observe quelles gates réagissent.
- Reste immobile et vois si la détection persiste.
Exemple d'usage
- Détecter une présence proche même immobile : augmentez le
still_threshold
dans les gates proches (g0 à g2). - Ignorer les mouvements lointains pour éviter les faux positifs : baissez le
move_threshold
dans les gates éloignées (g6 à g8).
Maillage et Bluetooth Proxy
Le Bluetooth Proxy enfin est une fonctionnalité introduite par Home Assistant qui permet à un ESP32 (car uniquement les ESP32 possèdent un module Bluetooth) de relayer les données Bluetooth vers votre serveur Home Assistant, même si celui-ci est physiquement éloigné ou ne dispose pas de Bluetooth intégré.
L’objectif est d’étendre la couverture Bluetooth dans toute la maison à l’aide de petits ESP32 répartis à des endroits stratégiques. Cela permet notamment de rendre accessibles des périphériques BLE (Bluetooth Low Energy) comme des thermomètres Xiaomi, des capteurs d’humidité, des traqueurs de présence, ou encore des serrures connectées.
L’avantage principal est que vous n’avez rien à faire de complexe : il suffit de flasher l’ESP32 avec ESPHome et d’y activer l’option bluetooth_proxy:
dans le fichier de configuration. Une fois en ligne, l’ESP32 apparaît dans Home Assistant et relaie automatiquement les périphériques BLE détectés dans sa zone. C’est une solution très efficace, peu coûteuse et idéale pour les maisons où le Bluetooth natif de Home Assistant est limité en portée ou bloqué par des obstacles (murs, étages, etc.). Il est même possible de mettre plusieurs ESP32 Bluetooth Proxy dans la maison pour former un maillage de couverture BLE.
En résumé, le Bluetooth Proxy via ESP32 permet de transformer un petit ESP en antenne Bluetooth distante, décuplant ainsi les capacités de détection BLE de votre domotique, sans matériel supplémentaire.
Depuis HA 2025.6.0, on peut se montrer plus exigeant avec le Bluetooth, mieux le comprendre, voir détecter des soucis.

Non, il n'y a pas d'adresses MAC sur l'image, et c'est normal 😉
Aller plus loin.
Nous avons vu comment créer un système multicapteurs complet avec un seul ESP32, capable de mesurer la température, la luminosité, la présence immobile, les mouvements, et même de relayer des informations Bluetooth. Grâce à ESPHome, tout cela est réalisé localement, sans cloud, de façon modulaire et évolutive.
Structure avancée avec !include
Mais ce projet ne représente qu’un socle. Une fois les bases acquises, il est vivement conseillé de structurer davantage vos fichiers YAML en utilisant des !include
. Cela permet de séparer chaque capteur ou fonctionnalité dans un fichier dédié (par exemple radar_gauche.yaml
, ble_presence.yaml
, sensors.yaml
…), ce qui rend le code plus lisible, réutilisable et facile à maintenir sur plusieurs ESP.
substitutions:
name: esp-xxx
friendly_name: esp-xxx
packages:
esphome.bluetooth-proxy: github://esphome/firmware/bluetooth-proxy/esp32-generic.yaml@main
base: !include .base.yaml
bluetooth: !include .bluetooth.yaml
presence: !include .presence.yaml
api:
encryption:
key: xxx
Mon base.yaml en exemple

esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: True
text_sensor:
- platform: wifi_info
ip_address:
name: "IP Address"
mac_address:
name: "MAC Address"
- platform: version
name: "${name}_version"
- platform: template
name: "Uptime (Jours, Heures et Minutes)"
lambda: |-
int seconds = id(uptime_sensor).state;
int days = seconds / 86400;
seconds = seconds % 86400;
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
// Renvoie la chaîne formatée
return (days > 0 ? std::to_string(days) + " j " : "") +
(hours > 0 ? std::to_string(hours) + " h " : "") +
(minutes > 0 ? std::to_string(minutes) + " min" : "0 min");
update_interval: 60s
entity_category: "diagnostic"
switch:
- platform: restart
name: "Restart"
logger:
level: INFO
sensor:
- platform: template
id: esp_memory
icon: mdi:memory
name: ESP Free Memory
lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024;
unit_of_measurement: 'kB'
state_class: measurement
entity_category: "diagnostic"
- platform: internal_temperature
name: "intern_temp"
- platform: uptime
name: "Uptime Raw"
id: uptime_sensor
- platform: wifi_signal
name: "WiFi Signal Strength"
update_interval: 60s
Dans les !includes, mettre un . devant le nom du fichier, permet de les rendre invisible dans l'interface ESPHome builder.
Trilatération BLE et géolocalisation intérieure
Enfin, pour les utilisateurs plus avancés, une autre piste passionnante s’ouvre : la trilatération BLE. Des projets comme Bermuda permettent, grâce à plusieurs ESP32 configurés en Bluetooth Proxy, de localiser un objet BLE (comme un badge ou une montre) en croisant les niveaux RSSI (signal) reçus par plusieurs ESP dans la maison. Cela ouvre la voie à une géolocalisation intérieure sans caméra, avec des usages tels que :
- suivre les déplacements d’une personne d’une pièce à l’autre,
- adapter automatiquement l’éclairage ou le chauffage à sa position,
- sécuriser des accès en fonction d’une présence réelle et localisée.
En combinant radars LD2410 pour la précision locale et Bluetooth Proxy pour la présence générale, vous posez les fondations d’un système domotique intelligent, autonome et sensible à votre environnement en temps réel.
Voilà, amusez-vous bien et n'hésitez pas à faire vos commentaires.