HA ESPHome MQTT UniqueID 충돌 해결

Home Assistant / ESPHome MQTT Unique ID 충돌 문제 해결 기록

1. 증상

Home Assistant 로그에 아래와 같은 에러가 반복적으로 발생.

로거: homeassistant.components.sensor
소스: helpers/entity_platform.py:929
Platform mqtt does not generate unique IDs.
ID ESPsensorco2 already exists - ignoring sensor.box_co2
  • 처음 발생: 오후 10:39:17
  • 이후 오후 10:55, 10:58, 11:07 등 반복 발생
  • 영향받은 엔티티: sensor.box_co2 (CO2 센서, 2024-08-16 최초 등록된 정식 엔티티)

2. 진단 과정 (요약)

  1. 처음에는 box 기기의 node_name이 과거 ESPsensorbox로 바뀌면서 예전 retained MQTT discovery 메시지가 남아있는 것으로 추정.
  2. MQTT Explorer로 실제 브로커 메시지를 확인한 결과:
    • homeassistant/sensor/mobile/co2/config 토픽에서 mobile이라는 전혀 다른 물리 기기uniq_id: "ESPsensorco2"retain: true로 발행하고 있는 것을 발견.
    • HA 엔티티 레지스트리 확인 결과 sensor.box_co2unique_id도 정확히 "ESPsensorco2"로 동일.
  3. mobile.yaml을 확인한 결과, node_name: mobile로 정상 설정되어 있었고 box.yaml직접적인 이름 충돌은 없었음 → 단순 이름 복사/재사용 문제가 아님을 확인.
  4. 두 YAML을 비교한 결과, 공통점은 둘 다 CO2 센서의 name: 필드가 "CO2"로 동일하다는 것뿐이었음 → ESPHome의 unique_id 생성 로직 자체를 재조사.

3. 근본 원인 (확정)

ESPHome MQTT 컴포넌트는 기본값(discovery_unique_id_generator: legacy)으로 unique_id를 아래 공식으로 생성한다.

unique_id = "ESP" + <component_type> + <object_id>
  • component_type = sensor
  • object_id = 센서 name: 필드를 정리한 값 → "CO2"co2

즉:

"ESP" + "sensor" + "co2" = "ESPsensorco2"

이 공식에는 node_name(esphome.name, 즉 기기 이름)이 전혀 관여하지 않는다. 따라서 boxmobile처럼 기기 이름이 완전히 다르더라도, 센서의 name: 값이 똑같이 "CO2"이기만 하면 두 기기는 정확히 동일한 unique_id ESPsensorco2를 생성한다.

이는 ESPHome의 legacy unique_id 생성 방식이 가진 구조적 한계로, 공식 이슈 트래커에도 동일 패턴이 다수 보고되어 있다 (예: esphome/issues#1093, #4840).

즉, 최초 추정했던 “이름 변경 후 남은 retained 메시지” 문제가 아니라, 서로 다른 두 기기가 같은 이름의 센서를 갖고 있어서 애초부터 unique_id가 겹치도록 설계되어 있던 것이 진짜 원인이었음.


4. 해결 방법

4-1. discovery_unique_id_generator: mac 설정 추가

box.yaml, mobile.yaml관련된 모든 ESPHome 기기의 mqtt: 블록에 아래 옵션을 추가한다.

mqtt:
  broker: clipman.ddns.net
  port: 1883
  username: admin
  password: admin3844
  discovery_unique_id_generator: mac   # ← 추가

이 설정을 적용하면 unique_id 생성 공식이 아래로 바뀐다.

unique_id = <mac_address> + "-" + <component_type> + "-" + fnv1_hash(<friendly_name>)

MAC 주소는 기기마다 고유하므로, 센서 이름이 같아도 기기 간 충돌이 발생하지 않는다.

4-2. 두 기기 모두 재컴파일 & 재업로드

discovery_unique_id_generator컴파일 타임에 반영되므로, 옵션 추가 후 반드시 재컴파일 및 재업로드가 필요하다.

4-3. HA에서 기존(구) 엔티티 정리

설정 → 기기 및 서비스 → 엔티티에서 예전 unique_id(ESPsensorco2) 기반으로 등록되어 있던 엔티티(sensor.box_co2 등)를 확인하고, 필요 시 삭제 후 새 unique_id로 다시 등록되는 엔티티를 확인한다.

unique_id가 바뀌면 자동화·대시보드에 연결된 참조가 끊어질 수 있으므로, 새로 생성된 엔티티에 재연결이 필요한지 함께 점검한다.

4-4. 예전 retained discovery 메시지 정리

MQTT Explorer 또는 mosquitto_pub으로 기존 uniq_id: "ESPsensorco2"를 게시하던 config 토픽에 빈 payload를 retain으로 발행하여 정리한다.

mosquitto_pub -h clipman.ddns.net -p 1883 -u admin -P admin3844 \
  -t "homeassistant/sensor/mobile/co2/config" -r -n

mosquitto_pub -h clipman.ddns.net -p 1883 -u admin -P admin3844 \
  -t "homeassistant/sensor/box/co2/config" -r -n

실행 위치: HA의 Terminal & SSH 애드온 / 로컬 PC(mosquitto-clients) / MQTT Explorer(GUI) 중 편한 방식 사용.


5. 결과

  • discovery_unique_id_generator: mac 적용 및 재업로드 후, boxmobile 각각의 CO2 센서가 서로 다른 고유 unique_id로 등록되어 충돌 에러가 해결됨.

6. 예방 및 참고 사항

  • ESPHome 기기를 여러 대 운용할 계획이라면, 처음부터 모든 기기의 mqtt: 설정에 discovery_unique_id_generator: mac을 기본으로 넣어두는 것을 권장한다. (legacy 방식은 기기 이름과 무관하게 센서 name: 값만으로 unique_id가 정해지므로, 같은 이름의 센서를 쓰는 기기가 늘어날수록 충돌 위험이 커짐)
  • YAML을 복사해서 새 기기를 만들 때는 node_name뿐 아니라, legacy 방식에서는 센서 name: 값도 unique_id에 영향을 준다는 점을 유의해야 함(다만 mac 방식으로 전환하면 이 문제 자체가 사라짐).
  • MQTT Explorer는 discovery topic과 uniq_id 값을 직접 눈으로 비교할 수 있어, 이런 “서로 다른 기기인데 unique_id가 겹치는” 유형의 문제를 진단하는 데 특히 유용함.