IoT Otomasyon

Home Assistant MQTT Discovery: Özel Cihazlar İçin Varlıkları Otomatik Oluşturun

Discovery config payload'larını yayınlayarak kendi sensörlerinizin ve anahtarlarınızın Home Assistant'ta erişilebilirlik, benzersiz kimlikler ve temiz silme desteğiyle eksiksiz bir cihaz olarak görünmesini sağlayın; hepsi bir Python cihaz simülatörüyle.

Home assistant mqtt discovery sayesinde akıllı ev panelinde otomatik olarak beliren özel sensör cihazı
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

Home Assistant MQTT discovery, bir cihazın kendini tanıtmasını ve Home Assistant'ın varlıklarını (entity) Home Assistant tarafında hiç YAML yazmadan otomatik olarak oluşturmasını sağlar. Bu eğitimde discovery topic biçimini öğrenecek, sensörler ve bir anahtar için config payload'ları yazacak, bunları tek bir cihaz altında gruplayacak, erişilebilirliği ve Home Assistant yeniden başlatmalarını yönetecek ve varlıkları temiz bir şekilde sileceksiniz; tüm bunları bir ConnectMQ broker'ına bağlı Python cihaz simülatörüyle yapacaksınız.

MQTT Discovery Nasıl Çalışır?

MQTT entegrasyonu başladığında, varsayılan olarak homeassistant olan bir discovery önekinin altındaki topic'lere abone olur. Bir cihaz, her varlık için bir config topic'ine retained bir JSON mesajı yayınlar:

<discovery_prefix>/<component>/[<node_id>/]<object_id>/config

homeassistant/sensor/hvac-node-1/temperature/config
homeassistant/switch/hvac-node-1/relay/config
  • component varlık platformudur: sensor, binary_sensor, switch, light, button, number, select, climate ve diğerleri.
  • node_id isteğe bağlıdır ve yalnızca topic'leri gruplar; cihazı oluşturmaz.
  • object_id varlığı düğüm içinde tanımlar.

Config payload'ı Home Assistant'a durumu nereden okuyacağını, komutları nereye göndereceğini, değerleri nasıl ayrıştıracağını ve varlığın hangi cihaza ait olduğunu söyler. Mesaj retained olduğu için broker, Home Assistant her yeniden bağlandığında onu tekrar iletir; böylece varlıklar yeniden başlatmadan sonra geri gelir.

Discovery yalnızca meta veridir. Gerçek veri, herhangi bir Home Assistant MQTT entegrasyonu için tasarlayacağınız gibi, yine kendi durum ve komut topic'leriniz üzerinden akar.

Ön Koşullar

  • MQTT entegrasyonu yapılandırılmış ve discovery etkin (varsayılan olarak açıktır) bir Home Assistant.
  • Özel bir ConnectMQ broker'ı: portalda bir tane oluşturun ve üretilen kullanıcı adını, parolayı ve client ID'yi not edin. Home Assistant ve simülatörün her birinin kendi kimlik bilgilerine ihtiyacı vardır.
  • pip install "paho-mqtt>=2.0" ile Python 3.10+.

Herkese açık MQTT test broker'ı üzerinde de deneme yapabilirsiniz, ancak iki konu bunu discovery için zahmetli hale getirir. Birincisi, paylaşılan homeassistant öneki altındaki retained config topic'leri oraya bağlanan her Home Assistant örneği tarafından görülebilir; bu yüzden entegrasyon seçeneklerinde özel bir discovery öneki belirleyin (örneğin cmqx7d2). İkincisi, herkese açık broker istemci başına 10 aboneliğe izin verir ve Home Assistant'ın discovery için birkaç, ayrıca her varlık için bir aboneliğe ihtiyacı vardır. Özel bir broker her iki sorunu da ortadan kaldırır.

Alan Alan Bir Discovery Payload'ı

Bir sıcaklık sensörünün config'i şöyledir:

{
  "name": "Supply Air Temperature",
  "unique_id": "hvacnode1_supply_temp",
  "object_id": "hvac_node_1_supply_temp",
  "state_topic": "home/hvac-node-1/state",
  "value_template": "{{ value_json.supply_c }}",
  "unit_of_measurement": "°C",
  "device_class": "temperature",
  "state_class": "measurement",
  "availability_topic": "home/hvac-node-1/availability",
  "device": {
    "identifiers": ["hvacnode1"],
    "name": "HVAC Node 1",
    "manufacturer": "DIY",
    "model": "ESP32 duct sensor",
    "sw_version": "1.3.0"
  }
}
Alan Neden önemli
unique_id Varlık kaydı için gereklidir: yeniden adlandırma, alanlar, devre dışı bırakma. Sonsuza kadar sabit kalmalıdır.
device.identifiers Aynı tanımlayıcıya sahip tüm varlıkları tek bir cihaz kartında gruplar.
state_topic + value_template Birden fazla varlık, tek bir JSON durum mesajının farklı alanlarını okuyabilir.
availability_topic Cihaz offline yayınladığında (genellikle last will ile) varlıklar kullanılamaz duruma geçer.
device_class, state_class Doğru simgeler, birimler ve uzun vadeli istatistikler.
object_id Üretilen entity ID'yi etkiler.

Uzun payload'larda belgelenmiş kısaltmalar kullanılabilir; örneğin state_topic için stat_t, unique_id için uniq_id ve device için dev. Bunlar küçük arabelleğe sahip mikrodenetleyicilerde işe yarar; bir PC'de tam adları okumak daha kolaydır.

Discovery Destekli Eksiksiz Bir Python Cihazı

Aşağıdaki simülatör gerçek bir cihaz gibi davranır: üç varlığı duyurur, her on saniyede bir JSON durumu yayınlar, anahtar komutlarına uyar, erişilebilirlik için bir last will ayarlar ve Home Assistant yeniden çevrimiçi olduğunda config'ini tekrar yayınlar.

import json
import random
import time

import paho.mqtt.client as mqtt

BROKER, PORT = "broker.connectmq.com", 8883
USERNAME, PASSWORD = "YOUR_USERNAME", "YOUR_PASSWORD"
CLIENT_ID = "YOUR_CLIENT_ID"

DISCOVERY_PREFIX = "homeassistant"
NODE = "hvac-node-1"
BASE = f"home/{NODE}"
STATE_T = f"{BASE}/state"
AVAIL_T = f"{BASE}/availability"
RELAY_CMD_T = f"{BASE}/relay/set"
RELAY_STATE_T = f"{BASE}/relay/state"

DEVICE = {
    "identifiers": ["hvacnode1"],
    "name": "HVAC Node 1",
    "manufacturer": "DIY",
    "model": "ESP32 duct sensor",
    "sw_version": "1.3.0",
}

ENTITIES = [
    ("sensor", "supply_temp", {
        "name": "Supply Air Temperature",
        "state_topic": STATE_T,
        "value_template": "{{ value_json.supply_c }}",
        "unit_of_measurement": "°C",
        "device_class": "temperature",
        "state_class": "measurement",
    }),
    ("sensor", "filter_dp", {
        "name": "Filter Pressure Drop",
        "state_topic": STATE_T,
        "value_template": "{{ value_json.filter_dp_pa }}",
        "unit_of_measurement": "Pa",
        "device_class": "pressure",
        "state_class": "measurement",
    }),
    ("switch", "relay", {
        "name": "Fan Relay",
        "command_topic": RELAY_CMD_T,
        "state_topic": RELAY_STATE_T,
        "payload_on": "ON",
        "payload_off": "OFF",
    }),
]

relay_on = False


def publish_discovery(client):
    for component, object_id, cfg in ENTITIES:
        payload = {
            **cfg,
            "unique_id": f"hvacnode1_{object_id}",
            "availability_topic": AVAIL_T,
            "device": DEVICE,
        }
        topic = f"{DISCOVERY_PREFIX}/{component}/{NODE}/{object_id}/config"
        client.publish(topic, json.dumps(payload), qos=1, retain=True)
    client.publish(AVAIL_T, "online", qos=1, retain=True)
    client.publish(RELAY_STATE_T, "ON" if relay_on else "OFF", qos=1, retain=True)


def on_connect(client, userdata, flags, reason_code, properties):
    print("connected:", reason_code)
    client.subscribe(RELAY_CMD_T, qos=1)
    client.subscribe("homeassistant/status", qos=1)   # Home Assistant birth mesajı
    publish_discovery(client)


def on_message(client, userdata, msg):
    global relay_on
    if msg.topic == "homeassistant/status" and msg.payload == b"online":
        time.sleep(random.uniform(0.5, 2.0))          # HA yeniden başlayınca yükü dağıt
        publish_discovery(client)
    elif msg.topic == RELAY_CMD_T:
        relay_on = msg.payload == b"ON"
        client.publish(RELAY_STATE_T, "ON" if relay_on else "OFF", qos=1, retain=True)


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.username_pw_set(USERNAME, PASSWORD)
client.tls_set()
client.will_set(AVAIL_T, "offline", qos=1, retain=True)
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT, keepalive=30)
client.loop_start()

while True:
    state = {"supply_c": round(random.uniform(12.5, 14.5), 1),
             "filter_dp_pa": random.randint(150, 190)}
    client.publish(STATE_T, json.dumps(state), qos=0)
    time.sleep(10)

Betiği çalıştırın, ardından Settings > Devices & services > MQTT bölümünü açın. İki sensör ve bir anahtar içeren HVAC Node 1 adlı bir cihaz görünür. Betiği Ctrl+C ile durdurduğunuzda, keep-alive süresi içinde broker last will mesajını yayınlar ve varlıklar kullanılamaz duruma geçer.

Birth mesajının işlenmesi önemlidir. Home Assistant başladığında homeassistant/status topic'ine online yayınlar. Retained config'ler genellikle yeniden yayını gereksiz kılar, ancak birth mesajında yeniden yayın yapan bir cihaz, retained mesajlar silinmiş olsa bile kendini toparlar.

Cihaz Tabanlı Discovery

Güncel Home Assistant sürümleri, <prefix>/device/<object_id>/config üzerinde cihaz başına tek bir config mesajını da kabul eder; bu mesaj tüm varlıkları her biri bir platform (p) içeren components anahtarı (kısaltması cmps) altında listeler. Ayrıca mesajı yayınlayan yazılımı belirten bir origin (o) bloğu da gerekir:

{
  "dev": {"ids": ["hvacnode1"], "name": "HVAC Node 1", "mf": "DIY", "mdl": "ESP32 duct sensor"},
  "o": {"name": "hvac-node-firmware", "sw": "1.3.0"},
  "avty_t": "home/hvac-node-1/availability",
  "stat_t": "home/hvac-node-1/state",
  "cmps": {
    "supply_temp": {"p": "sensor", "dev_cla": "temperature", "unit_of_meas": "°C",
                    "val_tpl": "{{ value_json.supply_c }}", "uniq_id": "hvacnode1_supply_temp"},
    "filter_dp":   {"p": "sensor", "dev_cla": "pressure", "unit_of_meas": "Pa",
                    "val_tpl": "{{ value_json.filter_dp_pa }}", "uniq_id": "hvacnode1_filter_dp"}
  }
}

Çok sayıda mesaj yerine tek bir retained mesaj, onlarca varlığa sahip cihazlar için caziptir. Her cihaz için tek bir stil kullanın; aynı unique ID'leri iki yöntemle birden duyurmayın.

Varlıkları Silme ve Değiştirme

Bir varlığı silmek için config topic'ine boş bir retained payload yayınlayın:

mosquitto_pub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
  -u YOUR_USERNAME -P YOUR_PASSWORD -i YOUR_CLIENT_ID -r -n \
  -t "homeassistant/sensor/hvac-node-1/filter_dp/config"

-n sıfır uzunlukta bir mesaj gönderir, -r ise onu retained yapar; bu da saklanan config'i broker'dan temizler. Bir varlığı değiştirmek için yeni config'i aynı topic'e aynı unique_id ile yayınlayın. unique_id değerini değiştirmek yeni bir varlık oluşturur ve eskisini sahipsiz bırakır.

Sorun Giderme Kontrol Listesi

  1. Hiçbir şey görünmüyor. Entegrasyon seçeneklerindeki discovery önekinin cihazınızın kullandığıyla eşleştiğini ve discovery'nin etkin olduğunu doğrulayın.
  2. Varlıklar görünüyor ama kullanılamaz durumda. Erişilebilirlik topic'inde retained bir online mesajı yok ya da payload tam olarak online değil.
  3. Günlükte "Unique ID already exists". İki config aynı unique_id değerini paylaşıyor. Bunları küresel olarak benzersiz yapın; ideal olarak bir MAC adresinden türetin.
  4. Firmware güncellemesinden sonra yinelenen cihazlar. device.identifiers değeri değişmiş. Sabit tutun.
  5. Hayalet varlıklar. Eski retained config'ler broker'da duruyor. ConnectMQ topic gezginini kullanarak bunları discovery öneki altında bulun ve boş retained mesajlarla temizleyin.
  6. Config sessizce reddediliyor. JSON'unuzu doğrulayın; elle yazılmış bir payload'daki sondaki virgül genellikle suçludur ve Home Assistant hatayı MQTT entegrasyonu altında günlüğe kaydeder.

ESP32'den Discovery

Bir mikrodenetleyicide mantık aynıdır: her config payload'ını oluşturun, her başarılı bağlantıdan sonra retained olarak yayınlayın ve birth topic'ine abone olun. Python'dan üç ayrıntıda farklılaşır. Birincisi, PubSubClient'ın varsayılan paket arabelleği küçüktür; bu yüzden bağlanmadan önce mqtt.setBufferSize(1024) veya daha büyük bir değer çağırın, aksi halde uzun discovery payload'ları sessizce düşürülür. İkincisi, unique_id ve device.identifiers değerlerini çipin MAC adresinden türetin; böylece her kart elle yapılandırma gerekmeden sabit ve benzersiz değerler alır. Üçüncüsü, erişilebilirliği connect() içindeki last will ile yayınlayın; böylece Home Assistant, cihazın hiçbir şey yapmasına gerek kalmadan güç kesintisinden haberdar olur.

Kısaltılmış anahtarlar küçük cihazlarda işe yarar ve payload'ları ArduinoJson ile oluşturmak elle yazılmış dizelerdeki tırnak hatalarını önler. Varlıkları Home Assistant'ta aramadan önce, herhangi bir MQTT istemcisiyle homeassistant/# topic'ine abone olarak firmware'inizin payload'larını test edin ve her config'in geçerli JSON olduğunu kontrol edin.

Discovery'nin Yeri

Tasmota, MQTT modundaki ESPHome ve Zigbee2MQTT gibi firmware'ler zaten discovery payload'ları yayınlar; cihazlarının anında görünmesinin nedeni budur. Kendi firmware'iniz için yukarıdaki Python örneği PubSubClient veya AsyncMqttClient ile doğrudan C++'a uyarlanabilir; yalnızca istemci arabellek boyutunu artırın, çünkü config payload'ları varsayılanı kolayca aşar. Cihazlar ev ağınızın dışında bulunuyorsa, Home Assistant ile harici bir MQTT broker'ı kullanma yazısında anlatıldığı gibi hepsini tek bir bulut MQTT broker'ına bağlayın. ESPHome MQTT rehberi ve IoT otomasyon rehberimiz discovery'ye dayanan daha fazla cihaz gösterir.

ConnectMQ Üzerinde Keşfedilebilir Cihazlar Oluşturun

app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz bir Serverless broker oluşturun ve Home Assistant ile her cihaz için kimlik bilgileri tanımlayın. ConnectMQ tarafından sunulan tam yönetilen bir MQTT hizmetiyle retained discovery config'leriniz hiç yama yapmanız gerekmeyen bir broker'da durur ve canlı topic gezgini her cihazın tam olarak neyi duyurduğunu gösterir.

Sık Sorulan Sorular

Discovery mesajlarının retained olması gerekir mi?

Olmalıdır. Retained config'ler, cihaz yeniden yayın yapmadan Home Assistant'ın yeniden başlatmadan sonra varlıkları yeniden oluşturmasını sağlar; birth mesajında yeniden yayın yapmak faydalı bir yedektir.

node_id ile cihaz arasındaki fark nedir?

node_id yalnızca düzenleme amaçlı bir topic seviyesidir. Cihaz kartı device bloğundan oluşturulur ve aynı identifiers değerini paylaşan varlıklar gruplanır.

Keşfedilen bir varlığı nasıl silerim?

Config topic'ine sıfır uzunlukta retained bir mesaj yayınlayın. Home Assistant varlığı siler ve broker retained config'i unutur.

Discovery önekini değiştirebilir miyim?

Evet, MQTT entegrasyonu seçeneklerinden. Bu durumda her cihazın config'lerini yeni önek altında yayınlaması gerekir.

İlgili yazılar

Zigbee2MQTT Kurulum Rehberi: Koordinatörden Panoya

Zigbee2MQTT'yi Docker ile kurun, koordinatörü ve MQTT bağlantısını yapılandırın, cihazları eşleştirip yeniden adlandırın, onları MQTT üzerinden kontrol edin ve durumlarını bir panoda görüntüleyin; önce ücretsiz herkese açık bir broker'da test edin.

7 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.