[gelöst]Ablaufsteuerung mit Perl, wie?

Begonnen von matze1999, 17 Juni 2022, 10:22:37

Vorheriges Thema - Nächstes Thema

Beta-User

Zitat von: matze1999 am 01 Juli 2022, 08:39:54
kann mann perl code in userreadings einbinden (es geht um das "hochzählen bis 6"?
In userReadings MUSS man mit Perl-Code arbeiten, und es gibt auch eine FHEM-Funktion "Each" (nicht: Perl-each!), mit der man sowas umsetzen könnte. Der Haken daran: der aktuelle Index-Wert wird als Internal verwaltet, was bedeutet, dass dieses Spiel von vorne losginge. Da wir es hier aber sowieso "nur" mit Zahlen zu tun haben, wäre der alte Reading-Wert der bessere Zwischenspeicher...

das ist relativ simple, der Trigger ist der state vom Bewässerungs Device:
Der Haken daran: als userReadings-trigger ist das nur dann geeignet, wenn es um _dasselbe_ Device geht.
Da das on/off am Bewässerungs-Device aber sowieso eine Folge aus dem ist, was du in der Bewässerungssteuerung machst, würde ich eher timer-basiert arbeiten, was aber ein Problem ist, wenn jemand das Bewässerungs-Device separat oder manuell/direkt vor Ort schaltet. Daher der Hinweis, dass es eine Möglichkeit geben muss, das wieder gradezuziehen (was wieder gegen eine Each-Lösung spräche bzw. die komplizierter machen würde).
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

MadMax-FHEM

#31
Zitat von: matze1999 am 01 Juli 2022, 08:39:54

kann mann perl code in userreadings einbinden (es geht um das "hochzählen bis 6"?

matze1999

Klar, steht doch in der commandref ;)

Zitat von: https://fhem.de/commandref_DE.html
userReadings
Komma getrennte Liste von benutzerdefinierten Readings. Jede Definition hat folgendes Format:

    <reading>[:<trigger>] [<modifier>] { <perl code> }

Diese benutzerdefinierte Readings werden bei jeder Aktualisierung der Gerätereadings gesetzt, indem das spezifizierte perl code { <perl code> } ausgeführt wird, und dessen Wert dem Reading zugewiesen wird. Falls <trigger> spezifiziert ist, dann findet diese Ausführung nur dann statt, falls einer der aktualisierten Readings dem regexp <trigger> entspricht (matched).
Beispiele:

    attr myEnergyMeter userReadings energy { ReadingsVal("myEnergyMeter","counters.A",0)/1250.0;; }
    attr myMultiMeter userReadings energy1:counters.A.* {ReadingsVal("myMultiMeter","counters.A",0)/1250.0}, energy2:counters.B.* {ReadingsVal("myMultiMeter","counters.B",0)/1250.0}


<modifier> kann die folgenden Werte haben:

    none: als ob man es gar nicht spezifiziert hätte.
    difference: das Reading wird auf die Differenz zw. dem aktuellen und dem vorherigen Wert gesetzt.
    differential: das Reading wird auf die Differenz zw. dem aktuellen und dem vorherigen Wert, geteilt durch die Sekunden zw. der aktuellen Zeit und der letzten Auswertung, sekundengenau. Kein Wert wird berechnet, falls der Unterschied unter eine Sekunde liegt.
    integral: das Gegenteil von differential. Das Ergebnis wird um das Produkt aus der Zeit-Differenz und der Durschnittswert der letzten zwei Readings erhöht.
    result += (time - timeold) * (oldval + value) / 2
    offset: wenn der aktuellen Wert kleiner als der vorherige Wert ist wird der vorherige Wert zum Reading addiert. Das Reading kann dann als offset verwendet werden um einen Zähler der durch Sromverlust zurückgesetzt wird zu korrigieren.
    monotonic: wenn die Differenz zw. dem aktuellen und dem vorherigen Wert positiv ist wird diese Differenz zum Reading addiert. Damit lässt sich von einem Zähler der bei Stromverlust zurückgesetzt wird ein monoton wachsender Zähler ableiten.

Beispiel:

    attr myPowerMeter userReadings power differential { ReadingsVal("myPowerMeter","counters.A",0)/1250.0}

Achtung:

    Falls difference oder differential spezifiziert ist, dann werden für die Berechnung ältere Werte benötigt, d.h. der Wert wird frühestens beim zweiten Änderung gesetzt.
    der Name der definierten Readings besteht aus alphanumerischen Zeichen, Unterstrich (_) und Minus-Zeichen (-).


Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

matze1999

So, erster versuch, funktioniert nicht:

defmod Ventilstellung.nt notify MQTT2_DVES_6C3AB1_CH2:.* {\
return if !$EVENT;;\
my @ventil;;\
\
    if ( $EVENT eq "on" && @ventil eq 6 ) {\
           @ventil = 1;;\
    } elsif ( $EVENT eq "on" && @ventil < 6 ) {\
           @ventil = @ventil + 1;;\
    } \
fhem("setreading MQTT2_DVES_6C3AB1_CH2 ventilnr @ventil");;\
;;\
}
attr Ventilstellung.nt room Bewässerung,Garten,nt+di

setstate Ventilstellung.nt active
setstate Ventilstellung.nt 2022-07-03 12:27:54 state active
setstate Ventilstellung.nt 2022-07-03 12:25:46 triggeredByDev MQTT2_DVES_6C3AB1_CH2
setstate Ventilstellung.nt 2022-07-03 12:25:46 triggeredByEvent on


Damit @ventil auch ausserhalb der Routine verfügbar ist habe ich in 99_myUtils.pm

das eingefügt:


# Enter you functions below _this_ line.

use vars qw(@ventil);
@ventil = 1;
l

Ich hab erst mal ein notify geamcht, um das mit einer Lampe zu testen.

matze1999

Beta-User

Zitat von: matze1999 am 03 Juli 2022, 12:32:43
So, erster versuch, funktioniert nicht:
Hast du im Log geschaut, was fhem.pl dazu "anmeckert"?

Lese-/Such-Tipp: Perl Data Types.
Du willst keine Liste (Array) haben, sondern einen einzelnen Wert (Scalar)...

ZitatDamit @ventil auch ausserhalb der Routine verfügbar ist habe ich in 99_myUtils.pm
Mehrfach ungeschickter Ansatz:
- Variablennamen im Main-Kontext sollten unverwechselbar sein. Meine Empfehlung wäre (hier aber nicht!) irgendeinen "Präfix" davor zu machen, aus dem sich ergibt, dass das von User-Seite her kommt (myActiveValveNr)
- Es gibt aber bessere Varianten, um innerhalb FHEM Daten zwischenzuspeichern:
-- Readings (!). Das ist m.E. der richtige Weg für einzelnen Scalar, v.a. dann, wenn der Wert eigentlich irgendwo an ein FHEM-Device gehört (wie hier)...
-- %data. Kann auch genutzt werden für komplexere Datenstrukturen. Ist aber nach meinem Eindruck eher selten, dass man das wirklich braucht...
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

matze1999

neuer Versuch, funktioniert erst mal:

defmod Ventilstellung.nt notify MQTT2_DVES_6C3AB1_CH2:on {\
my $ventil = ReadingsVal("Ventilstellung.nt","ventilnr",0);;\
\
\
    if ( $ventil ne 6 ) {\
           $ventil = $ventil + 1;;\
    } elsif ( $ventil eq 6 ) {\
           $ventil = 1;;\
    } \
fhem("setreading Ventilstellung.nt ventilnr $ventil");;\
;;\
}


Irgendwas, was ich übersehen habe?

matze1999

matze1999

So, jetzt wollte ich das als userreading in das eigentliche Devce rein bringen:

attr HUEDevice8 userReadings HUEDevice8:off {\
my $ventil = ReadingsVal("HUEDevice8","VentilNr",1);;\
\
\
    if ( $ventil ne 6 ) {\
           $ventil = $ventil + 1;;\
    } elsif ( $ventil eq 6 ) {\
           $ventil = 1;;\
    } \
fhem("setreading HUEDevice8 VentilNr $ventil");;\
;;\
}


Dann kommt aber folgende Fehlermeldung im Log:

2022.07.03 15:44:12 4: parse status message for HUEDevice8
2022.07.03 15:44:12 5: Cmd: >setreading HUEDevice8 VentilNr 3<
2022.07.03 15:44:12 1: 'setreading HUEDevice8 VentilNr 3' called form userReadings is prohibited
2022.07.03 15:44:12 1: PERL WARNING: HUEDevice8 userReadings HUEDevice8 evaluated to undef at fhem.pl line 4917.
2022.07.03 15:44:12 3: eval: {
my $ventil = ReadingsVal("HUEDevice8","VentilNr",1);


    if ( $ventil ne 6 ) {
           $ventil = $ventil + 1;
    } elsif ( $ventil eq 6 ) {
           $ventil = 1;
    }
fhem("setreading HUEDevice8 VentilNr $ventil");
;
}


'setreading HUEDevice8 VentilNr 3' called form userReadings is prohibited

das geht wohl generell nicht, ich muss ein externes notify nehmen, dann sollte es gehen.

Und die Warnung verstehe ich nicht:

PERL WARNING: HUEDevice8 userReadings HUEDevice8 evaluated to undef at fhem.pl line 4917.

matze1999

MadMax-FHEM

#36
Damit soll verhindert werden, dass eine Event-Loop "von sich selbst aus" erneut triggert.

Weil du bist ja in einem notify/userReadings/... eines Devices und darin geht dann setreading Device Reading Wert nicht, weil du damit ja u.U. erneut triggerst usw. -> "Endlosschleife"...

Wenn du userReadings mit Trigger verwendest und dieser dafür sorgt, dass das nicht passiert, dann kannst du folgendes tun:


fhem("sleep0.1; setreading HUEDevice8 VentilNr $ventil");


EDIT: bzw. über Eingabe ALLES per FhemWeb-Eingabezeile, dann eben doppelte Strichpunkte... BTW: müssen die ganzen doppelten Strichpunkte am Ende wirklich?

Aber wie geschrieben: wenn du nicht sauber gearbeitet hast, dann "zerlegt" es dich ;)

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

Beta-User

Zitat von: matze1999 am 03 Juli 2022, 15:50:06
das geht wohl generell nicht, ich muss ein externes notify nehmen, dann sollte es gehen.
Das ist so nicht richtig. setreading hatte ich vorgeschlagen, weil es an den dummy gehört, und eben nicht an den Aktor. Aber wenn man es richtig macht, braucht man auch den Umweg über das sleep hier (!) nicht...

Aber erst solltest du dich mit der Syntax von userReadings vertraut machen - das was du geschrieben hattest, klang nach einem mehrfachen Missverständnis, sowohl was den Namen des userReadings angeht, wie auch den trigger und den Rückgabewert...
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

matze1999

ich hab die Strichpunkte raus genommen und lass es bei dem notify.

ich würde gern noch einen "Informations" Dummy mit dem Reading versorgen, irgendwie gelingt mir das nicht, das habe ich mit Strichpunkten versucht.

1.
HUEDevice8:off {
my $ventil = ReadingsVal("HUEDevice8","VentilNr",0);


    if ( $ventil ne 6 ) {
           $ventil = $ventil + 1
    } elsif ( $ventil eq 6 ) {
           $ventil = 1
    }
fhem("setreading HUEDevice8 VentilNr $ventil ; set manuelle.Beregnung VentilNr $ventil")
}


HUEDevice8:off {
my $ventil = ReadingsVal("HUEDevice8","VentilNr",0);


    if ( $ventil ne 6 ) {
           $ventil = $ventil + 1
    } elsif ( $ventil eq 6 ) {
           $ventil = 1
    }
fhem("setreading HUEDevice8 VentilNr $ventil ;; set manuelle.Beregnung VentilNr $ventil")
}


matze1999

MadMax-FHEM

#39
Zitat von: Beta-User am 03 Juli 2022, 16:34:31
Das ist so nicht richtig. setreading hatte ich vorgeschlagen, weil es an den dummy gehört, und eben nicht an den Aktor. Aber wenn man es richtig macht, braucht man auch den Umweg über das sleep hier (!) nicht...

Ups, richtig ;)

Ja, man kann/sollte den Namen des gewünschten Readings nehmen und einfach zurückgeben: fertig 8)

@matze1999:

Zitat
fhem("setreading HUEDevice8 VentilNr $ventil ;; set manuelle.Beregnung VentilNr $ventil")

Also setreading DeviceName ReadingName Wert vs. set DeviceName Wert / fällt was auf?

Entweder setzt du bei deinem komischen manuell-Dummy ein Reading, dann eben wieder setreading oder es sollte (da dummy) eigentlich sogar VentilNr X (mit X = die entspr. "errechnete" Nummer) in state stehen...
EDIT: alternativ geht auch die setList des dummy entsprechend angeben, dann klappt auch der set ;)

Evtl. statt (einfach) trial & error etwas einlesen/einarbeiten und dein ganzes Konstrukt noch mal (in Ruhe) durchdenken? ;)

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

Beta-User

Zitat von: matze1999 am 03 Juli 2022, 16:36:17
irgendwie gelingt mir das nicht, das habe ich mit Strichpunkten versucht.
Was steht im log?

Mein Tipp: es gibt in dem dummy dieses Reading nicht als setzbares 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

matze1999

 ;D
funktioniert nun alles wie gewünscht:

defmod Ventilstellung.nt notify HUEDevice8:off {\
my $ventil = ReadingsVal("HUEDevice8","VentilNr",1);;\
\
\
    if ( $ventil < 6 ) {\
           $ventil = $ventil + 1\
    } elsif ( $ventil > 5 ) {\
           $ventil = 1\
    } \
fhem("setreading HUEDevice8,manuelle.Beregnung VentilNr $ventil")\
}


matze1999