ReadingsNum und sehr kleine Zahlen wie 2e-05

Begonnen von AlexMuc, 29 Februar 2024, 13:20:46

Vorheriges Thema - Nächstes Thema

AlexMuc

Hallo zusammen,
mein Wechselrichter liefert morgens ganz zu Anfang naturbedingt noch sehr wenig Energie. Da tauchen dann Werte wie zB 2e-05 auf.
Verwende ich ReadingsVal, so wird in weiteren Berechnungen der "Text" des Readings korrekt zu 0,00002 konvertiert. ReadingsNum dagegen liefert dann 2 als Zahlenwert... Ich hab das vorläufig abgefangen indem ich die per HttpMod eingehenden Werte formatiert ausgeben lasse aber so wirklich im Sinne des Erfinders (ReadingsNum sollte möglichst immer die korrekte Zahl zurück geben) kann das doch nicht sein.
Auf der Suche nach einer Lösung min ich über einige Beiträge gestolpert, die "intern" bei solchen Umwandlungen potentiell Einheiten "entfernen / strippen". Scheinbar gehen ReadingsVal und ReadingsNum hier eigene Wege wobei der von ReadingsVal bei diesem Beispiel der bessere / richtigere zu sein scheint.
Wer kennt sich mit den FHEM Interna aus und könnte dieses "Problem" beheben?

Otto123

Hi,
Zitat von: AlexMuc am 29 Februar 2024, 13:20:46so wirklich im Sinne des Erfinders
oder im Auge des Betrachters ;) das soll ReadingsNum machen:
https://wiki.fhem.de/wiki/DevelopmentModuleAPI#ReadingsNum

Interessant - aber es ist scheinbar so: Bei ReadingsVal wird die Textkette gelesen und Perl interpretiert die Zahl richtig.
ReadingsNum ist der Text egal, der extrahiert die erste Zahl in der Zeichenkette.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

rudolfkoenig

Bin unschluessig: eigentlich hat AlexMuc recht, andererseits wuerde eine Aenderung womoeglich funktionierenden Code brechen, da ReadingsNum alt ist.

Die Frage gehoert in einem anderen Forumsbereich, sonst liest das kaum jemand mit relevanter Meinung :)

betateilchen

Zitat von: AlexMuc am 29 Februar 2024, 13:20:46Da tauchen dann Werte wie zB 2e-05 auf.

Nur der numerische Wert oder auch noch mit einer Einheit dahinter?

Könnte man ReadingsNum() nicht so erweitern, dass der Wert unverändert zurückgegeben wird, wenn ReadingsVal() schon einen rein numerischen Wert liefert?

{looks_like_number "2e-05"}
erkennt den Wert zumindest als Zahl und liefert 1 zurück.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

AlexMuc

Wohin mit dem Thread, bin für alle Verschiebungen offen :-)

@Otto:
Dein Link hilft nicht wirklich, da wird mein Problem nicht beschrieben. Der Wert der Zahl wird ja vom Wechselrichter geliefert, der Inhalt des Readings ist also vorhanden und praktisch auch eine gültige Zahl.
Bei meiner Ursachenforschung bin ich im Forum schon über Diskussionen gestolpert bei deren um Einheiten in Readings geht und das mancher ziemliche Verrenkungen macht, um selbige aus Readings zu entfernen. Und ich vermute, das die beiden Funktionen von unterschiedlichen Leuten betreut werden die unterschiedlich vorgehen und einer die Notation von Zahlen in Exponentioalschreibweise bei seiner Arbeit nicht auf dem Schirm hatte. Was kein Vorwurf sein soll.

@Rudolf:
Das hab ich befürchtet und mich gewundert, das ausgerechnet mir als Laie das jetzt auffällt bzw auf die Nase gefallen ist. Das sehe ich als Wunder ;-)

Was nun die genaue Ursache ist und wie man das ohne irgendwelche Kollateralschäden beheben kann, das mögen die Weisen im Forum unter sich klären. Zumindest könnte es sinnvoll sein, wenn in dem Artikel aus Ottos Link ein kleines ACHTUNG auftaucht, das ReadingsNum momentan ein "kleines" Problem mit gewissen Zahlen hat.

Gruß
Michael

betateilchen

#5
Zitat von: AlexMuc am 29 Februar 2024, 19:46:52Wohin mit dem Thread, bin für alle Verschiebungen offen

Der Thread wurde schon verschoben.


Naja, ReadingsNum() hat auch in bestimmten anderen Fällen Probleme mit dem korrekte Extrahieren von Zahlenwerten. Vor einiger Zeit bin ich in einer meiner Installationen schonmal über das Thema gestolpert, weiß aber aktuell nicht mehr, was damals das konkrete Szenario war. Seinerzeit hatte ich mir mit einer eigenen Funktion in myUtils beholfen.

Zitat von: AlexMuc am 29 Februar 2024, 19:46:52Und ich vermute, das die beiden Funktionen von unterschiedlichen Leuten betreut werden die unterschiedlich vorgehen und einer die Notation von Zahlen in Exponentioalschreibweise bei seiner Arbeit nicht auf dem Schirm hatte.

Nein. ReadingsNum() und ReadingsVal() sind beides Kernfunktionen von FHEM, die in der fhem.pl verankert sind.

ReadingsNum() verwendet intern zuerst ReadingsVal(), um den zu untersuchenden String zu ermitteln. Dann wird mit einer regex versucht, aus dem String numerische Teile zu extrahieren. Damit können prinzipbedingt nicht 100% aller denkbaren Darstellungsfälle abgedeckt werden.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

erwin

pragramatischer Ansatz:
Wenn man ganz sicher ist, dass das reading ausschließlich Zahlen enthält -> readingsVal verwenden! evtl anschließend runden/formatieren...

readingsNum wurde für solche szenarien entwickelt:
setreading Ptest test abrakadabra12.34ist Zauberei
{ReadingsNum('Ptest','test',0)}
ergibt: 12.34
das aufzudröseln / backward kompatibel zu lösen wird schwierig, zumal es ja auch module gibt, die value und unit zusammengeschrieben in readings schreiben.
Zum Nachdenken, Beispiel text: 'der wert ist zwischen hex 2e-30 gültig' ? was soll da eurer Meinung nach rauskommen?

etwas abwegig finde ich allerdings 2e-05 als Wert (W/kW)? von einem Wechselrichter - das ist jedenfalls jenseits jeder Messgenauigkeit...Da wäre mein Ansatz für einen fix!
l.g. erwin
FHEM aktuell auf RaspberryPI Mdl 1-4
Maintainer: 00_KNXIO.pm 10_KNX.pm
User: CUNO2 (868 SLOWRF) - HMS100xx, FS20, FHT, 1-Wire  - 2401(iButton), 18x20, 2406, 2413 (AVR), 2450,..,MQTT2, KNX, SONOFF, mySENSORS,....
Hardware:  Busware ROT, Weinzierl IP731, 1-Wire GW,...

betateilchen

Zitat von: erwin am 29 Februar 2024, 20:36:29etwas abwegig finde ich allerdings 2e-05 als Wert (W/kW)? von einem Wechselrichter - das ist jedenfalls jenseits jeder Messgenauigkeit...Da wäre mein Ansatz für einen fix!

Darauf wollte ich nicht explizit eingehen, ich sehe das aber ähnlich. Da würde ich schon in HTTPMOD oder JsonMod oder wo auch immer die Werte eingelesen werden, dafür sorgen, dass Werte < 1 als 0 interpretiert werden.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

AlexMuc

@erwin:
Wenn das so ist, dann hab ich tatsächlich den vorgesehenen Einsatzzweck für ReadingsNum falsch verstanden. Ich dachte, man nimmt es, wann immer man eine Zahl aus einem Reading holen will. Wenn es aber ,,nur" dazu dient, möglichst einfach eine Zahl aus einem Text herauszuoperieren, dann wechsel ich wieder zurück auf ReadingsVal.

@betateilchen:
Ich müßte nochmal die Logs prüfen, ob diese Zahl erst entstanden ist, nachdem ich die Energie zweier Strings addiert hab oder die schon in den Eingangsreadings auftauchen. Klar ist auch, das in meinem speziellen Fall da eher ne klare 0 sein sollte und ich das inzwischen für mich ja auch gelöst habe.

@alle:
Wenn keiner was dagegen hat, können wir den von mir angestoßenen Sturm im Wasserglas beenden. Außer es findet noch jemand einen wichtigen Grund doch weiterzumachen :-)

rudolfkoenig

ZitatKönnte man ReadingsNum() nicht so erweitern, dass der Wert unverändert zurückgegeben wird, wenn ReadingsVal() schon einen rein numerischen Wert liefert?
Das habe ich jetzt wie vorgeschlagen gemacht.

Ich glaube, dass wir moegliche Problem-Meldungen damit erfolgreich niederdiskutieren koennen :)

betateilchen

Zitat von: rudolfkoenig am 01 März 2024, 17:14:07Ich glaube, dass wir moegliche Problem-Meldungen damit erfolgreich niederdiskutieren koennen :)

Das hoffe ich auch. Auf meine Unterstützung kannst Du dabei zählen 8)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

frober

#11
Hi, prinzipiell eine gute Lösung, nur funktioniert das Runden so nicht mehr, wenn direkt eine Zahl geliefert wird.

Klar kann man das auch anders lösen, aber es stiftet Verwirrung, wenn Runden mal funktioniert mal nicht...

Vorschlag:
return round($val,$round) if(looks_like_number($val));

...ich hoffe ich habe nichts übersehen.

Nachtrag,:
if(defined $round)
fehlt, wie macht man das am besten, 2 Zeilen?

return round($val,$round) if(looks_like_number($val) && defined $round);
return $val if(looks_like_number($val));
Raspi 3b mit Raspbian Buster und relativ aktuellem Fhem,  FS20, LGW, PCA301, Zigbee, MQTT, MySensors mit RS485(CAN-Receiver) und RFM69, etc.,
einiges umgesetzt, vieles in Planung, smile

********************************************
...man wächst mit der Herausforderung...

noansi

#12
Hallo Rudolf,

ZitatBin unschluessig: eigentlich hat AlexMuc recht, andererseits wuerde eine Aenderung womoeglich funktionierenden Code brechen, da ReadingsNum alt ist.
Wird zwei Zeilen nach dem Fix zutreffen betateilchen, octal numbers, da z.B.

{ looks_like_number("04") }oder
{ looks_like_number("04.3") }
eine 1 liefert.
Damit wird der Octal Fix nicht mehr erreicht.

Warum soll wissenschaftliche Notation nicht einfach auch als Num erlaubt werden?:
  $val = ($val =~ m/([-]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?)/ ? $1 : '');statt nur
  $val = ($val =~ /(-?\d+(\.\d+)?)/ ? $1 : "");
Gruß, Ansgar.

Edit: InternalNum ist bezüglich beider Probleme/Fragestellungen ebenfalls betroffen und die Verwirrung wäre geringer, würden sich InternalNum und ReadingsNum gleich verhalten.

rudolfkoenig

Offensichtlich war mein Gefuehl, dass eine beliebige Aenderung im alten Code Probleme verursacht richtig, und dass man die kleine Aenderung niederdiskutieren kann, falsch.

ZitatWarum soll wissenschaftliche Notation nicht einfach auch als Num erlaubt werden?:
Weil ein Regexp dafuer nicht einfach ist, deine Version erwischt z.Bsp. .12 nicht.
Ich habe jetzt die Version aus dem perl cookbook genommen, und looks_like_numer rausgeschmissen.

ZitatInternalNum ist bezüglich beider Probleme/Fragestellungen ebenfalls betroffen und die Verwirrung wäre geringer, würden sich InternalNum und ReadingsNum gleich verhalten.
Danke fuer den Hinweis, ab sofort wird aus allen drei "Num" Funktionen die neue numberFromString aufgerufen.

noansi

Hallo Rudolf,

ZitatWeil ein Regexp dafuer nicht einfach ist, deine Version erwischt z.Bsp. .12 nicht.
Korrekt und korrekt.

Ich hatte aus der alten regexp interpretiert, dass so "kaputte" Zahlen nicht erwünscht sind und waren.

Mit der von Dir gewählten C-Style Variante wäre auch ein Reading/Internal
Das ist ein mehrdeutiges Reading.12Uhr könnte gemeint sein.eher problematisch bezüglich Kompatibilität.

Wenn sich keine Nebenwirkungen an bestehendem Code durch diese größere Offenheit ergeben, würde ich jedoch Deine Variante ebenfalls bevorzugen.

Gruß, Ansgar.