Hallo zusammen,
ich habe ein etwas kniffeliges Problem:
Für eine spezielle Konstruktion, eine Art Rollladensteuerung, möchte ich unterschiedliche Positionen ansteuern können.
Damit eine bestimmte Postion agefahren wird, muss jedoch eine spezielle Schaltfrequenz eingeahlten werden. Zum Öffnen muss bspw. zunächst der öffnen, und dann verzögert der schließen und ein weiteres Mal verzögert der Stop Befehl abgesetzt werden.
D.h., es zunächst die richtigen Wait-Timer errechnet und gesetzt werden, bevor die eigentliche "Ansteuerung" erfolgen kann. Zudem muss eine Fallunterscheidung möglich sein, abhängig ob die Lamellen auf, oder zu gehen sollen.
Für die Fallunterscheidung errechne ich zunächst die jeweilige Positionsdifferenz. Abhängig vom Fall wird die Rechnung der Laufzeit so ausgeführt, dass der Wert immer positiv ist.
Die Werte errechne ich jeweils über ein DOIF_Reading.
Nun habe ich testweise probiert, erstmal einen Wert zu dynamisieren. Es wird aber kein Timer gesetzt.
Internals:
CFGFN
DEF ([$SELF:open:d] > OldReadingsNum("di_lamellendach","open",0))
(set lamellendach open) (set lamellendach close) (set lamellendach stop)
DOELSE
(set lamellendach close) (set lamellendach open) (set lamellendach stop)
FUUID 5e91be5d-f33f-f340-96f3-09039e4ac3de544b
MODEL FHEM
NAME di_lamellendach
NOTIFYDEV di_lamellendach,global
NR 3671
NTFY_ORDER 50-di_lamellendach
STATE initialized
TYPE DOIF
VERSION 21224 2020-02-18 18:45:49
CHANGED:
pos_diff_dwn: -7.5
pos_diff_up: 7.5
CHANGEDWITHSTATE:
pos_diff_dwn: -7.5
pos_diff_up: 7.5
DOIF_Readings:
pos_diff_dwn ((OldReadingsNum("di_lamellendach","open",0)) - ::ReadingValDoIf($hash,'di_lamellendach','open','','d'))*.15
pos_diff_up {((::ReadingValDoIf($hash,'di_lamellendach','open','','d') - (OldReadingsNum("di_lamellendach","open",0)))*.15)}
OLDREADINGS:
2020-04-12 17:09:36 open 0
READINGS:
2020-04-12 17:12:53 cmd 0
2020-04-11 19:55:50 direction close
2020-04-12 17:12:53 mode enabled
2020-04-12 17:10:06 open 50
2020-04-12 17:12:53 pos_diff_dwn -7.5
2020-04-12 17:12:53 pos_diff_up 7.5
2020-04-12 17:12:53 state initialized
Regex:
DOIF_Readings:
di_lamellendach:
pos_diff_dwn:
open ^di_lamellendach$:^open:
pos_diff_up:
open ^di_lamellendach$:^open:
accu:
cond:
di_lamellendach:
0:
open ^di_lamellendach$:^open:
attr:
cmdState:
wait:
0:
0
[$SELF:pos_diff_up:d0]
1
waitdel:
condition:
0 ::ReadingValDoIf($hash,'di_lamellendach','open','','d') > OldReadingsNum("di_lamellendach","open",0)
do:
0:
0 set lamellendach open
1 set lamellendach close
2 set lamellendach stop
1:
0 set lamellendach close
1 set lamellendach open
2 set lamellendach stop
helper:
DEVFILTER ^global$|^di_lamellendach$
NOTIFYDEV global|di_lamellendach
globalinit 1
last_timer 0
sleeptimer -1
triggerDev
triggerEvents
triggerEventsState
readings:
all di_lamellendach:open
uiState:
uiTable:
Attributes:
DOIF_Readings pos_diff_up:{(([$SELF:open:d] - (OldReadingsNum("di_lamellendach","open",0)))*.15)},
pos_diff_dwn: ((OldReadingsNum("di_lamellendach","open",0)) - [$SELF:open:d])*.15,
do always
oldreadings open,time
readingList open
setList open:slider,0,10,100
wait 0,[$SELF:pos_diff_up:d0],1
webCmd open
In einer anderen Version (hier nicht gepostet), hatte ich für den "Hochfall" im Ausführungsteil noch folgende Anweisung der eigentlichen Ansteuerung vorgeschaltet:
(Bedingung)
((attr di_lamellendach wait 0,[$SELF:pos_diff_up:d0],1))
(set lamellendach open) (set lamellendach close) (set lamellendach stop)
Das Wait Attribut wurde zwar mit dem richtig aufgerundeten Werten gesetzt, der Timer wurde aber nicht mehr korrekt berücksichtig.
Hat jemand eine Idee, wie ich das Prolem lösen kann?
Besten Dank und frohe Ostern,
Max
Ein Timer wird erst gesetzt, wenn das DOIF getriggert wird (Änderung von $SELF:open ), und die Bedingung wahr ist. Im Moment steht er auf "initialized".
Achso, das heißt in dem Fall nichts. Das habe ich per Hand gemacht.
Die Frage ist aber, wie die Abarbeitung läuft:
wann werden die Readings berechnet? Darauf greift der Timer ja zurück .
Viele Grüße,
Max
Die Auswertungsreihenfolge ist normalerweise:
DOIF_Readings
DOIF-Bedingungen
Wait-Attribut
DOIF-Ausführungen
Du kannst also nicht im gleichen DOIF-Zweig in der Ausführung etwas berechnen, was den Wait-Timer für diesen Zweig beeinflusst.
Hi Damian,
besten Dank! Das hatte ich mir dann auch gedacht ::)
Kann ich beim Wait denn eine IF Bedingung einbauen? IF CMD 1 then pos_diff_up else pos_diff_dwn?
Wichtig ist auch, dass die Rundung wie bei [xxx:yyyy:d0] funktioniert oder kann wait mit Millisekunden umgehen?
Besten Dank und Gruß,
Max
Beim Wait kannst du mit Perlanweisungen arbeiten:
if (...) {...}
Wait kann auch mit Millisekunden umgehen, ob das dein System allerdings so genau schafft, ist eine andere Frage.
Hi Damian,
so richtig will es nicht bei mir funktionieren.
Ich habe jetzt folgendes beim Attr. Wait stehen:
0,{if (ReadingsNum("di_lamellendach","direction",120) > 0) {ReadingsNum("di_lamellendach","pos_diff_up",120)} else {ReadingsNum("di_lamellendach","pos_diff_up",120)*-1+10}}
So eingegebene, bekomme ich die richtigen Werte angezeigt.
Woran liegt das?
Viele Grüße und Dank vorab,
Max
Anbei noch mal das ganze Listing:
Internals:
CFGFN
DEF ([$SELF:open:d] > OldReadingsNum("di_lamellendach","open",0))
(set Test an) (set Test aus) (set Test an)
DOELSE
(set Test an) (set Test aus) (set Test an)
FUUID 5e91be5d-f33f-f340-96f3-09039e4ac3de544b
MODEL FHEM
NAME di_lamellendach
NOTIFYDEV di_lamellendach,global
NR 3671
NTFY_ORDER 50-di_lamellendach
STATE cmd_2
TYPE DOIF
VERSION 21224 2020-02-18 18:45:49
CHANGED:
pos_diff_dwn: 1.5
direction: -10
pos_diff_up: -1.5
pos_diff_dwn: -6
direction: 40
pos_diff_up: 6
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
pos_diff_dwn: -6
direction: 40
pos_diff_up: 6
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
CHANGEDWITHSTATE:
pos_diff_dwn: 1.5
direction: -10
pos_diff_up: -1.5
pos_diff_dwn: -6
direction: 40
pos_diff_up: 6
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
pos_diff_dwn: -6
direction: 40
pos_diff_up: 6
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
DOIF_Readings:
direction ::ReadingValDoIf($hash,'di_lamellendach','open','','d') - (OldReadingsNum("di_lamellendach","open",0))
pos_diff_dwn ((OldReadingsNum("di_lamellendach","open",0)) - ::ReadingValDoIf($hash,'di_lamellendach','open','','d'))*.15
pos_diff_up {((::ReadingValDoIf($hash,'di_lamellendach','open','','d') - (OldReadingsNum("di_lamellendach","open",0)))*.15)}
OLDREADINGS:
2020-04-13 00:44:56 open 60
READINGS:
2020-04-13 00:48:04 cmd 2.3
2020-04-13 00:48:04 cmd_event di_lamellendach
2020-04-13 00:48:04 cmd_nr 2
2020-04-13 00:48:04 cmd_seqnr 3
2020-04-13 00:48:04 direction -20
2020-04-13 00:48:04 e_di_lamellendach_open 40
2020-04-12 23:42:44 mode enabled
2020-04-13 00:48:04 open 40
2020-04-13 00:48:04 pos_diff_dwn 3
2020-04-13 00:48:04 pos_diff_up -3
2020-04-13 00:48:04 state cmd_2
2020-04-13 00:45:01 wait_timer no timer
Regex:
DOIF_Readings:
di_lamellendach:
direction:
open ^di_lamellendach$:^open:
pos_diff_dwn:
open ^di_lamellendach$:^open:
pos_diff_up:
open ^di_lamellendach$:^open:
accu:
cond:
di_lamellendach:
0:
open ^di_lamellendach$:^open:
attr:
cmdState:
wait:
0:
0
{if (ReadingsNum("di_lamellendach","direction",120) > 0) {ReadingsNum("di_lamellendach","pos_diff_up",120)} else {ReadingsNum("di_lamellendach","pos_diff_up",120)*-1+10}}
waitdel:
condition:
0 ::ReadingValDoIf($hash,'di_lamellendach','open','','d') > OldReadingsNum("di_lamellendach","open",0)
do:
0:
0 set Test an
1 set Test aus
2 set Test an
1:
0 set Test an
1 set Test aus
2 set Test an
helper:
DEVFILTER ^global$|^di_lamellendach$
NOTIFYDEV global|di_lamellendach
event open: 40,e_di_lamellendach_open: 40,cmd_nr: 2,cmd_seqnr: 1,cmd: 2.1,cmd_event: di_lamellendach,cmd_2_1,cmd_nr: 2,cmd_seqnr: 2,cmd: 2.2,cmd_event: di_lamellendach,cmd_2_2,cmd_nr: 2,cmd_seqnr: 3,cmd: 2.3,cmd_event: di_lamellendach,cmd_2,pos_diff_dwn: 3,direction: -20
globalinit 1
last_timer 0
sleepdevice di_lamellendach
sleepsubtimer -1
sleeptimer -1
timerdev di_lamellendach
timerevent open: 40
triggerDev di_lamellendach
timerevents:
open: 40
e_di_lamellendach_open: 40
cmd_nr: 2
cmd_seqnr: 1
cmd: 2.1
cmd_event: di_lamellendach
cmd_2_1
cmd_nr: 2
cmd_seqnr: 2
cmd: 2.2
cmd_event: di_lamellendach
cmd_2_2
cmd_nr: 2
cmd_seqnr: 3
cmd: 2.3
cmd_event: di_lamellendach
cmd_2
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
timereventsState:
open: 40
e_di_lamellendach_open: 40
cmd_nr: 2
cmd_seqnr: 1
cmd: 2.1
cmd_event: di_lamellendach
cmd_2_1
cmd_nr: 2
cmd_seqnr: 2
cmd: 2.2
cmd_event: di_lamellendach
cmd_2_2
cmd_nr: 2
cmd_seqnr: 3
cmd: 2.3
cmd_event: di_lamellendach
cmd_2
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
triggerEvents:
open: 40
e_di_lamellendach_open: 40
cmd_nr: 2
cmd_seqnr: 1
cmd: 2.1
cmd_event: di_lamellendach
cmd_2_1
cmd_nr: 2
cmd_seqnr: 2
cmd: 2.2
cmd_event: di_lamellendach
cmd_2_2
cmd_nr: 2
cmd_seqnr: 3
cmd: 2.3
cmd_event: di_lamellendach
cmd_2
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
triggerEventsState:
open: 40
e_di_lamellendach_open: 40
cmd_nr: 2
cmd_seqnr: 1
cmd: 2.1
cmd_event: di_lamellendach
cmd_2_1
cmd_nr: 2
cmd_seqnr: 2
cmd: 2.2
cmd_event: di_lamellendach
cmd_2_2
cmd_nr: 2
cmd_seqnr: 3
cmd: 2.3
cmd_event: di_lamellendach
cmd_2
pos_diff_dwn: 3
direction: -20
pos_diff_up: -3
internals:
readings:
all di_lamellendach:open
trigger:
uiState:
uiTable:
Attributes:
DOIF_Readings pos_diff_up:{(([$SELF:open:d] - (OldReadingsNum("di_lamellendach","open",0)))*.15)},
pos_diff_dwn: ((OldReadingsNum("di_lamellendach","open",0)) - [$SELF:open:d])*.15,
direction: [$SELF:open:d] - (OldReadingsNum("di_lamellendach","open",0))
do always
oldreadings open,time
readingList open
setList open:slider,0,10,100
wait 0,{if (ReadingsNum("di_lamellendach","direction",120) > 0) {ReadingsNum("di_lamellendach","pos_diff_up",120)} else {ReadingsNum("di_lamellendach","pos_diff_up",120)*-1+10}}
webCmd open
Die if-Anweisung sollte so im wait funktionieren, warum es konkret in deinem DOIF nicht funktioniert, kann ich dir nicht sagen. Für wiederholende Ausführung musst du das Attribut do always setzen.