[gelöst] Frage zur Herangehensweise/ performante (Funktions)-Prog

Begonnen von tklein, 26 April 2017, 19:53:04

Vorheriges Thema - Nächstes Thema

tklein

Hallo,

es wäre klasse, wenn mein Lösungsansatz kritisch hinterfragt werden könnte da ich mir nicht sicher bin, wie man am besten/perfomantesten eine Funktion aufbauen sollte.

Ausgangslage:

  • Ein dimmbares/togglebares Device im Bad
  • ESP Bridge liefert mir den LUX-Wert (per BH1750) und ob jemand in den Raum geht (per PIR 501)
  • Dummymerker "badlicht_an

Mein Idee:


sub schalte_licht_lux($$$$) {

my ($dev,$lux,$dauer,$dimm) = @_;
my $status_licht = ReadingsVal("badlicht_an", "state", 0);


# nur ausführen, wenn  merker aus oder lux-schwllwert unterscritten?
#{ system("/opt/fhem/FhemUtils/schalte_licht_lux.sh $dev $lux $dauer $dimm &")};
..
# device "sperren" gegen erneutes Schalten, wird im Script nach dem "austoggeln" auf "off" gesetzt
fhem("set badlicht_an on");
..
}


Der Funktion übergebe ich das Device welches geschaltet werden soll, den Luxschwellwert bis wann das Licht bei Bewegung aktiviert werden soll, Anzahl der Sekunden wie lange das Device an bleiben soll, Flag, ob an bzw. ausgedimmt werden soll. Mein Dummymerker wird während der Zeit der Ausführung auf "on" gesetzt. Damit nicht erneut getoggelt wird und die Lampe ausgeschaltet wird. Das ganze würde ich in ein DOIF packen wollen.

Frage: Was macht mehr Sinn, im DOIF den Dummy und/oder den LUX-Wert als Bedingung zur Ausführung zu nehmen oder immer die Skriptdatei die Arbeit machen lassen? Ein in hoher FRequenz laufender AT-Befehl macht ja keinen Sinn, oder?

Oder gibt es einen anderen vielleicht auch eleganteren Weg?

Freue mich auf eure Vorschläge
Thomas
FHEM auf Pi 3, Echo (Plus, Dot und Connect), CUL868/433, HM Komponenten, Broadlink, Enigma (VU DUO2), Alexa/Homebridge, Sonoffs (POW, RF, Basic), Wemos D1 (IR, DHT, BH1750, OLED, BMP180), IT/Steckdosen, Fritzbox mit SIP, Wifilight, MQTT, Pilight, Xiaomi Flower Sensor, Spotify, Dooya, Shelly, Conbee2

bartman121

#1
ein notify auf den PIR ....

im notify, dann prüfen ob der Lux-Wert unterschritten ist und dann schalten?

my 2 cents ohne Kenntnisse von DOIF :)

Deine Herangehensweise ist doch folgende:
Licht schalten, wenn Bewegung erkannt wird, aber nur, wenn es Dunkel ist.

Hier mal meine Lösung:
Wenn Bewegung erkannt und es dunkel ist, dann wird die Lampe für 90Sekunden eingeschaltet, ist die Lampe an und es wird eine weitere Bewegung erkannt, dann wird der Aus-Timer auf 40Sekunden gestellt ....

Mit dieser Lösung bleibt das Licht solange an, wie Bewegungen erkannt werden und schaltet dann von selbst ab ....

BA.SPIEGEL:motion:.ON {
if (ReadingsVal("T","twilight_weather","")<80) {
if(ReadingsVal("BA.SPIEGEL","motion","") eq "ON"){
if(ReadingsVal("BA.SPIEGEL","state","") eq "OFF"){
fhem("set BA.SPIEGEL ON");;
fhem("defmod at_ba_spiegel_off at +00:00:40 set BA.SPIEGEL OFF");
}
else {
fhem("defmod at_ba_spiegel_off at +00:01:30 set BA.SPIEGEL OFF");

}

}
}
}

tklein

danke für den notify-ansatz. Jetzt müsste man nur wissen, welcher Prozess mehr auf dem System hängt. Ich würde das dann denn gerne für einige Räume umsetzen.
DIe ganzen If's könnte man doch auch als Bedingung mit "and" verknüpfen, oder?

Wieso hast du einmalig 90 sek bei Aktivierung drin und bei "Verlängerung" nur 40 sek? Was macht das "defmod"?

Grüße
Thomas
FHEM auf Pi 3, Echo (Plus, Dot und Connect), CUL868/433, HM Komponenten, Broadlink, Enigma (VU DUO2), Alexa/Homebridge, Sonoffs (POW, RF, Basic), Wemos D1 (IR, DHT, BH1750, OLED, BMP180), IT/Steckdosen, Fritzbox mit SIP, Wifilight, MQTT, Pilight, Xiaomi Flower Sensor, Spotify, Dooya, Shelly, Conbee2

bartman121

also erstmal zur Performance .... ich kenne mich mit DOIF nicht aus, daher nur zum Notify ....

Das Notify wird NUR ausgeführt, wenn der PIR eine Bewegung meldet ... wenn du mittels event-on-change-reading arbeitest, dann würde das notify nur sehr selten getriggert. Du könntest deinem PIR sogar beibrigen, dass er sich selbst "retriggert", dann könntest du die Timer aus meinem Beispiel sogar weglassen und nur ein- bzw. ausschalten.

Zum Thema defmod:
https://forum.fhem.de/index.php?topic=36326.0

Timer kann man mit "define" ebenfalls machen, immer wenn du aber versuchst einen Timer neu zu definen, während der alte Timer noch da ist, dann gibt es eine Fehlermeldugn im Log. Es funktioniert zwar trotzdem, ist aber unschön. Daher "def(ine)mod(ify).

Bei den IFs hast du natürlich recht, ob das performanter wäre, wage ich zu bezweifeln.

Wegen der 90sek/40sek ....
Die Überlegung war, dass das Licht nur kurz beim Toilettengang nachts eingeschaltet werden soll. Dafür reichen die 90Sekunden durchaus, dauert es doch länger, dann halt jeweils nochmal 40sek .... man könnte aber auch 90sek immer wieder machen, je nach belieben.

Hinsichtlich der Performanceunterscheide zwischen DOIF und notify gibt es vermutlich keine allgemeingültige Aussage:
https://forum.fhem.de/index.php?topic=48134.0

Es ist zwar nicht wirklich sauber, schlechten langsamen code zu schreiben, aber solange du nicht fhem auf dem Taschenrechner laufen lässt, sollte es bei normalem Grad der Automatisierung sicher nicht wirklich zu Performance-Problemen kommen. Besonders gut ist der Hinweis, dass die Logik beim notify eher besser nachvollziehbar und transparent für dich ist. Es ist zwar komplizierter für dich, weil du deine Bedingungen/Verzweigungen usw. selbst ausdenken musst. Schlussendlich obliegt es deinem Verstand ob es funktioniert oder nicht.




tklein

Danke für deine Infos.

Deine Version werde ich auch mal ausprobieren. Muss mal nur schauen, wie ich meinen Merker "licht ist bereits an" integriere. Sonst habe ich Disko im Bad da ich ja nur togglen kann :-)

Gruß
Thomas
FHEM auf Pi 3, Echo (Plus, Dot und Connect), CUL868/433, HM Komponenten, Broadlink, Enigma (VU DUO2), Alexa/Homebridge, Sonoffs (POW, RF, Basic), Wemos D1 (IR, DHT, BH1750, OLED, BMP180), IT/Steckdosen, Fritzbox mit SIP, Wifilight, MQTT, Pilight, Xiaomi Flower Sensor, Spotify, Dooya, Shelly, Conbee2

tklein

soweit bin ich jetzt:


ESPEasy_Wemos_Bad:Switch:.on {
if ((ReadingsVal("ESPEasy_Wemos_Bad","Lux","")<1080) and (ReadingsVal("ESPEasy_Wemos_Bad","Switch","") eq "on")) {
           if(ReadingsVal("badlicht_an","state","") eq "off"){ # merker ist auf off
                 fhem("set badlicht_an on"); # merker auf on setzen
# fhem("set ESPEasy_Wemos_Bad gpio 14 0"); # pir manuell sofort auf off setzen
fhem("set StripeSchlafzimmer toggle"); # anschalten/togglen da Lampe aus war
                 fhem("defmod at_ba_licht_off at +00:00:15 set StripeSchlafzimmer toggle");         # nach 15 sek toggeln --> auf aus
fhem("defmod at_badlicht_an_off at +00:00:15 set badlicht_an off"); # merker auf off setzen

                 }
                 else { # bei auslösung ist merker auf on
                 fhem("defmod at_ba_licht1_off at +00:00:15 set StripeSchlafzimmer toggle");             # nach 15 sek toggeln --> auf aus
fhem("defmod at_badlicht1_an_off at +00:00:15 set badlicht_an off"); # merker auf off setzen
fhem("set IT_00FFFFFF0F on"); # "debugausgabe" ob dieser zweig durchlaufen wird
sleep (1);
fhem("set IT_00FFFFFF0F off");

                 }

         }
   }


Allerdings werden im ersten Zweig das Licht ausgetoggelt und wenn während der merker auf on ist noch ein notify ausgeführt wird, wird der else-Zweig genommen inkl. toggle, aber der toggle aus dem if-Zweig wird auch noch ausgeführt. Da ist die Lampe noch zum Schluss an. Der Befehl " fhem("defmod at_ba_licht_off at +00:00:15 set StripeSchlafzimmer toggle");" müsste in dem Fall "gelöscht" werden.
Vielleicht gibt es ja ein undefmod :-) Werde mal schauen.

Wie kann ich das lösen?
FHEM auf Pi 3, Echo (Plus, Dot und Connect), CUL868/433, HM Komponenten, Broadlink, Enigma (VU DUO2), Alexa/Homebridge, Sonoffs (POW, RF, Basic), Wemos D1 (IR, DHT, BH1750, OLED, BMP180), IT/Steckdosen, Fritzbox mit SIP, Wifilight, MQTT, Pilight, Xiaomi Flower Sensor, Spotify, Dooya, Shelly, Conbee2

Thorsten Pferdekaemper

FUIP

bartman121

oh ... mir war jetzt nicht klar, dass du ein Gerät nur "togglen" kannst. Ist auch irgendwie komisch, gibt es wirklich kein echtes "on" oder "off" ...

hier wäre es jetzt nochmal notwendig deinen Prozess nochmal zu analysieren und deinen Algorhytmus neu zu überdenken.

Kannst du dein Problem nochmal neu und vollständig beschreiben.

Welche Geräte sind beteiligt, welche Eigenschaften?  (am besten auch "list $DEVICE" hier als Code einfügen.)

textliche Beschreibung was du erreichen willst ....





tklein

@Thorsten:

Dann ist es mit dem Delete doch schon zu spät, oder? Wenn ich initial auslöse und nach 5 Sek wieder auslöse und dann das delete eines Devices aufgerufen wird, das aber erst in der Zukunft (per at) erzeugt wird.


@bartman121:
Hier ist das Gerät welches ich nur mit dimm/toggle ansprechen kann und zu Hauf eingebunden habe. Einen Sonoff noch davor möchte ich nicht. Es sei denn, es gibt einen dimmbaren RF Sonoff.
https://www.amazon.de/TOOGOO-Kabellos-Regler-Dimmer-LED-Controller/dp/B00UBOJOAM/ref=sr_1_13?ie=UTF8&qid=1493317826&sr=8-13&keywords=funk+led+controller

Hier das Devicelisting: (Die Stripes sind wie gesagt alle identisch)

Internals:
   NAME       StripeSchlafzimmer
   NR         145
   STATE      toggle
   TYPE       dummy
   Readings:
     2017-04-27 14:15:10   state           toggle
Attributes:
   alexaName  Schlafzimmerled
   alexaRoom  Schlafzimmer
   genericDeviceType light
   group      Stripes
   icon       light_led_stripe
   room       Homekit,Schlafzimmer,Stripes,alexa
   setList    toggle up down on off
   webCmd     toggle:up:down:on:off



-------------------

Internals:
   DEF        192.168.0.88 80 espBridge Wemos_Bad
   ESP_BUILD  147
   ESP_SLEEP  0
   ESP_UNIT   2
   HOST       192.168.0.88
   IDENT      Wemos_Bad
   INTERVAL   300
   IODev      espBridge
   LASTInputDev espBridge
   MSGCNT     68428
   NAME       ESPEasy_Wemos_Bad
   NOTIFYDEV  global
   NR         904
   NTFY_ORDER 50-ESPEasy_Wemos_Bad
   PORT       80
   STATE      Lux: 12 Switch: off freeram: 26256.00 humidit: 54 tempera: 18.3 wifi: -48.00
   SUBTYPE    device
   TYPE       ESPEasy
   VERSION    1.03
   espBridge_MSGCNT 68428
   espBridge_TIME 2017-04-27 20:22:51
   Readings:
     2017-04-27 20:22:51   Lux             12
     2017-04-27 20:22:27   Switch          off
     2017-04-27 20:22:33   freeram         26256.00
     2017-04-27 20:22:30   humidity        54
     2017-04-27 20:20:40   presence        present
     2017-04-27 20:22:51   state           Lux: 12 Switch: off freeram: 26256.00 humidit: 54 tempera: 18.3 wifi: -48.00
     2017-04-27 20:22:30   temperature     18.3
     2017-04-27 20:22:32   wifi            -48.00
   Helper:
     fpc        1493195593
     Intat:
       1:
         FN         ESPEasy_statusRequest
         INTERVAL   305
         TRIGGERTIME 27.04.2017 20:25:44
     Received:
       Lux        1493317371
       Switch     1493317347
       freeram    1493317353
       humidity   1493317350
       temperature 1493317350
       wifi       1493317352
Attributes:
   IODev      espBridge
   Interval   300
   group      ESPEasy Device
   homebridgeMapping [CurrentTemperature=temperature] CurrentRelativeHumidity=humidity
   presenceCheck 1
   readingSwitchText 1
   room       Badezimmer,ESPEasy
   setState   7


Ziel ist es, dass der Stripe/Beleuchtung im Bad bei Bewegung und der entsprechenden Dunkelheit eine gewisse Zeit eingeschaltet wird. Bei Bewegung während einer bereits aktivierten Beleuchtung soll die Leuchtdauer jeweils um z.B. 30 Sek verlängert werden. Solange bis keine Bewegung detektiert wird.

Hoffe, dass die Anforderung jetzt besser ersichtlich ist/wird.

Grüße
Thomas
FHEM auf Pi 3, Echo (Plus, Dot und Connect), CUL868/433, HM Komponenten, Broadlink, Enigma (VU DUO2), Alexa/Homebridge, Sonoffs (POW, RF, Basic), Wemos D1 (IR, DHT, BH1750, OLED, BMP180), IT/Steckdosen, Fritzbox mit SIP, Wifilight, MQTT, Pilight, Xiaomi Flower Sensor, Spotify, Dooya, Shelly, Conbee2

bartman121

hmmm ...


setList    toggle up down on off


lt. deiner setlist, kann er aber on und off ...

Fakt ist, dafür benötigst du ein device, welches den aktuellen Zustand des Stripes abbildet....

Auf dieses Device könntest du mittels notify deinen Stripes togglen .... Dafür bietet sich in deinem Beispiel das Dummy "badlicht_an" quasi perfekt an :)

in deinem notify schaltest du also nur den dummy.

Gedankenexperiemnt:

alles ist aus
Bewegung
--> Dummy an (Änderung von off auf on --> toggle des stripes)
Bewegung
--> Dummy an (Änderung von on auf on --> nichts machen [event on change-reading verwenden])
Bewegung
--> Dummy an (Änderung von on auf on --> nichts machen [event on change-reading verwenden])
Zeit abgelaufen
--> Dummy aus (Änderung von on auf off --> toggle des stripes)

Trotzdem finde ich ein Device, welches keinen "definierten" Zustand hat, nicht sonderlich schön :)

Thorsten Pferdekaemper

Zitat von: tklein am 27 April 2017, 20:42:34
@Thorsten:
Dann ist es mit dem Delete doch schon zu spät, oder? Wenn ich initial auslöse und nach 5 Sek wieder auslöse und dann das delete eines Devices aufgerufen wird, das aber erst in der Zukunft (per at) erzeugt wird.
So ganz kann ich Deinen Gedankengang nicht nachvollziehen.
Möglicherweise beziehst Du Dich darauf:


fhem("defmod at_ba_licht_off at +00:00:15 set StripeSchlafzimmer toggle");         # nach 15 sek toggeln --> auf aus
fhem("defmod at_badlicht_an_off at +00:00:15 set badlicht_an off");

Das legt allerdings sofort die beiden ats an. Du kannst die also wieder mit delete während der 15 Sekunden löschen.
Es kann nur sein, dass die beiden ats nicht zusammen ausgeführt werden, so dass tatsächlich etwas zwischen die beiden set-Befehle kommen kann. Deshalb sollte man das so machen:

fhem("defmod at_ba_licht_off at +00:00:15 set StripeSchlafzimmer toggle;;set badlicht_an off");        

Dann geschieht das auf jeden Fall zusammen und es kann kein notify oder so dazwischen.

Das ganze mit dem toggle ist übrigens wirklich ein bisschen blöd. Das braucht nur ein einziges Mal nicht zu funktionieren und schon geht das Licht bei Bewegung aus und ist ansonsten an...

Gruß,
   Thorsten
FUIP

tklein

@Thorsten

Ok, dann habe ich da einen Gedankenfehler gehabt. Bin der Meinung gewesen, dass das "at-device" erst zum ausführungszeitpunkt angelegt wird. Danke für die Optimierung der beiden At's. Wofür sind die beiden ";;" im Befehl drin? Irgendeine leere Anweisung?

@bartman121

Wie sähe dein Gedankengang in FHEM aus? Bei mir hapert es gerade gedanklich mit der Verbindung von dem notify und dem event on change-reading. Mit oder ohne Zeitintervall?


Den Teil mit dem Dimmen werde ich rauslassen habe ich gerade beschlossen. Bin froh, wenn ich es hinbekomme. :-)

Grüße
Thomas
FHEM auf Pi 3, Echo (Plus, Dot und Connect), CUL868/433, HM Komponenten, Broadlink, Enigma (VU DUO2), Alexa/Homebridge, Sonoffs (POW, RF, Basic), Wemos D1 (IR, DHT, BH1750, OLED, BMP180), IT/Steckdosen, Fritzbox mit SIP, Wifilight, MQTT, Pilight, Xiaomi Flower Sensor, Spotify, Dooya, Shelly, Conbee2

Thorsten Pferdekaemper

Zitat von: tklein am 28 April 2017, 17:15:42
Ok, dann habe ich da einen Gedankenfehler gehabt. Bin der Meinung gewesen, dass das "at-device" erst zum ausführungszeitpunkt angelegt wird. Danke für die Optimierung der beiden At's. Wofür sind die beiden ";;" im Befehl drin? Irgendeine leere Anweisung?
Siehe hier:
https://fhem.de/commandref.html#command

FUIP

bartman121

#13
Hallo Thomas,

grundsätzlich hapert es an dem "undefinierten Zustand" des "Toggle-Devices" ..... dieser muss bekannt sein, damit du derartige Logik machen kannst....

Ich habe hier mal den Dummy und das notify für dieses Problem gemacht:

defmod licht_for_tklein dummy
attr licht_for_tklein event-on-change-reading *
attr licht_for_tklein setList on off


defmod n_licht_for_tklein notify licht_for_tklein:.* {\
my $state=ReadingsVal("licht_for_tklein","state","");;\
if ($state eq "off") {\
#Licht/Dummy wurde ausgeschaltet\
Log 3, "Licht wurde ausgeschaltet";;#Logausgabe zum debuggen\
# hier könnte und sollte man das toggle-Device per toogle einschalten\
}\
else {\
#Licht/Dummy wurde eingeschaltet\
Log 3, "Licht wurde eingeschaltet";; #Logausgabe zum debuggen\
# hier könnte und sollte man das toggle-Device per toogle ausschalten\
}\
}


Den Code kannst du so direkt importieren: https://wiki.fhem.de/wiki/Import_von_Code_Snippets

Jetzt musst du im PIR-notify nur noch "licht_for_tklein" auf on bzw. off setzen ...

attr licht_for_tklein event-on-change-reading *
das bewirkt, dass kein Event ausgelöst wird, wenn der Zustand von on auf on bzw. von off auf off geht, lediglich on->off bzw. off->triggern einen Event bzw. das zugehörige notify

Wie aber Thorsten bereits geschrieben hat, wenn der toggle-Befehl einmal danaben geht, dann ist die ganze Logik dahin. Bitte gib mal weitere Infos wie du den Stripe-Controller an fhem angebunden hast. Wenn ich das gestern richtig gegoogelt habe, dann sind das doch IT-Geräte?


EDITH:
Wie DeeSPe richtig anmerkte, ist mein regex falsch ....

Bitte entsprechend korrigieren:
attr licht_for_tklein event-on-change-reading .*

DeeSPe

Zitat von: bartman121 am 28 April 2017, 18:30:40
attr licht_for_tklein event-on-change-reading *

Bitte keine völlig falschen Vorschläge machen!
* ist kein gültiger Regex und wird zur Fehlermeldung führen!

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe