another automation challenge I can't solve by myself. Let me explain....
I turn of the lights in the livingroom automatically every weekday with the command:
at *23:00:00 {fhem("set lamp off") if($wday<5)}
This is very annoying if I'm still watching the television ;) so I'm looking for a way to delay the switch off in case someone is still in the room.
My first thought was to place a motion sensor in the room, read the status at 23.00 and if there was motion in the last 5 minutes than delay the lamp off command with 15 min. And repeat that procedure again at 23.15, etc.
The next day the lamp off command should be again start at 23.00 off course.
That's the idea (maybe there are better approaches?), but I can't figure out how to script this in fhem.
Any ideas?
Thanks,
Alex
Hi,
did you check the DOIF module ?
regards
joerg
I did but I didn't got the impression that I could solve this question with the DOIF. Or am I wrong?
imho it should fit perfect. The german doc is much more complete than the englich one and includes examples. A combination of fixed time, readings and timewait should solve your question.
http://fhem.de/commandref_DE.html#DOIF
btw, a motion sensor may be not sensitive enough to capture motion while you are watching tv (it depends ... :) ). Another option could be he tv itself (if you can read its state, may be by lan) or its power consumption.
Or use a brightness sensor instead of a motion type: If it´s still bright in there, don´t switch the light off... ;D
Yes, that sound like the perfect solution :P
Anyway, I succeeded in changing my original at statements to DOIF and this now reads like:
define ev_light DOIF ([{sunset_abs(-3000,"17:00","22:00")}-23:00]) (set wk.light on) DOELSE (set wk.light off)
But I still haven't figured out how to dynamically calculate the end time. With {OldTimestamp("Sensor")} I get the time and date of the last detected motion, but how to transform this to a time only format and add 15 min to it?
Any ideas?
you should add a second condition, in your case a motion sensor (whatever)
DOIF use a wait feature (attrib) to trigger a action based on time elapsed, and therefore a combination of conditions leads to delayed actions.
Unfortunally, the german doc is more complete, so you may want to use a translator.
But you may also join the famous DOIT thread, the dev of the module is very present and helpful there.
Last but not least, if you want to follow fiedels advice, its important to mount the brightness sensor in close distance to the bulbs and isolation from ambient light source.
The problem isn't really the working of the DOIF module but how to get the appropiate end time.
As mentioned earlier I have now the statement: define ev_light DOIF ([{sunset_abs(-3000,"17:00","22:00")}-23:00]) (set wk.light on) DOELSE (set wk.light off)
and this switches the light off at exactly 23.00.
Instead of 23.00 I now want to have the end time calculated based on the last time motion was detected. If this time (+15min) is later than 23:00 than that time should be taken as end-time, otherwise 23.00h.
So in logical words:
<end time> = max ( 23:00, <motion.detector> + 0:15).
I tried reading the motion detector logfile and convert that string value to a time format, but I can't figure out how to get the right time calculated.
With code like "{substr(OldTimestamp("Sensor"),index(OldTimestamp("Sensor")," ")+1)}" I get the time in string form ("21:10:16"), but how to add 15 minutes to this?
Thanks for any help...
ps. I don't want to use a brightness sensor as I also could just be reading a book or listen to music.
not sure if it works but try
define ev_light DOIF ( [22:45] and ([motiondetector] eq "nomotion")) (set light off)
attr ev_light wait 900
the idea is to check both conditions (time and "nomotion"). the time will allways be triggered and if there is no motion at 22:45 a timer (wait) starts . If there is a motion the timer restart.
Brilliant, sound like a good solution. Will test in a couple of days and let you know.
Thanks
Hi alex,
thanks, but I played with it yesterdaya bit to see if it works: it will not! although the way should be the right one.
It will not work because the time spec wont trigger the internal DOIF wait timer. Therefore you should use a dummy in the first expression (two states, day and night) that will be triggered by a "at" and "and" it with the motion sensor, but I didnt worked it out completely.
Anyway, you got the idea.
I also suggest to change the thread topic and add the "DOIF" keyword, so there is a chance that damian (the dev of DOIF) make him aware, he is very helpfull, it isnt solved by now
btw: there "classical" ways of solving that:
wiriting a sub, getting the ReadingsTimestamp() of the motion sensor and modify the "at" - or - firing a event at 11:00, catching it with with notify, get ReadingsTimestamp() and doing a fhem (! nonblocking) sleep (in case there was motion), trigger the event again and so on.
but DOIF should do the job more cleanly
I couldn't get it to work with the DOIF command so I finally gave up and solved it the old fashioned way and used a external subroutine.
Used the following code:
define ev_light DOIF ([{sunset_abs(-3000,"17:00","22:00")}-23:00]) (set wk.light on) DOELSE ({LightsOutOrNot()})
and in 99_myUtils.pm:
#
sub LightsOutOrNot {
if ( (time-time_str2num(OldTimestamp("wk.Sensor")) > 900)) {
{fhem ("set test off")}
}
else {
{fhem ("delete a5")}
{fhem ("define a5 at +00:05:00 {LightsOutOrNot()}")}
}
}
So the result is that from 23.00 on it will check every 5 min. if there was some motion detected in the last 15 minutes. If not, it will switch all lights of. If yes, than a new command is scheduled in 5 min. to check again.
It works exactly as I want, but if someone has a more elegant solution .....