Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. [gelöst] Generischen Datenpunkt via Blockly (openHasp)

    NEWS

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    [gelöst] Generischen Datenpunkt via Blockly (openHasp)

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

      Hallo,

      ich bein gerade dabei ein openHasp-Display via ioBroker anzusprechen. Da funktioniert nur der MQTT-Client Adapter vernünftig.
      Man muss für jeden Button, Slider etc. 2 separate Datenpunkte mit MQTT-Verknüpfung manuell erstellen (1 mal subscribe und einmal publish). Das muss doch einfacher und fehlerfreier gehen. Zumal ich demnächst ein 2. Display einbinden muss.

      Ich dachte an ein Blockly, welchem ich die Variablem übergeben und ein Javascript erstellt mir das dann generisch. Hab schonmal gestartet, da tut sich aber nix. Könnt ihr mir bitte den Anstoss in die richtige Richtung geben?

      Mein vorhandenes Blockly (mit JS):

      var host_name, button_id, name2, adapter, type, role;
      
      // Beschreibe diese Funktion …
      async function createIoBrokerDataPoint() {
          function createIoBrokerDataPoint(adapter, button_id, name, type) {
              // Überprüfen, ob die notwendigen Parameter vorhanden sind
              if (!adapter || !button_id || !name || !type) {
                  console.error('Bitte alle Parameter übergeben: adapter, button_id, name, type.');
                  return;
              }
          
                      // Datenpunkt erstellen
                      const objDefinition = {
                          type: 'state',
                          common: {
                              name: name,
                              type: type,
                              role: 'state',
                              read: true,
                              write: true,
                          },
                          native: {},
                      };
          
                  }
          
          // Beispielaufruf der Funktion
          // Angenommen, "adapter" ist dein ioBroker-Adapter
          createIoBrokerDataPoint(adapter, button_id, name2, type);
      
      }
      
      
      host_name = '';
      button_id = 'p1b1';
      name2 = 'beschreibung';
      adapter = 'mqtt-client.0';
      type = 'string';
      role = '';
      
      on({ id: '0_userdata.0.create_openHasp_object' /* create_openHasp_object */, change: 'ne' }, async (obj) => {
        let value = obj.state.val;
        let oldValue = obj.oldState.val;
        if ((obj.state ? obj.state.val : '')) {
          setState('0_userdata.0.create_openHasp_object' /* create_openHasp_object */, false);
          await createIoBrokerDataPoint();
          console.info('createIoBrokerDataPoint');
        }
      });
      

      36705092-8db2-4dcb-8ce0-91569b8ad86f-grafik.png

      Der Datenpunkt soll dann später auch die MQTT-Sachen enthalten, automatisch. Hier ein Beispiel:

      {
        "common": {
          "name": "p7b46_Power_Sofalampe_Mitte",
          "desc": "Manuell erzeugt",
          "role": "state",
          "type": "string",
          "read": true,
          "write": true,
          "def": "",
          "custom": {
            "mqtt-client.0": {
              "enabled": true,
              "publish": false,
              "pubChangesOnly": false,
              "pubAsObject": false,
              "qos": false,
              "retain": false,
              "subscribe": true,
              "subChangesOnly": false,
              "subAsObject": false,
              "subQos": false,
              "setAck": false,
              "topic": "hasp/buero_sofa/state/p7b46"
            }
          }
        },
        "type": "state",
        "native": {},
        "_id": "mqtt-client.0.buero_sofa.state.p7b46_Power_Sofalampe_Mitte",
        "acl": {
          "object": 1636,
          "state": 1636,
          "owner": "system.user.admin",
          "ownerGroup": "system.group.administrator"
        },
        "from": "system.adapter.admin.0",
        "user": "system.user.admin",
        "ts": 1742849606787
      }
      

      p7b46 - ist der Button (button_id) des Displays und Teil des Topics.
      Sofalampe wäre hier Beispielsweise der Name.
      buero_sofa ist der hostname in diesem Fall.

      Wenn ich das schonmal hinbekomme, dann könnte ich relativ leicht auch den 2. Datenpunkt zum publishen gleich miterstellen...
      "topic": "hasp/buero_sofa/command/p7b46.val"

      Codierknecht 1 Reply Last reply Reply Quote 0
      • Codierknecht
        Codierknecht Developer Most Active @oberfragger last edited by

        @oberfragger
        Zunächst wäre es wohl hilfreich, der Funktion auch ein paar Parameter mitzugeben 😉

        3cf7036a-a6c5-4950-b8b2-220e23846bb2-image.png

        oberfragger 1 Reply Last reply Reply Quote 1
        • oberfragger
          oberfragger @Codierknecht last edited by oberfragger

          @codierknecht sagte in Generischen Datenpunkt via Blockly erstellen:

          @oberfragger
          Zunächst wäre es wohl hilfreich, der Funktion auch ein paar Parameter mitzugeben 😉

          3cf7036a-a6c5-4950-b8b2-220e23846bb2-image.png

          Oh. Vielen Dank. Logisch.

          Sorry, nächste Frage...
          Ich hab mal bisschen mit dem Copilot gespielt (bestehenden Datenpunkt genommen und einfach mal ID verändert. So wollte ich mal via JS das alles anlegen.

          const datapoint = {
              common: {
                  name: "p7b77_Power_Sofalampe_Mitte",
                  desc: "Manuell erzeugt",
                  role: "state",
                  type: "string",
                  read: true,
                  write: true,
                  def: "",
                  custom: {
                      "mqtt-client.0": {
                          enabled: true,
                          publish: false,
                          pubChangesOnly: false,
                          pubAsObject: false,
                          qos: false,
                          retain: false,
                          subscribe: true,
                          subChangesOnly: false,
                          subAsObject: false,
                          subQos: false,
                          setAck: false,
                          topic: "hasp/buero_sofa/state/p7b77"
                      }
                  }
              },
              type: "state",
              native: {},
              acl: {
                  object: 1636,
                  state: 1636,
                  owner: "system.user.admin",
                  ownerGroup: "system.group.administrator"
              }
          };
          
          const id = "mqtt-client.0.buero_sofa.state.p7b77_Power_Sofalampe_Mitte";
          
          createState(id, datapoint.common, true, (err) => {
              if (err) {
                  console.error(`Fehler beim Anlegen des Datenpunkts: ${err}`);
              } else {
                  console.log(`Datenpunkt "${id}" erfolgreich angelegt.`);
              }
          });
          

          Ich erhalte auch nach dem starten die Ausgabe:

          javascript.0	12:11:15.701	info	script.js.common.openHasp_Datenpunkt_JS: Datenpunkt "mqtt-client.0.buero_sofa.state.p7b77_Power_Sofalampe_Mitte" erfolgreich angelegt.
          

          Aber leider ist kein derartiger datenpunkt zu sehen...!?! Hab auch oben auf "refresh" geklickt.

          9e4c47ad-3793-452a-9adf-642334021777-grafik.png
          Irgendwo ein Denkfehler drin?

          paul53 1 Reply Last reply Reply Quote 0
          • paul53
            paul53 @oberfragger last edited by paul53

            @oberfragger sagte: Irgendwo ein Denkfehler drin?

            Wenn man den MQTT-Client Adapter verwendet, erstellt man die Datenpunkte unter "0_userdata.0" und unter common.custom wird der Bezug zur MQTT-Client-Instanz hergestellt.
            createState() kann nur unter "javascript.N" und "0_userdata.0" Datenpunkte erstellen.

            EDIT: Beispiel:

            const common = {
                name: "Power Sofalampe Mitte",
                role: "state",
                type: "string",
                read: true,
                write: false,
                def: "",
                custom: {
                    "mqtt-client.0": {
                        enabled: true,
                        publish: false,
                        pubChangesOnly: false,
                        pubAsObject: false,
                        qos: false,
                        retain: false,
                        subscribe: true,
                        subChangesOnly: false,
                        subAsObject: false,
                        subQos: false,
                        setAck: false,
                        topic: "hasp/buero_sofa/state/p7b77"
                    }
                }
            };
            
            const id = "0_userdata.0.buero_sofa.Sofalampe_Mitte.Power.state";
            createState(id, '', common);
            
            oberfragger 1 Reply Last reply Reply Quote 0
            • oberfragger
              oberfragger @paul53 last edited by

              @paul53 Danke.
              Das werde ich probieren. Ich poste ein Update.

              Wenn ich das so wie gewünscht hinbekomme, kann es meines Erachtens die Benutzung von openHasp-Devices für alle enorm vereinfachen, da leider mit normalem MQTT keine zurückgegeben Werte ausgewertet werden können.

              paul53 1 Reply Last reply Reply Quote 0
              • paul53
                paul53 @oberfragger last edited by paul53

                @oberfragger
                Etwas flexibler durch Auswertung des Topic:

                const topic = 'hasp/buero_sofa/state/p7b77';
                const Name = 'Power Sofalampe_Mitte';
                const def = ''; // Typ muss übereinstimmen
                
                const arrTop = topic.split('/');
                const arrName = Name.split(' ');
                const id = '0_userdata.0.' + arrTop[1] + '.' + arrName[1] + '.' + arrName[0] + '.' + arrTop[2];
                
                const common = {
                    name: Name.replace('_', ' '),
                    role: "state",
                    type: typeof def,
                    read: arrTop[2] == 'state',
                    write: arrTop[2] == 'command',
                    def: def,
                    custom: {
                        "mqtt-client.0": {
                            enabled: true,
                            publish: arrTop[2] == 'command',
                            pubChangesOnly: false,
                            pubAsObject: false,
                            qos: false,
                            retain: false,
                            subscribe: arrTop[2] == 'state',
                            subChangesOnly: false,
                            subAsObject: false,
                            subQos: false,
                            setAck: false,
                            topic: topic
                        }
                    }
                };
                
                createState(id, def, common);
                

                EDIT: Mittels Alias lassen sich "state" und "command" zu einem DP verbinden.

                oberfragger 1 Reply Last reply Reply Quote 0
                • oberfragger
                  oberfragger @paul53 last edited by oberfragger

                  @paul53 Ich hab gerade den von mir generierten Datenpunkt gefunden- der wurde unter javascript.0 erstellt. So wie du geschrieben hast. Das ist natürlich nicht so schön. Userdata.0 ist ebsser.
                  e7e5c599-824d-4268-a665-526d7a3c148e-image.png

                  Mit dem vorletzten Script von dir, erstellt er mir leider garnix. Ich möchte mich da halt langtasten und sukzessive verstehen was ich da mache -> dann kann ich das auch mal selbst machen.

                  Hier ist das Blockly (wie gesagt- ich möchte später mal einfach die Werte wie Button etc. eintragen und somit schnell erstellen können. Die Idee mit dem Alias finde ich super. Aber Schritt für Schritt.

                  Warum wird bei Aktivierung (ich setze da einfach den Datenpunkt auf "true" um das Script dann auszuführen...) der Datenpunkt unter userdata.0 nicht erstellt?

                  paul53 1 Reply Last reply Reply Quote 0
                  • paul53
                    paul53 @oberfragger last edited by paul53

                    @oberfragger sagte: Mit dem vorletzten Script von dir, erstellt er mir leider garnix.

                    Bei Skriptstart sollte der DP "0_userdata.0.buero_sofa.Sofalampe_Mitte.Power.state" erstellt werden.

                    Bei mir erfolgt es mit dem zuletzt geposteten Skript:

                    Sofalampe.JPG

                    oberfragger 1 Reply Last reply Reply Quote 0
                    • oberfragger
                      oberfragger @paul53 last edited by oberfragger

                      @paul53 Keine Ahnung- jetzt klappts bei mir auch.

                      Ich hangel mich gerade durch. Muss noch bisschen frickeln, so dass ich die notwendigen Sachen aus dem blockly an die Funktion übergeben bekomme.
                      f1f560d4-84c8-4f9b-9154-2fb3c5c4fcea-image.png

                      Danke auf jeden Fall für deine Mühe.
                      Nach ein bisschen grübeln habe ich auch verstanden was du hier machst:
                      873e9266-6c38-4bbf-b3dd-7c026afbdbed-image.png
                      Mein Ziel ist es primär, die notwendigen Variablen an die Funktion zu übergeben (zum Beispiel Button "p7b77") und dann legt er mir für jeden Button sowohl einen state, als auch command an. Somit kann ich dann bequem für jeden Button auf dem openHasp-Display die Sachen eingeben und beide Datenpunkte automatisch generieren lassen. Und wenn das klappt, dann schaue ich mir mal die Alias-Geschichte an.

                      oberfragger 1 Reply Last reply Reply Quote 0
                      • oberfragger
                        oberfragger @oberfragger last edited by oberfragger

                        Kurzes Update.
                        Das Script & Blockly scheint fertig. Damit kann ich nun recht generisch Datenpunkte für openHasp-Displays erstellen bzw. für die diversen Buttons.

                        @paul53 hat Starthilfe gegeben. Danke nochmal.
                        Den Rest dann mit chatgpt beendet. Waren noch paar kleine Stolpersteine drin.

                        Wenn ich auch passende Scripte fertig und alles getestet habe, dann schreibe ich mal eine Anleitung für openHasp.

                        cbed5891-de9b-4916-8db9-71066cb384d4-grafik.png

                        <xml xmlns="https://developers.google.com/blockly/xml">
                          <variables>
                            <variable id="t]mHQ2(O[i~,~{Z1[+%!">button_id</variable>
                            <variable id="mPT5a/ZZM;ltIo{jt;]v">buttonfunktion</variable>
                            <variable id="O5fjg~@mC^kh:.OT[4tI">speicherpfad</variable>
                            <variable id="r2OFNb5JSoE#g];#4K3Y">pretopic</variable>
                            <variable id="5gtZow7y)14]oqV=GyN|">hostname</variable>
                            <variable id="`wmra-.jA.[a)@dMnQN7">type</variable>
                          </variables>
                          <block type="procedures_defcustomnoreturn" id="@UFkkX.yv%])Ff}F2;|j" x="238" y="163">
                            <mutation statements="false">
                              <arg name="button_id" varid="t]mHQ2(O[i~,~{Z1[+%!"></arg>
                              <arg name="buttonfunktion" varid="mPT5a/ZZM;ltIo{jt;]v"></arg>
                              <arg name="speicherpfad" varid="O5fjg~@mC^kh:.OT[4tI"></arg>
                              <arg name="pretopic" varid="r2OFNb5JSoE#g];#4K3Y"></arg>
                              <arg name="hostname" varid="5gtZow7y)14]oqV=GyN|"></arg>
                              <arg name="type" varid="`wmra-.jA.[a)@dMnQN7"></arg>
                            </mutation>
                            <field name="NAME">paul53</field>
                            <field name="SCRIPT">Y29uc3QgY3JlYXRlVG9waWMgPSAoYWN0aW9uKSA9PiBgJHtwcmV0b3BpY30vJHtob3N0bmFtZX0vJHthY3Rpb259LyR7YnV0dG9uX2lkfWA7DQpjb25zdCBjcmVhdGVJRCA9IChhY3Rpb24pID0+IGAwX3VzZXJkYXRhLjAuJHtzcGVpY2hlcnBmYWR9LiR7aG9zdG5hbWV9LiR7YWN0aW9ufS4ke2J1dHRvbl9pZH1gOw0KDQpjb25zdCBzdGF0ZXRvcGljID0gY3JlYXRlVG9waWMoJ3N0YXRlJyk7DQpjb25zdCBjb21tYW5kdG9waWMgPSBjcmVhdGVUb3BpYygnY29tbWFuZCcpICsgKHR5cGUudG9Mb3dlckNhc2UoKSA9PT0gJ251bWJlcicgPyAnLnZhbCcgOiAnJyk7DQoNCmNvbnN0IHN0YXRlX2lkID0gY3JlYXRlSUQoJ3N0YXRlJyk7DQpjb25zdCBjb21tYW5kX2lkID0gY3JlYXRlSUQoJ2NvbW1hbmQnKTsNCg0KLy8gU3RhbmRhcmR3ZXJ0IGbDvHIgZGVmDQpjb25zdCBnZXREZWZhdWx0VmFsdWUgPSAodCkgPT4gKHQgPT09ICdudW1iZXInID8gMCA6IHQgPT09ICdib29sZWFuJyA/IGZhbHNlIDogJycpOw0KDQpjb25zdCBzdGF0ZV9jb21tb24gPSB7DQogICAgbmFtZTogYnV0dG9uZnVua3Rpb24sDQogICAgcm9sZTogInN0YXRlIiwNCiAgICB0eXBlOiAic3RyaW5nIiwNCiAgICByZWFkOiB0cnVlLA0KICAgIHdyaXRlOiBmYWxzZSwNCiAgICBkZWY6ICcnLA0KICAgIGN1c3RvbTogew0KICAgICAgICAibXF0dC1jbGllbnQuMCI6IHsgZW5hYmxlZDogdHJ1ZSwgcHVibGlzaDogZmFsc2UsIHN1YnNjcmliZTogdHJ1ZSwgdG9waWM6IHN0YXRldG9waWMgfQ0KICAgIH0NCn07DQoNCmNvbnN0IGNvbW1hbmRfY29tbW9uID0gew0KICAgIG5hbWU6IGJ1dHRvbmZ1bmt0aW9uLA0KICAgIHJvbGU6ICJzdGF0ZSIsDQogICAgdHlwZSwNCiAgICByZWFkOiB0cnVlLA0KICAgIHdyaXRlOiB0cnVlLA0KICAgIGRlZjogZ2V0RGVmYXVsdFZhbHVlKHR5cGUpLA0KICAgIGN1c3RvbTogew0KICAgICAgICAibXF0dC1jbGllbnQuMCI6IHsgZW5hYmxlZDogdHJ1ZSwgcHVibGlzaDogdHJ1ZSwgc3Vic2NyaWJlOiBmYWxzZSwgdG9waWM6IGNvbW1hbmR0b3BpYyB9DQogICAgfQ0KfTsNCg0KY3JlYXRlU3RhdGUoc3RhdGVfaWQsICcnLCBzdGF0ZV9jb21tb24pOw0KY3JlYXRlU3RhdGUoY29tbWFuZF9pZCwgZ2V0RGVmYXVsdFZhbHVlKHR5cGUpLCBjb21tYW5kX2NvbW1vbik7</field>
                            <comment pinned="false" h="80" w="160">Beschreibe diese Funktion …</comment>
                          </block>
                          <block type="comment" id="$RQ:rwIC/g6xPOV+A1Ss" x="237" y="212">
                            <field name="COMMENT">Adapter: mqtt-client.0&amp;#10;button_id: Den Button angeben&amp;#10;buttonfunktion: Was soll durch den Button ausgelöst werden&amp;#10;speicherpfad: hinter userdata_0.0&amp;#10;pretopic: siehe mqtt-setting des hasp devices&amp;#10;hostname des hasp-devices&amp;#10;typ des Buttons (bool, string, number)</field>
                            <next>
                              <block type="on" id="V?L;5Nr}OxT)BT]~^#Jc">
                                <field name="OID">0_userdata.0.test</field>
                                <field name="CONDITION">ne</field>
                                <field name="ACK_CONDITION"></field>
                                <statement name="STATEMENT">
                                  <block type="controls_if" id="0),V(RPzI|S:?3|,7W]!">
                                    <value name="IF0">
                                      <block type="on_source" id="3z%t2xus(;q~YGyZh}SN">
                                        <field name="ATTR">state.val</field>
                                      </block>
                                    </value>
                                    <statement name="DO0">
                                      <block type="procedures_callcustomnoreturn" id="=gS(Blp?cNt|^k7%1[k%">
                                        <mutation name="paul53">
                                          <arg name="button_id"></arg>
                                          <arg name="buttonfunktion"></arg>
                                          <arg name="speicherpfad"></arg>
                                          <arg name="pretopic"></arg>
                                          <arg name="hostname"></arg>
                                          <arg name="type"></arg>
                                        </mutation>
                                        <value name="ARG0">
                                          <block type="text" id="E~iotn9wF;Let({7%t2E">
                                            <field name="TEXT">p1b7</field>
                                          </block>
                                        </value>
                                        <value name="ARG1">
                                          <block type="text" id="FAP!atq!u%WrvXl^R2ts">
                                            <field name="TEXT">Lampe Ecke Helligkeit</field>
                                          </block>
                                        </value>
                                        <value name="ARG2">
                                          <block type="text" id="umuTAU1|5gG|sv/$[=6a">
                                            <field name="TEXT">Büro</field>
                                          </block>
                                        </value>
                                        <value name="ARG3">
                                          <block type="text" id="f{Ht+f@lncWjnT7EMvY7">
                                            <field name="TEXT">hasp</field>
                                          </block>
                                        </value>
                                        <value name="ARG4">
                                          <block type="text" id="Jr_osU%Iy/{u}}oP=Os3">
                                            <field name="TEXT">buero_sofa</field>
                                          </block>
                                        </value>
                                        <value name="ARG5">
                                          <block type="text" id="||K]*]sydI[Jq6;7:*O|">
                                            <field name="TEXT">number</field>
                                          </block>
                                        </value>
                                        <next>
                                          <block type="control" id="I@W^acpevmW@{].wv{Cb">
                                            <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                                            <field name="OID">0_userdata.0.test</field>
                                            <field name="WITH_DELAY">FALSE</field>
                                            <value name="VALUE">
                                              <block type="logic_boolean" id="S=gT0|j);wtj0Jsc1Maa">
                                                <field name="BOOL">FALSE</field>
                                              </block>
                                            </value>
                                          </block>
                                        </next>
                                      </block>
                                    </statement>
                                  </block>
                                </statement>
                              </block>
                            </next>
                          </block>
                        </xml>
                        
                        const createTopic = (action) => `${pretopic}/${hostname}/${action}/${button_id}`;
                        const createID = (action) => `0_userdata.0.${speicherpfad}.${hostname}.${action}.${button_id}`;
                        
                        const statetopic = createTopic('state');
                        const commandtopic = createTopic('command') + (type.toLowerCase() === 'number' ? '.val' : '');
                        
                        const state_id = createID('state');
                        const command_id = createID('command');
                        
                        // Standardwert für def
                        const getDefaultValue = (t) => (t === 'number' ? 0 : t === 'boolean' ? false : '');
                        
                        const state_common = {
                            name: buttonfunktion,
                            role: "state",
                            type: "string",
                            read: true,
                            write: false,
                            def: '',
                            custom: {
                                "mqtt-client.0": { enabled: true, publish: false, subscribe: true, topic: statetopic }
                            }
                        };
                        
                        const command_common = {
                            name: buttonfunktion,
                            role: "state",
                            type,
                            read: true,
                            write: true,
                            def: getDefaultValue(type),
                            custom: {
                                "mqtt-client.0": { enabled: true, publish: true, subscribe: false, topic: commandtopic }
                            }
                        };
                        
                        createState(state_id, '', state_common);
                        createState(command_id, getDefaultValue(type), command_common);
                        
                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post

                        Support us

                        ioBroker
                        Community Adapters
                        Donate

                        841
                        Online

                        31.7k
                        Users

                        79.7k
                        Topics

                        1.3m
                        Posts

                        3
                        10
                        322
                        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