Readings, values und Units

Begonnen von martinp876, 10 März 2014, 07:33:17

Vorheriges Thema - Nächstes Thema

ntruchsess

Zitat von: martinp876 am 22 März 2014, 20:06:22
Bitte nicht vergessen dass einer der Punkte war, eine Methode zur Daten-Formatierung zu erstellen - insbesondere ein Float als "string' mit fix n Nachkommastellen. So in der Art - betateilchen kann sicher am besten beschreiben, was er erwartet.

Ich bin dagegen numerische Readings als formatierte Strings (sowas wie 'immer mit Punkt und 2 Nachkommastellen) abzulegen. Das ist Sache des Frontends. Eine leistungsfähige Funktion (sprintf) zum Formatieren nach Wunsch ist in perl ja schon drin.
Wichtig ist, dass numerische Werte so abgelegt sind, dass man unmittelbar mit Ihnen Rechnen kann.

Der Rest von Martins Zusammenfassung ist für mich OK. Literale als Typ mit definierbarer Wertemenge würde ich auch unterstützen, hab aber noch keine (gute) Idee, wie man das effizient am Reading unterbringt. Irgendwie sieht es für mich so aus, als ob man ein Reading erst mit Angabe eines Datentyps definieren können sollte um später nur noch den eigentlichen Wert zu aktualisieren.

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

Markus Bloch

Generell sollten unter $hash->{READING} die Rohwerte stehen (also ohne sprintf, round,..), so dass (wie von Norbert angemerkt) man nachwievor mit dem Rohwert selber weiterarbeiten kann.

Ich finde die Formatierungs- und Umrechnungsformeln in den Typendefinitionen super, aber sie sollten nur von Frontendmodulen verwendet werden.

Könnte man die modulspezifischen Typen nicht im Modul in der Initialize-Funktion definieren? Dann hat man alles zusammen und keine weitere separate Datei die von allen gepflegt werden muss?

Wir definieren einmal eine Reihe an Grundtypen und alle modulspezifischen Typen müssen in den Modulen definiert werden mit sämtlichen Umrechnungsmöglichkeiten und Einheiten.

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Dr. Boris Neubert

Zitat von: Markus Bloch am 22 März 2014, 21:27:18
Generell sollten unter $hash->{READING} die Rohwerte stehen (also ohne sprintf, round,..), so dass (wie von Norbert angemerkt) man nachwievor mit dem Rohwert selber weiterarbeiten kann.

Ich meine, daß wir darüber schon dieses auch als Konsens erzielt hatten.

Ich hatte Martin auch nicht so verstanden, daß er einen String in READING-VAL schreiben wollte. Lediglich String als Default in der Typdefinition für die Anzeige unterstellen. Wenn es der Anwender besser als das Frontend weiß, darf er natürlich mit den Zahlenwerten rechnen, die dem Frontend mangels Semantik (fehlende oder dem Programmierer des Frontends unbekannte Typdefinition) nur als String erscheinen.

Zitat
Ich finde die Formatierungs- und Umrechnungsformeln in den Typendefinitionen super, aber sie sollten nur von Frontendmodulen verwendet werden.

So habe ich das auch gemeint.

Zitat
Könnte man die modulspezifischen Typen nicht im Modul in der Initialize-Funktion definieren? Dann hat man alles zusammen und keine weitere separate Datei die von allen gepflegt werden muss?

So hätte man genau einen Verantwortlichen für die globalen Typdefinitionen.

Die Frage ist aber, ob die individuellen Typdefinitionen überhaupt zu einem bestimmten Modul gehören? Also wo werden Typen redundanzfrei definiert, die in mehreren Modulen (einer Modulgruppe) benötigt werden.

In welchem Format würde man denn dann die Typdefinitionen abliefern? Es sollte für Mensch und Maschine gleich gut lesbar sein. JSON wäre so ein Format. Oder ein strukturiertes Hash wie in die Orgie von Definitionen am Anfang von 11_OWDevice.pm.

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

Markus Bloch

#93
Ich sehe hier folgende Möglichkeiten:


1. eine komplette Datei mit sämtlichen Definitionen als Perl Hash oder NV-Pairs. XML und JSON würde ich nicht verwenden aufgrund zusätzlicher Module bei kleinen System (FritzBox, u. ä.) und der schwierigen Platzierung von Kommentaren (insbesondere bei JSON).

2. Pro Typdefinition eine Datei mit einem Perl Hash oder NV-Pairs. Vorteil ist, wenn eine Datei einen Syntaxfehler hat, sind alle anderen Typendefinitionen nicht davon betroffen.

Desweiteren sollte eine Typendefinition dokumentatorisch einen Hinweis enthalten welche Basiseinheit einer Typendefinition zu Grunde liegt. Also Readings vom Typ temperature müssen in °C bereitgestellt werden. Nur so funktionieren die darüber hinaus definierten Umrechnungsformeln. Genauso auch muss eine Stromstärke in Ampere bereitgestellt werden und nicht Milli-Ampere, usw.

Diesen Dokumentationsteil inkl. den Umrechnungsmöglichkeiten könnte man dann einfach in die commandref integrieren lassen.

Gruß
Markus

Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Dr. Boris Neubert

Angenommen, eine Typdefinition wäre ein Hash.

Würde man dann am Reading den Namen des Typs oder eine Referenz auf das Hash hinterlegen.

Hashreferenz hat vermutlich den Vorteil, daß man keinen Typen referenzieren kann, den es nicht gibt.

BN

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

Markus Bloch

Hashreferenz finde ich super, diese Zuweisung sollten dann die readingsUpdate-Funktionen durchführen in dem sie die entsprechende Referenz der gewünschten Typendefinition zuweisen. Sollte ein Modul eine Typdefinition angeben, die nicht existiert, so sollte eine Art Standardtyp zugewiesen werden, der den Wert ungefiltert und ohne Interpretation an das Frontend weitergibt.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Dr. Boris Neubert

Und alles in einem globalen %types-Hash, das uns dann mit $types{temperatureCelsius} die Referenz auf das Hash mit dem benannten Typ liefert.

Mal sehen, was die anderen dazu sagen.

BN
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

martinp876

Zitatund jeder Entwickler fügt dann Typen an diese Datei an,
das ist ein nogo. Wiederspricht allem, was FHEM aktuell tut. Die Modul-spezifischen Typen sollten unbedingt auch dort definiert werden. Gründe gibt es zu hauf - u.a. das Dateien immer einem Entwickler 'gehören'
Zitat
Wie sähen Typdefinitionen aus, in Pseudokode
halte ich für exterm ungeschickt. Perl kann zwar viel, ist aber exterm langsam. Man sollte es deutlich geradliniger machen. Möglich ware, einen Pseudo-code zu nutzen, aber beim Starten zu 'kompilieren'. Am Ende sollte ein Hash existieren, mit klaren Werten, maschienen nutzbar.

ZitatIch bin dagegen numerische Readings als formatierte Strings (sowas wie 'immer mit Punkt und 2 Nachkommastellen) abzulegen
zustimmung. Die idee ist nicht, den Wert formatiert abzulegen sondern eine Methode bereitzustellen, die so etwas leistet. Sonst muss es jeder User selbst machen. Einfach nur ein Service.

ZitatLiterale als Typ mit definierbarer Wertemenge würde ich auch unterstützen, hab aber noch keine (gute) Idee, wie man das effizient am Reading unterbringt.
In CUL_HM nutze ich das bereits - so kann ich register(deviceparameter) User-readable übersetzen. Bein Schreiben und Lesen.

ZitatIch finde die Formatierungs- und Umrechnungsformeln in den Typendefinitionen super, aber sie sollten nur von Frontendmodulen verwendet werden.
Die Idee ist (schon ganz am Anfang in Threat) neben ReadingsVal ein ReadingsNum (liefert einen Numerischen Wert, wenn das Reading numerisch ist oder zumindest so beginnt - stript Units u.ä.) und wenn man will ein ReadingsNumFromated - für Nachkommastellen. Alles nur ein Service, das es nicht jeder, der nicht so firm ist es nicht selbst machen muss.

Ich erwarte eine Typdefinition die maschinenlesbar so aussehen könnte:
%readTypes = (
  time   =>{type=>"float",step=>0.2,min=>0  ,max=>10000,format=>'1.1' ,unit=>'s' ,conv=>''         ,displayLevel=>2, t=>"Ein Zeitwert"       },
  length =>{type=>"int"  ,step=>1.0,min=>0  ,max=>1000 ,format=>''    ,unit=>'m' ,conv=>'myConvFkt',displayLevel=>3, t=>"Länge in Metern"    },
  temp   =>{type=>"float",step=>0.5,min=>-40 ,max=>70  ,format=>'3.1' ,unit=>'C' ,conv=>''         ,displayLevel=>0, t=>"Temperatur Sollwert"},
  text1  =>{type=>"lit"  ,step=>0  ,min=>0  ,max=>0    ,format=>''    ,unit=>''  ,conv=>''         ,displayLevel=>1, t=>"irgend ein text"    ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3}},
......


Befüllen, wie gesagt, kann man auch mit Methoden und somit abstrahiert

Gruss Martin

Dr. Boris Neubert

Zitat von: martinp876 am 23 März 2014, 10:26:37
das ist ein nogo. Wiederspricht allem, was FHEM aktuell tut. Die Modul-spezifischen Typen sollten unbedingt auch dort definiert werden.

Der Punkt, die allgemeingültigen Typen zentral und die individuellen Typen dezentral in der Verantwortung jeweils genau eines Entwicklers (Dateieigentümer) zu halten, ist akzeptiert. Ich habe noch gefragt, wo die individuelle Typen redundanzfrei hinterlegt werden in dem Fall, daß ein Entwickler diese Typen in mehreren seiner Module nutzen möchte.

Zitat
In CUL_HM nutze ich das bereits - so kann ich register(deviceparameter) User-readable übersetzen. Bein Schreiben und Lesen.
Die Idee ist (schon ganz am Anfang in Threat) neben ReadingsVal ein ReadingsNum (liefert einen Numerischen Wert, wenn das Reading numerisch ist oder zumindest so beginnt - stript Units u.ä.) und wenn man will ein ReadingsNumFromated - für Nachkommastellen. Alles nur ein Service, das es nicht jeder, der nicht so firm ist es nicht selbst machen muss.

Schlägst Du ein ReadingsNum vor? Ich verstehe nicht, warum wir ein ReadingsNum brauchen. Die Werte in VAL sind ja numerisch, wenn das Modul eine Zahl (Temperatur, Füllstand, ...) reinschreibt. Immer wenn damit gerechnet wird, tut das entweder der Benutzer (weiß, was er tut) oder das Frontend (liest es aus der Typdefinition).

Zitat
Ich erwarte eine Typdefinition die maschinenlesbar so aussehen könnte:
%readTypes = (
  time   =>{type=>"float",step=>0.2,min=>0  ,max=>10000,format=>'1.1' ,unit=>'s' ,conv=>''         ,displayLevel=>2, t=>"Ein Zeitwert"       },
  length =>{type=>"int"  ,step=>1.0,min=>0  ,max=>1000 ,format=>''    ,unit=>'m' ,conv=>'myConvFkt',displayLevel=>3, t=>"Länge in Metern"    },
  temp   =>{type=>"float",step=>0.5,min=>-40 ,max=>70  ,format=>'3.1' ,unit=>'C' ,conv=>''         ,displayLevel=>0, t=>"Temperatur Sollwert"},
  text1  =>{type=>"lit"  ,step=>0  ,min=>0  ,max=>0    ,format=>''    ,unit=>''  ,conv=>''         ,displayLevel=>1, t=>"irgend ein text"    ,lit=>{off=>0,jmpToTarget=>1,toggleToCnt=>2,toggleToCntInv=>3}},
......


Ich befürworte auch das Hash. Es ist gleichzeitig maschinen- und menschenlesbar. Über die Form müssen wir uns noch gut Gedanken machen.

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

ntruchsess

Zitat von: martinp876 am 23 März 2014, 10:26:37
Die Modul-spezifischen Typen sollten unbedingt auch dort definiert werden.

Zitat von: Dr. Boris Neubert am 23 März 2014, 10:38:53
Der Punkt, die allgemeingültigen Typen zentral und die individuellen Typen dezentral in der Verantwortung jeweils genau eines Entwicklers (Dateieigentümer) zu halten, ist akzeptiert. Ich habe noch gefragt, wo die individuelle Typen redundanzfrei hinterlegt werden in dem Fall, daß ein Entwickler diese Typen in mehreren seiner Module nutzen möchte.

OffTopic:
ich persönlich bin ja dringend dafür, dass man mal die Doktrin '1 Fhem-modul = 1 Datei' aufgibt und dafür ganz normale perl-module in 'lib' ablegt (lib sollte dann natürlich von fhem.pl schon in @INC aufgenommen werden). Dann kann man seinen modulübergreifenden code wie in perl sonst auch üblich mit einem 'use <modul> qw/zu importierende symbole/' zur Compiletime einbinden und müsste nicht auf 'LoadModule zurückgreifen um dies zur Laufzeit zu tun.

OnTopic:
Zitat von: Dr. Boris Neubert am 22 März 2014, 22:58:29
Und alles in einem globalen %types-Hash, das uns dann mit $types{temperatureCelsius} die Referenz auf das Hash mit dem benannten Typ liefert.

Ein globaler %types-Hash wäre auch nach meinem Geschmack. Da finden sich dann alle 'globalen' Typen wieder, die fhem.pl beim Startup läd. Alle modulspezifischen Typen legt das jeweilige Modul beim Aufruf seiner Initialize-methode darin ab. Setz natürlich vorraus, dass modulspezifische Typen sowas wie einen Namespace a la $types{MY_MODULE_whateverReadingType} verwenden sollten um Namenskonflikte zu vermeiden.

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

martinp876

ZitatSchlägst Du ein ReadingsNum vor?
ja
ZitatIch verstehe nicht, warum wir ein ReadingsNum brauchen. Die Werte in VAL sind ja numerisch, wenn das Modul eine Zahl (Temperatur, Füllstand, ...) reinschreibt.
Stand aktuell ist, dass Einheiten drin stehen - oder auch mal Werte ersetzt werden (on/off statt 0/100 habe ich häufig gesehen...)

Andererseits, wenn es korrekt implementiert ist, könnte es sich erübrigen. Einheiten sollte wegfallen. Das mit On/Off mögen einige (z.B. bei dimmern). Natürlich könnten wir ein Mapping einführen  - readingsVal ist dann ein Wert, im Display und in den Events erscheint aber kein On/Off sondern ein 0/100
=> Das sind heikle Fragen, welche die Evolution betreffen. Wenn sich hier etwas ändert werden den Usern einige Notifies um die Ohren fliegen.
Alternativ wäre ein Reading mit "Wertebereich" [on|off|0.5...99.5] auch als text möglich - ein Reading "level" wäre der reine Zahlenwert (so mache ich das Aktuell, würde sich bei HM nichts ändern)

Zitat
Dann kann man seinen modulübergreifenden code wie in perl sonst auch üblich mit einem 'use <modul> qw/zu importierende symbole/' zur Compiletime einbinden und müsste nicht auf 'LoadModule zurückgreifen um dies zur Laufzeit zu tun.
hmmm... geht das nicht? Ich habe meine Definitionen in HMConfig und nutze sie in 10_CUL_HM sowie in 98_HMInfo.  Dazu brauch ich niemanden sonst.

ZitatEin globaler %types-Hash wäre auch nach meinem Geschmack. ...modulspezifische Typen sowas wie einen Namespace a la $types{MY_MODULE_whateverReadingType} verwenden sollten um Namenskonflikte zu vermeiden.
genau.
Aber auch hier (wie immer in guter SW) sollte man nicht einfach "reingreifen" und typen definieren sondern dies mit einer Methode machen. Die Zentrale kann, wenn sie will... prüfen: gibt es Namenskonflikte, sind mindest-felder vorhanden, sind konventionen eingehalten,... was immer man für nötig hält.
Die Readingstypen müssen auch nicht zwingend im Init definiert werden. Ist zwar ein sinnvoller Zeitpunkt, muss aber keine Vorschrift sein. Wenn jemand das später machen will, dynamísch,... sollte es ok sein.
Löschen kann man sie nicht - oder???


martinp876

Hallo Leute,

aktuell betrachte ich diese Diskussion als
- interessant
- grundlegend
- gescheitert (oder political correct: bis auf weiteres verschoben)

Ein Problem war und ist, dass einige nicht unterscheiden können zwischen backend (scripting und maschinen interface) und frontend (web und human readable interface). Sonst gäbe es keine Diskussion was in {READINGS}{name}{Val} steht und was ReadingsVal() liefert, also Daten und Methoden, sondern welche Methode man braucht, um den User zu unterstützen.
Fakt ist (nicht in zukunft sondern jetzt) dass der User Werte in Scripten verarbeiten will - und das mit numerischen und textuelle Daten. Perl ist hier - wie alle wissen - eine einzige Sauerei. Daher sollte FHEM dem User einfach eine Methode zu Verfügung stellen, die einen String und eine andere die einen numerischen Wert zurück liefert.
Wenn dies mit Methoden gemacht wird ist es kein Problem, später auch auf komplexe Datenstruktur einzuführen - das ist für den User transparent.

Dass es notwendig ist zeigen die Reaktionen der Nutzer (und sogar manche Developer haben hier offensichtlich massive Probleme). Es gibt werte wie "15,7","15,7 %","15,7%","15,7% - limit reached","15,7 C","15,7 Celsius". Die Nutzer kämpfen offensichtlich, hier die 15,7 zu erhalten, dabei ist es ein Kinderspiel. Schon ein blank mehr oder weniger machen Probleme. Es ist ein 3-zeiler, der das Problem KOMPLETT löst (der Vorschlag liegt von mir an mehreren Stellen bereits vor)

Dieser Threat ist begonnen worden um dieses Problem zu lösen.
Es ist eigentlich Irrsinn, dass aus diesem simplen Grund
- das Frontend keine Units darstellen soll/darf/kann (Steinzeit...)
- Developer sich über den Inhalt von {val} unterhalten - der sie von anderen Modulen eigentlich garnichts angeht. Es wird doch hoffentlich über Methoden zugegriffen!  - und hier braucht es nur die Korrekten/Fehlenden.
Aktuell ist das ganze auf einem schlechten Weg!

So, das ist meine Sicht zu diesem Sachverhalt. Ich ziehe mich hier zurück und hoffe, dass eine userfreundliche und praktikable Entscheidung von den Verantwortlichen getroffen wird - es wäre zu einfach.

Gruss Martin

betateilchen

Nicht weinen Martin,

die ReadingsNum() ist doch in der fhem.pl bereits vorhanden. Ich betrachte das als durchaus brauchbare Interims-Lösung (-Hilfe).
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

martinp876

hoffentlich nicht interims - das wird hoffentlich auch genutzt werden, wenn es ein egal wie komplexes Objekt "READINGS" gibt.
Und du hast jetzt endlich keine Probleme mehr, wenn Units in Readings gepackt werden. Keine Ahnung, warum du immer noch in Foren darüber referierst und zankst, anstatt den Usern die korrekte Methode nahe zu bringen.
Diese Diskussion hier scheint mir jedenfalls aktuell ziemlich tot.

betateilchen

#104
Zitat von: martinp876 am 28 März 2014, 10:16:43Keine Ahnung, warum du immer noch in Foren darüber referierst und zankst,

Tu ich doch gar nicht mehr?

Und ich betrachte die Diskussion hier im Thread bei weitem nicht als "tot" - aber sie ist auch definitiv noch nicht zu Ende geführt.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!