Fronthem - Eine FHEM-Schnittstelle für Frontends

Begonnen von Tropaion, 22 September 2014, 17:44:56

Vorheriges Thema - Nächstes Thema

herrmannj

Hi Norbert,

Zitathat es einen besonderen Grund, warum du die 'webif-data'-requests aus smartVisuEditor.js über die get-methode abwickelst und nicht über den sowieso zur Verfügung stehenden Websocket?
ja klar, Kapselung und Single-Responsibility-Prinzip. Der Editor ist Aufgabe in fhem web und sollte komplett darüber erfüllbar sein.
ZitatWas hälst Du davon an dem Modul zu kooperieren
Ja klar! Super gern! Das passt auch gerade wie arsch auf eimer (sorry), ich habe kommende Woche endlich wieder coding Zeit und milestone 1 (also items) ist schon lange überfällig.

Wir müssen uns aber auf eine gemeinsame Strategie einigen. Die Architektur ist ja in eine bestimmte Richtung angelegt. Ich würde Dir gern morgen mal zusammenschreiben wie (stand jetzt) der Plan ist. Ich erwarte natürlich nicht das Du Dich dann da drauf stürzt und anfängst die AP abzuarbeiten. Schau es Dir bitte mal an, schau wo Du evtl Einwände hast (die lass uns besprechen) und was Du mitträgst. Dann (nur so) können wir effizient arbeitsteilig in die gleiche Richtung arbeiten.

Passt das für Dich ?

vg
jörg

ntruchsess

while (!asleep()) {sheep++};

herrmannj

Hi,

na denn.

geplanter (erster) Milestone ist das items bedient werden. "Von unten", also dem smartVisu Modul kommen ja dazu schon die "monitor" und die "item" auf das individuelle svDevice. Events von fhem kommen über die notify fn in das individuelle  svDevice. In beiden Fällen hast Du die Strukturen im code vmtl. schon erkkannt.

Geplant und in Teilen vorbereitet (fhem -> sv):
* in der notifyfn (vom svDevce) kommen device:reading an.
* die globale config ist so angelegt das die Struktur von device:reading auf @gad (liste weil durchaus geläufig das ein reading mehrere GAD bedient) in einen hash gelegt werden. Der hash gilt für alle svDevice und wird von smartVisu.pm verwaltet.

Wenn also ein event in fhem erzeugt wird prüft svDevice anhand @gad = $hash -> {device} -> {reading} ob (global) die Kombi device:reading für sv gebraucht wird. Wenn ja dann wird @gad gegen die aktuelle Monitorlist geprüft (also: wird das gad jetzt gerade benötigt / dargestellt).

Wenn ja wird das einzelne Gad aus der gadlist gegen die Berechtigungen geprüft.

Reihenfolge gesamt also: 1. kenne ich es, 2. benötige ich es aktuell, 3. Ich darf lesen||schreiben.

4.Wenn ja kommt der "converter" (siehst ja schon im editor). Prinzip converter: eine Menge perl sub mit definierten Aufruf und return.
Beispiel "on/off". Die perl sub (name vielleicht svcOnOff) bekommt das "on" von "oben" rein und schickt "1" raus. Das geht dann per "item" / Gad an smartVisu.pm (weil das die Verbindung verwaltet) und das schickt es an das Frontend. Die converter stelle ich mir so vor das der user den converter Namen in den Editor eingibt. Prinzip excel funktionen; die muss man wissen oder eben nachschlagen, je nach dem was ich von wo nach wo konvertieren möchte.

Die mitgelieferter Standard - converter sollen in einer *.pm liegen und von smartVisu.pm beim start eingebunden werden (und im Umfang je nach Bedarf wachsen). Außerdem hat der user die Möglichkeit, zB für homebrew device, sich bei Bedarf converter in die 99_myUtils zu schreiben. Dazu müssen nur das Naming und der Aufruf standardisiert sein, die eigentliche Konvertierung dürften in der Mehrzahl der Fälle Einzeiler sein. Das habe ich jetzt etwas vereinfacht beschrieben, tatsächlich muss der converter natürlich device, reading und einige andere parameter mit übergeben bekommen um spzialfälle handeln zu können.

Die Spezialfälle werden eintreten, ein Beispiel welches mir jetzt schon klar ist, sind zum Beispiel RGB Device. In Richtung sv->fhem ist das so gelöst das jeder Channel ein eigenes GAD ist. Wenn man jetzt ein widget hat wo zum Beispiel 3 einzelne slider (rgb) sind dann ist das auch ok. Bei Farbwahlfelder oder dem Farbrad ist das jedoch doof weil die Lampen dann flackern (weil erst r, dann g dann b nacheinander gesetzt werden).

Für rgb device werden drei converter (einer pro channel) benötigt und sowohl r und g müssten sinnvollerweise puffern während b dann den Wert zusammensetzt und auf das device bringt. Dazu muss der den context kennen (also die beiden anderen zugehörigen converter). Ebenfalls keine Raketenwissenschaft aber Erklärung der "weiteren Paramter" die eben eingeplant sein müssen.

Der genrelle Weg sv-> fhem sogar noch einfacher: "monitor" setzt die gleichnamige Liste (im svDevice. is ja schon drin), im Anschluss müssen die einzelnen GADs der List noch ein mal initial (Schritt 4 oben) ausgelöst werden. Wenn das sv Frontend Aktionen per item auslöst: converter und dann den (editor) set Befehl.

Ich glaube der post ist jetzt schon länger als der code den er beschreibt, mir gehts darum möglichst viel zum geplanten funktionsverständniß beitragen zu können.

An diesem Punkt wäre dann milestone 1 erreicht, fhem erkennt und verwaltet unterschiedliche svdevice und kann sie beliefern bzw führt die Aktionen aus.

Das smartVisu frontend erkennt unterschiedliche device allerdings noch nicht, dort muss man manuell das entsprechende Unterverzeichnisse ansurfen. Diese Unterscheidung soll jedoch stattfinden. Außerdem fehlt Verschlüsselung und client certifiakte. In smartVisu.pm ist das vorbereitet. "startWSServer" muss einmal dupliziert werden nach "startWWSServer", genauso einfach wie Du das für TCPUtils beschrieben hast wird dort ein ssl sock gestartet und mit den certifiakten versorgt. Ursprünglich habe ich mal darüber nachgedacht die Zertifikate dann auf den sv host zu kopieren und dort den entsprechenden Server (Apache, nginx whatever) zu konfigurieren und in die index.php eine Weiche (für das client certifikat einzubauen). Allerdings halte ich es für sehr erstrebenswert an smartVisu möglichst wenig (nichts) zu ändern. SmartVisu wird von einem eigenen Team weiterentwickelt mit denen ich nichts zu tun habe, die haben eine eigene Roadmap und jede eigene Änderung an sv ist riskant weil man nie weiß ob die nach evtl. Updates noch funktioniert. Man müsste außerdem dann neu patchen, testen etc. Kurz: doof.

Ich denke das ich ein viel besseres System (sowohl für den user, Einfachkeit der Bedienung, als auch im Hinblick auf sv updates) gefunden habe: smartVisu.pm bekommt einen einfachen reverse proxy (tls, die Zertifikate hat fhem ja sowieso). Der muss ja nix tun als einen Port aufzumachen, die Verbungen nach per accept zu bedienen, das cert des clients zu prüfen, (entschlüsseln macht der sock selber) und dann seinerseits vom svhost die Daten per hhtprequest aus dem richtigen Verzeichniss zu holen). Verständlich ? Damit entfällt alles patchen, das Zertifikat braucht nicht doppelt vorgehalten werden etc, und die lines auf code sind auch nicht mehr gegenüber dem patchen der index.php mit weiche usw. (da müsste der client test etc ja genauso implementiert werden)

Zu diesem Zeitpunkt wäre dann die Sicherheit auch nach aktuellen Fachstand gewährleistet. Der client validiert den host (per cert). Die Verbindung ist Verschlüsselt. Der client wird per cert identifiziert. Für Zugriff benötigt man Besitz (mobile mit cert) und Wissen (pin des mobile).

Danach würde dann die Integration von Dirks webViewControl sowei plots und log dransein.

Einwände, Ideen, Anmerkungen, Befürchtungen ?

vg
Jörg

Tropaion

@herrmannj

Wäre die Reihenfolge nicht besser?
1. Ich darf lesen||schreiben.
2. Kenne ich es
3. Benötige ich es aktuell

Weil wenn er eh nicht lesen||schreiben darf, verwirken ja dann 2&3 und man "spart" sich die Schritte, oder liege ich falsch?

herrmannj

Hi,

Die Reihenfolge ergibt sich aus den notwendigen Schritten um aus device Reading das Gad zu identifizieren.

Vg
Jörg

bgewehr

Hallo, Jörg,

kannst Du etwas zu den Voraussetzungen der aktuellen Installation sagen?

Ich habe mit

cpan
force install warnings
install socket
install Fcntl
install POSIX
install Net::WebSocket::Server
install IO::Socket
install IO::Select
install JSON
exit


nachhelfen müssen, um den define erfolgreich durchzuführen.

Force install warnings war ein ziemliches Frage-Antwort-Spiel. Ich habe einfach alle defaults übernommen.

Fehlt sonst noch etwas? Ist z. B. Perl 5.20 Pflicht?

Gruß, Bernd
FritzBox 7590, Synology DS216+II mit Docker
Docker: FHEM mit hmlan, Homebridge, node-red, mosquitto, ems-collector für Buderus EMS mit AVR Net-IO
Gartenwasser über MQTT auf R/Pi A+
Volkszaehler.org auf R/Pi 2B mit Pi_Erweiterung
Raspberrymatic auf R/Pi 4B mit RPI-RF-MOD u. CUL868

herrmannj

Hi,

eigentlich fällt mir nur  Net::WebSocket::Server und JSON ein.

da ich keine smartmatch mehr verwende sollte die perl version unkritisch sein. Aus user (nicht dev) Sicht siehst Du noch nicht viel. Die Autobahn sieht schon gut aus, in der Mitte fehlt noch eine Brücke  ;)

vg
jörg

ntruchsess

#187
Hallo Jörg,

Danke, das habe ich mir so im Großen und Ganzen schon so aus Deinem code zusammengereimt.

Mal meine Gedanken dazu (bitte nicht als falsche Kritik verstehen, ich betrachte das halt in einem etwas größeren Kontext)

Um eine Insellösung zu vermeiden sollte man die Themen Berechtigungsprüfung, Mapping und Konvertierung unabhängig von SmartVisu als generischen Mechanismus relativ nahe am FHEM-kern implementieren. Wenn es richtig gemacht ist, könnte man den eventMap-mechanismus endlich mal durch was vernünftiges ersetzen. Da hätte auch FHEMWeb oder das MQTT-modul etwas davon und die Benutzer müssen nicht für jede Schnittstelle bzw. Frontend eine neue Lösung lernen. Spricht ja nichts dagegen, wenn das smartVisu-device für jedes GAD-device ein- oder mehrere Readings hätte, die so gemappt wären, dass sie die von den items erwarteten Werte enthalten. Das mapping von smartVisu-reading auf item wäre dann 1<->1 (und müsste bei passender Namenskonvention gar nicht weiter konfiguriert werden).

Das gleiche gilt für die Berechtigungsprüfung. Wenn man nur ein Frontend so absichert wird sich die überwiegende Mehrheit der User in Scheinsicherheit wiegen (weil das FHEMWeb-frontend und telnet per default laufen und nur rudimentär geschützt sind).
Wg. der Client-Zertificate: Da würde ich keine Arbeit reinstecken. Die meisten Benutzer werden das gar nicht einrichten wollen (oder auch können). Abgesehen davon ist das auf einem Enduser-gerät auch nur dann sicher, wenn das Zertifikat auch durch ein (weiteres) Passwort geschützt ist. (Und dann gehört das auch in den FHEM-kern - sonst ist sicherheitstechnisch nix gewonnen wenn die anderen Kanäle nicht genauso abgesichert sind). Eigentlich ist das nur was für Maschine<->Maschine Kommunikation (und auch da ist es prinzipiell auch nur dann sicherer als normales SSLv2 mit sicher abgelegten Credentials, wenn man beide Seiten validieren läßt, ob sie tatsächlich mit dem erwarteten Gegenüber verbunden sind, oder wenn man keine anderen trusted-root-Zertifikate als das eigene erlaubt).

Wenn man das so generisch lösen würde, wäre das eigentliche SmartVisu-modul sehr schlank. Als Nebeneffekt könnte man auch viel besser zusammenarbeiten: wenn man die zueinander orthogonalen Aspekte modular getrennt implementiert muss man sich nur einigen, wer was angeht und kommt sich dabei kaum in die Quere.

- Norbert
while (!asleep()) {sheep++};

herrmannj

Hi,

ne, Danke, alles gut, seh ich nicht als Kritik  :) Ich biete ja gar keine Diskussion an wenn ich sie nicht will  ;)

ZitatUm eine Insellösung zu vermeiden sollte man die Themen Berechtigungsprüfung, Mapping und Konvertierung unabhängig von SmartVisu als generischen Mechanismus relativ nahe am FHEM-kern implementieren
Ja das wäre wünschenswert. Aber Ziele müssen realistisch sein. Ich sehe nicht das sich da eine Mehrheit, geschweige denn Umsetzung, findet. Die Eingriffe in den core wären gigantisch.
ZitatSpricht ja nichts dagegen, wenn das smartVisu-device für jedes GAD-device ein- oder mehrere Readings hätte, die so gemappt wären, dass sie die von den items erwarteten Werte enthalten.
Das verstehe ich nicht wie Du das meinst. Das mapping passiert doch, wozu die readings ?
ZitatWenn man nur ein Frontend so absichert wird sich die überwiegende Mehrheit der User in Scheinsicherheit wiegen.
Ne, das lass ich so nicht gelten. Der Umkehrschluss lautet ja fhemweb ist nicht abgesichert, also lass ich das bei anderen Implementierungen auch weg. Richtig sollte sein: smartVisu wird fachlich korrekt gesichert. Ich verantworte den smartVisu Treiber, nicht fhemweb. Ob man dann fhemweb über das Netz zugänglich  macht oder nicht darf (und muss) jeder selbst entscheiden, jeder für sich.
ZitatClient-Zertificate: ... Die meisten Benutzer werden das gar nicht einrichten wollen (oder auch können).
Lass Dich überraschen, alle aktuellen Device/browser haben den support dafür alle eingebaut. Das ist viel einfacher als Du denkst. Das cert wird über das interface des svDevice erstellt, der browser fragt Dich ob er das importieren soll (die haben ein Art safe dafür drin) fertig  ;)

Sag nochmal bitte welche Zuständigkeiten und Verantwortungen Du in welchem Modul (oder Teil) siehst, vielleicht verstehe ich Dich dann besser. Ich habe noch nicht verstanden welche Änderungen Du konkret vorschlägst. (sorry, my fault)

vg
Jörg

herrmannj

Hi Norbert,

post#2,

Wahrscheinlich ist es hilfreich nochmal genau zu spezifizieren was wir "noch alles" damit bedienen wollen.

Also, reden wir über hypothetische, zukünftige Frontends ? Wer genau soll auf den websocket noch zugreifen ? Welche Daten würden benötigt ?

vg
Jörg

ntruchsess

Das mit den Readings meine ich so: basierend auf der Mapping und Konvertierungskonfiguration sollen in einem (konfigurierbaren) Device (bidirektional) Readings erzeugt bzw. aktualisiert werden. Das Reading kann dann z.B. so wie das SmartVisu-item heißen (ggf. auch mit einem Präfix). Der Wert des Readings kann dann vom SmartVisu-treiber ohne weitere Umwandlung direkt an das item geschickt werden. Durch die Abbildung auf Readings wären die Mapping und Konvertierungsfunktionen aber auch für andere Frontends und/oder Devices nutzbar, das wäre dann sowas wie ein deutlich leistungsfähigeres readingsProxy oder readingsGroup-device. Der Mehraufwand bei der Implementierung gegenüber einer in den smartVisu-treiber integrierten Lösung wäre sehr gering, der Nutzen durch die mögliche Wiederverwendbarkeit hoch.

Beim Zugriff auf Websocket denke ich nicht nur an reine Frontends. Es gibt da z.B. auch leistungsfähige Middleware auf Node.js (z.B. NodeRed). Natürlich würde das FHEM in die Nähe eines reinen Hardwaretreibers rücken - für Leute, die schon mit einer anderen Lösung arbeiten und nur ein paar (in FHEM verfügbare) Devices integrieren wollen, würde das aber Sinn machen.

Und wegen der Security und 'im Core' - da stelle ich mir jetzt nicht vor, dass plötzlich alles irgendwie hart abgesichert sein soll (da fehlen Perl selbst die notwendigen Funktionen für), wenn die Frage 'darf jemand und wenn ja, auf welchem Level (lesend/schreibend/konfigurierend) auf ein Device oder Reading zugreifen' aber übergreifend über eine (von Frontends und remote-schnittstellen) nutzbare API überhaupt erst mal abfragbar wäre, dann könnte man so eine Prüfung leicht in weitere relevante Module einbauen auch ohne dass dafür zwingend der SmartVisu-trieber laufen müsste.
while (!asleep()) {sheep++};

herrmannj

#191
Wahrscheinlich liegst an mir, aber so richtig schlauer bin ich jetzt nicht.  ;)

Die Funktionalität, so wie du sie beschreibst, ist ja im großen und ganzen so wie sie auch geplant ist. Das readingsproxy device das du beschreibst ist doch das svdevice ?

Ich denke die Schwierigkeit besteht darin jetzt da irgendwelche hypothetischen Frontend gedanklich reinzumischen deren Anforderungen ja eigentlich gar keiner kennt oder benennen kann. Das ist doch wie bei jedem anderen fhem device auch, wenn ich homematic bedienen will muss ich mir anschauen was brauch ich, was wird geliefert, wie verbinde ich das sinnvoll. Jetzt irgendwie zu versuchen ein fhem device zu bauen um dann alle zukünftigen rf Schalter zu bedienen wird nicht funktionieren.

Zu den hypothetischen Frontend mal ganz klar, was spricht denn dagegen das die, wenn der Autor das wünscht (!), sich über die vs. Schnittstelle bedienen ? Da kommt doch alles raus was man braucht ? Und wenn dann im konkreten Fall was fehlt bin ich gerne bereit das dann einzubauen wenn es passt. Die Schnittstelle abstrahiert doch sowieso ...

Das gilt doch genauso für middleware. Die Schnittstelle bedient kein Design, nur Funktion. Ich kann dir aus dem Stegreif einen Schalter für die Wand da ransetzen. Der (hypothetische) wifi Schalter öffnet die Verbindung, sendet "Monitor" mit seinem Namen, das Modul schickt den Status zurück, der Schalter aktiviert seine led und heureka, es läuft. Alles ohne auch nur eine Zeile Code ändern zu müssen.

Wird vielleicht so ein Schuh draus ?

Vg
Jörg

ntruchsess

na, Funktionell will ich im Großen und Ganzen schon in etwa auf das Gleiche raus. Nur so wie Du es planst und implementierst scheint es mir eher monolithisch als modular zu werden. Ein FHEM-modul, das ausschließlich über WebSocket-schnittstelle nutzbar ist, ist dann halt auch genau dafür gut. Wenn es dabei losgelöst von der Websocket-Schnittstelle einige (im Kontext FHEM) neue Konzepte implementiert, die aber innerhalb von FHEM nicht (bzw. nicht über saubere und dafür gedachte Interfaces) von anderen Modulen nutzbar sind, dann ist das halt monolithisch. Da habe ich auch keinen Schmerz damit, wenn Du das so implementieren willst, das wird schon funktionieren. Ich hätte Dir halt angeboten, Dich bei einer möglichen Modularisierung zu unterstützen.

Gruß,

Norbert
while (!asleep()) {sheep++};

bgewehr

Hallo, Jörg,

ich habe jetzt die Voraussetzungen für das

define Test smartVisu

alle geschaffen, bekomme aber dennoch - ohne irgendein debug-output -

Cannot load module smartVisu

Kann's an der define syntax liegen? Ich werde da aus dem Code noch nicht sooo schlau.

Gruß, Bernd
FritzBox 7590, Synology DS216+II mit Docker
Docker: FHEM mit hmlan, Homebridge, node-red, mosquitto, ems-collector für Buderus EMS mit AVR Net-IO
Gartenwasser über MQTT auf R/Pi A+
Volkszaehler.org auf R/Pi 2B mit Pi_Erweiterung
Raspberrymatic auf R/Pi 4B mit RPI-RF-MOD u. CUL868

herrmannj

Hi,

Die ist ja noch nicht gar, aber schau mal ins Log .

Denke mal die config fehlt

Vg
Jörg