Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Modulare Skripe

    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

    Modulare Skripe

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

      Hallo alle!

      Meine Skriptsammlung ist mittlerweile recht groß und ich würde sie gerne in Modulen verwalten. Ein Modul soll hierbei folgendes können

      • Persistenten Zustand haben (zumindest bis zum Adapter-Neustart)
      • Interne Datenstrukturen kapseln und vor dem "Nutzer" verstecken
      • Nur bestimmte Funktionalität für andere Module und Skripte anbieten
      • Eigene subscriptions/schedules für die interne Funktionalität haben

      Ein Modul sieht bei mir so aus:

      const someModule = function() {
        const internaldata1 = {
        };
        
        // ...
      
        doSomeFancyInitialization();
        on("x", ...)
        on("x", ...)
      
        // ...
      
        return {
          function1() {
          },
          function2() {
          }
        }
      }();
      

      Nun habe ich die Möglichkeit, dieses Modul entweder Global oder als normales Skript zu speichern und beides ist mit Problemen behaftet:

      • Als normales Skript sind someModule.function1 und someModule.function2 nicht von anderen Skripten erreichbar
      • Als globales Skript hat jedes normale Skript eine eigene Instanz des Moduls (Code wird einfach "davor" gehangen) und ich habe keinen zentralen State

      Folgendes kam mir in den Sinn, ich hätte hier aber gerne die Meinung der Experten:

      • Alle internen Daten als Datenpunkte speichern und alle Modulinstanzen subscriben sich darauf um ihren internen Zustand synchron zu halten
        • Bekommt man dann alles synchron? Ich könnte mir vorstellen dass das eine komplexe Aufgabe ist
      • Alle Module als echte node-Module direkt in node_modules speichern
        • Kann ich dann aus meinen Modulen heraus die ioBroker-Funktionen getState etc. nutzen?

      Für Input bin ich sehr dankbar!

      paul53 AlCalzone 2 Replies Last reply Reply Quote 0
      • paul53
        paul53 @azamir last edited by paul53

        @azamir sagte in Modulare Skripe:

        Kann ich dann aus meinen Modulen heraus die ioBroker-Funktionen getState etc. nutzen?

        Nein, habe es gerade getestet mit folgendem Modul test.js:

        'use strict';
        module.exports = function (id) {
           return getState(id);
        };
        

        mit diesem Aufruf

        const test = require('../../../iobroker-data/modules/test.js');
        
        log(test('javascript.1.test.array1'));
        

        erhalte ich folgende Fehlermeldungen:

        javascript.1	2019-12-21 19:50:19.705	error	(6331) at module.exports (/opt/iobroker/iobroker-data/modules/test.js:3:4)
        javascript.1	2019-12-21 19:50:19.705	error	(6331) ReferenceError: getState is not defined
        
        A 1 Reply Last reply Reply Quote 0
        • A
          azamir @paul53 last edited by

          @paul53 Vielen Dank für den schnellen Test. Ich habe selber noch keine Node-Module geschrieben. Hätte ich gewusst dass das so einfach ist, hätte ich es auch selber tun können 😊 Sorry

          Vielleicht wird getState ja von irgendeinem Modul zur Verfügung gestellt, das man wiederum in seinem Modul per require einbinden muss (und hoffentlich kann)?

          1 Reply Last reply Reply Quote 0
          • N
            Nahasapee last edited by

            Hi, also
            was du hier vor hast habe ich in meinen telegram npm paket indirekt eigentlich umgesetzt,
            das nutze ich um dynamisch Menüs in Telegram zu generieren

            Ich übergebe im JavaScript -Adapter in einem initialen javascript einfach an meinem NPM Paket die JavaScript Instanz
            und habe dann im Modul vollen Zugriff auf alle iobroker funktionen
            Um das jetzt der korrekte weg ist kann ich dir aber nicht sagen.
            wie ich das umgesetzt habe kannst du hier schauen :

            https://github.com/Nahasapeemapetilon/MyTelegramMenu
            viele grüße

            A 1 Reply Last reply Reply Quote 0
            • AlCalzone
              AlCalzone Developer @azamir last edited by

              @azamir sagte in Modulare Skripe:

              Kann ich dann aus meinen Modulen heraus die ioBroker-Funktionen getState etc. nutzen?

              Nur wenn du deine Module jeweils in eine Funktion kapselst, der du diese Funktionen beim Laden übergibst, etwa so:

              // modul.js
              module.exports = function(getState, ... /* weitere benötigte Funktionen */) {
                // hier der Modul-Code
              }
              
              // skript.js
              const modul = require("../pfad/zum/modul.js")(getState, ... /* weitere benötigte Funktionen */);
              
              1 Reply Last reply Reply Quote 0
              • Homoran
                Homoran Global Moderator Administrators last edited by

                Ich möchte den Thread nicht kapern, wollte selber einen solchen eröffnen.
                Habe vom scripten leider viel zu wenig Ahnung und wollte für die Nutzung von tts via sonos ein "Modul" schreiben, dem man irgendwie bei anderen Aufrufen einige Parameter übergeben kann.
                Deswegen habe ich die Variablen verwendet.

                https://github.com/Homoran/iobroker.sonos_api#beispiel-fenster-offen-meldung

                Der untere Teil mit der Übergabe an die Sonos api sollte ein "Modul" werden.

                Wie kann man so etwas verwenden

                • "Modul" sichern
                • Werte durch ein anderes Skript übergeben und das Modul aufrufen
                AlCalzone 1 Reply Last reply Reply Quote 0
                • AlCalzone
                  AlCalzone Developer @Homoran last edited by

                  @Homoran sagte in Modulare Skripe:

                  Werte durch ein anderes Skript übergeben und das Modul aufrufen

                  Die Essenz steht direkt über deinem Post 😉 Der Trick liegt im Export einer Funktion sowie dem Aufrufen dieser Funktion beim Laden (Klammern hinter require("...")).

                  Homoran 1 Reply Last reply Reply Quote 0
                  • Homoran
                    Homoran Global Moderator Administrators @AlCalzone last edited by

                    @AlCalzone sagte in Modulare Skripe:

                    Die Essenz steht direkt über deinem Post

                    Hab ich fast befürchtet 😢

                    Dabrauche ich aber noch Jahrzehnte bis ich das verstehe - ich werde mich bemühen.

                    1 Reply Last reply Reply Quote 0
                    • Z
                      zerraxys last edited by

                      Ich stehe vor dem selben Problem und experimentiere gerade mit einer Lösung über eval (ich weiß, das ist eigentlich evil). Als globale Funktion habe ich ein load Skript, dass wir folgt aussieht

                      const loadCache = {};
                      function load (filename) {
                          if (!loadCache[filename]) {
                              const path = require("path");
                              const fs = require("fs");
                      
                              const fn = path.resolve("opt", "iobroker", "iobroker-scripts", "scripts", "Modules", filename) + ".js";
                              const source = fs.readFileSync(fn, "utf8");
                      
                              var module = {};
                              eval(source);
                              loadCache[filename] = module.exports;
                          }
                      
                          return loadCache[filename];
                      };
                      
                      

                      In meinen Skripten kann ich miit einem einfachen

                      var meinModul = load("mein_modul");
                      

                      die Datei /opt/iobroker/iobroker-scripts/scripts/Modules/mein_modul.js laden und deren "module.exports"-Wert bekommen. Offene Ideen sind im Moment noch:

                      • Das globale require überladen, damit es natürlicher aussieht
                      • Den Pfad irgendwie zur Laufzeit bestimmen, damit er nicht hart eingebrannt ist

                      Aber zumindest läuft es erstmal und ich kann anfangen, etwas Ordnung zu schaffen.

                      A 1 Reply Last reply Reply Quote 0
                      • A
                        azamir @zerraxys last edited by

                        @zerraxys Bedeutet das dann aber nicht, dass der loadCache in jeden Skript einzeln gefüllt wird?

                        Z 1 Reply Last reply Reply Quote 0
                        • A
                          azamir @Nahasapee last edited by

                          @Nahasapee Vielen Dank, ich schaue mir das mal genauer an und poste dann hier meine Erkenntnisse und was ich daraus gemacht habe.

                          1 Reply Last reply Reply Quote 0
                          • A
                            azamir last edited by

                            Ich habe ein bisschen rumprobiert und folgendes getan:

                            • Verzeichnis /opt/iobroker/node_modules/ioBroker.javascript/node_modules/mymodules angelegt
                            • npm init darin ausgeführt
                            • Folgendes in die index.js geschrieben
                            let modules = {};
                            let instance = null;
                            let initialized = null;
                            
                            // above only boilerplate code
                            
                            modules.inspect = function() {
                                    return {
                                            initialized() {
                                                    return initialized;
                                            },
                                            instance() {
                                                    return instance;
                                            }
                                    }
                            }()
                            
                            // below only boilerplate code
                            
                            module.exports = function(js_instance) {
                                    if (!instance) {
                                            console.log("Initializing modules");
                                            initialized = new Date();
                                            instance = js_instance;
                                    }
                                    return modules;
                            }
                            
                            • mymodules in der Adapterkonfiguration zu den benötigten Modulen hinzugefügt
                            • Um zu prüfen, ob meine Datenstrukturen auch wirklich nur einmal initialisiert werden, habe ich zwei identische Skripte mit folgendem Inhalt angelegt:
                            const mymodules = require('mymodules')(this);
                            console.log(mymodules.inspect.initialized());
                            

                            Beide Skripte geben den gleichen Zeitstempel aus, wodurch ich davon ausgehe dass die Initialisierung tatsächlich nur einmal stattgefunden hat. Ich kann nun (und man möge mich bitte korrigieren wenn ich einen Denkfehler gemacht habe!) an beliebigen Stellen in meinen Skripten - vorzugsweise am Anfang wo this noch ganz eindeutig definiert ist - mit einem

                            const mymodules = require('mymodules')(this);
                            

                            auf meine Module zugreifen

                            Nächste Schritte:

                            • Module selber auch wieder per require in das "Obermodul" einbinden
                            • Irgendwie so hosten, dass ich bequeme Versionsverwaltung habe aber es trotzdem nicht öffentlich machen muss (Hat jemand eine Idee?)

                            Danke für eure guten Ideen und ich bin immer offen für Verbesserungsvorschläge!

                            1 Reply Last reply Reply Quote 0
                            • Z
                              zerraxys @azamir last edited by

                              @azamir Ja, ich denke das ist der Fall. Aber Skripte laufen doch auch so unabhängig voneinander. Ich wüsste nicht, wie man Daten zwischen denen teilen kann.

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

                              Support us

                              ioBroker
                              Community Adapters
                              Donate

                              941
                              Online

                              31.9k
                              Users

                              80.1k
                              Topics

                              1.3m
                              Posts

                              javascript
                              6
                              13
                              1698
                              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