Niveau : Débutant / Intermédiaire
Mots-clés : esphome bluetooth-proxy wireguard m5stack bm6 voiture
Objectif du projet
Ce projet permet de surveiller la batterie de sa voiture Ă distance, mĂȘme en dĂ©placement, grĂące Ă un ESP32 qui fait le pont entre le capteur Bluetooth BM6 et Home Assistant.
Le capteur BM6 (testeur de batterie 12V) ne communique quâen Bluetooth courte portĂ©e. Le M5Stack Atom ESP32 capte ses trames BLE et les transmet Ă Home Assistant via WiFi. Pour que ça fonctionne aussi quand la voiture est loin de la maison (parking, garage, dĂ©placement), un tunnel VPN WireGuard est Ă©tabli entre lâESP32 et le serveur maison.
Architecture réseau
[BM6 Batterie]
â Bluetooth BLE
âŒ
[M5Stack Atom ESP32] âââ WiFi maison (prioritĂ© 1)
VPN 10.0.0.5 âââ Hotspot tĂ©lĂ©phone (fallback)
â WireGuard VPN chiffrĂ© (UDP 51820)
âŒ
[Proxmox 192.168.1.14]
WireGuard LXC Serveur
â RĂ©seau local
âŒ
[Home Assistant 192.168.1.10]
- WiFi maison â LED verte, connexion directe
- Hotspot mobile â LED bleue, connexion via Internet + VPN
- Dans les deux cas, Home Assistant reçoit les données identiquement
Matériel nécessaire
| Composant | Description | Prix indicatif |
|---|---|---|
| M5Stack Atom Lite | ESP32 compact, LED RGB intégrée, bouton | ~10⏠|
| Capteur BM6 | Testeur batterie 12V Bluetooth BLE | ~15⏠|
| Home Assistant | InstallĂ© sur Proxmox, NUC, RPi⊠| â |
| ESPHome | Add-on HA ou standalone | Gratuit |
| Serveur WireGuard | LXC sur Proxmox dans cet exemple | â |
| DuckDNS | Domaine dynamique gratuit pour joindre le serveur | Gratuit |
| Battery Monitor BM6 | GitHub - Rafciq/BM6: Home Assistant integration for Battery Monitor BM6 · GitHub | Gratuit |
Le M5Stack Atom se branche directement sur lâallume-cigare ou sur une prise USB de la voiture pour sâalimenter en permanence.
A savoir : Certaine constructeur / voiture coupe le 12 volts aprĂšs lâarrĂȘt de la voiture. Donc lâesp32 ne sera plus alimentĂ© .
Ătape 1 â PrĂ©parer les clĂ©s WireGuard
Sur ton serveur WireGuard (Linux), gĂ©nĂšre une paire de clĂ©s pour lâESP32 :
# Générer la clé privée de l'ESP32
wg genkey | tee esp_ferrari_private.key | wg pubkey > esp_ferrari_public.key
cat esp_ferrari_private.key # â Ă mettre dans secrets.yaml (cĂŽtĂ© ESP)
cat esp_ferrari_public.key # â Ă dĂ©clarer dans wg0.conf (cĂŽtĂ© serveur)
Dans ta config serveur /etc/wireguard/wg0.conf, ajoute un peer :
[Peer]
# M5Stack Atom Ferrari
PublicKey = <contenu de esp_ferrari_public.key>
AllowedIPs = 10.0.0.5/32
Nâoublie pas dâouvrir le port UDP 51820 sur ton routeur (redirection vers le Proxmox).
Ătape 2 â Configurer secrets.yaml dans ESPHome
Ce fichier contient tous tes mots de passe. Ne le partage jamais.
# Réseau WiFi principal (maison)
wifi_ssid_ax56: "NomDeMonWiFiMaison"
wifi_password_ax56: "MotDePasseWiFi"
# Hotspot téléphone (en déplacement)
wifi_ssid_phone: "NomHotspot"
wifi_password_phone: "MotDePasseHotspot"
# Clés WireGuard
wg_esp_ferrari_private_key: "CLĂ_PRIVĂE_ESP32_EN_BASE64="
wg_esp_ferrari_server_public_key: "CLĂ_PUBLIQUE_SERVEUR_EN_BASE64="
Ătape 3 â Le fichier YAML complet commentĂ©
esphome:
name: bt-ferrari-mobile
friendly_name: BT Proxy FERRARI Mobile
on_boot:
priority: -100
then:
- light.turn_on:
id: led_atom
brightness: 20%
red: 1
green: 0.5
blue: 0 # LED orange au démarrage = initialisation
esp32:
board: m5stack-atom
framework:
type: esp-idf # Plus stable que Arduino pour BLE + WireGuard
wifi:
networks:
- ssid: !secret wifi_ssid_ax56 # WiFi maison en priorité
password: !secret wifi_password_ax56
priority: 10
- ssid: !secret wifi_ssid_phone # Hotspot mobile en fallback
password: !secret wifi_password_phone
priority: 5
power_save_mode: NONE # IMPORTANT : désactiver l'économie d'énergie pour le BLE
reboot_timeout: 3min # Redémarre si pas de WiFi aprÚs 3 minutes
on_connect:
then:
- logger.log: "WiFi connecté"
on_disconnect:
then:
- logger.log: "WiFi perdu"
- light.turn_on:
id: led_atom
brightness: 20%
red: 1
green: 0.5
blue: 0 # Retour orange si déconnexion
ap:
ssid: "Bt-Ferrari-Mobile-Fallback"
password: "VOTRE_MDP_FALLBACK"
# Heure via HA ou NTP (pour les logs)
time:
- platform: homeassistant
id: ha_time
- platform: sntp
id: sntp_time
servers:
- pool.ntp.org
# VPN WireGuard
wireguard:
address: 10.0.0.5 # IP de l'ESP32 dans le réseau VPN
netmask: 255.255.255.0
private_key: !secret wg_esp_ferrari_private_key
peer_endpoint: votre-domaine.duckdns.org # Ton domaine DuckDNS ou IP fixe
peer_port: 51820
peer_public_key: !secret wg_esp_ferrari_server_public_key
peer_allowed_ips:
- 10.0.0.0/24 # Réseau VPN
- 192.168.1.0/24 # Réseau local maison (pour joindre HA)
peer_persistent_keepalive: 21s # Maintien de la connexion derriĂšre NAT 4G/5G
# Capteurs
sensor:
- platform: wifi_signal
name: "Force Signal WiFi Ferrari"
update_interval: 60s
text_sensor:
- platform: wifi_info
ssid:
name: "FERRARI WiFi Connecté"
id: wifi_nom_actuel
on_value:
then:
- lambda: |-
if (x.empty()) return;
auto call = id(led_atom).turn_on();
call.set_brightness(0.2);
if (x == "NTG") { // Remplace "NTG" par ton SSID maison
call.set_rgb(0, 1, 0); // VERT = WiFi maison
} else {
call.set_rgb(0, 0, 1); // BLEU = Hotspot mobile
}
call.perform();
mac_address:
name: "FERRARI MAC Address WiFi"
id: wifi_mac
ip_address:
name: "FERRARI IP Address"
- platform: template
name: "FERRARI MAC Address Bluetooth"
lambda: |-
std::string mac_str = id(wifi_mac).state;
if (mac_str.length() < 17) return std::string("N/A");
int last = std::stoi(mac_str.substr(15, 2), nullptr, 16);
last = (last + 2) & 0xFF;
char buf[3];
sprintf(buf, "%02X", last);
return mac_str.substr(0, 15) + std::string(buf);
update_interval: 60s
- platform: wireguard
address:
name: "IP Interne WireGuard Ferrari"
binary_sensor:
- platform: status
name: "Statut Proxy FERRARI"
on_press:
then:
- lambda: |-
if (id(wifi_nom_actuel).state.empty()) return;
auto call = id(led_atom).turn_on();
call.set_brightness(0.2);
if (id(wifi_nom_actuel).state == "NTG") {
call.set_rgb(0, 1, 0); // VERT si maison
} else {
call.set_rgb(0, 0, 1); // BLEU si mobile
}
call.perform();
on_release:
then:
- light.turn_on:
id: led_atom
brightness: 20%
red: 1
green: 0
blue: 0 # ROUGE = HA déconnecté
- platform: gpio
pin:
number: GPIO39
inverted: true
name: "Bouton Atom FERRARI"
id: bouton_atom
on_click:
- min_length: 50ms
max_length: 350ms
then: # Clic court â flash blanc 1s
- lambda: |-
auto call = id(led_atom).turn_on();
call.set_brightness(0.5);
call.set_rgb(1, 1, 1);
call.perform();
- delay: 1s
- lambda: |-
auto call = id(led_atom).turn_on();
call.set_brightness(0.2);
if (id(wifi_nom_actuel).state == "NTG") {
call.set_rgb(0, 1, 0);
} else {
call.set_rgb(0, 0, 1);
}
call.perform();
- min_length: 1000ms
max_length: 3000ms
then: # Appui long â redĂ©marrage
- button.press: restart_btn
# Bluetooth Proxy
esp32_ble_tracker:
scan_parameters:
interval: 300ms # Scan toutes les 300ms
window: 250ms # Ăcoute pendant 250ms
active: true
bluetooth_proxy:
active: true # Proxy bidirectionnel avec Home Assistant
# SystĂšme
api:
encryption:
key: "VOTRE_CLĂ_API_ESPHOME_ICI"
web_server:
port: 80
version: 3
ota:
- platform: esphome
password: "VOTRE_MOT_DE_PASSE_OTA"
logger:
captive_portal:
light:
- platform: esp32_rmt_led_strip
id: led_atom
name: "LED Statut Atom FERRARI"
pin: GPIO27
num_leds: 1
rgb_order: GRB
chipset: WS2812
button:
- platform: restart
name: "Redémarrer Proxy FERRARI"
id: restart_btn
- platform: safe_mode
id: button_safe_mode
name: Safe Mode Boot
- platform: factory_reset
id: factory_reset_btn
name: Factory reset
Code couleur de la LED RGB
| Couleur | Signification |
|---|---|
| Démarrage ou déconnexion WiFi | |
| Connecté au WiFi maison | |
| Connecté au hotspot mobile (en déplacement) | |
| HA déconnecté (perte API) | |
| Confirmation dâun clic bouton |
Utilisation du bouton physique
- Clic court (50ms â 350ms) â Flash blanc 1 seconde, vĂ©rifie que lâappareil rĂ©pond
- Appui long (1s â 3s) â RedĂ©marre lâESP32 proprement
Ătape 4 â Flasher lâESP32
- Ouvre ESPHome dans Home Assistant
- CrĂ©e un nouveau device â colle le YAML complet
- Adapte dans le code : remplace
"NTG"par le SSID de ton WiFi maison - Clique sur Install â Plug into this computer (premier flash USB)
- Les mises Ă jour suivantes se font en OTA sans fil

- Dans les logs, tu dois voir :
WiFi connectĂ©- LâĂ©tablissement du tunnel WireGuard
- Les scans BLE actifs
Dans ParamĂštres â Appareils â ESPHome, le proxy apparaĂźt et le BM6 est dĂ©tectĂ© automatiquement.
Dépannage
LED reste orange indéfiniment
â WiFi non trouvĂ©. VĂ©rifie SSID/mot de passe dans secrets.yaml. Active le hotspot si en dĂ©placement.
WireGuard ne se connecte pas
â VĂ©rifie que le port UDP 51820 est redirigĂ© sur le routeur vers le Proxmox. VĂ©rifie que DuckDNS pointe vers ta bonne IP publique.
BM6 non détecté dans HA
â LâintĂ©gration ESPHome Bluetooth Proxy doit ĂȘtre configurĂ©e dans HA. Va dans ParamĂštres â Appareils et accepte la dĂ©couverte du proxy.
Redémarre souvent en déplacement
â Normal si tu passes en zone sans signal. Tu peux augmenter reboot_timeout: 10min pour Ă©viter les redĂ©marrages intempestifs.
Ressources
- Documentation ESPHome Bluetooth Proxy
- Documentation ESPHome WireGuard
- M5Stack Atom sur la boutique officielle
- DuckDNS (IP dynamique gratuite)
TestĂ© sur M5Stack Atom Lite â ESPHome 2024.x â Home Assistant 2024.x
NâhĂ©sitez pas Ă poser vos questions en rĂ©ponse ! ![]()



