DevelopmentReadingsAPI

Aus FHEMWiki


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.
  • Attribute sind für den Endanwender gedacht. Was gibt es hier zu Standardisieren ausser den möglichen Werten?

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 bidirektional eineindeutig ist, soll es möglich sein durch Setzen des abgeleiteten Wertes die zugrunde liegenden Größen zu verändern.
    • 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 wurde die Anforderung genannt, dass sich der Wertebereich ermitteln lassen sollte. Mir ist nicht klar, ob dies für Readings erforderlich ist (es wäre für Settings erforderlich).
  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").
  • Wir müssen darüber nachdenken, welche Kunden das API hat und was es denen nutzen soll. FHEMWEB und DBLog 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.