Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. iobroker -> MQTT -> HomeAssistent AutoDiscovery

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    iobroker -> MQTT -> HomeAssistent AutoDiscovery

    This topic has been deleted. Only users with topic management privileges can see it.
    • F
      flachdachdecker last edited by

      Hallo liebes IObroker Forum,

      aus diversen Gründen habe ih neben meinem geliebten IOB auch noch eine HomeAssistant Installation laufen.

      Mit dem folgenden Script ist es möglich IObroker states AUTOMATISCH via Autodiscovery im HomeAssistent sichtbar zu machen - ohne umtändlich in YAML files rumfuhrwerken zu müssen und ohne im IObrocker an jedem State das pub & sub zu aktivieren. .

      Dazu setzt man einfach an einem State die Funktion "homeassistent_enabled":

      3223858b-7619-4b90-80ab-0dfea6e6016f-image.png

      Das Script scannt nach diesen Objekten und published sie via MQTT (ein Broker entweder in HA oder extern ist notwendig) an den HA:
      55fed696-d532-4bc3-9ade-6de972b0e000-image.png

      Im JS-Adapter muss als zusätzliches Modul "mqtt" geladen werden:
      9b9b56c8-ba87-4a84-aed6-678cc384e892-image.png

      Hier das script (Probleme siehe unten):

      // Required libraries
      const mqtt = require('mqtt');
      
      // Configuration
      const MQTT_BROKER_URL = 'mqtt://<IP>:<PORT>'; // Replace with your broker's address
      const MQTT_USERNAME = '<username>'; // Replace with your MQTT username
      const MQTT_PASSWORD = '<password>'; // Replace with your MQTT password
      const DEBUG = true; // Set to true for debugging output
      
      // MQTT client setup
      const mqttClient = mqtt.connect(MQTT_BROKER_URL, {
          username: MQTT_USERNAME,
          password: MQTT_PASSWORD
      });
      
      mqttClient.on('connect', () => {
          console.log('Connected to MQTT broker');
      });
      
      mqttClient.on('error', (err) => {
          console.error('MQTT connection error:', err);
      });
      
      // Function to log debug information
      function debugLog(message) {
          if (DEBUG) {
              console.log(message);
          }
      }
      
      // Function to determine the type of a state
      function determineStateType(stateObj) {
          if (typeof stateObj.val === 'boolean') {
              return 'switch';
          } else if (typeof stateObj.val === 'number') {
              return 'sensor';
          } else if (typeof stateObj.val === 'string') {
              return 'text';
          } else {
              return 'unknown';
          }
      }
      
      // Function to publish MQTT discovery messages
      function publishMQTTDiscovery(id, stateObj, deviceName) {
          const baseTopic = `homeassistant`;
          const deviceId = id.replace(/\./g, '_');
          const stateType = determineStateType(stateObj);
      
          let configTopic;
          let configPayload;
      
          switch (stateType) {
              case 'switch':
                  configTopic = `${baseTopic}/switch/${deviceId}/config`;
                  configPayload = {
                      name: deviceName || id, // Use the provided deviceName or fallback to id
                      state_topic: `${baseTopic}/switch/${deviceId}/state`, 
                      command_topic: `${baseTopic}/switch/${deviceId}/set`,
                      payload_on: true,
                      payload_off: false,
                      unique_id: deviceId,
                      device: {
                          identifiers: [deviceId],
                          name: deviceName || id, // Use deviceName for the device itself
                      },
                  };
                  break;
              case 'sensor':
                  configTopic = `${baseTopic}/sensor/${deviceId}/config`;
                  configPayload = {
                      name: deviceName || id,
                      state_topic: `${baseTopic}/sensor/${deviceId}/state`,
                      unique_id: deviceId,
                      device: {
                          identifiers: [deviceId],
                          name: deviceName || id,
                      },
                  };
                  break;
              case 'text':
                  configTopic = `${baseTopic}/text/${deviceId}/config`;
                  configPayload = {
                      name: deviceName || id,
                      state_topic: `${baseTopic}/text/${deviceId}/state`,
                      command_topic: `${baseTopic}/text/${deviceId}/set`,
                      unique_id: deviceId,
                      device: {
                          identifiers: [deviceId],
                          name: deviceName || id,
                      },
                  };
                  break;
              default:
                  debugLog(`Unknown state type for ${id}`);
                  return;
          }
      
          mqttClient.publish(configTopic, JSON.stringify(configPayload), { retain: true });
      
          // Publish initial state
          const stateTopic = configPayload.state_topic;
          mqttClient.publish(stateTopic, JSON.stringify(stateObj.val));
      
          // Subscribe to command topic if applicable
          if (configPayload.command_topic) {
              mqttClient.subscribe(configPayload.command_topic);
              mqttClient.on('message', (topic, message) => {
                  if (topic === configPayload.command_topic) {
                      try {
                          // Check if the message is JSON
                          let newValue;
                          if (message.toString().startsWith('{') || message.toString().startsWith('[')) {
                              newValue = JSON.parse(message.toString());
                          } else {
                              // Handle non-JSON payloads (e.g., "true", "false", "42")
                              newValue = message.toString().trim().toLowerCase();
                              if (newValue === 'true') newValue = true;
                              else if (newValue === 'false') newValue = false;
                              else if (!isNaN(newValue)) newValue = parseFloat(newValue);
                          }
      
                          setState(id, newValue); // Update ioBroker state
                      } catch (err) {
                          console.error(`Failed to process MQTT message on ${topic}:`, err);
                      }
                  }
              });
          }
      
          debugLog(`Published MQTT discovery for ${id}: ${JSON.stringify(configPayload)}`);
      }
      
      
      function scanAndPublish() {
          const homeAssistantDevices = getObject('enum.functions.homeassistent_enabled');
      
          if (homeAssistantDevices) {
              console.log('Devices with homeassistent_enabled function:');
              homeAssistantDevices.common.members.forEach(deviceId => {
                  const deviceObj = getObject(deviceId); // Fetch the device object
                  const stateObj = getState(deviceId); // Fetch the state of the device
                  
                  if (deviceObj && stateObj) {
                      console.log(`- ${deviceObj.common.name} (${deviceId})`);
                      // Pass the device name as an additional argument
                      publishMQTTDiscovery(deviceId, stateObj, deviceObj.common.name);
                  } else {
                      console.log(`Skipping device ${deviceId}: Unable to retrieve object or state.`);
                  }
              });
          } else {
              console.log('No devices found with homeassistent_enabled function');
          }
      }
      
      
      // Run the script periodically
      schedule('*/1 * * * *', () => {
        debugLog('Scanning for states with homeassistent_enabled...');
      scanAndPublish();
      });
      
      

      Soweit so gut - ein Problemchen habe ich noch:
      Wenn im HA einen der "switches" betätige schaltet es im IOB wie es soll, die Statusrückmeldung kommt aber entweder nicht im HA an oder bleibt nicht erhalten. Die Icons im HA werden also nicht blau (was für aktiviert steht). Hier ein Debug der herauskommt wenn ich im HA dem "sonoff_0_zwstecker_1_weihnachtsbaum_power" auf "true" schalte:

      javascript.1	08:09:13.401	info	Start JavaScript script.js.in_Entwicklung.MQTT2 (Javascript/js)
      javascript.1	08:09:13.405	info	script.js.in_Entwicklung.MQTT2: Scanning for states with homeassistent_enabled...
      javascript.1	08:09:13.405	info	script.js.in_Entwicklung.MQTT2: Devices with homeassistent_enabled function:
      javascript.1	08:09:13.405	info	script.js.in_Entwicklung.MQTT2: - Lüfter Elternbad.STATE (hm-rpc.0.LEQ0233457.13.STATE)
      javascript.1	08:09:13.405	info	script.js.in_Entwicklung.MQTT2: Published MQTT discovery for hm-rpc.0.LEQ0233457.13.STATE: {"name":"Lüfter Elternbad.STATE","state_topic":"homeassistant/switch/hm-rpc_0_LEQ0233457_13_STATE/state","command_topic":"homeassistant/switch/hm-rpc_0_LEQ0233457_13_STATE/set","payload_on":true,"payload_off":false,"unique_id":"hm-rpc_0_LEQ0233457_13_STATE","device":{"identifiers":["hm-rpc_0_LEQ0233457_13_STATE"],"name":"Lüfter Elternbad.STATE"}}
      javascript.1	08:09:13.405	info	script.js.in_Entwicklung.MQTT2: - Termostat Wohnzimmer:1.ACTUAL_TEMPERATURE (hm-rpc.2.000C9A49A7D845.1.ACTUAL_TEMPERATURE)
      javascript.1	08:09:13.405	info	script.js.in_Entwicklung.MQTT2: Published MQTT discovery for hm-rpc.2.000C9A49A7D845.1.ACTUAL_TEMPERATURE: {"name":"Termostat Wohnzimmer:1.ACTUAL_TEMPERATURE","state_topic":"homeassistant/sensor/hm-rpc_2_000C9A49A7D845_1_ACTUAL_TEMPERATURE/state","unique_id":"hm-rpc_2_000C9A49A7D845_1_ACTUAL_TEMPERATURE","device":{"identifiers":["hm-rpc_2_000C9A49A7D845_1_ACTUAL_TEMPERATURE"],"name":"Termostat Wohnzimmer:1.ACTUAL_TEMPERATURE"}}
      javascript.1	08:09:13.406	info	script.js.in_Entwicklung.MQTT2: - ZwStecker_1_Weihnachtsbaum POWER (sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER)
      javascript.1	08:09:13.406	info	script.js.in_Entwicklung.MQTT2: Published MQTT discovery for sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"name":"ZwStecker_1_Weihnachtsbaum POWER","state_topic":"homeassistant/switch/sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER/state","command_topic":"homeassistant/switch/sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER/set","payload_on":true,"payload_off":false,"unique_id":"sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER","device":{"identifiers":["sonoff_0_ZwStecker_1_Weihnachtsbaum_POWER"],"name":"ZwStecker_1_Weihnachtsbaum POWER"}}
      javascript.1	08:09:13.406	info	script.js.in_Entwicklung.MQTT2: - On/off state of the switch (zigbee.0.4c97a1fffe27ff06.state)
      javascript.1	08:09:13.406	info	script.js.in_Entwicklung.MQTT2: Published MQTT discovery for zigbee.0.4c97a1fffe27ff06.state: {"name":"On/off state of the switch","state_topic":"homeassistant/switch/zigbee_0_4c97a1fffe27ff06_state/state","command_topic":"homeassistant/switch/zigbee_0_4c97a1fffe27ff06_state/set","payload_on":true,"payload_off":false,"unique_id":"zigbee_0_4c97a1fffe27ff06_state","device":{"identifiers":["zigbee_0_4c97a1fffe27ff06_state"],"name":"On/off state of the switch"}}
      javascript.1	08:09:13.407	info	script.js.in_Entwicklung.MQTT2: registered 0 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions
      javascript.1	08:09:13.408	info	script.js.in_Entwicklung.MQTT2: Connected to MQTT broker
      javascript.1	08:09:27.343	silly	States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.342	silly	States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	debug	stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	debug	onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367340,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      javascript.1	08:09:27.343	silly	States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      javascript.1	08:09:27.343	silly	States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	silly	States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	debug	stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	debug	onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	silly	States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.343	debug	stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.344	debug	onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.384	silly	States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.384	debug	stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      javascript.1	08:09:27.384	silly	States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.384	debug	onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.384	silly	States user redis pmessage sonoff.0.*/sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.384	debug	stateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      sonoff.0	08:09:27.384	debug	onStateChange sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER: {"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      javascript.1	08:09:27.384	silly	States user redis pmessage */sonoff.0.ZwStecker_1_Weihnachtsbaum.POWER:{"val":true,"ack":false,"ts":1734419367341,"q":0,"c":"script.js.in_Entwicklung.MQTT2","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1734419367340}
      

      Hat dazu jemand eine Idee?

      Und hat jemand weitere Ideen was man verbessern könnte?

      1 Reply Last reply Reply Quote 1
      • T
        Tom last edited by

        Hallo Flachdachdecker,
        vielen Dank für das Script. Ist im Prinzip genau das was ich gesucht habe. Das Script legt die in iobroker markierten Varianten in HA als entitäten an. Wenn ich in HA die entität ändere ist das sofort in iobroker zu sehen. Ändere ich aber in iobroker den Datenpunkt, wird das nicht an HA weitergereicht. In einem MQTT Explorer ist die Änderung des Zustandes aber zu sehen. Hast Du eine Idee, warum das so ist? Ist es normal, dass der Status nur alle 60s geändert wird.

        Marcus M. simatec 2 Replies Last reply Reply Quote 0
        • Marcus M.
          Marcus M. @Tom last edited by

          Hallo zusammen,

          Vielen Dank für das Skript.
          Ich habe es etwas modifiziert, um meine TUYA Fenster-Kontakte in HA zu bringen, da meine Modelle dort nicht unterstützt werden und iobroker und HA sowieso parallel laufen 🙂 (siehe hier https://github.com/home-assistant/core/issues/132105#issuecomment-3003720654)

          hier mein modifiziertes Skript:
          script-makedevicesHADiscovery.txt

          Ich markiere den state "doorcontact_state" mit der function "homeassistent_enabled" und starte das Skript.

          Es läuft nicht regelmäßig, sondern registriert sich für updates der Elemente.

          Ich nutze es nur für diesen einen Sensor-Typ und wahrscheinlich funktionieren andere Elemente nicht auf Anhieb.

          Viele Grüße
          Marcus

          404invalid-user created this issue in home-assistant/core

          open Tuya: Contact Sensor (unsupported) (p6sqiuesvhmhvv4f) #132105

          1 Reply Last reply Reply Quote 0
          • simatec
            simatec Developer Most Active @Tom last edited by

            @tom sagte in iobroker -> MQTT -> HomeAssistent AutoDiscovery:

            Hast Du eine Idee, warum das so ist? Ist es normal, dass der Status nur alle 60s geändert wird.

            So wie ich das im Script sehe, wird nur alle 60 Sekunden ein publish ausgeführt.
            Das macht in meinen Augen kein Sinn. Es sollte bei Änderung eines State ebenfalls immer ein Publish erfolgen

            Marcus M. 1 Reply Last reply Reply Quote 0
            • Marcus M.
              Marcus M. @simatec last edited by

              @simatec
              ich habe das Skript so geändert, dass es auf Änderungen der State lauscht und die Änderung dann auch direkt via MQTT sendet 🙂

              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              901
              Online

              31.8k
              Users

              80.0k
              Topics

              1.3m
              Posts

              4
              5
              387
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo