Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. Blockly
  5. "Blockly for dummies" ... Starthilfe und Tipps

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.2k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    1.9k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.2k

"Blockly for dummies" ... Starthilfe und Tipps

Geplant Angeheftet Gesperrt Verschoben Blockly
13 Beiträge 2 Kommentatoren 20.3k Aufrufe 24 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • CodierknechtC Online
    CodierknechtC Online
    Codierknecht
    Developer Most Active
    schrieb am zuletzt editiert von Codierknecht
    #2

    Falls / mache / sonst
    Um Entscheidungen anhand von Werten zu treffen und zumindest ein Minimum an Logik in ein Script einzubauen, müssen Werte überprüft werden.

    16ef8e79-fd2f-4b22-bdb8-f25ebfc2b98c-image.png
    Diese Prüfungen können selbstverständlich miteinander kombiniert werden.

    7d2342ce-0b1b-4738-a6b9-1de64878684f-image.png
    Dies sind nur rudimentäre einfach Beispiele.
    Mehr dazu siehe hier

    Verzögerungen (Timeouts)
    Es kommt verhältnismäßig häufig vor, dass bestimmte Aktionen erst nach einer gewissen Zeit ausgeführt werden sollen.
    Es soll z.B. eine Meldung erfolgen, wenn ein bestimmter Wert mindestens eine gewisse Zeit vorliegt. Oder eine Lampe soll ausgeschaltet werden, wenn ein Bewegungsmelder eine gewisse Zeit X keine Bewegung mehr erkannt hat.
    Dazu bedient man sich eines "timeout".

    d4145331-c25a-4b08-9550-4edf59e82692-image.png
    In den allermeisten Fällen muss auch dafür Sorge getragen werden, dass ein laufender timeout abgebrochen wird, wenn die Bedingung nicht mehr zutrifft.

    Mehr dazu hier

    Schleifen
    Will man aus eine Menge von Einzelwerten - z.B. eine Liste von Statuswerten, jeden Einzelwert verarbeiten, verwendet man Schleifen.

    837a0126-122b-455d-aa82-b1624f4faf8a-image.png
    Diese Liste kann man (wie hier) natürlich selbst erzeugen. Wesenlich häufiger enthalten aber Datenpunkte solche Listen als Wert. Das können die Genre eines laufenden Films oder die Musikstile des gerade über Alexa gespielten Liedes sein etc.

    70466267-89b1-45bc-b843-aa984d8d9211-image.png
    Mehr dazu hier

    Listen
    Im letzten Absatz wurde gezeigt, wie man mit einer Schleife durch eine "Liste" iteriert.
    Das war in den Beispielen eine bereits existierende Liste von Werten.
    ad177ae4-0269-4cc4-a394-ba256d206185-image.png
    Man kann solche Listen natürlich auch selbst erzeugen und mit diesen mehr oder weniger sinnvolle Dinge anstellen.

    Mehr dazu hier

    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

    Proxmox 9.0.18 LXC|8 GB|Core i7-6700
    HmIP|ZigBee|Tasmota|Unifi
    Zabbix Certified Specialist
    Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

    1 Antwort Letzte Antwort
    5
    • CodierknechtC Online
      CodierknechtC Online
      Codierknecht
      Developer Most Active
      schrieb am zuletzt editiert von Codierknecht
      #3

      Hier noch ein paar grundsätzliche Überlegungen:

      Lesbarkeit
      Code (auch Blockly) wird deutlich häufiger gelesen als geschrieben.
      In der Regel muss man früher oder später an ein Script nochmal "Hand anlegen".
      Viel häufiger als zu vermuten kommt es dann vor dass man denkt "welcher Vollhorst" hat das denn verbrochen?", um dann vielleicht festzustellen: "huch, das war ich ja selbst!"
      Es liegt also im eigenen Interesse, den Code so zu gestalten, dass er auch nach Wochen und Monaten noch problemlos zu verstehen ist. Damit verbessert man die Wartbarkeit ... und die Notwendigkeit dafür kommt - garantiert.
      Ich zitiere hier gerne aus "Refactoring" von Martin Fowler:
      "Any fool can write code that a computer can understand. Good programmers write code that humans can understand."

      Kommentare
      Man kann Bausteine mit Kommentaren versehen
      fc138d5a-9595-483c-932c-ab14a913df6b-image.png
      oder zusätzlich bzw. alternativ Kommentarbausteine einfügen
      a7496713-16b3-49c0-84e2-e8c3b66ddeb6-image.png
      Man erkennt hier hoffentlich schon:
      Es ist sinnvoller, seinen Variablen und/oder Funktionen sprechende Namen zu geben, statt sie aufwändig zu kommentieren.
      "Don't comment bad code - rewrite it"

      Verstehen vor Kopieren
      Die Verlockung ist groß: Man sucht sich etwas passendes im Internet und kopiert das ohne groß nachzudenken in seinen ioBroker. Der Anbieter hat ja schließlich geschrieben, was das Ding macht.
      Aber macht der Code auch wirklich (nur) das was der nette Kerl (m/w/d) da geschrieben hat?
      Versuche zunächst zu verstehen, was der angebotene Code so tut. Im Zweifelsfall kannst Du hier im Forum nachfragen.
      Wäre blöd, wenn der Code Deine Zugangsdaten zu einem Service benötigt und diese irgendwo hinschickt.
      Mindestens genau so blöd wäre es, wenn der Code Deinen ioBroker zerschießt oder Geräte unbrauchbar macht.

      Code behind
      Wer zumindest eine grundsätzliche Ahnung von Programmierung hat, sollte sich ab und an mal ansehen, was Blockly da "unter der Haube" an Code produziert. Das hilft möglicherweise, die Funktionsweise zu verstehen und ggf. Fehler zu finden.
      3b78b380-070d-4274-9813-42b1aa5b324b-image.png

      "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

      Proxmox 9.0.18 LXC|8 GB|Core i7-6700
      HmIP|ZigBee|Tasmota|Unifi
      Zabbix Certified Specialist
      Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

      1 Antwort Letzte Antwort
      5
      • CodierknechtC Online
        CodierknechtC Online
        Codierknecht
        Developer Most Active
        schrieb am zuletzt editiert von Codierknecht
        #4

        Grundsätzliches
        Insbesondere wer von der prozeduralen Programmierung oder einer SPS zu Blockly kommt, muss sich hier neu orientieren und umdenken.
        Im ioBroker werden Programme nicht bei Zeile 1 gestartet und laufen dann bis Zeile xyz nacheinander ab.
        In der Regel "reagieren" Programme (Scripte) nur auf äußere Einflüsse und werden aktiv, wenn ein bestimmtes Ereignis eintritt. Das kann die Änderung eines Datenpunktes oder auch das Erreichen eines bestimmten Zeitpunktes sein.
        Die meiste Zeit "schlafen" die Programme ... solange, bis eines der genannten Ereignisse eintritt.

        Trigger
        Ein Trigger ist eine Ereignisbehandlung. Das kann man sich als eine Art Abonnement vorstellen.
        Tritt das Ereignis ein, wird der Code im Trigger ausgeführt.

        • Will man bei bool'schen Datenpunkten (true/false) nur reagieren, wenn der DP auf true wechselt, verwendet man am besten "ist größer als Letztes".
          Analog dazu lässt sich der Wechsel auf false mit "ist kleiner als Letztes" verarbeiten.
          Hintergrund: Ein true wird intern als 1 und ein false intern als 0 verarbeitet.

        • Echte "Änderungen" am DP prüft man mit "wurde geändert". Datenpunkte werden von den Adaptern gerne mal zyklisch "aufgefrischt". Eine Prüfung auf "wurde aktualisiert" würde dann viel zu häufig den Trigger auslösen.

        Hier ein ganz einfaches Beispiel: Ändert sich der Zustand eines Schalters "SwitchState", wird die Lampe "Licht" mit dem Wert des Schalters (an oder aus) geschaltet.
        Was es mit dem Baustein "Wert" auf sich hat, wird hier erläutert.
        0f43a4de-3c25-4516-8903-7fc3af448ea9-image.png

        ACHTUNG:
        Niemals mehrere Trigger (oder Zeitpläne oder eine Kombination daraus) ineinander verschachteln. Sowas hier funktioniert nicht:

        541d21b1-d16d-4b1a-b08f-f9e926fc90fb-image.png

        Zeitpläne
        Mit einem Zeitplan kann man Dinge zu bestimmten Zeiten oder auch zyklisch alle x-Minuten ausführen lassen.

        • Vermeide den "Wizard", sondern verwende nach Möglichkeit CRON.
          Mit dem Wizard produzierte Zeitpläne funktionieren häufig nicht - zumindest nicht wie gewünscht

        • Vermeide zyklisch Ausführungen alle x-Minuten, wenn die gleiche Aufgabe auch mit einem Trigger ausgeführt werden kann.
          Man muss nicht alle paar Minuten prüfen, ob ein Datenpunkt einen bestimmten Wert angenommen hat. Das belastet das System. Besser ist es, einen Trigger auf den DP zu setzen.

        In diesem einfachen Beispiel wird eine Lampe täglich um 20:00 Uhr eingeschaltet.
        c970b559-26f7-48f1-8243-85843591876f-image.png

        Alles was außerhalb von Triggern oder Zeitplänen hinzugefügt wird, wird nur 1x - beim Start des Scriptes - ausgeführt.
        Damit lassen sich z.B, verwendete Variablen beim Start des Scriptes auf einen definierten Wert setzen.
        Dabei ist es unerheblich, ob der Baustein losgelöst von allen anderen "in der Luft schwebt" oder ob er z.B. oben (oder unten) an einen anderen Baustein angepinnt wird.

        26864d01-e426-49a8-a386-39319fe97cec-image.png

        ACHTUNG: Ein in Blockly erzeugter Zeitplan wird nur 1x beim Start des Scriptes aktiviert.
        Wenn man "variable" Zeitpläne benötigt, die sich z.B. bei Änderungen an einem Datenpunkt ändern sollen, muss man etwas mehr Aufwand treiben.
        Im einfachsten Fall verwendet man einen "Zeitplan aus Zeit-Zustand" Den setzt man auf einen Datenpunkt vom Typ "String (Text)". Ändert man den Inhalt des DP, ändert sich automatisch auch der Zeitplan. Ohne weiteres Zutun.
        01aefdf2-49f8-4b6d-a9d1-b74572414af3-image.png
        Mehr würde allerdings an dieser Stelle zu weit führen. Wenn Du so etwas benötigst, schau in die Doku.

        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

        Proxmox 9.0.18 LXC|8 GB|Core i7-6700
        HmIP|ZigBee|Tasmota|Unifi
        Zabbix Certified Specialist
        Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

        1 Antwort Letzte Antwort
        6
        • CodierknechtC Online
          CodierknechtC Online
          Codierknecht
          Developer Most Active
          schrieb am zuletzt editiert von Codierknecht
          #5

          Werte auslesen
          So ziemlich jedes Blockly benötigt den Wert aus einem oder gar mehreren Datenpunkten.

          bf0177f0-afe0-4382-8a78-9240cf4e788c-image.png
          Dabei ist zu beachten, dass hier in der Regel der "Wert" des Objektes von Interesse ist.
          Wählt man hier nur ein Objekt (rechts), enthält dieses die definierten (statischen) Eigenschaften desselben (ID, Name, Typ, Rolle usw.).
          Das ist in den meisten Fällen nicht das gewünschte - gefordert ist hier lediglich der "Wert" des Objektes und nicht sämtliche Eigenschaften.

          Tipp:
          Möchte man innerhalb eines Triggers auf den Wert des auslösenden Objektes zugreifen, muss der Wert nicht mit "Wert vom Objekt" ausgelesen werden.

          20fad51b-0dd7-46f6-bab7-26100b2e604c-image.png

          Stattdessen verwendet man den Baustein "Wert" aus dem Bereich Trigger. Der auslösende Trigger kennt nämlich bereits den Wert (und eine Reihe weiterer Eigenschaften) seines Objektes.
          Damit vermeidet man unnötige Leseoperationen. Die belasten nicht nur das System, sondern können auch zu Fehlern führen.

          "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

          Proxmox 9.0.18 LXC|8 GB|Core i7-6700
          HmIP|ZigBee|Tasmota|Unifi
          Zabbix Certified Specialist
          Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

          1 Antwort Letzte Antwort
          3
          • CodierknechtC Online
            CodierknechtC Online
            Codierknecht
            Developer Most Active
            schrieb am zuletzt editiert von Codierknecht
            #6

            Werte schreiben (Datenpunkte ändern)
            Um den Wert eines Datenpunktes zu ändern und damit z.B. ein Gerät einzuschalten, stehen grundsätzlich zwei (relativ ähnliche) Bausteine zur Verfügung.

            88d1c85c-de6b-4aef-bd28-98d5ce275aea-image.png

            Steuere
            Diesen Baustein verwendet man, um Datenpunkte zu verändern die einem Adapter "gehören", um z.B. eine Lampe oder einen Schalter zu schalten.
            Im Detail wird damit eine Änderung "ohne Bestätigung" (Ackknowledge) geschrieben. Diese fehlende Bestätigung ist für den Adapter die Veranlassung, etwas zu tun.
            Die allermeisten Adapter reagieren nicht, wenn hier eine Änderung per "Aktualisiere" (mit Bestätigung) geschrieben wird.
            Das gilt im Übrigen auch für Alias-Datenpunkte, die auf den "echten" DP eines Adapters verweisen.

            Aktualisiere
            Dieser Baustein wird zur Änderung eigener Datenpunkte verwendet, die Du unterhalb von 0_userdata.0 selbst angelegt hast.
            Hierbei wird "mit Bestätigung" geschrieben. Damit wird verhindert, dass der Wert im Objektbaum in rot dargestellt wird. In den meisten Fällen also eine lediglich kosmetische Sache.

            "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

            Proxmox 9.0.18 LXC|8 GB|Core i7-6700
            HmIP|ZigBee|Tasmota|Unifi
            Zabbix Certified Specialist
            Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

            1 Antwort Letzte Antwort
            6
            • CodierknechtC Online
              CodierknechtC Online
              Codierknecht
              Developer Most Active
              schrieb am zuletzt editiert von Codierknecht
              #7

              Variablen
              Mit Variablen lassen sich ermittelte oder berechnete Werte für die weitere Verarbeitung zwischenspeichern.
              Variablen werden manuell erstellt und sind im gesamten Script gültig.
              f5616d29-ada0-40d8-aeda-d7543ecdc736-image.png
              Sinnvoll ist das überall dort, wo ansonsten der Wert aus einem DP mehrfach ausgelesen werden müsste.
              Auch die Les- und Wartbarkeit eines Scriptes lässt sich durch die Verwendung von Variablen deutlich verbessern.
              Insbesondere komplexe Prüfungen werden durch Variablen deutlich besser lesbar und damit verständlicher.

              Klingt zunächst unwichtig. Aber Code wird in aller Regel deutlich häufiger gelesen als dass er geschrieben (geändert) wird. Auch Blockly.
              Wichtig wird das, wenn man nach Wochen oder gar Monaten nochmal da ran muss, um etwas zu überprüfen oder zu verändern. Es kommt nicht unbedingt selten vor, dass man dann seinen eigenen Code nicht mehr versteht ;-)

              7efa0136-0173-41bb-8f7a-db66cfd6696e-image.png
              In diesem Beispiel müsste der Wert des Objektes "Licht" ohne die Verwendung von Variablen 2x gelesen werden.
              So etwas belastet das System unnötig und kann durch die Verwendung von Variablen vermieden werden.

              Auch die Prüfung, ob "Licht" gerade eingeschaltet "und Vormittag" wird gleich wesentlich besser lesbar.

              Dabei gelten Variablen im ganzen Script! Aber nur in diesem Script!

              ACHTUNG: In den Namen von Variablen sollten auf keinen Fall Leer- oder gar Sonderzeichen verwendet werden.
              Dazu gehören insbesondere Umlaute.
              Ausnahme: _ und $ - aber auch die würde ich persönlich vermeiden.

              Auch in JavaScript reservierte Schlüsselworte und Anweisungen wie "Object", "true", "String" oder "let" etc. sollte man tunlichst vermeiden. Das führt zu ganz seltsamen Verhaltensweisen und schwer zu findenden Fehlern.
              Eine Liste der reservierten Wörter usw. findest Du hier.
              Auch sollten Variablen und Funktionen oder deren Parameter niemals den gleichen Namen tragen.

              "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

              Proxmox 9.0.18 LXC|8 GB|Core i7-6700
              HmIP|ZigBee|Tasmota|Unifi
              Zabbix Certified Specialist
              Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

              1 Antwort Letzte Antwort
              5
              • CodierknechtC Online
                CodierknechtC Online
                Codierknecht
                Developer Most Active
                schrieb am zuletzt editiert von Codierknecht
                #8

                Falls / mache / sonst
                In den allermeisten Scripten muss zur Laufzeit mindestens eine Bedingung geprüft werden.
                Dabei wird oft nicht nur eine, sondern ggf. mehrere Bedingungen geprüft.

                cdf2362b-f424-40fd-a98e-fe09bcdebf27-image.png

                Tipp 1
                Wenn mehrere Bedingungen geprüft werden müssen, wird das Ganze oft übersichtlicher wenn man die Ansicht auf "externe Eingänge" umstellt:
                83e071e7-169d-4f11-a9dc-6c8fc3af2ec1-image.png 1da8653f-3cf6-4a2a-9f87-77eaf2a79311-image.png

                Tipp 2
                Kleiner Ausflug in bool'sche Algebra:
                Wenn eine Bedingung mit "falls" geprüft wird, muss der zu prüfende Ausdruck entweder "wahr" oder "falsch" werden. Heißt auf Deutsch: " Ist der Wert von "power" jetzt gößer als 500? Ja oder Nein?

                Das gleiche gilt hier aber auch für den zweiten Ausdruck: Ist "istEingeschaltet" jetzt "wahr" oder "falsch"?
                Der Punkt ist: "istEingeschaltet" ist ja bereits ein Wert, der entweder nur "wahr" oder "falsch" sein kann (Boolean). Das lässt sich jetzt also folgendermaßen vereinfachen:

                55941b92-c93c-41a2-8246-4ab6147aeb3b-image.png
                Falls auf falsch geprüft werden soll, ist dieser Ansatz hier der bessere:
                c604ff3d-08c4-4cb7-8e0d-2ce21af44f10-image.png
                Zum Einen benötigt man hier nur 2 statt 3 Bausteine und zum Anderen wird mit einem "nicht" der Code minimal schneller ausgeführt.

                Tipp 3
                Verschachtelte Ausdrücke werden schnell unübersichtlich.

                0a5c2973-813f-4723-846b-6a2b7c0c2d11-image.png
                Hier hilft es oft, wenn man einzelne Teilausdrücke vorher einer Variablen zuweist.

                6091e2a6-624a-4bd5-b8ef-105fd6e8c13a-image.png
                Wie bereits erwähnt: Code wird häufiger gelesen als geschrieben.
                Es erleichtert die Fehlersuche und die spätere Wartung, wenn Code gut lesbar ist.

                Tipp 4
                Es ist in den allermeisten Fällen nicht nötig, mehrere Prüfungen mit einzelnen "Falls"-Bausteinen auszuführen.
                Viel einfacher ist eine Logik nach dem Motto " Falls x" => "mache etwas" => "sonst" => ... mache etwas anderes.
                Dazu klickst Du auf das kleine blaue Zahnrad und ziehst den gewünschten Block nach rechts unter das "falls".
                3e6c4e64-2cc5-4d63-9944-c333147b8c67-image.png

                Tipp 5
                Noch komplexere Prüfungen? Dann ist vielleicht der folgende Baustein der richtige:
                d1037ead-630a-4ebd-9005-9148f739c7f7-image.png
                Das ist schneller und erspart einiges an "Puzzelei".

                Aber Achtung: Der Wert eines DP muss zunächst einer Variablen zugewiesen werden. Die Prüfung funktioniert nicht direkt mit dem "Wert vom Objekt"-Baustein!

                Und unbedingt darauf achten, dass hinter jedem "Im Falle von" ein Wert steht. Hier stehen keine logischen Ausdrücke!

                "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                Proxmox 9.0.18 LXC|8 GB|Core i7-6700
                HmIP|ZigBee|Tasmota|Unifi
                Zabbix Certified Specialist
                Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                1 Antwort Letzte Antwort
                6
                • CodierknechtC Online
                  CodierknechtC Online
                  Codierknecht
                  Developer Most Active
                  schrieb am zuletzt editiert von Codierknecht
                  #9

                  Verzögerungen (Timeouts)
                  Der Klassiker unter den Anforderungen in Richtung "timeout" ist der berühmte Bewegungsmelder, der bei erkannter Bewegung eine Lampe ein- und nach Ablauf einer gewissen Zeit ohne Bewegung wieder ausschalten soll.

                  71872411-fb02-493a-9903-9ba1c31a5635-image.png
                  Auch wenn es zunächst einfach und verlockend aussieht: Die Option "mit Verzögerung" funktioniert häufig nicht bzw. nicht so wie erwartet.

                  Als Alternative kann (und sollte) stattdessen ein "timeout" verwendet werden.

                  19794719-662a-4fc2-a165-98f76036d450-image.png
                  Hier hat man deutlich mehr Kontrolle über den Ablauf.
                  Zu beachten ist hier der Block "stop timeout". Der sorgt dafür, dass eine einmal angestoßene Verzögerung zum Ausschalten wieder abgebrochen wird, falls sich der Wert des Objektes (Bewegungsmelder) erneut ändert.

                  Im Beispiel passiert folgendes:

                  • Wird irgendwann erkannt, dass keine Bewegung im Erfassungsbereich mehr stattfindet, startet der Timeout. Der soll nach 10 Sekunden eine Lampe ausschalten.
                  • Sollte innerhalb der Zeitspanne erneut eine Bewegung erkannt werden, wird der Timeout gestoppt.
                  • Sobald dann wieder keine Bewegung stattfindet, startet der Timeout erneut.
                    Ändert sich der Zustand (keine Bewegung) nun 10 Sekunden lang nicht mehr, wird die Lampe tatsächlich ausgeschaltet.

                  Da diese Anforderung im Forum recht häufig nachgefragt wird, gibt es dieses Blockly hier ausnahmsweise auch als Vorlage:

                  <xml xmlns="https://developers.google.com/blockly/xml">
                   <variables>
                     <variable type="timeout" id="timeout">timeout</variable>
                   </variables>
                   <block type="on" id=":8z:j#EtCHumq|0zP3ur" x="62" y="162">
                     <field name="OID">ID auswählen</field>
                     <field name="CONDITION">ne</field>
                     <field name="ACK_CONDITION"></field>
                     <statement name="STATEMENT">
                       <block type="timeouts_cleartimeout" id="#ncMQn8c^$d4d:;hdT|U">
                         <field name="NAME">timeout</field>
                         <next>
                           <block type="controls_if" id="2eHpM$}U9iw%;iZT{ycO">
                             <value name="IF0">
                               <block type="logic_negate" id="nhHNSc=WeM/n7ZYh4FC]">
                                 <value name="BOOL">
                                   <block type="on_source" id="YwOprx|.Lx6;}C,O!ekF">
                                     <field name="ATTR">state.val</field>
                                   </block>
                                 </value>
                               </block>
                             </value>
                             <statement name="DO0">
                               <block type="timeouts_settimeout" id="Xc,`P9(!nMn5xvMs9)!0">
                                 <field name="NAME">timeout</field>
                                 <field name="DELAY">10</field>
                                 <field name="UNIT">sec</field>
                                 <statement name="STATEMENT">
                                   <block type="control" id=";t$xX#ZhJrENHq?Z:f}a">
                                     <mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
                                     <field name="OID">ID auswählen</field>
                                     <field name="WITH_DELAY">FALSE</field>
                                     <value name="VALUE">
                                       <block type="logic_boolean" id="[+*(OH`@QFCC7L.%PH63">
                                         <field name="BOOL">FALSE</field>
                                       </block>
                                     </value>
                                   </block>
                                 </statement>
                               </block>
                             </statement>
                           </block>
                         </next>
                       </block>
                     </statement>
                   </block>
                  </xml>
                  

                  "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                  Proxmox 9.0.18 LXC|8 GB|Core i7-6700
                  HmIP|ZigBee|Tasmota|Unifi
                  Zabbix Certified Specialist
                  Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                  1 Antwort Letzte Antwort
                  6
                  • CodierknechtC Online
                    CodierknechtC Online
                    Codierknecht
                    Developer Most Active
                    schrieb am zuletzt editiert von Codierknecht
                    #10

                    Schleifen

                    So etwas hier wird relativ häufig benötigt:
                    bccb6361-3f88-4892-89b5-ffc81913b268-image.png
                    Das kann eine Liste der Musikstile zum durch den MediaPlayer abgespielten Song, eine Liste von Genres zum gerade gezeigten Film oder ein anderes beliebiges "Array" sein.

                    519f96ee-826e-4ddb-b2d9-4d2fb31259a4-image.png
                    Hilfreich (im Sinne von "lesbar") ist es, den Inhalt des DP zunächst in eine sinnvoll benannte Variable einzulesen.
                    Damit hat man beim Lesen schon mal eine Idee, was da denn drinsteckt.
                    Und als Nächstes sollte man die "Laufvariable" umbenennen. Die heißt per Vorgabe standardmäßig "i". Hier solltest Du einen besseren, "sprechenderen" Namen vergeben.

                    Was man auf jeden Fall vermeiden sollte, wäre ein solches Konstrukt:
                    6c084c92-c618-49fe-adec-25571fc04500-image.png
                    Da innerhalb der Schleife der Wert von power nicht verändert und neu zugewiesen wird, hat man hier eine wunderbare Endlosschleife produziert.
                    Solche Endlosschleifen können ein System innerhalb kürzester Zeit in die Knie zwingen.
                    Dabei "stürzt" es nicht unbedingt ab. Es ist aber schnell dermaßen mit sich selbst beschäftigt, dass es auf keine Aktion mehr reagiert. Was dann letztendlich aufs Gleiche hinausläuft.

                    Achtung:
                    Schleifen mit "Wiederhole solange" oder "Wiederhole bis", in denen Datenpunkte gelesen oder geschrieben werden, sind ebenfalls Kandidaten für einen plötzlichen System-Suizid.
                    Wenn man hier nicht genau weiß was man da tut, hat man sich ganz schnell das System lahmgelegt.

                    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                    Proxmox 9.0.18 LXC|8 GB|Core i7-6700
                    HmIP|ZigBee|Tasmota|Unifi
                    Zabbix Certified Specialist
                    Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                    1 Antwort Letzte Antwort
                    5
                    • CodierknechtC Online
                      CodierknechtC Online
                      Codierknecht
                      Developer Most Active
                      schrieb am zuletzt editiert von Codierknecht
                      #11

                      Listen

                      Hier mal ein halbwegs sinnvolles "real life" Beispiel, was man z.B. mit Listen anstellen kann:

                      decc32ad-4229-4acb-ab78-85ebe1d73e15-image.png
                      Hier wird eine Liste dazu verwendet, die Tagesmitteltemperatur zu ermitteln.

                      Zunächst wird beim Start des Scriptes eine leere Liste erzeugt.

                      Der Zeitplan sorgt nun dafür, dass jede Minute die Temperatur aus einem Datenpunkt gelesen und am Anfang der Liste eingefügt wird.
                      Das "vorne anfügen" hat den Vorteil, dass Änderungen auch im Objektbaum ersichtlich sind.
                      Der ermittelte Mittelwert wird hier nur ausgegeben. Wie man das in einen DP schreibt, ist hier beschrieben.

                      Am Ende wird per Zeitplan um 23:59:30 Uhr die Liste wieder geleert, damit am nächsten Tag wieder mit komplett neuen Werten gerechnet werden kann.

                      Das Ganze stellt hier nur ganz rudimentär das grundsätzliche Verhalten dar.
                      Man kann das je nach den Anforderungen noch abwandeln/ergänzen:

                      • Man arbeitet nicht zyklisch per Zeitplan, sondern triggert auf das Temperatur-Objekt
                        073541b0-29d4-4132-b4c0-e3961fe8b937-image.png
                      • Man arbeitet mit einer festen Anzahl an Werten. Wurde die erreicht, wird die Liste geleert
                        aee1cbe5-0c60-4580-b337-271cee9d6c95-image.png

                      Hier ins Detail zu gehen, würde eindeutig zu weit gehen.
                      Bei besonderen Anforderungen wird Dir sicher im Forum weitergeholfen.

                      "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                      Proxmox 9.0.18 LXC|8 GB|Core i7-6700
                      HmIP|ZigBee|Tasmota|Unifi
                      Zabbix Certified Specialist
                      Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                      1 Antwort Letzte Antwort
                      18
                      • CodierknechtC Online
                        CodierknechtC Online
                        Codierknecht
                        Developer Most Active
                        schrieb am zuletzt editiert von Codierknecht
                        #12

                        Berechnungen ohne Blockly: Aliase

                        Nicht selten kann man sich viel Programmiererei sparen, wenn man stattdessen Aliase verwendet.
                        Damit werden vorhandene Datenpunkte quasi "gespiegelt" und unterhalb von alias.0 im Objektbaum angelegt.
                        Die Struktur denkt man sich - wie auch in 0_userdata.0 - selbst aus.

                        Der entscheidende Punkt um sich ein Blockly zu sparen: Man kann im Alias auch eine "Konvertierungsfunktion" angeben. Mit dieser wird dann der ursprüngliche Wert (meist von einem Adapter geliefert) mehr oder weniger umgewandelt.

                        Alias anlegen
                        Hier führen zwei Wege zum Ziel:

                        1. Anlegen "von Hand"
                          Hier wird - wie auch in 0_userdata.0 - der DP (und vorher ggf. die Ordnerstruktur) im Objektbaum angelegt.
                          a065dbcd-b9f7-400e-bec8-8b09c05dcc6d-grafik.png

                        2. Noch viel einfacher geht's, indem man mit der rechten Maustaste auf den "Original"-DP klickt und dort "Alias erstellen" wählt.
                          0aec3593-9b84-48fc-a76c-67c01a83c505-grafik.png

                        Im weiteren Verlauf wird Methode 2) beschrieben. Methode 1) funktioniert prinzipiell analog.

                        06dae673-95a8-4bf3-82da-37554088ad0a-grafik.png

                        • In "ID" wird die Objekt-ID unterhalb von alias.0 festgelegt. Hier kann (durch Punkte getrennt) auch eine sinnvolle Struktur und eine passende ID für den DP vergeben werden. Die resultierende ID wird dann oben gezeigt.
                        • In "Beschreibung" kann ein erklärender Text vergeben werden.
                        • In "Typ" wird der Typ (Zahl, Zeichenkette, Logikwert usw.) des Ziel-DP festgelegt.
                          Der muss nicht zwingend mit dem Typ des Original DP übereinstimmen und hängt von der Konvertierung ab.
                        • "Einheit" gibt eine Bezeichnung für die Einheit (m², °C, km/h) mit, die im Objektbaum mit angezeigt wird.
                          Die Einheit wird nur im Baum angezeigt und ist nicht Teil des Wertes!
                        • In der "Konvertierung" kann bei Bedarf der Eingangswert (mehr oder weniger umfangreich) umgerechnet werden.
                          Dabei steckt in der Variablen val immer der Eingangswert aus dem Original-DP.

                        Konvertierungsfunktionen
                        In der Konvertierung können übliche Berechnungen per JavaScript vorgenommen werden.
                        Das ist der Punkt, an dem man sich nicht selten ein komplettes Blockly sparen kann.

                        Hier mal eine (unvollständige) Liste mit oft verwendeten Konvertierungen:

                        1. Wert aus JSON extrahieren
                          JSON.parse(val).energy.power
                          JSON.parse(val).months[12].name
                        2. Impulse in m³ umrechnen (Gas- oder Wasserzähler)
                          val * 0.01
                        3. Windgeschwindigkeit von m/s in km/h umrechnen
                          val * 60 * 60 / 1000 oder auch val * 3.6
                        4. Gleitkommazahlen mit fester Anzahl Nachkommastellen
                          Math.trunc(val * 100) / 100 (2 Stellen)
                        5. Byte in Gigabyte
                          val / 1024 / 1024 / 1024
                        6. °C in °F
                          val * 9 / 5 + 32

                        Auf die gleiche Art können bei beschreibbaren Datenpunkten die umgewandelten Werte wieder in die Form verwandelt werden, die der Adapter erwartet. val repräsentiert hier den zuvor umgerechneten Wert, der im Alias steckt.
                        Beispiele:

                        1. km/h wieder in m/s umrechnen
                          val / 60 / 60 * 1000 oder val / 3.6
                        2. Knoten in km/h
                          val * 1.852
                        3. °F in °C
                          (val - 32) * 5 / 9

                        Es macht in der Regel keinen Sinn, nur die Schreibkonvertierung zu verwenden. Wenn beim Schreiben konvertiert wird, sollte der Wert vorher auch beim Lesen konvertiert werden.

                        .. to be continued

                        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                        Proxmox 9.0.18 LXC|8 GB|Core i7-6700
                        HmIP|ZigBee|Tasmota|Unifi
                        Zabbix Certified Specialist
                        Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                        1 Antwort Letzte Antwort
                        7
                        • CodierknechtC Online
                          CodierknechtC Online
                          Codierknecht
                          Developer Most Active
                          schrieb am zuletzt editiert von Codierknecht
                          #13

                          Zeitpläne:
                          Wie bereits erwähnt, funktioniert ein CRON (zumindest meiner Erfahrung nach) stabiler als Zeitpläne mit dem "Wizard".

                          Hier mal einige Beispiele:

                          Letzter Tag des Monats
                          051251c5-aa62-4cc0-a1cb-5aabcd0ffea0-image.png
                          Dieser Zeitplan wird um 20:45 Uhr ausgeführt. Allerdings nur zwischen dem 28. und dem 31. eines Monats, denn sonst könnte der nächste Tag niemals der 1. sein. Die Aktionen werden nur gestartet, wenn der nächste Tag der 1. ist und damit nur am letzten Tag eines Monats.

                          Erster XXXtag des Monats
                          6590796e-937a-4253-964b-86f6f912f0e5-image.png
                          Dieser Zeitplan wird an jedem Samstag um 20:15 Uhr ausgeführt. Die Aktionen werden aber nur gestartet, wenn das aktuelle Tagesdatum am oder vor dem 7. des Monats liegt und damit nur am ersten Samstag eines jeden Monats.

                          Jeden zweiten XXXtag
                          c7352f39-c6d8-48f5-b2c2-6c14bc4b8225-image.png
                          Dieser Zeitplan wird an jedem Sonntag um 20:15 Uhr ausgeführt. Die Aktionen werden aber nur gestartet, wenn die Kalenderwoche gerade ist und damit nur jede zweite Woche.

                          Jeden X-ten Tag
                          3c732eaf-3335-467a-96bf-59e0ebf42d7d-image.png
                          Dieser Zeitplan wird an jeden Tag um 05:30 Uhr ausgeführt. Die Aktionen werden aber nur gestartet, wenn ein Zähler ohne Rest durch 3 teilbar ist und damit nur jeden dritten Tag.
                          Dazu wird ein "Tageszähler" in einem eigenen Datenpunkt geführt. Dieser DP muss (unterhalb von 0_userdata.0) selbst angelegt werden!

                          "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                          Proxmox 9.0.18 LXC|8 GB|Core i7-6700
                          HmIP|ZigBee|Tasmota|Unifi
                          Zabbix Certified Specialist
                          Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                          1 Antwort Letzte Antwort
                          6
                          Antworten
                          • In einem neuen Thema antworten
                          Anmelden zum Antworten
                          • Älteste zuerst
                          • Neuste zuerst
                          • Meiste Stimmen


                          Support us

                          ioBroker
                          Community Adapters
                          Donate

                          443

                          Online

                          32.4k

                          Benutzer

                          81.4k

                          Themen

                          1.3m

                          Beiträge
                          Community
                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                          ioBroker Community 2014-2025
                          logo
                          • Anmelden

                          • Du hast noch kein Konto? Registrieren

                          • Anmelden oder registrieren, um zu suchen
                          • Erster Beitrag
                            Letzter Beitrag
                          0
                          • Home
                          • Aktuell
                          • Tags
                          • Ungelesen 0
                          • Kategorien
                          • Unreplied
                          • Beliebt
                          • GitHub
                          • Docu
                          • Hilfe