neuer vorschlag zu einheiten und formatierung von readings im fontend

Begonnen von justme1968, 04 Januar 2016, 17:48:06

Vorheriges Thema - Nächstes Thema

justme1968

anbei ein neuer vorschlag wie man mit readings und einheiten in fhem umgehen könnte.

die grundidee: es gibt ein dictionary das readingsNamen zu einheiten (si- und daraus abgeleitet) zuordnet:

  • das dictionary beschreibt eine größe über ein einheiten symbol, ein dimensions symbol und ein format (beim modul dictioary eventuell noch eine textuelle beschreibung. z.b. 'gemessene temperatur inklusive offset Korrektur').

  • die darstellung eines wertes kann automatisch abhängig von seiner größe angepasst werden und das einheiten symbol mit dem passenden si prefix versehen werden.

  • readings mir gleichem namen können modul abhängig um eine feste größenordnung von der si basiseinheit abweichen. bei der formatierung wird darstellung vereinheitlicht. (bsp: messsteckdosen verschiedener hersteller messen der verbrauch mal in Wh mal in kWh oder den strom mal in A und mal in mA. im frontend wird alles einheitlich in kWh und A mit dargestellt und die skala abhängig vom absoluten wert passend verschoben.)

  • es ist möglich spezielle formatierungs funktionen für größen anzugeben die auf einem nicht-dezimalen system beruhen (z.b.: zeit in sekunden wird bei entsprechender größe zu minuten und stunden. entweder mit nachkommt anteil oder im hh:mm:ss format).

  • das dictionary kann ist hierarchisch aufgebaut, einträge werden in einem globalen default, in einem modul spezifischen und in einem device spezifischen teil gesucht. ein anwender kann auf device ebene die komplette beschreibung einer größe anpassen oder nur die reine formatierung (attribute readingsDesc und readingsFormat).

  • dieses dictionary wird verwendet um readings wie oben beschrieben im frontend darzustellen und zu formatieren.

  • ReadingsVal und ReadingsNum verhalten sich wie bisher.

  • zusätzlich gibt es formatValue, formatReading, readingsUnit und  readingsDimension routinen.

  • es gibt eine makeSTATE routine die analog zu stateFormat funktioniert aber zusätzlich automatisch das dimensions zeichen darstellt und das reading (mit optionaler einheit) wie oben beschrieben formatiert.

  • code änderungen an den modulen sind nicht nötig, an den frontends minimal. im prinzip ist nur das dictionary zu füllen.


über das showUnits attribut lässt sich in telnet und fhemweb instanzen das formatieren der readings abstellen.


das ganze ist natürlich nicht komplett. sondern ein erster entwurf um zu sehen ob etwas in dieser art mehrheitsfähig ist.

unter anderem fehlt:

  • die beschreibung oben ist auf die schnelle viel zu oberflächlich und kurz geworden :)
  • defaults für mehr readings
  • die möglichkeit für den endanwender auf modul ebene oder global die defaults zu ändern.
  • readings die schon eine einheit im reading haben werden zur zeit noch nicht weiter berücksichtigt. das ziel ist ja diese los zu werden :). im prinzip könnte man aber auch parsen und entsprechend rechnen.
  • mit einer kleinen erweiterung müsste das ganze auch in der lage sein für die darstellung zwischen einheitensystemen wie metrisch und imperial umzurechnen.
  • die longpoll updates erfolgen zur zeit mit dem formatierten wert. eventuell ist es besser hier basis wert und einheit zusätzlich auch noch getrennt zu senden.
  • readingsGroup ist noch nicht umgestellt.

als beispiel das gleiche device ein mal mit:list d1
Internals:
   NAME       d1
   NR         26
   STATE      T: 12.12, H: 35.1, p: 998
   TYPE       dummy
   Readings:
     2016-01-04 15:45:48   consumption     25
     2016-01-04 15:40:22   current         1000
     2016-01-04 15:50:11   energy          21390.9
     2016-01-04 15:00:52   humidity        35.1
     2016-01-04 15:31:52   pressure        998
     2016-01-04 15:01:20   temperature     12.12
Attributes:
   stateFormat T: temperature, H: humidity, p: pressure


und ein mal ohne showUnits:list d1
Internals:
   NAME       d1
   NR         26
   STATE      T: 12.1°C, H: 35 %, p: 998 hPa
   TYPE       dummy
   Readings:
     2016-01-04 15:45:48   consumption     25 kWh
     2016-01-04 15:40:22   current         1.0 A
     2016-01-04 15:50:11   energy          21 kWh
     2016-01-04 15:00:52   humidity        35 %
     2016-01-04 15:31:52   pressure        998 hPa
     2016-01-04 15:01:20   temperature     12.1°C
Attributes:
   stateFormat {makeSTATE($name,"temperature, humidity, pressure",1)}


hier ist zu sehen: consumption speichert den wert in kWh, energy in Wh, beide werden auf Wh zurück gerechnet und dann automatisch abhängig vom betrag als kWh mit dem passenden k prefix dargestellt.
current liegt in mA vor wird in A dargestellt.
pressure liegt intern in hPa vor, wird auf die basiseinheit Pa zurück gerechnet und dann als hPa mit passendem prefix dargestellt.
humidity und temperature werden mit der konfigurierten genauigkeit und einheit dargestellt.
alle einheiten bis auf °C werden mit dem vorgesehen leerzeichen zwischen wert und einheit dargestellt.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Dr. Boris Neubert

Hallo Andre,

ich finde Deinen Vorschlag gut und trage ihn mit. Wichtig ist mir, dass wir nicht ausgiebig darüber diskutieren sondern dass ein Prototyp hingeholzt wird, auf dem wir dann konstruktiv aufbauen können.

Folgende Anmerkungen:
- Ohne das Thema von damals(R) nachgelesen zu haben ist mir, als ob Dein Vorschlag alle wesentlichen Punkte abdeckt, die wir in der Diskussion aufgerufen hatten.
- Du kannst gerne FHEM/RTypes.pm verwenden. Das Modul ist die leere Hülle, in die ich damals(R) den Prototypen einbauen wollte. Der Aufruf erfolgt bereits von geeigneter Stelle aus fhem.pl heraus.
- Ich würde eine zusätzliche Abstraktionsschicht einbauen, die das individuelle Reading auf eine allgemeine Größe abbildet, bevor das Dictionary zum Tragen kommt. Beispiel: Reading "energy" -> Größe "energy (electric)" -> Dictionary. Das entspricht den Interfaces. Über die Größen würde ich nicht diskutieren wollen sondern eine geeignete Wahl dem Implementierer überlassen - Beispiele gibt es im entsprechenden Kapitel im Wiki.
- Man sollte jedem Device (mit Default auf Modulebene) nicht verpflichtend die Möglichkeit geben selbst anzugeben, um welche Größe es sich handelt und in welcher Einheit die im Reading ausgewiesene Zahl zu nehmen ist. Beispiel: consumption -> "energy (electric)", kWh.

Folgende Fragen:
- Wie wird mit textuellen Darstellungen in Readings umgegangen, die nach Standardisierung schreien (on/off, On/Off, 1/0; dim47%; open/Open, closed/Closed; low/Low, ok, OK)?
- Wie pflegt der Anwender die Formatierungen?

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

justme1968

hallo boris,

die beiden angehängten files implementieren die oben beschriebene funktionalität schon komplett. der erste prototyp ist also im prinzip da.

die zwischenschicht gibt es. allerdings nicht zwingend sondern freiwillig und implizit über die konfigurierten si und abgeleiteten einheiten. diese werden dann im normal fall im dictionary für die readings nur noch referenziert. das ist auch der grund warum die readings beschreibung und die formatierung getrennt werden kann. der modul autor kann die art des readings (z.b. energy) vorgeben und der anwender kann dann die formatierung bestimmen.

der default auf modul ebene geht. das modul ist auch frei in welcher größenordnung es die jeweilige einheit intern verwendet. z.b. energy in Wh oder in kWh. die darstellung wird dann automatisch (je nach konfiguration) vereinheitlicht.

es schaut also normalerweise so aus: reading -> standard einheit und magnitude -> formatierung

einschub: bei der referenzierung geht im prototypen noch der name der basis einheit verloren. wenn man diesen im hash einfach noch zusätzlich mitführt dann ist auch die oben erwähnte konvertierung zwischen dein einheiten systemen möglich.


zu den fragen:
der prototyp ist erst mal nur für numerische readings gedacht. für die die textuelle readings habe ich eine art erlaubt liste und ein mapping der verwendeten auf diese generischen im hinterkopf. etwas ähnliches habe ich schon für die homekit bridge gemacht. ich glaube aber es ist besser hier richtlinien zu geben und dann tatsächlich im modul den code zu ändern da es sinnvoll ist das hier auch die vereinheitlichten werte in den events erscheinen. das macht es für die frontends viel einfacher und ist unterm strich nicht mehr arbeit.

der anwender hat in jedem device die beiden neuen attribute readingsDesc und readingsFormat zur verfügung. im einfachsten fall schaut das z.b. so aus: attr <device> readingsFormat { temperature => '%1.f', humidity => '%i' }

die temperatur wird hier mit einer nachkommt stelle formatiert und die feuchte ohne nachkommt stellen.

das format abhängig von der größenordnung des wertes vorzugeben funktioniert genau so. der hash hat nur mehr einträge.

was hier noch fehlt ist das der endanwender auch global und auf modul ebene die defaults überschreiben kann.

man kann auch recht einfach ein passendes fhemwidget zum zusammenflicken des formats und der skalieren bauen.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Dr. Boris Neubert

Hallo Andre,

Danke für Deine Antwort. Ich muss mir das in Ruhe zu Gemüte führen (= meine Umgebung patchen und damit herumspielen). Im Moment hänge ich noch in den Tests vom Calendar-Modul - kann also dauern, bis ich erste Erfahrungen berichte.

Warum mir die Abstraktionsschicht über die Größe so wichtig ist: es würde FHEMWEB die Auswahl einer geeigneten visuellen Darstellung ermöglichen (Icon, Schaltregler, ...). Das ist dann aber schon RTypes.pm und nicht mehr "nur"  units.patch.

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

Loredo

Hallo André,


danke, dass du dich dem annimmst. Liest sich auf den ersten Blick sehr gut und logisch.
Es wäre wirklich toll, wenn man nicht mehr den gesamten Code in Fhem durchsuchen müsste, damit man bei einem neuen Modul die Reading Namen (und Einheiten) durchsuchen müsste in der Hoffnung, dass man nichts übersehen hat (mein letztes Beispiel: HP1000).




Gruß
Julian
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

klaus.schauer

Neben der Option ein Reading im Modul bezogen auf einen Readingstyp - in EnOcean ist dies "subType" bzw. das EEP-Profil - oder spezifisch für einen Readingtyp z. B. airPressure zu beschreiben, sollte auch eine Definition zur Laufzeit möglich sein.

In EnOcean gibt es u. a. den GeräteTyp "Generic Profile". Bei diesem Typ werden die Readings (Kanäle) zur Fhem Laufzeit per Anlernbefehl definiert. Die Kanäle werden dabei mit mehren Parametern beschrieben:
- Einheit (°C, m, kg, ppm, N/A, ...)
- Kanaltyp (enum, flag, data)
- WerteTyp (value, setpointAbs, ...)
- Wertebereich
- Genauigkeit

Derzeit werden neben dem eigentlichen Reading zusätzliche Hilfsreadings für die notwendigen Zusatzinformatioen z. B. Einheit ausgegeben:


     2016-01-06 06:13:18   00-occupanyMode standby
     2016-01-06 06:13:18   00-occupanyModeChannelType enum
     2016-01-06 06:13:18   00-occupanyModeUnit N/A
     2016-01-06 06:13:18   00-occupanyModeValueType setpointAbs
     2016-01-06 06:13:25   01-buttonPressed pressed
     2016-01-06 06:13:25   01-buttonPressedChannelType flag
     2016-01-06 06:13:25   01-buttonPressedUnit N/A
     2016-01-06 06:13:25   01-buttonPressedValueType value
     2016-01-06 06:13:45   02-temperature  31.953
     2016-01-06 06:13:45   02-temperatureChannelType data
     2016-01-06 06:13:45   02-temperatureUnit C
     2016-01-06 06:13:45   02-temperatureValueType value
     2016-01-06 06:14:03   03-magnetic_field_strength 319999.9
     2016-01-06 06:14:03   03-magnetic_field_strengthChannelType data
     2016-01-06 06:14:03   03-magnetic_field_strengthUnit A/m
     2016-01-06 06:14:03   03-magnetic_field_strengthValueType value
     2016-01-06 06:12:05   04-hvacMode     comfort
     2016-01-06 06:12:05   04-hvacModeChannelType enum
     2016-01-06 06:12:05   04-hvacModeUnit N/A
     2016-01-06 06:12:05   04-hvacModeValueType setpointAbs
     2016-01-06 06:12:10   05-occupancy    occupied
     2016-01-06 06:12:10   05-occupancyChannelType flag
     2016-01-06 06:12:10   05-occupancyUnit N/A
     2016-01-06 06:12:10   05-occupancyValueType value
     2016-01-06 06:12:16   06-concentration 39.3390656
     2016-01-06 06:12:16   06-concentrationChannelType data
     2016-01-06 06:12:16   06-concentrationUnit ppm
     2016-01-06 06:12:16   06-concentrationValueType value
     2016-01-06 06:12:21   07-distance     53444.9937
     2016-01-06 06:12:21   07-distanceChannelType data
     2016-01-06 06:12:21   07-distanceUnit m
     2016-01-06 06:12:21   07-distanceValueType value


Da die Kanäle dynamisch angelegt werden und mehrere Kanäle mit z. B. gleichen Einheiten vorkommen können, müssen die Kanäle selbst zusätzlich eindeutig gemacht werden. Dies erfolgt über die vorangestellten Kanalnummern. Zusätzlich kann der Anwender die Kanalnamen später ändern.

Insgesamt bedeutet das aber, dass für die ordnungsgemäße Formatierung des Readings die Einheit und die Anzahl der Nachkommastellen bei der Berechnung zur Laufzeit übergeben werden müssen.

E. M. wäre des deshalb notwendig, dies bei der Überarbeitung der Readingsformatierung zu berücksichtigen.

justme1968

ich denke das kann man abdecken in dem das modul beim anlernen das readingsDesc attribut für dieses device ein mal passend setzt. in der aktuell vorgeschlagen version wäre dann einheit, magnitude und formatierung abgedeckt. zumindest diese hilft readings wären dann keine readings mehr sondern das würde über den obigen vorschlag abgedeckt.

die hier verwendeten datanstrukturen sind nicht statisch und können im prinzip alle zur laufzeit überschrieben und geändert werden. auf allen ebenen. in deinem fall wäre das die device ebene.

ein wertebereich ist noch nicht vorgesehen. wäre aber kein problem.

mehrere kanäle mit gleichem typ messgröße sind auch kein problem, die beschreibungen würden jeweils auf den gleichen typ verweisen. beim umbenennen eines kanals müsste man dann diesen verweis automatisch mit umbenennen. zur zeit müsse das der anwender noch von hand nachziehen.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klaus.schauer

Alternativ wäre es aber gut, wenn des neben den vorhandenen Routinen readingsXUpdate auch Routinen gäbe, bei denen die Werte für Einheit, Magnitude und Formatierung mit übergeben werden könnten. Dann kann man sich in den Modulen von Fall zu Fall für die jeweils sinnvollste Formatierung über zusätzliche Tabellen bzw. Attribute oder über Werteübergabe in der Readingsroutine entscheiden.