DevelopmentReadingsAPI

Aus FHEMWiki
Wechseln zu: Navigation, Suche

Abstract

Diese Seite beschreibt ein Konzept für ein API für Readings in FHEM. Diese Seite dokumentiert den aktuellen Stand der Diskussion.

Ausgangspunkt ist dieser Thread.

Ausgangssituation

In FHEM besitzen Geräte sogenannte Readings (Anzeigewerte). Diese bestehen aus einem Zeitstempel und einem Wert. Die Änderung eines Readings wird in der Regel durch einen Event daran interessierten Geräten über die NotifyFn mitgeteilt. Die Werte von Readings sind Zeichenketten. Sie können beim Herunterfahren in einer eigenen Datei (fhem.save) gesichert und beim Neustarten von FHEM wiederhergestellt werden. Readings sind von der Natur her schnellveränderlich.

Geräte können Attribute besitzen. Attribute besitzen nur einen Werte ohne Zeitstempel. Sie sind in der Regel un- bzw. langsamveränderlich und dienen typischerweise zur Konfiguration. Attribute werden persistent in der Konfiguration abgelegt. Änderungen an Attributen werden auch analog zu Reading-änderungen durch Events distributiert. Auch Attribute sind Zeichenketten.

Geräte besitzen interne Werte (sog. Internals). Auch diese besitzen nur einen Werte ohne Zeitstempel. Internals können perl-skalare oder Referenztypen (z.B. hashes oder Arrays) sein. Änderungen an Internals werden nicht per Event weitergegeben, die Werte werden nicht persistiert.

Readings, Attribute und Internals genügen keiner festgelegten Syntax: es gibt bezüglich der Werte keine Vorgaben zur Standardisierung. Diese können z. B. Zahlenwerte, Kombinationen aus Zahlen und physikalischen Einheiten oder Texte enthalten. Beispielsweise können Readings, die Temperaturen darstellen, die Temperatur in Celsius-Graden oder Kelvin-Graden mit oder ohne Einheitensymbol enthalten. Das erschwert die Weiterverarbeitung. Soll beispielsweise eine Temperatur in einer graphischen Benutzeroberfläche mit einem Thermometer-Widget dargestellt werden, müssen für jede Geräteklasse individuelle Transformationsregeln von der Darstellung im Reading auf den Eingangsparameter im Widget transformiert werden.

Keine Semantik: Es gibt kein API, anhand dessen eine Funktion erkennen kann, was das Reading inhaltlich darstellt. Eine graphische Benutzeroberfläche kann beispielsweise nicht ermitteln, ob für ein bestimmtes Reading ein Thermometer-Widget oder eine Lampe dargestellt werden soll.

Zielsetzung

Es soll ein API eingeführt werden, das einen bzgl. Syntax und Semantik standardisierten Zugriff auf Readings, Attribute und Internals erlaubt.

Gehören Attribute und Internals wirklich hierher?

  • Internals sind device-intern und normalerweise nicht für Dritte gedacht. Wenn etwas 'öffentlich' und auswertebar sein soll gehört es womöglich in ein Reading oder Attribut.
  • manche Devices legen aus der Definition abgeleitete Werte in Internals ab. Auch diese sollten externen Schnittstellen einheitlich zugänglich gemacht werden können.
  • Attribute sind für den Endanwender gedacht. Was gibt es hier zu Standardisieren ausser den möglichen Werten?
  • Eine externe Schnittstelle kennt die FHEM-interne Struktur nicht, soll aber ggf. trotzdem vereinheitlichen Zugriff auf die Konfiguration (= die Attribute) bekommen können.

Frühere Ansätze sind Interfaces und Guidelines und diese Diskussion.

Anforderungen an das API

  1. Funktionale Anforderungen
    • Es soll möglich sein einen aus den Werten von Readings, Attributen und Internals abgeleiteten Wert abzufragen
    • die Zugrunde liegenden Werte (Readings, Attribute und Internals) sollen beliebigen Devices zuordenbar sein. Es soll z.B. ermöglicht werden mehrere getrennte Analoge Ausgabedevices zu einem einzigen RGB-Wert zu aggregieren.
    • Sofern die Abbildevorschrift bijektiv ist, soll es möglich sein durch Setzen des abgeleiteten Wertes die zugrunde liegenden Größen zu verändern. Readings sind per definitionem nur aus dem Gerät selbst heraus und nicht in das Gerät hinein veränderbar. Oder wollen wir zulassen, dass Readings manipuliert werden können? (Warum gibt es ein 'CommandSetReading' in der bestehenden fhem-api?). Welchen Anwendungsfall gibt es dafür?
    • Es soll möglich sein eine Benachrichtigung zu erhalten, wenn sich dieser abgeleitete Wert ändert (ggf. mit Verzicht auf Änderungen von Internals die ja keine Events auslösen).
    • Es soll sich die Bedeutung eines abgeleiteten Wertes ermitteln lassen (Temperatur, Schaltzustand, Länge, Füllmenge, ...).
    • Es sollen sich bei physikalischen Größen Wert und Einheit ermitteln lassen.
    • Es soll möglich sein, physikalische Größen in andere Einheitensysteme umrechnen zu können (z.B. K in °C, °C in °F, l im cbm, ...).
    • Es sollen Formatierungen unterstützt werden (globaler Default, Default je physikalischer Größe, individuell je Geräteklasse, individuell je Gerät), z.B. Temperaturen grundsätzlich in °C mit einer Nachkommastelle, Uhrzeiten grundsätzlich in 24-Stunden-Notation oder in AM/PM-Schreibweise.
    • Es soll sich der Wertebereich ermitteln lassen. Ein Wertebereich könnte zur sinnvollen Skalierung analoger Werte (z.B. Slider) benutzt werden.
    • Es soll möglich sein mehrere Sets von Abildungsvorschriften konfigurativ hinterlegen zu können. Damit können unterschiedliche Schnittstellen oder Frontends parallel nutzbar gemacht werden. Unterschiedliche Frontends benötigen z.B. RGB-Werte in unterschiedlichen Formaten auf ggf. auf einen oder mehrere Kanäle abgebildet. -> Widerspricht das nicht dem Standardgedanken? Sollte es nicht eine Weise geben, wie RGB-Werte bereit gestellt werden, und der Kunde sollte diese dann in das eigene Format bringen? <- Wenn beide Seiten einer Schnittstelle jeweils ihrem eigenen Standard genügen, dann muss man dazwischen übersetzen.
  2. Nichtfunktionale Anforderungen
    • Kein Modul soll das API unterstützen müssen, damit althergebrachte Module ohne Anpassungen weiterfunktionieren.
    • das API soll abwärtskompatibel sein und einen (bidirektionalen) Zugriff auf bestehende Module ermöglichen.
    • Das API soll nur unwesentlichen Overhead bzgl. Speicherverbrauch und Verarbeitungszeiten erzeugen.
    • Es soll keine Vereinheitlichung von Readings-Namen erfolgen (temp, temperature) (das war früher einmal eine Forderung).

Erste Überlegungen

  • Einheiten alleine genügen nicht, es sollte die physikalische Größe bekannt sein, die von dem Reading repräsentiert wird (Temperatur, Druck, ...).
  • Dazu eine Regel, in welcher Einheit diese physikalische Größe vorliegt.
  • Es bringt keinen Zusatznutzen, die physikalische Größe am Reading verfügbar zu haben.
  • Stattdessen meldet das Device, dass es einem Standard gehorcht (ein Interface implementiert, z.B "temperature").
  • Ein GUI weiß dadurch, was es anzuzeigen hat.
  • KEINE Einheiten im {readings}{VAL}. Das muß bei wirklich jeder anderen Verwendung außer "Anzeige für Mensch mit selben Locale wie Entwickler." gestrippt werden.
  • An jedes Reading werden Metainformationen geklebt. Welche?
  • Die Metainformationen könnten Zeiger in eine hierarchische Liste standardisierter Beschreibungen sein. Sind die Interfaces modellhaft?
  • Es ist klar, dass die Bedeutung eine Vereinbarung darstellt, die außerhalb des Systems liegt. GGf. kann man die Implementierung aber ihre eigene Dokumentation enthalten lassen.
  • Wir brauchen für die Formatierungen einen Speicher für die globalen Defaults und die Geräteklassen- und Geräte- und Readings-spezifischen Überschreibungen.
  • Die allgemeinen Zugriffsmethoden können in RTypes.pm eingefügt werden. So was wie RUnit($hash, "desired-temp").
  • Wie wäre es, erst die Zugriffsmethoden zu definieren? Z.B. RUnit, RValue, RValue(..., $unit), RType, ...? Das macht es griffig. Ich meine damit, dass die Kunden sagen, was sie brauchen, und wir daraus das API definieren.
  • Wir müssen darüber nachdenken, welche Kunden das API hat und was es denen nutzen soll. FHEMWEB, DBLog, MQTT, smartVisu, mobile Clients sind Kunden.
  • Zum Frontend: man kann sich ja viel fürs Backend ausdenken. Aber das richtige Gespür dafür, ob das Design auch wirklich was taugt, bekomme ich erst, wenn ich es einsetze und sehe, wie es sich für den Verwender anfühlt. Daher die Idee für einen Durchstich, ein Proof-of-Concept eben.
  • Think big, start small: vermutlich bringen wir nur etwas zu Wege, wenn wir nicht gleich den großen Wurf anstreben, sondern mit einem Aspekt beginnen (de facto Readings) und dabei stets das gesamte Zielbild im Auge halten.