I have editted the example that Andrew has in Appdaemon.
Added option for several lights, scripts, scenes
Added option for several motiondetectors
Added option to just turn out light after timer ended
Added controle if timer from motionsensor is longer then the delay
Changed handlenaming bug
Changed reset flow
import appdaemon.appapi as appapi
##############################################################################################
# Args:
#
# sensor: binary sensor to use as trigger. several motion detectors are seperated with ,
# entity_on : entity to turn on when detecting motion, can be a light, script, scene or anything else that can be turned on. more lights are sepetated with ,
# entity_off : entity to turn off when detecting motion, can be a light, script or anything else that can be turned off. Can also be a scene which will be turned on. more lights are sepetated with ,
# delay: amount of time after turning on to turn off again. If not specified defaults to 60 seconds.
#
# Release Notes
#
# Version 1.1:
# Added option for several lights, scripts, scenes (Rene Tode)
# Added option for several motiondetectors (Rene Tode)
# Added option to just turn out light after timer ended (Rene Tode)
# Added controle if timer from motionsensor is longer then the delay (Rene Tode)
# Changed handlenaming bug (Rene Tode)
# Changed reset flow (Rene Tode)
# Version 1.0:
# Initial Version (aimc)
class MotionLights(appapi.AppDaemon):
def initialize(self):
self.handle = None
if "sensor" in self.args:
self.sensors = self.args["sensor"].split(",")
for sensor in self.sensors:
self.listen_state(self.motion, sensor)
else:
self.log("No sensor specified, doing nothing")
def motion(self, entity, attribute, old, new, kwargs):
if "delay" in self.args:
delay = self.args["delay"]
else:
delay = 60
if new == "on":
if self.handle == None:
if "entity_on" in self.args:
on_entities = self.args["entity_on"].split(",")
for on_entity in on_entities:
self.turn_on(on_entity)
self.log("First motion detected: i turned {} on, and did set timer".format(self.args["entity_on"]))
else:
self.log("First motion detected: i turned nothing on, but did set timer")
self.handle = self.run_in(self.light_off, delay)
else:
self.cancel_timer(self.handle)
self.handle = self.run_in(self.light_off, delay)
self.log("Motion detected again, i have reset the timer")
def light_off(self, kwargs):
motion_still_detected = False
for sensor in self.sensors:
if self.get_state(sensor) == "on":
motion_still_detected = True
if not motion_still_detected:
self.handle = None
if "entity_off" in self.args:
off_entities = self.args["entity_off"].split(",")
for off_entity in off_entities:
# If it's a scene we need to turn it on not off
device, entity = self.split_entity(off_entity)
if device == "scene":
self.log("I activated {}".format(off_entity))
self.turn_on(off_entity)
else:
self.log("I turned {} off".format(off_entity))
self.turn_off(off_entity)
else:
self.log("Timer has Ended, but a motion detector is still on. This shouldnt happen, probably is the delay to short.")
I have only tested it for 24 hours, so could be that a revision is coming.
to do list:
check if lights are on before motion detection to keep them on.
I have a running AppDaemon config (two apps running from Andrew) so that part is all fine. I have created a motionlights.py file in my apps directory and copied above into that file.
2016-11-23 21:18:36.018188 WARNING ------------------------------------------------------------
2016-11-23 21:19:24.008126 WARNING ------------------------------------------------------------
2016-11-23 21:19:24.008835 WARNING Unexpected error during loading of motionlights.py:
2016-11-23 21:19:24.009157 WARNING ------------------------------------------------------------
2016-11-23 21:19:24.010398 WARNING Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/appdaemon/appdaemon.py", line 675, in readApp
conf.modules[module_name] = importlib.import_module(module_name)
File "/usr/lib/python3.4/importlib/__init__.py", line 109, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1129, in _exec
File "<frozen importlib._bootstrap>", line 1471, in exec_module
File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
File "/home/pi/appdaemon/conf/apps/motionlights.py", line 20, in <module>
class MotionLights(appapi.AppDaemon):
NameError: name 'appapi' is not defined
2016-11-23 21:19:24.010830 WARNING ------------------------------------------------------------
Update: Solved; this needed to be MotionLights (capital M & L). Running ok!
p.s. Would it be possible to add an extra âparameterâ for elevation to the config? Actually only want the automation to work when below is true (in this case):
and yeah, you can reuse this app as often as you like. thats the big advantage from appdaemon.
so just create a new block in your cfg file with a different name and you can use different args, so different rooms.
delay is seconds.
so it should turn off after 5 mins.
if it detects a second movement you should see that in your log or on screen.
and also after the timer ends you should get an entry in your log or on screen.
i added an off function to your version of motion_lights.py to reset the timer, when at least one entity is turned off manually. if this functionalty is missing, an entity that is being turned off in HA, wonât turn on when motion is detected, as long as the timer is still running.
Why do you specifically want new == on when setting up the timer? Wouldnât it be better to allow for off to also trigger the timer? Then I think you could clean up your light_off to not need to look for motion still detected right?
to post code correctly you need ` 3 times and then a new line. before and after the code.
not â and not " (sorry dont know the names from those symbols) the one you use to create è.
your question to diplix is right. that would be the way.
why do i want new= on?
i know that there are motion detectors which have there own timer. they keep on for the time they are set to, for instance between 5 an 30 seconds and you can set that with a potentiometer.
but my code has no way to detect that. so your delay would be affected by that.
the second thing you say is that you dont need to look after the motion detection is set to off.
and thats also not true. if you have an motion detector which goes to off after 5 seconds then you need to stay reel busy to make sure it still keeps detecting you.
suppose you use it for a bathroom. you want the light to stay on while you are on the toilet.
you dont move very much. lets say you move not at all for 60 seconds. allmost every motion detector would have gone to off by that time. but you still like the lights to stay on, untill your gone.
so thats why i think you need to keep checking untill the end off the delay. and only for movement.
thats also why the last line checks if the motion detector is still set to on at the end off the timer.
to use motion detection like this you want your motiondetector settings to be as short as possible.
Ok. Will try that out for posting code. Stay tuned!
Regarding what I meant with off is that new == off should also trigger the timer, not turn off the lights. Because then you will cover more more scenarios. E.g. When you move detection will go to on and timer will set but only at the beginning of movement. If the detection stays hi for longer than 60 seconds, the lights will turn off. But if you also care about the signal for new == off as in no motion detected and then also set the timer for countdown you will be less likely to actually need to check if sensors are still active.
Am I explaining it well enough or should I write a logical example of what I mean?
i think your logic is wrong.
actually the best motion detector you would have goes off diectly without any delay after the motion is detected.
but lets say you have 1 that stays high for 4 minutes.
the motion is detected and your timer is set to 5 mins. (bacause you like it to stay on for 5 mins after detection)
if your timer is influenced by your detector going to off, you lights would stay on for 9 minutes total.
going off is saying nothing about the motion, because of the fact that every motion detector is different.
it can say that there was no motion for some time (if you have a motion detector which stays high for repeated motion) but it can also say that just some time has passed since the first motion is detected.
and the some in some time is also unknown.
i set my detectors as low as possible. so it wont stay high for 60 seconds.
if you have a detector which stays high as long as it detects movement (and also has its own delay) you actually dont need an app like this. they you just would like your lights to go off when the detector goes to off.
so there is a hardware difference. some do have a decent program like this included in the hardware and some dont.
with this app you like the once that dont have any delay.
i use cheap motion detectors that i can connect to my arduinos.
i could also use arduino programming to set my delay. but if it is in the hardware or the arduino is the same.
i dont want that because i like to be able to change settings from my pc and not on my hardware
Havenât changed this for a long time but now I want to differentiate the same light for evening use and night use. With this I mean that, when after 0:00 until sunrise, I want the motionlight still to work but with a dimmed light. What is the easiest way to achieve this? Was think of just duplicating the current one and then use times that are adjacent and refer to different scene. Code below. Is that the easiest way and would that work?