[gelöst] Syntax von stateFormat

Begonnen von reini3549, 14 September 2014, 13:22:17

Vorheriges Thema - Nächstes Thema

reini3549

Hallo
kann mir bitte jemand helfen
Ich möchte den Inhalt der dummy Variable Tagesverbrauch formatiert ausgeben.
attr Tagesverbrauch stateFormat {sprintf("%.2f kWh")} gibt natürlich nur 0.00 kWh aus. Wie muss ich die Zeile schreiben, dass der Inhalt der Variablen genommen wird?

LG
Reinhard

Puschel74

Hallo,

stateFormat {sprintf("%.2f"." W",ReadingsVal("Laptop_Lader_Mess","power",0))}

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

reini3549

danke!
Nur zum Verständnis, d.h. ich kann die Formatierung nur beim Einlesen vom Gerät (SO Zähler), bei mir in einem Modul in der 99_myUtils.pm machen. Die dummy Vatiable habe ich ja in der cfg definiert. Das Modul wird immer um Mitternacht gestartet. Da gibt es keine Möglichkeit die Formatierung in der cfg zu machen? state wird immer richtig aktualisiert, nur halt mit zig Kommastellen.

hexenmeister

Wie meinst Du das? Welche Möglichkeit fehlt Dir noch? Du kannst ja alles in stateFormat machen... Ist doch "in cfg"...
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

reini3549

Danke für die Antwort

ich habe folgendes in der cfg definiert:

# Ermittlung Strom Tagesverbrauch
define DailyPowerDiff dummy
attr DailyPowerDiff room hidden
define Tagesverbrauch dummy
attr Tagesverbrauch room Flur
# attr Tagesverbrauch stateFormat {sprintf("%.2f kWh")...............} hier möchte ich die Formatierung machen
define Tagesverbrauch_Haushalt at *23:59 {prg_Daily_Stat}


LG
Reinhard


hexenmeister

Verstehe nicht ganz, was das tun soll...
Hast Du eine Funktion, die die Werte liefert und per AT in ein DUMMY schreibt? Und diesen möchtest Du noch formatieren? Warum dann nicht gleich in der Funktion selbst? Und auch wenn so, dann wo liegt noch das Problem? Bei Deinem sprintf fehlt natürlich noch der eigentliche Wert... etwas so:
...stateFormat {sprintf("%.2f kWh", ReadingsVal($name,"wasweissich",0))}

Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

reini3549

danke habs verstanden. Ich wollte es nicht in der Funktion machen, sondern direkt beim dummy, das wird ja ausgegeben, und wollte wissen wie es geht. Dachte es ist so eleganter.

reini3549

Entschuldigt, habs doch noch nicht verstanden.

in der cfg steht folgendes:

# Ermittlung Strom Tagesverbrauch
define DailyPowerDiff dummy
attr DailyPowerDiff room hidden
define DailyPower dummy
attr DailyPower room Flur
define Tagesverbrauch_Haushalt at *23:59 {prg_Daily_Stat}


in der 99_myUtils.pm folgendes:
sub
prg_Daily_Stat()
{
#
# Zunächst Differenz aktueller Wert - Wert von Gestern berechnen
$data{DPval} = ReadingsVal("Counter","counters.A",0)/1000.0 - Value("DailyPowerDiff");
# Tagesverbrauch in DailyPower speichern
fhem ("set DailyPower $data{DPval}");
# Aktuellen Wert speichern
$data{DPval} = ReadingsVal("Counter","counters.A",0)/1000.0;
fhem ("set DailyPowerDiff $data{DPval}");
}


Das Ganze funktioniert, aber ich bekomme die Formatierung nicht hin. Wo und wie schreibe ich das stateFormat hin, Kann ich das in der cfg machen, oder nur im Unterprogram.

Vielen Dank
Reinhard

hexenmeister

stateFormat ist ein Attribut an dem Device, dessen Reading Du umformatieren möchtest. Du kannst das Ganze in der Weboberfläche erzeugen.
Das wäre dann Config. Aber auch eine Formatierung im Code ist genauso möglich. Beantwortet das Deine Frage, oder habe ich Dich nicht richtig verstanden?
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

reini3549

vielen Dank, die Theorie war mir schon klar, aber am wie scheitere ich noch. Ich habs über die  Weboberfläche versucht, also in der config, bekomme dann aber keinen Wert mehr ausgegeben, sondern 0,00 kWh. Ich mache also was falsch?

Das es so nicht passt ist mir schon klar:

attr DailyPower stateFormat {sprintf("%.2f kWh",ReadingsVal($name,"DailyPower","?"))}

aber wie schreibe ich das Ganze, wenn ich den Inhalt der Dummy Variablen formatiert ausgeben möchte?

viele Grüße
Reinhard



hexenmeister

Ich glaube, ich fange an, das Problem zu verstehen ;)
ReadingsVal liest in Deinem Fall ein Reading namens 'DailyPower' aud dem Dummy 'DailyPower'. Das Reading gibt es dort gar nicht. Also entweder Du setzt in Deinem Perl-Code ein entsprechendes Reading (mit setreading), oder, wenn Du Reading 'state' nutzt (mit set), dann benutze das:
attr DailyPower stateFormat {sprintf("%.2f kWh",ReadingsVal($name,"state","?"))}
Das setzt den internen Wert STATE (ist nicht ganz das gleiche wie Reading 'state') auf den formatierten String.


Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

reini3549

Hallo Hexenmeister,

vielen Dank, so funktioniert es. Jetzt hab ich es dank deiner Hilfe verstanden.

LG
Reinhard

Puschel74

Hallo,

Beiträge bitte nicht schließen.
Ein gelöst vor dem Titel genügt - siehe die anderen Beiträge.
Danke.

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

reini3549

Ok, sorry wusste ich nicht, bin ja neu hier

LG
Reinhard

Puschel74

Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

Christian72D

Wie kann ich eine Ausgabe einkürzen?

Ich habe als stateFormat für meinen Abfall Kalender folgendes: "next_text am next_date (next_weekday)".
Aber: in "next_date" steht auch die Uhrzeit am Ende, wie kann ich das auf die ersten 6 Zeichen einkürzen?


Christian72D

Und wie genau?
Wenn ich jetzt "next_text am {substr next_date, 4, 5;} (next_weekday)" eingebe klappt es nicht, er gibt es komplett so aus.

dev0

commandref/stateFormat:
Zitat
If the value of this attribute is enclused in {}, then it is evaluated.
Der komplette Wert (value) des Attributs muss ein gültiger Perlausdruck sein, nicht nur ein Teil davon. Wie zB. im 2. Beitrag dieses Threads gezeigt.

Christian72D

Ich komme nicht weiter...

SO läuft es jetzt: stateFormat {sprintf(ReadingsVal("Muelltonnen","next_date",0), ReadingsVal("Muelltonnen","next_weekday",0))}

Aber dann bekomme ich das substr nicht eingebunden.

dev0

ZitatIch komme nicht weiter...
Kann ich Dich mit Links zu Perlgrundlagen unterstützen?

Christian72D

Sorry, aber um 1x ein Problem zu lösen macht es m.M. nach wenig Sinn.

Wäre das selbe als wenn ich 1x in meinem Leben in einem besteimmten Land drei wochen Urlaub mache und dann die ganze Sprache lerne.

chq

#22
Mir geht es zwar im Hinblick auf dieses Problem (siehe Link) eigentlich genauso, wäre u.U. aber trotzdem an Links interessiert; zumindest mehr als daran, dass in diesem Thema seit 120 Tagen nichts mehr geschrieben wurde.  ;D

Wenn ich mir Perl Grundlagen anschaue und diese mit dem einzeiligen funktionierenden Code (siehe Link) vergleich, verstehe ich z.B. gleich zu Beginn nicht, warum diese eine Zeile (siehe Link) funktioniert, obwohl die darin enthaltenen Befehle nicht mit ";" abgeschlossen werden. Bitte keine aufs Dach haun fürs Crossposting. Ich such mir nur nen Wolf für mein Problem und find selbst in den tiefsten Tiefen des Forums nix Passendes.  :(

Gruß Chris

Link: https://forum.fhem.de/index.php/topic,98357.msg917562.html#msg917562
So einfach wie möglich, so kompliziert wie nötig

Otto123

#23
Hi Chris,

irgendwie versteh ich deine Frage nicht!?
Perl Befehle müssen "im Block" von einander mit ; getrennt werden. Ob die in mehreren oder einer Zeile stehen spielt keine Rolle.
Beispiel: 2 Befehle in einem Perl Script (am Ende der Große Block aussen herum)
my $s = "The black cat climbed the green tree";
my $color  = substr $s, 4, 5; 


In deinem Link ist ein Befehl mit einzelnen Perlblöcken {}:
{if(Bedingung) {Perlbefehl} else {Perl Befehl}}
Bei meheren Befehlen im Block sähe es so aus.
{if(Bedingung) {Perlbefehl1;Befehl2;Befehl3} else {Perlbefehl1;Befehl2;Befehl3;Befehl4}}

Ein Zitat aus perldoc.perl.org
ZitatBut generally, a block is delimited by curly brackets, also known as braces. We will call this syntactic construct a BLOCK.

The following compound statements may be used to control flow:

    if (EXPR) BLOCK
    if (EXPR) BLOCK else BLOCK
    if (EXPR) BLOCK elsif (EXPR) BLOCK ...
    if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
...

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

chq

Aber hier finden doch z.B. ganz viele Dinge völlig unabhängig in einem Block statt, ohne dass auch nur ein einziges ";" gesetzt ist:

{"Wind: ".round(ReadingsVal("Wetterstation","wind_speed",0),0).
" Böen: ".round(ReadingsVal("Wetterstation","wind_gust",0),0).
"<br>UVR: ".round(ReadingsVal("Wetterstation","UVR",0),1).
" LF: ".round(ReadingsVal("Wetterstation","humidity",0),0)."%"}


Da findet wohl eine Trennung durch Punkte statt. Mache ich dann aber das hier..

{"Wind: ".round(ReadingsVal("Wetterstation","wind_speed",0),0).
" Böen: ".round(ReadingsVal("Wetterstation","wind_gust",0),0).
"<br>UVR: ".round(ReadingsVal("Wetterstation","UVR",0),1).
" Hum: ".round(ReadingsVal("Wetterstation","humidity",0),0).
if(ReadingsVal("Wetterstation","UVR",0)>=10) {round(ReadingsVal("Wetterstation","UVR",0),0)} else {round(ReadingsVal("Wetterstation","UVR",0),1)}


..kommt eine Fehlermeldung.  :-\
So einfach wie möglich, so kompliziert wie nötig

Wernieman

Weil der "." kein ";" ist, sondern Strings verbindet ....

Auch fehlt mir eigentlich ein print o.Ä.
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

Beta-User

Zitat von: Wernieman am 11 März 2019, 14:37:50
Weil der "." kein ";" ist, sondern Strings verbindet ....

Auch fehlt mir eigentlich ein print o.Ä.
Hmm, na ja, "an sich" funktioniert das schon, aber dann müssen m.E. die einzelnen Anweisungen unmittelbar Ergebnisse liefern. Deswegen funktioniert der erste code vermutlich, der zweite nicht (vielleicht aber doch, wenn man eine Klammer um die if-Geschichte macht).

(Unterstellt, der erste geht wirklich,) müßte eigentlich sowas hier auch gehen:
{my $uvr = round(ReadingsVal("Wetterstation","UVR",0),1); $uvr = round(ReadingsVal("Wetterstation","UVR",0),0) if(ReadingsVal("Wetterstation","UVR",0)>=10);
"Wind: ".round(ReadingsVal("Wetterstation","wind_speed",0),0).
" Böen: ".round(ReadingsVal("Wetterstation","wind_gust",0),0).
"<br>UVR: ".$uvr.
" Hum: ".round(ReadingsVal("Wetterstation","humidity",0),0)}

Aber m.E. ist es übersichtlicher, erst ein paar Variablen zu definieren und dann hinterher nur den Gesamtausdruck zusammenzusetzen.

Auch möglich: den Rückgabewert erst zu initialisieren (my $ret;) und dann jeweils $ret .= "Wind: ".round(ReadingsVal("Wetterstation","wind_speed",0),0);
Und am Ende dann $ret zurückgeben.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

chq

Ich musste im Rahmen meines FHEM-Systems bisher noch keine Variablen selber definieren, von daher hatte ich mich bisher noch nicht damit beschäftigt. Ich werde mich da aber mal reinlesen. Der Code funktioniert jedenfalls astrein, Beta-User. Vielen Dank!

Gruß Chris
So einfach wie möglich, so kompliziert wie nötig

Beta-User

Danke für die Rückmeldung.

Habe erst nach dem "Schreiben" noch eine kleine Optimierungsmöglichkeit gesehen:
$uvr = round($uvr,0) if($uvr>=10);
(Statt der wiederholten Rückgriffe auf das Reading).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Otto123

@Chris Noch zur Erklärung:

Was Du da in #24 hast ist von der Sache her kein Block mit Perl Befehlen die nacheinander abgearbeitet werden  sondern ein String, der aus mehreren Ergebnissen von Perl Befehlen zusammengesetzt wird -> concatenation falls Du nachlesen willst. Die concatenation passiert mit dem Punkt zwischen den Strings.
{"Wind: ".Befehl1(Befehl2(),0).
" Böen: ".Befehl3(Befehl4(),0).
"<br>UVR: ".Befehl5.
" LF: ".Befehl6."%"}

Jeder Befehl könnte aber auch wieder ein Perl Block sein, ist es aber in deinem Fall nicht. Ein Befehl ruft den anderen als Sub auf, da braucht es kein Semikolon.

Bei dem Code von Beta User ist das dann genau der Fall: Er baut vornan einen Befehlsblock am Ende wird dann wieder der String zusammen getackert.

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