FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: stobor am 24 Dezember 2021, 11:51:14

Titel: Wiederholende Prozeduren auslagern?
Beitrag von: stobor am 24 Dezember 2021, 11:51:14
Hallo,

ich habe immer wieder auftretende Prozeduren, die durch unterschiedliche Sensoren ausgelöst werden. Bisher schreibe ich die Abläufe für jedes Gerät separat. So wie hier:

define PIR_SuedHM_aus notify Bewegungsmelder_Sued_HM:motion:.on.* {\
if ((Value("PIR_Automatik") eq "on") && (Value("isNACHT") eq "on") && ((Value("Arduino_Pin4_Licht_Sued") eq "off") || (defined(InternalVal('Arduino_Pin4_Licht_Sued','TIMED_OnOff',undef)) eq "1"))) {\
fhem "set Arduino_Pin4_Licht_Sued on-for-timer 320";;\
if (Value("UeberwachungEG") eq "on") {\
fhem "set HM_Sw_Kueche_Sued on-for-timer 120";;\
}\
fhem "delete PIR_SD_aus";;\
fhem "define PIR_SD_aus at +00:05:00 set Bewegungsmelder_Sued_West,Bewegungsmelder_Sued_HM off";;\
} else {\
fhem "delete PIR_SD_aus";;\
fhem "define PIR_SD_aus at +00:05:00 set Bewegungsmelder_Sued_West,Bewegungsmelder_Sued_HM off";;\
}\
if (Value("UeberwachungEG") eq "on") {\
  my $date = strftime "%a %e.%m.%Y %H.%M.%S", localtime;;\
  fhem "attr SSCam.Sued snapEmailTxt subject => Bewegungsalarm PIR Sued Ost, body => $date - Kamera Sued";;\
  fhem "set SSCam.Sued snap 6 2";;\
  fhem "attr SSCam.Ost snapEmailTxt subject => Bewegungsalarm PIR Sued Ost, body => $date - Kamera Ost";;\
  fhem "set SSCam.Ost snap 6 2";;\
  fhem "attr SSCam.Nord_Ost snapEmailTxt subject => Bewegungsalarm PIR Sued Ost, body => $date - Kamera Nord_Ost";;\
  fhem "set SSCam.Nord_Ost snap 6 2";;\
}\
}


Kann man das irgendwie zentral auslagern? Wie? Was müsste ich genau tun?
Wie kann ich ggf. Parameter mitgeben, da zum Teil etwas andere Abläufe innerhalb der Prozedur erfolgen sollen - je nach auslösendem Gerät sollen bspw. andere Kamerabilder gesendet werden?
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: Wernieman am 24 Dezember 2021, 11:55:06
Eine Funktion in myUtils anlegen
https://wiki.fhem.de/wiki/99_myUtils_anlegen (https://wiki.fhem.de/wiki/99_myUtils_anlegen)

Per Perl-Parameterübergabe sind auch Variablenübergabe möglich.

Hinweis:
Sind das Ausgaben direkt aus der fhem.cfg? Besser innerhalb von fhem bearbeiten ....
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: stobor am 24 Dezember 2021, 13:19:28
Zitat von: Wernieman am 24 Dezember 2021, 11:55:06
Eine Funktion in myUtils anlegen
https://wiki.fhem.de/wiki/99_myUtils_anlegen (https://wiki.fhem.de/wiki/99_myUtils_anlegen)

Per Perl-Parameterübergabe sind auch Variablenübergabe möglich.

Hinweis:
Sind das Ausgaben direkt aus der fhem.cfg? Besser innerhalb von fhem bearbeiten ....

Wie würde der Code denn innerhalb von FHEM aussehen?

Wie würde das denn in Pearl aussehen Aufrufe mit Parameter) - sowohl in Pearl (Funktionskopf) als auch der Aufruf selber?
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: Wernieman am 24 Dezember 2021, 13:33:23
Hast Du Dir den Link durchgelesen? Sind doch Beispiele drin ...
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: MadMax-FHEM am 24 Dezember 2021, 14:00:13
Zitat von: Wernieman am 24 Dezember 2021, 13:33:23
Hast Du Dir den Link durchgelesen? Sind doch Beispiele drin ...

Eben, hier z.B.: https://wiki.fhem.de/wiki/99_myUtils_anlegen#Eigene_Routinen_einf.C3.BCgen

Für dein Beispiel dann:


define PIR_SuedHM_aus notify Bewegungsmelder_Sued_HM:motion:.on.* {meineSub($NAME)}


so wird dann eben das auslösende Device übergeben...

In der Sub dann entweder mittels "shift" oder eben (wie im Wiki) my ($obj) = @_; dann steht in $obj eben der Devicename...

Wenn du nun das notify "weiter" gestaltest und eine gute Namensgebung deiner Devices hast, dann hast du in der Sub doch alles was du brauchst... ;)

Wenn z.B. bestimmte Device-Typen im selben Raum dann "zusammengehören", dann kannst du ja z.B. den Raum des triggernden Devices abfragen und dich so durch die dazu gehörenden anderen Devices "hangeln" etc.
Gibt viele weitere Möglichkeiten...
Stichwort: devspec

Anmerkungen: nimm nicht Value!! Sondern ReadingsVal/ReadingsNum! (Value "frägt" STATE das INTERNAL!! ab nicht state! Und: STATE kann/wird z.B. durch stateFormat beeinflusst)

Und warum setzt du attribute?
Gibt das "unschöne" Fragezeichen und bei shutdown/restart sind die "weg"...
(gut evtl. kann das das Modul nicht anders: ist aber unschön)

Gruß, Joachim
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: Prof. Dr. Peter Henning am 24 Dezember 2021, 21:19:00
Und es heißt nicht
ZitatPearl
.

LG

pah
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: stobor am 08 Juni 2022, 10:26:42
Muss ich tatsächlich alle Werte, die ich irgendwie abprüfen möchte als Parameter mit übergeben?
Ich werte ja bspw.
aus.

Würde das dann so aussehen:
define PIR_SuedHM_aus notify Bewegungsmelder_Sued_HM:motion:.on.* { myCode($NAME , Value("PIR_Automatik") , Value("isNACHT") , Value("Arduino_Pin4_Licht_Sued") , InternalVal('Arduino_Pin4_Licht_Sued','TIMED_OnOff',undef)) }

mit
sub myCode($$$$){
   my ($object , $Automatik , $Nacht , $LichtSued , $LichtSuedInt) = @_;
   ...
}

Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: Beta-User am 08 Juni 2022, 11:10:50
Zitat von: stobor am 08 Juni 2022, 10:26:42
Muss ich tatsächlich alle Werte, die ich irgendwie abprüfen möchte als Parameter mit übergeben?
Jein!

a) Wenn du dich mit Prototypen so "einmauerst", musst du die als zwingend gemarkterten Parameter ("sub myCode($$$$)") auch tatsächlich angeben. Man kann das aber auch anders machen.

b) Alles, was geprüft werden soll, muss _ermittelbar_ sein. Ob du das als Parameter-Übergabe machst, oder die (ggf: jeweils) erforderlichen Parameter im Code ermittelst, ist teilweise eine Geschmacksfrage, und zu einem guten Teil auch eine Frage der Übung...

Wenn du beispielsweise wirklich immer "PIR_Automatik" und "isNACHT" auswerten willst, kannst du das ja auch direkt in den Code schreiben (wobei ich empfehlen würde, auf Value() zu verzichten und stattdessen das "stabilere" "state" auszuwerten).

Wenn du "Querbeziehungen" zwischen Devices zu solchen Auswertezwecken herstellen willst, ginge das auch über Readings oder Attribute. Ich verwende z.B. Attribute (zugelassen als userattr), um aus Fenster- oder Türöffnungs-Events abzuleiten, ob/welcher virtuelle Fensterkontakt (nur bei Heizperiode) "auf- oder zugemacht" werden soll. (Anwendungsbeispiel siehe https://forum.fhem.de/index.php/topic,97430.msg1223653.html#msg1223653).
Mein Angang dabei ist in der Regel, dass Funktionen in myUtils "devicelos" sein sollen, sich also alles relevante aus den übergebenen Parametern (und ggf. der Auswertung dauaus abzuleitender Infos aus dem laufenden FHEM) ergibt. Ist in der Erstellung mehr Aufwand, kann dann aber auch leichter geteilt (und geändert!) werden.
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: stobor am 08 Juni 2022, 12:00:16
ich würde natürlich lieber die Zustände im Code ermitteln, damit die Aufrufe übersichtlicher werden.

D.h. ich kann in der Perl Prozedur auch direkt die verschiedenen Geräte/Zustände erfragen?
Einfach per Value("PIR_Automatik") ?

Wie werte ich denn state aus? Wäre das bspw. ReadingsVal("PIR_Automatik","state",0) - in Perl also:
my $myVariable = ReadingsVal("PIR_Automatik","state",0);
So komme ich dann an die Zustände, ohne dass das Objekt mit im Aufruf übergeben wurde?
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: Beta-User am 08 Juni 2022, 12:08:22
Im Prinzip: 3x "ja"...
Zitat von: Beta-User am 08 Juni 2022, 11:10:50
und zu einem guten Teil auch eine Frage der Übung...
Das gilt auch für's Austesten. Im Zweifel logs schreiben und/oder Test-Readings setzen.

Schnelles Stichwort noch: "Quotes in Perl" - alles, was nicht evaluiert werden muss, kommt in einfache Quotes (oder das "harte" q). In deinem letzten Beitrag wäre das _alles_:
ReadingsVal('PIR_Automatik','state',0)

Und wenn du dir beim Code-Kenntlichmachen einfach die code-Tags merkst, wird nicht nur das Formatieren schneller, sondern v.a. auch das Lesen einfacher...
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: DetlefR am 08 Juni 2022, 12:29:50
Hallo,

als erstes musst Du die Namensgebung für die Geräte überdenken. Dann kannst Du ein Notify anlegen das für alle Bewegungsmelder passt.
define PIR_all notify Bewegungsmelder.*:motion:.* .
Das passt für alle Geräte die "Bewegungsmelder..." heißen. Und reagiert auf alles was "motion" ausgibt. Es ist natürlich hilfreich, dass alle PIR auch "motion" als Reading benutzen.
Dann rufst du im Notify deine Funktion auf.
meineFunktion($NAME,$EVTPART1);
In $NAME steht der Name des PIR ersetzt und in $EVTPART1 on oder off.https://wiki.fhem.de/wiki/Notify (https://wiki.fhem.de/wiki/Notify)
Das wird dann an deine Funktion übergeben. Die Funktion fängt dann so ansub meineFunktion($$){
my ($name,$motion)= @_;

ZitatD.h. ich kann in der Perl Prozedur auch direkt die verschiedenen Geräte/Zustände erfragen?
Einfach per Value("PIR_Automatik") ?
würde dann Value($name)lauten.
Wobei ich ReadingsVal immer Value vorziehen würde. ;)
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: Beta-User am 08 Juni 2022, 12:44:05
Aha, noch einer, der von Prototypen überzeugt ist ::) und shift nicht "kann" oder kennt...
Zitat von: DetlefR am 08 Juni 2022, 12:29:50
würde dann Value($name)lauten.
Da wette ich im gezeigten Schnippsel dagegen :P ...
(Jedenfalls habe ich arge Schwierigkeiten, "Bewegungsmelder.*" (übeegeben nach $name) und "PIR_Automatik" zur Deckung zu bringen).
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: stobor am 08 Juni 2022, 13:15:59
Was wäre dann der Vorschlag?
Titel: Antw:Wiederholende Prozeduren auslgern?
Beitrag von: Beta-User am 08 Juni 2022, 13:42:23
Zitat von: stobor am 08 Juni 2022, 13:15:59
Was wäre dann der Vorschlag?
Es gibt viele Möglichkeiten. Da du scheinbar sowas wie einen "allgemeinen Hauptschalter" zu haben scheinst (!), der einen ganz bestimmten Namen hat, kannst du den auch direkt "vercoden" (wie bereits von dir vorgeschlagen):
my $autoison = ReadingsVal('PIR_Automatik','state',0)

Das "Problem" bei sowas ist nur, dass sich dann irgendwo quer durch den Code verteilt plötzlich irgendwelche Device-Namen finden, von denen ein "Unbedarfter" nicht weiß, warum die grade da auftauchen, und was sie zu bedeuten haben könnten...

Zitat von: Beta-User am 08 Juni 2022, 12:08:22
Das gilt auch für's Austesten. Im Zweifel logs schreiben und/oder Test-Readings setzen.
Im Zweifel musst du selbst rausfinden, welcher Weg der übersichtlichste für dich ist...

Hier noch ein paar Möglichkeiten:
- an das jeweilige auslösende Device ein Attribut hängen, in dem der für dieses Device relevante Automatik-Anzeiger hängt;
- dto. für ein Reading, wobei da auch gleich stehen könnte, ob die Automatik an oder aus ist;
- eine komplexere Auswertung aufrufen (weitere Perl-Sub), die z.B. erst nach dem Reading schaut, wenn das nicht da ist, das Attribut liest, und sich dann, wenn da dann da auch nichts steht auf den "allgemeinen Hauptschalter" schaut...
- in %data die entsprechenden Infos zentral hinterlegen (das ist ein zentraler Hash, in dem User-Daten gespeichert und für den allgemeinen Zugriff vorgehalten werden können).

Nur der von DetlevR vorgeschlagene Weg wird nicht funktionieren, weil die Variable $name eben nicht auf das für diese Info relevante Device zeigt (jedenfalls nicht in deinem aktuellen setup).
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: kjmEjfu am 08 Juni 2022, 14:23:39
Um mal einen neuen Gedanken in diesen Thread zu werfen: man könnte sowas auch mit einem DOIF-Template lösen https://wiki.fhem.de/wiki/DOIF/Automatisierung
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: DetlefR am 08 Juni 2022, 15:25:03
ZitatAha, noch einer, der von Prototypen überzeugt ist ::) und shift nicht "kann" oder kennt.
oder nicht unbedingt mag  ;)
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: alanblack am 09 Juni 2022, 20:49:55
Zitat von: DetlefR am 08 Juni 2022, 12:29:50
Hallo,

als erstes musst Du die Namensgebung für die Geräte überdenken. Dann kannst Du ein Notify anlegen das für alle Bewegungsmelder passt.
define PIR_all notify Bewegungsmelder.*:motion:.* .
So etwas würde ich mit Hinblick auf z.B. https://forum.fhem.de/index.php/topic,125831.0.html (https://forum.fhem.de/index.php/topic,125831.0.html) und der im Verlauf verlinkten anderen Threads nur mit großer Vorsicht machen - wenn überhaupt.

Grüße
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: DetlefR am 09 Juni 2022, 22:17:18
ZitatSo etwas würde ich mit Hinblick auf z.B. https://forum.fhem.de/index.php/topic,125831.0.html und der im Verlauf verlinkten anderen Threads nur mit großer Vorsicht machen - wenn überhaupt.
Hallo,
der Hauptgrund, warum ich es vorgeschlagen habe, es ist einfacher 45 Notify zu pflegen und zu Warten als wie in dem Thread angegeben 450. Und wenn die Last auf dem Rechner zu groß wird dann würde ich zuerst versuchen, die Ursache abzustellen. Das sind m.M.n die Events. Wo kein Event ist wird auch kein Notify/DOIF abgearbeitet.

Gruß
Detlef
Titel: Antw:Wiederholende Prozeduren auslagern?
Beitrag von: Beta-User am 10 Juni 2022, 09:40:33
Zitat von: alanblack am 09 Juni 2022, 20:49:55
So etwas würde ich mit Hinblick auf z.B. https://forum.fhem.de/index.php/topic,125831.0.html (https://forum.fhem.de/index.php/topic,125831.0.html) und der im Verlauf verlinkten anderen Threads nur mit großer Vorsicht machen - wenn überhaupt.
Ich kann in dem verlinkten Thread kein wirkliches Argument erkennen, aus dem sich ableiten lassen würde, dass es _nicht sinnvoll_ ist, das Namensschema so zu gestalten, dass man per regular expression die auslösenden Devices gruppenweise erfassen könnte. Im Gegenteil: Wenn man es sinnvoll macht (und ggf. auch den trigger weiter hinten entsprechend eingrenzt!), vermindert das die Last erheblich und man hat dafür auch im Rahmen von generalisiertem Code die Option, einfacher Debugging-Optionen vorzusehen...

Zitat von: DetlefR am 09 Juni 2022, 22:17:18
Hallo,
der Hauptgrund, warum ich es vorgeschlagen habe, es ist einfacher 45 Notify zu pflegen und zu Warten als wie in dem Thread angegeben 450. Und wenn die Last auf dem Rechner zu groß wird dann würde ich zuerst versuchen, die Ursache abzustellen. Das sind m.M.n die Events. Wo kein Event ist wird auch kein Notify/DOIF abgearbeitet.
Das stimmt zwar zum Teil auch, aber nicht immer ist es sinnvoll, Events zu unterdrücken, und zu warten, bis die Last groß ist, ist auch keine optimale Vorgehensweise.

Sinnvoll ist es in jedem Fall, sich über "Strukturen" Gedanken zu machen, also Dinge, die immer gleich laufen sollen (und die Ausnahmen dazu). Genau für solche Sachen macht das Auslagern von Prozeduren dann auch Sinn.
Wenn man es richtig macht
- werden Events nur "von den richtigen Devices" überhaupt erfaßt (NOTIFYDEV);
- werden nur "passende Events" überhaupt zum Anlass genommen, dass der Code aufgerufen wird (bei notify: die ganze regexp paßt);
- werden bricht der Code schnell ab, wenn nichts relevantes passiert ist (Beispiel: Thermostate verstellen, wenn die ganze Heizung aus ist, macht nur beim Ausschalten der Heizung Sinn...)
- ist der Code selbst modular aufgebaut. Beispiel: ggf. wird dann eine "passende" Unterfunktionen aufgerufen, die die "Reaktion" dann auf die jeweilige Hardware anpassen (z.B. kann nicht jeder Heizkörper per virtuellem Peer über eine Fensteröffnung informiert werden; das geht mit CUL_HM, aber für ZigBee muss das anders aussehen, und zwar dann wieder je nachdem, ob HUEDevice oder MQTT2_DEVICE (und dort ggf. wieder nach "model" unterschiedlich!)...

Letztlich muss man sich eigentlich immer erst Gedanken über die "Struktur" machen, und die Eingangsbedingungen, Rahmenbedingungen und möglichen Ergebnis-Aktionen mal auf einen Zettel schreiben, dann ist die konkrete Lösung eigentlich meistens gar nicht soooo sehr das Problem...