{"id":10260,"date":"2026-08-15T00:49:51","date_gmt":"2026-08-14T22:49:51","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/werkzeuge\/mqtt-home-assistant-discovery-builder\/"},"modified":"2026-08-15T00:49:51","modified_gmt":"2026-08-14T22:49:51","slug":"mqtt-home-assistant-discovery-builder","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/","title":{"rendered":"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">Home Assistant \u00fcbernimmt eine MQTT-Entit\u00e4t von allein, sobald eine dauerhaft gespeicherte Konfigurationsnachricht auf dem richtigen Topic liegt. Dieser Baukasten schreibt diese Nachricht und pr\u00fcft die Kombinationen, die eine Entit\u00e4t ergeben, die zwar da ist, aber nie funktioniert.<\/p>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap;\">\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"mq-komponente\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Komponente<\/label><br \/>\n            <select id=\"mq-komponente\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\"><option value=\"sensor\">sensor<\/option><option value=\"binary_sensor\">binary_sensor<\/option><option value=\"switch\">switch<\/option><option value=\"number\">number<\/option><option value=\"light\">light<\/option><\/select>\n        <\/div>\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"mq-klasse\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Ger\u00e4teklasse<\/label><br \/>\n            <select id=\"mq-klasse\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\"><\/select>\n        <\/div>\n<div style=\"flex: 1; min-width: 150px;\">\n            <label for=\"mq-einheit\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Einheit<\/label><br \/>\n            <input type=\"text\" id=\"mq-einheit\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"W\">\n        <\/div>\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"mq-praefix\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Discovery-Pr\u00e4fix<\/label><br \/>\n            <input type=\"text\" id=\"mq-praefix\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"homeassistant\">\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;\">\n<div style=\"flex: 1; min-width: 190px;\">\n            <label for=\"mq-geraet\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Name des Ger\u00e4ts<\/label><br \/>\n            <input type=\"text\" id=\"mq-geraet\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"Zaehlerschrank\">\n        <\/div>\n<div style=\"flex: 1; min-width: 190px;\">\n            <label for=\"mq-kennung\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Ger\u00e4tekennung<\/label><br \/>\n            <input type=\"text\" id=\"mq-kennung\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"sdm630_01\">\n        <\/div>\n<div style=\"flex: 1; min-width: 190px;\">\n            <label for=\"mq-name\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Name der Entit\u00e4t<\/label><br \/>\n            <input type=\"text\" id=\"mq-name\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"Bezug L1\">\n        <\/div>\n<div style=\"flex: 2; min-width: 240px;\">\n            <label for=\"mq-topic\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Zustands-Topic<\/label><br \/>\n            <input type=\"text\" id=\"mq-topic\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"zaehler\/sdm630\/status\">\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;\">\n<div style=\"flex: 1; min-width: 220px;\">\n            <label for=\"mq-vorlage\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Wertvorlage<\/label><br \/>\n            <input type=\"text\" id=\"mq-vorlage\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"{{ value_json.power_l1 }}\">\n        <\/div>\n<div style=\"flex: 1; min-width: 220px;\">\n            <label for=\"mq-verfuegbar\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Topic f\u00fcr die Erreichbarkeit (optional)<\/label><br \/>\n            <input type=\"text\" id=\"mq-verfuegbar\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"zaehler\/sdm630\/verfuegbar\">\n        <\/div>\n<div style=\"flex: 1; min-width: 220px;\">\n            <label for=\"mq-hersteller\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Hersteller<\/label><br \/>\n            <input type=\"text\" id=\"mq-hersteller\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"Eastron\">\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap; margin: 18px 0 0;\">\n        <button id=\"mq-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Nutzlast bauen<\/button>\n    <\/div>\n<div id=\"mq-ergebnis\" style=\"margin-top: 22px;\"><\/div>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Home Assistant \u00fcbernimmt eine MQTT-Entit\u00e4t von allein, sobald eine dauerhaft gespeicherte Konfigurationsnachricht auf dem richtigen Topic liegt. Dieser Baukasten schreibt diese Nachricht und pr\u00fcft die Kombinationen, die eine Entit\u00e4t ergeben, die zwar da ist, aber nie funktioniert.\",\"label_komponente\":\"Komponente\",\"label_klasse\":\"Ger\u00e4teklasse\",\"label_einheit\":\"Einheit\",\"label_praefix\":\"Discovery-Pr\u00e4fix\",\"label_geraet\":\"Name des Ger\u00e4ts\",\"label_kennung\":\"Ger\u00e4tekennung\",\"label_entitaet\":\"Name der Entit\u00e4t\",\"label_topic\":\"Zustands-Topic\",\"label_vorlage\":\"Wertvorlage\",\"label_verfuegbar\":\"Topic f\u00fcr die Erreichbarkeit (optional)\",\"label_hersteller\":\"Hersteller\",\"klasse_keine\":\"keine\",\"knopf\":\"Nutzlast bauen\",\"fehler_name\":\"Der Name der Entit\u00e4t fehlt.\",\"fehler_kennung\":\"Die Ger\u00e4tekennung fehlt.\",\"fehler_kennung_zeichen\":\"Die Ger\u00e4tekennung darf nur Buchstaben, Ziffern, Unterstrich und Bindestrich enthalten.\",\"fehler_name_zeichen\":\"Aus dem Namen der Entit\u00e4t l\u00e4sst sich keine brauchbare Objektkennung ableiten.\",\"fehler_topic\":\"Das Zustands-Topic fehlt oder enth\u00e4lt ein Leerzeichen, ein Plus oder eine Raute. Platzhalter geh\u00f6ren in ein Abonnement, nicht in ein Topic, auf das ver\u00f6ffentlicht wird.\",\"fehler_praefix\":\"Das Discovery-Pr\u00e4fix ist kein g\u00fcltiges Topic.\",\"fehler_verfuegbar\":\"Das Topic f\u00fcr die Erreichbarkeit ist kein g\u00fcltiges Topic.\",\"h_topic\":\"Discovery-Topic\",\"h_nutzlast\":\"Konfigurationsnachricht\",\"h_befehl\":\"Einmal ver\u00f6ffentlichen\",\"h_befunde\":\"Befunde\",\"b_einheit\":\"Die Ger\u00e4teklasse %k erwartet eine dieser Einheiten: %l. Hier steht %e, und Home Assistant weist die Entit\u00e4t ab.\",\"b_energie\":\"Ein Energiesensor braucht einen Z\u00e4hler, der ausschlie\u00dflich steigt. F\u00e4llt der Wert beim Neustart auf null, liest die Energie\u00fcbersicht das als Verbrauch.\",\"b_klasse_binaer\":\"%s ist keine Ger\u00e4teklasse f\u00fcr einen bin\u00e4ren Sensor.\",\"b_ohne_klasse\":\"Eine Einheit ohne Ger\u00e4teklasse ergibt eine Entit\u00e4t, die au\u00dfer in der Liste nirgends auftaucht.\",\"b_vorlage\":\"Die Wertvorlage nennt weder value_json noch value, sie liest damit nichts aus der Nachricht heraus.\",\"b_vorlage_klammern\":\"Der Wertvorlage fehlen die doppelten geschweiften Klammern.\",\"b_ohne_verfuegbar\":\"Ohne Topic f\u00fcr die Erreichbarkeit zeigt die Entit\u00e4t weiter ihren letzten Wert, auch wenn das Ger\u00e4t seit Tagen aus ist.\",\"b_retain\":\"Die Konfigurationsnachricht muss dauerhaft gespeichert ver\u00f6ffentlicht werden, sonst verschwindet die Entit\u00e4t beim n\u00e4chsten Neustart von Home Assistant.\",\"b_topic_praefix\":\"Das Zustands-Topic liegt unterhalb des Discovery-Pr\u00e4fixes. Beides geh\u00f6rt auseinander, sonst versucht Home Assistant, die Messwerte als Konfiguration zu lesen.\"};<\/p>\n<p>    \/\/ --- reine Rechenlogik ---<\/p>\n<p>    \/\/ Geraeteklassen mit den Einheiten, die Home Assistant dazu erwartet, und\n    \/\/ der passenden Zustandsklasse. Eine falsche Kombination erzeugt eine\n    \/\/ Entitaet, die in der Energieuebersicht nicht auftaucht.\n    const KLASSEN = {\n        '': { einheiten: [], zustand: '' },\n        'temperature': { einheiten: ['\u00b0C', '\u00b0F', 'K'], zustand: 'measurement' },\n        'humidity': { einheiten: ['%'], zustand: 'measurement' },\n        'pressure': { einheiten: ['hPa', 'mbar', 'Pa', 'bar', 'psi'], zustand: 'measurement' },\n        'power': { einheiten: ['W', 'kW'], zustand: 'measurement' },\n        'energy': { einheiten: ['Wh', 'kWh', 'MWh'], zustand: 'total_increasing' },\n        'voltage': { einheiten: ['V', 'mV'], zustand: 'measurement' },\n        'current': { einheiten: ['A', 'mA'], zustand: 'measurement' },\n        'battery': { einheiten: ['%'], zustand: 'measurement' },\n        'illuminance': { einheiten: ['lx'], zustand: 'measurement' },\n        'signal_strength': { einheiten: ['dBm', 'dB'], zustand: 'measurement' },\n        'carbon_dioxide': { einheiten: ['ppm'], zustand: 'measurement' },\n        'pm25': { einheiten: ['\u00b5g\/m\u00b3'], zustand: 'measurement' }\n    };<\/p>\n<p>    const BINAER_KLASSEN = ['', 'motion', 'door', 'window', 'moisture', 'smoke', 'occupancy', 'problem', 'connectivity'];<\/p>\n<p>    function text(wert) { return String(wert === undefined || wert === null ? '' : wert).trim(); }<\/p>\n<p>    function topicGueltig(topic) {\n        const t = text(topic);\n        if (t === '') { return false; }\n        if (\/[+#\\s]\/.test(t)) { return false; }\n        if (t.charAt(0) === '\/' || t.charAt(t.length - 1) === '\/') { return false; }\n        return true;\n    }<\/p>\n<p>    function kennungGueltig(wert) {\n        return \/^[A-Za-z0-9_-]+$\/.test(text(wert));\n    }<\/p>\n<p>    function bauen(e) {\n        const ergebnis = { ok: false, fehler: '', topic: '', nutzlast: null, json: '', befehl: '', befunde: [] };\n        const eingabe = e || {};<\/p>\n<p>        const komponente = text(eingabe.komponente) || 'sensor';\n        const praefix = text(eingabe.praefix) || 'homeassistant';\n        const geraet = text(eingabe.geraet);\n        const kennung = text(eingabe.kennung);\n        const name = text(eingabe.name);\n        const topic = text(eingabe.topic);\n        const klasse = text(eingabe.klasse);\n        const einheit = text(eingabe.einheit);\n        const vorlage = text(eingabe.vorlage);\n        const verfuegbar = text(eingabe.verfuegbar);\n        const hersteller = text(eingabe.hersteller);<\/p>\n<p>        if (name === '') { ergebnis.fehler = T.fehler_name; return ergebnis; }\n        if (kennung === '') { ergebnis.fehler = T.fehler_kennung; return ergebnis; }\n        if (!kennungGueltig(kennung)) { ergebnis.fehler = T.fehler_kennung_zeichen; return ergebnis; }\n        if (!topicGueltig(topic)) { ergebnis.fehler = T.fehler_topic; return ergebnis; }\n        if (!topicGueltig(praefix)) { ergebnis.fehler = T.fehler_praefix; return ergebnis; }\n        if (verfuegbar !== '' && !topicGueltig(verfuegbar)) { ergebnis.fehler = T.fehler_verfuegbar; return ergebnis; }<\/p>\n<p>        \/\/ Aus dem Namen wird die Objektkennung, damit sie zum Topic passt.\n        const objekt = name.toLowerCase()\n            .replace(\/[\u00e4\u00e0\u00e1\u00e2]\/g, 'a').replace(\/[\u00f6\u00f2\u00f3\u00f4]\/g, 'o').replace(\/[\u00fc\u00f9\u00fa\u00fb]\/g, 'u')\n            .replace(\/\u00df\/g, 'ss').replace(\/[^a-z0-9]+\/g, '_').replace(\/^_+|_+$\/g, '');\n        if (objekt === '') { ergebnis.fehler = T.fehler_name_zeichen; return ergebnis; }<\/p>\n<p>        const nutzlast = {\n            name: name,\n            unique_id: kennung + '_' + objekt,\n            object_id: kennung + '_' + objekt,\n            state_topic: topic\n        };\n        if (vorlage !== '') { nutzlast.value_template = vorlage; }\n        if (klasse !== '') { nutzlast.device_class = klasse; }\n        if (komponente === 'sensor') {\n            if (einheit !== '') { nutzlast.unit_of_measurement = einheit; }\n            const eintrag = KLASSEN[klasse];\n            if (eintrag && eintrag.zustand) { nutzlast.state_class = eintrag.zustand; }\n        }\n        if (komponente === 'switch' || komponente === 'light' || komponente === 'number') {\n            nutzlast.command_topic = topic.replace(\/\\\/status$\/, '') + '\/set';\n        }\n        if (verfuegbar !== '') {\n            nutzlast.availability_topic = verfuegbar;\n            nutzlast.payload_available = 'online';\n            nutzlast.payload_not_available = 'offline';\n        }\n        nutzlast.device = {\n            identifiers: [kennung],\n            name: geraet || name,\n            manufacturer: hersteller || undefined,\n            model: text(eingabe.modell) || undefined\n        };\n        if (!nutzlast.device.manufacturer) { delete nutzlast.device.manufacturer; }\n        if (!nutzlast.device.model) { delete nutzlast.device.model; }<\/p>\n<p>        ergebnis.topic = praefix + '\/' + komponente + '\/' + kennung + '\/' + objekt + '\/config';\n        ergebnis.nutzlast = nutzlast;\n        ergebnis.json = JSON.stringify(nutzlast, null, 2);\n        ergebnis.befehl = 'mosquitto_pub -h 192.168.1.10 -u benutzer -P geheim -r \\\\\\n'\n            + '  -t ' + hochkomma(ergebnis.topic) + ' \\\\\\n'\n            + '  -m ' + hochkomma(JSON.stringify(nutzlast));<\/p>\n<p>        \/\/ --- Befunde ---\n        if (komponente === 'sensor' && klasse !== '') {\n            const eintrag = KLASSEN[klasse];\n            if (eintrag && eintrag.einheiten.length && eintrag.einheiten.indexOf(einheit) === -1) {\n                ergebnis.befunde.push({ schwer: true, text: T.b_einheit.replace('%k', klasse).replace('%e', einheit || '-').replace('%l', eintrag.einheiten.join(', ')) });\n            }\n            if (klasse === 'energy') {\n                ergebnis.befunde.push({ schwer: false, text: T.b_energie });\n            }\n        }\n        if (komponente === 'binary_sensor' && klasse !== '' && BINAER_KLASSEN.indexOf(klasse) === -1) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_klasse_binaer.replace('%s', klasse) });\n        }\n        if (komponente === 'sensor' && einheit !== '' && klasse === '') {\n            ergebnis.befunde.push({ schwer: false, text: T.b_ohne_klasse });\n        }\n        if (vorlage !== '' && vorlage.indexOf('value_json') === -1 && vorlage.indexOf('value') === -1) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_vorlage });\n        }\n        if (vorlage !== '' && (vorlage.indexOf('{{') === -1 || vorlage.indexOf('}}') === -1)) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_vorlage_klammern });\n        }\n        if (verfuegbar === '') {\n            ergebnis.befunde.push({ schwer: false, text: T.b_ohne_verfuegbar });\n        }\n        ergebnis.befunde.push({ schwer: false, text: T.b_retain });\n        if (topic.indexOf(praefix + '\/') === 0) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_topic_praefix });\n        }<\/p>\n<p>        ergebnis.ok = true;\n        return ergebnis;\n    }<\/p>\n<p>    function hochkomma(wert) {\n        return \"'\" + String(wert).replace(\/'\/g, \"'\\\\''\") + \"'\";\n    }<\/p>\n<p>    if (typeof window !== 'undefined') {\n        window.LW_TEST = window.LW_TEST || {};\n        window.LW_TEST.MQ = { bauen: bauen, topicGueltig: topicGueltig, kennungGueltig: kennungGueltig, KLASSEN: KLASSEN };\n    }<\/p>\n<p>    \/\/ --- Anbindung an das Dokument ---<\/p>\n<p>    const btn = document.getElementById('mq-btn');\n    const out = document.getElementById('mq-ergebnis');\n    const komponenteFeld = document.getElementById('mq-komponente');\n    const klasseFeld = document.getElementById('mq-klasse');\n    if (!btn || !out || !komponenteFeld || !klasseFeld) { return; }<\/p>\n<p>    const KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 6px; padding: 14px; margin-bottom: 18px;';\n    const UEBERSCHRIFT = 'color: var(--text-primary, #e8e8ee); font-weight: 700; margin-bottom: 8px;';<\/p>\n<p>    function el(tag, css, inhalt) {\n        const knoten = document.createElement(tag);\n        if (css) { knoten.setAttribute('style', css); }\n        if (inhalt !== undefined && inhalt !== null) { knoten.textContent = inhalt; }\n        return knoten;\n    }<\/p>\n<p>    function wert(id) {\n        const knoten = document.getElementById(id);\n        return knoten ? knoten.value : '';\n    }<\/p>\n<p>    function klassenFuellen() {\n        const liste = komponenteFeld.value === 'binary_sensor' ? BINAER_KLASSEN : Object.keys(KLASSEN);\n        const vorher = klasseFeld.value;\n        klasseFeld.textContent = '';\n        liste.forEach(function (name) {\n            const option = document.createElement('option');\n            option.value = name;\n            option.textContent = name === '' ? T.klasse_keine : name;\n            klasseFeld.appendChild(option);\n        });\n        if (liste.indexOf(vorher) !== -1) { klasseFeld.value = vorher; }\n        else if (komponenteFeld.value === 'sensor') { klasseFeld.value = 'power'; }\n    }<\/p>\n<p>    komponenteFeld.addEventListener('change', klassenFuellen);\n    klassenFuellen();\n    klasseFeld.value = 'power';<\/p>\n<p>    btn.addEventListener('click', function () {\n        const erg = bauen({\n            komponente: komponenteFeld.value,\n            klasse: klasseFeld.value,\n            einheit: wert('mq-einheit'),\n            praefix: wert('mq-praefix'),\n            geraet: wert('mq-geraet'),\n            kennung: wert('mq-kennung'),\n            name: wert('mq-name'),\n            topic: wert('mq-topic'),\n            vorlage: wert('mq-vorlage'),\n            verfuegbar: wert('mq-verfuegbar'),\n            hersteller: wert('mq-hersteller')\n        });<\/p>\n<p>        out.textContent = '';\n        if (!erg.ok) {\n            out.appendChild(el('div', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left: 3px solid #ffb86c; color: var(--text-secondary, #a0a0b0); padding: 14px; border-radius: 6px;', erg.fehler));\n            return;\n        }<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_topic));\n        out.appendChild(el('pre', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--accent, #7ee787); padding: 14px; border-radius: 6px; overflow-x: auto; font-family: monospace; font-size: 0.85rem; white-space: pre-wrap; word-break: break-all; margin-bottom: 18px;', erg.topic));<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_nutzlast));\n        out.appendChild(el('pre', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); padding: 16px; border-radius: 6px; overflow-x: auto; font-family: monospace; font-size: 0.82rem; line-height: 1.5; white-space: pre; margin-bottom: 18px;', erg.json));<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_befehl));\n        out.appendChild(el('pre', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); padding: 16px; border-radius: 6px; overflow-x: auto; font-family: monospace; font-size: 0.8rem; line-height: 1.5; white-space: pre; margin-bottom: 18px;', erg.befehl));<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_befunde));\n        const kasten = el('div', KASTEN);\n        erg.befunde.forEach(function (b) {\n            const z = el('div', 'display: flex; gap: 10px; padding: 5px 0;');\n            z.appendChild(el('span', 'color: ' + (b.schwer ? '#ffb86c' : 'var(--text-secondary, #a0a0b0)') + '; font-family: monospace;', b.schwer ? '!' : '-'));\n            z.appendChild(el('span', 'color: var(--text-secondary, #a0a0b0); font-size: 0.9rem; line-height: 1.5;', b.text));\n            kasten.appendChild(z);\n        });\n        out.appendChild(kasten);\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Baut Topic und Konfigurationsnachricht f\u00fcr eine MQTT-Entit\u00e4t und f\u00e4ngt die Kombinationen aus Ger\u00e4teklasse, Einheit und Zustandsklasse ab, die einen Sensor aus der Energie\u00fcbersicht heraushalten.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9283,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92055,92211,92187],"class_list":["post-10260","page","type-page","status-publish","hentry","tag-automation-de","tag-self-hosting-de","tag-smart-home-de-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Baut Topic und Konfigurationsnachricht f\u00fcr eine MQTT-Entit\u00e4t und f\u00e4ngt die Kombinationen aus Ger\u00e4teklasse, Einheit und Zustandsklasse ab, die einen Sensor aus der Energie\u00fcbersicht heraushalten.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/mqtt-home-assistant-discovery-builder\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/mqtt-home-assistant-discovery-builder\\\/\",\"name\":\"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-08-14T22:49:51+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/mqtt-home-assistant-discovery-builder\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/mqtt-home-assistant-discovery-builder\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/mqtt-home-assistant-discovery-builder\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/toolbox-2\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/","og_locale":"en_US","og_type":"article","og_title":"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen - Lukas Wojcik - Blog","og_description":"Baut Topic und Konfigurationsnachricht f\u00fcr eine MQTT-Entit\u00e4t und f\u00e4ngt die Kombinationen aus Ger\u00e4teklasse, Einheit und Zustandsklasse ab, die einen Sensor aus der Energie\u00fcbersicht heraushalten.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/","og_site_name":"Lukas Wojcik - Blog","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/","name":"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-08-14T22:49:51+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/mqtt-home-assistant-discovery-builder\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/toolbox-2\/"},{"@type":"ListItem","position":3,"name":"MQTT-Discovery-Nutzlast f\u00fcr Home Assistant bauen"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10260","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=10260"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10260\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9283"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=10260"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=10260"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}