Esphome Face Recognition HLK-FM22X

Salut tout le monde,

Surement de nombreux projets à venir avec cette mise à jour quand elle sera accessible:

Qui à déjà mis ça en place?
Qui aurait un modèle de boitier 3D avec esp integré?

1 « J'aime »

Bonjour @tikismoke
ça y est, c’est sorti, je vais regarder ça et commander pour tester.

A priori le 225 est meilleur en infrarouge que le 223.
Soyons fou, un de chaque, après il faudra tester.

Bob

3 « J'aime »

Bonjour,
c’est commandé, 3 modèles différents, je vous tiendrai informé de ce que j’arrive à faire avec.

Bob

Bonsoir, bien reçu les trois, je commencerai demain soir je pense, si vous avez trouvé des ressources ESPHome yaml en complément du site esphome.io je suis preneur;-)
Bonne soirée
Bob

1 « J'aime »

J’attends le miens encore :sob:

Il faut mettre à jour ESPHome en 2025.11.3 pour pouvoir utiliser la reconnaissance de visage directement depuis HA.
Déjà, le HLK FM225 est reconnu:

Je poursuis.
Bob

1 « J'aime »

La valeur 31 est un bitmask qui correspond à toutes les directions à la fois :

  • Centre = 1
  • Droite = 2
  • Gauche = 4
  • Bas = 8
  • Haut = 16
  • Total = 1+2+4+8+16 = 31

Pour l’instant je n’ai pas réussi à enregistrer un visage.
Aucune instruction pour l’apprentissage.

Suite plus tard.

Bob

Bonjour,
je pense qu’hier soir il travaillait en IR.
Je viens de refaire un test en plein jour et c’est OK.

Je vais continuer pour voir comment bien utiliser ce capteur dans HA, très peu de ressources trouvées sur le web.

Bob

EDIT:
Alors @tikismoke
il est arrivé ce capteur, ici ça avance, j’allume une lampe en regardant le capteur:

[15:14:29.559][D][hlk_fm22x:237]: Face verified. ID: 1, name: Bruno
[15:14:29.559][D][text_sensor:087]: 'FM225 - Last recognized name': Sending state 'Bruno'
[15:14:29.582][D][homeassistant.binary_sensor:026]: 'light.lampe_marine': Got state ON
[15:14:29.582][D][binary_sensor:041]: 'lampe_marine': New state is ON

Je vais un peu encore étudier la façon de reconnaitre un visage pour blinder l’affaire.
Bob

1 « J'aime »

Salut, oui il est arrivé hier (sans cordon/nappe pour le raccordement… je vais devoir soudé le bus directement).
Par contre avant les vacances de Noël je n’ai pas le temps de regarder plus que ça et encore c’est plutôt sur le bas de la pile que le haut :sob:

Ok, tu me diras @tikismoke , j’ai testé le 225, je vais aussi tester le 223 et me familiariser avec l’apprentissage du visage.

Bonne soirée
Bob

Hii bob… I just bought this HLK-FM225 sensor and tried it with esphome… I gave 8V VCC for the sensor… since it supports 5.5V -9V @1A.. I can see that delete and delete all command works pretty good… but I got no success on enrolling a face… what did you enter in the direction tab… I am getting error 0x0D which is timed out error..

Bonjour @SMART_HOME
j’ai utilisé 31, j’ai indiqué les détails dans le post 7.

Bob

Hii… thanks for the quick reply, I saw the post 7 and tried using direction 31… I am getting 0x0D error when I try to use enroll or scan… it is night time here but still I tried with led ring light with different brightness and tried different distance from the sensor..

Can you send me your config?

Le yaml Esphome :

esphome:
  name: esp32-fm225-facial
  friendly_name: ESP32 FM225 Facial

    
esp32:
  board: esp32dev
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "9/l1y3MYpK8kAq1TDwYkNBzE3uCYh05CG0sDunAAWcg="

  actions:
  - action: enroll
    variables:
      name: string
      direction: int
    then:
      - hlk_fm22x.enroll:
          name: !lambda 'return name;'
          direction: !lambda 'return direction;'
  - action: scan
    then:
      - hlk_fm22x.scan:
  - action: delete
    variables:
      face_id: int
    then:
      - hlk_fm22x.delete:
          face_id: !lambda 'return face_id;'
  - action: delete_all
    then:
      - hlk_fm22x.delete_all:
  - action: reset
    then:
      - hlk_fm22x.reset:

ota:
  - platform: esphome
    password: "c33d9f59541cd0632156f96647d24048"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.1.35
    gateway: 192.168.1.254
    subnet: 255.255.255.0
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp32-Fm225-Facial"
    password: "v9vXcNCoDYqS"

captive_portal:

# -----------------------------
# UART CONNECTION TO HLK-FM225
# -----------------------------
uart:
  id: uart_face
  rx_pin: GPIO16    # FM225 TX  -> ESP32 RX
  tx_pin: GPIO17    # FM225 RX  -> ESP32 TX
  baud_rate: 115200

hlk_fm22x:
  id: face_scanner # L'ID de votre composant
  uart_id: uart_face # Fait référence à l'ID de l'UART ci-dessus

  on_face_scan_invalid:
    - homeassistant.event:
        event: esphome.test_node_face_scan_invalid
        data:
          error: !lambda 'return error;'
    - text_sensor.template.publish:
        id: face_log
        state: !lambda 'return "Scan invalide ";'


  on_face_scan_matched:
    - homeassistant.event:
        event: esphome.test_node_face_scan_matched
        data:
          face_id: !lambda 'return face_id;'
          name: !lambda 'return name;'

    - if:
        condition:
          lambda: |
            return (face_id == 1) || (name == "Bruno");
        then:
          - homeassistant.service:
              service: light.toggle
              data:
                entity_id: light.lampe_marine
          - homeassistant.service:
              service: light.toggle
              data:
                entity_id: light.salon_plante_10               

    - switch.turn_on:
        id: ledbleu225

    #- text_sensor.template.publish:
    #    id: face_log
    #    state: !lambda 'return "Scan OK " + to_string(face_id) +" : "+ name;'
    - text_sensor.template.publish:
        id: face_log
        state: !lambda |-
          // 1. Convertir le std::string 'name' en pointeur C (const char*)
          const char* name_c_str = name.c_str();
          // 2. Utiliser strlen() sur le pointeur C pour trouver la longueur réelle
          size_t name_length = strlen(name_c_str);
          // 3. Crée un std::string propre en utilisant la longueur trouvée.
          std::string person_name(name_c_str, name_length);
          return "Scan OK ID: " + to_string(face_id) + " : " + person_name;


    - homeassistant.service:
        service: tts.speak
        data:
          media_player_entity_id: media_player.respeaker_satellite
          #pour ajouter ID + to_string(face_id) + le code permet de lire en TTS le name qui sinon ne passe pas
          message: !lambda |-
            const char* name_c_str = name.c_str();
            size_t name_length = strlen(name_c_str);
            std::string person_name(name_c_str, name_length);
            return "Bonjour " + person_name + ", je t'ai reconnu, bienvenu à la maison.";
          entity_id: tts.piper

    - delay: 5s

    - switch.turn_off:
        id: ledbleu225

  on_face_scan_unmatched:
    - homeassistant.event:
        event: esphome.test_node_face_scan_unmatched
    - text_sensor.template.publish:
        id: face_log
        state: !lambda 'return "Personne non reconnue ";'

  on_face_info:
    - homeassistant.event:
        event: esphome.test_node_face_info
        data:
          status: !lambda 'return status;'
          left: !lambda 'return left;'
          top: !lambda 'return top;'
          right: !lambda 'return right;'
          bottom: !lambda 'return bottom;'
          yaw: !lambda 'return yaw;'
          pitch: !lambda 'return pitch;'
          roll: !lambda 'return roll;'

  on_enrollment_done:
    - homeassistant.event:
        event: esphome.test_node_enrollment_done
        data:
          face_id: !lambda 'return face_id;'
          direction: !lambda 'return direction;'
    - logger.log: "Enrôlement du visage terminé avec succès."
    
    - text_sensor.template.publish:
        id: face_log
        state: !lambda 'return "Enrolled into slot " + to_string(face_id);'
    - switch.turn_on:
        id: ledbleu225
    - delay: 2s
    - switch.turn_off:
        id: ledbleu225

  on_enrollment_failed:
    - homeassistant.event:
        event: esphome.test_node_enrollment_failed
        data:
          error: !lambda 'return error;'
    - text_sensor.template.publish:
        id: face_log
        state: !lambda 'return "Failed to enroll face. Error: " + to_string(error);'
# -----------------------------
# Sensors and Entities
# -----------------------------
sensor:
  - platform: hlk_fm22x
    face_count:
      name: "FM225 - Number of enrolled faces"

text_sensor:
  - platform: hlk_fm22x
    last_face_name:
      name: "FM225 - Last recognized name"
    version:
      name: "FM225 - Firmware version"
  - platform: template
    name: "Résultat capteur"
    id: face_log
  - platform: wifi_info
    ip_address:
      name: device/ip
    mac_address:
      name: device/mac    

binary_sensor: 
  - platform: homeassistant
    id: lampe_marine
    entity_id: light.lampe_marine
    internal: true
  - platform: homeassistant
    id: lampe_plante
    entity_id: light.salon_plante_10
    internal: true    

  - platform: gpio
    pin: 
      number: GPIO21 
      mode: INPUT_PULLUP # Utilise la résistance interne pour maintenir l'état HAUT (HIGH)
      inverted: true     # Étant donné que le bouton tire le signal à GND (LOW), on inverse la logique pour que l'état "ON" corresponde à la pression.
    name: "Bouton Lancement Scan"
    
    # ⬇️ Les actions se déclenchent lors du relâchement du bouton (le press.duration permet d'éviter le 'bouncing')
    on_release:
      # Lancement du service de scan
      then:
        - homeassistant.service:
            service: esphome.esp32_fm225_facial_scan

button:
  - platform: restart
    id: reboot
    name: "Reboot 225"
  - platform: template
    name: "Bouton Appel Scan"
    on_press:
      then:
        - homeassistant.service:
            service: esphome.esp32_fm225_facial_scan

switch:
  - platform: gpio
    id: ledbleu225
    name: "LedBleu 225 Face"
    pin: 2


web_server:
  port: 80

  

Bob

Hii Bob, I tried your configuration. still I get the same error :frowning:

Il faut une alimentation suffisamment puissante, la mienne, 5V / 3A.

Bob

1 « J'aime »