🚗 Proxy Bluetooth Ferrari avec M5Stack Atom + WireGuard VPN via ESPHome

Niveau : Débutant / Intermédiaire
Mots-clés : esphome bluetooth-proxy wireguard m5stack bm6 voiture


:bullseye: 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


:shopping_cart: 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

:light_bulb: 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Ă© .


:gear: É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).


:gear: É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="

:gear: É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

:light_bulb: Code couleur de la LED RGB

Couleur Signification
:orange_circle: Orange Démarrage ou déconnexion WiFi
:green_circle: Vert Connecté au WiFi maison
:blue_circle: Bleu Connecté au hotspot mobile (en déplacement)
:red_circle: Rouge HA déconnecté (perte API)
:white_circle: Blanc (1s) Confirmation d’un clic bouton

:radio_button: 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

:rocket: Étape 4 — Flasher l’ESP32

  1. Ouvre ESPHome dans Home Assistant
  2. CrĂ©e un nouveau device → colle le YAML complet
  3. Adapte dans le code : remplace "NTG" par le SSID de ton WiFi maison
  4. Clique sur Install → Plug into this computer (premier flash USB)
  5. Les mises Ă  jour suivantes se font en OTA sans fil :sparkles:
  6. 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.


:wrench: 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.


:paperclip: Ressources


TestĂ© sur M5Stack Atom Lite — ESPHome 2024.x — Home Assistant 2024.x
N’hĂ©sitez pas Ă  poser vos questions en rĂ©ponse ! :slightly_smiling_face:

1 « J'aime »

Quelle surprise, un retour de @ClassicRed :smiley:

1 « J'aime »

Je trouve ça dommage de voir de plus en plus de posts rĂ©digĂ©s entiĂšrement avec l’IA sur le forum, ça perd d’authenticitĂ© je trouve.