NodeJS Binding für Module

Begonnen von dominik, 02 Juni 2020, 00:38:26

Vorheriges Thema - Nächstes Thema

dominik

Hallo zusammen,

ich habe immer wieder die Herausforderung, dass ich bei Modulen, wie z.B. GOOGLECAST, BOSEST, o.ä. ziemlich viel selbst in Perl bauen muss da keine Libraries dazu existieren. Nun dachte ich mir, dass es generell Sinn machen könnte in FHEM auch NodeJS Module anzuflanschen. Somit kann man, sofern vorhanden, NodeJS Libraries nutzen und erspart sich damit Arbeit.

Folgendes habe ich daher mal testweise gebaut:
- NodeModule.pm Modul
- NodeJS Websocket Server
- NodeJS FHEM Interface
- NodeJS FHEM Modul

Funktionsweise:
Das NodeModule.pm schickt beim Define, ... immer eine Message inkl. Parameter per Websocket an den NodeJS Server. Dieser lädt das notwendige NodeJS FHEM Modul und verarbeitet die Message und schickt per Websocket den Return-Wert zurück. Im NodeJS Teil kann man dann auch readingsSingleUpdate (aktuell nur das, andere Funktionen will ich noch implementieren) aufrufen. Dazu schickt das NodeJS FHEM Modul per FHEM Interface den Befehl wieder an NodeModule.pm wo es per eval ausgeführt wird.
Aktuell baue ich nur beim Define, ... eine Websocket Verbindung auf. Befehle die danach (Events vom Device) an FHEM geschickt werden, sende ich zur Zeit direkt per FHEMWEB.

Testweise habe ich mal ein GOOGLECAST Modul mit Play/Status auf Basis von NodeJS Chromecast-API gebaut. Mit wenigen Zeilen Code klappt das bereits :)
Das Define sieht dann so aus:
define testcast NodeModule googlecast Wohnzimmer
googlecast ist das NodeJS Modul welches dann dynamisch geladen wird wenn ein Define erfolgt und danach die restlichen Parameter wie gewohnt.

Ob mein Weg der Implementierung der beste ist, kann ich nicht sagen, ich habe lange recherchiert und leider keine bessere Lösung gefunden. Wenn jemand Ideen hat wie man das besser umzusetzen kann, gerne melden. Was meint ihr?


Hier der Code vom Test googlecast NodeJS Modul, damit man sich etwas vorstellen kann. Den restlichen Code muss ich noch aufräumen bevor ich es zur Verfügung stelle.
#!/usr/bin/env node

'use strict';

const fhem = require("./fhem");
const ChromecastAPI = require('chromecast-api')
const client = new ChromecastAPI()

function googlecast() {
}

googlecast.prototype.Define = async function (hash, args, argsh) {
  this._device = {};

  client.on('device', async function (device) {
    await fhem.readingsSingleUpdate(hash, device.friendlyName, "online", 1);

    if (device.friendlyName === "NestHubMax") {
      this._device = device;
    }

    device.on('status', async function (status) {
      await fhem.readingsSingleUpdate(hash, "status-" + device.friendlyName, JSON.stringify(status), 1);
    });
  }.bind(this));
}

googlecast.prototype.Set = async function (hash, args, argsh) {
  if (args.length < 2 || args[1] === "?") {
    return "Unknown argument ?, choose one of play:noArg";
  } else if (args[1] === "play") {
    this._device.play("https://www.youtube.com/watch?v=RacxNskxySo");
  }
}

module.exports = googlecast;
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik