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
componentvarlık platformudur:sensor,binary_sensor,switch,light,button,number,select,climateve diğerleri.node_idisteğe bağlıdır ve yalnızca topic'leri gruplar; cihazı oluşturmaz.object_idvarlığı 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
- 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.
- Varlıklar görünüyor ama kullanılamaz durumda. Erişilebilirlik topic'inde retained bir
onlinemesajı yok ya da payload tam olarakonlinedeğil. - Günlükte "Unique ID already exists". İki config aynı
unique_iddeğerini paylaşıyor. Bunları küresel olarak benzersiz yapın; ideal olarak bir MAC adresinden türetin. - Firmware güncellemesinden sonra yinelenen cihazlar.
device.identifiersdeğeri değişmiş. Sabit tutun. - 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.
- 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.



