NEWS
Modulare Skripe
-
@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
-
@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)?
-
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 generierenIch ü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 -
@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 */);
-
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
-
@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("...")).
-
@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.
-
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.
-
@zerraxys Bedeutet das dann aber nicht, dass der loadCache in jeden Skript einzeln gefüllt wird?
-
@Nahasapee Vielen Dank, ich schaue mir das mal genauer an und poste dann hier meine Erkenntnisse und was ich daraus gemacht habe.
-
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 einemconst 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!
- Verzeichnis
-
@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.