Trigger light by movement but with 4 different time profiles (color and brightness)

Does anyone have any examples of how to vary light brightness and color depending on the time of night?

I think this will be a lot easier with AppDaemon.

I currently have 3 or 4 YAML automations per light, as a general rule:
Early evening: 100%
Mid evening: 50% Brightness
Night: 15% Brightness
Early morning for work: 75% Brightness

Its really nice to get up in the middle of the night and have a light go on but dim :slight_smile:

I am aware that my current setup its not very elegant and trying to think of something easy to maintain like a single app daemon app that either takes multiple parameters for each instance (light) or that has and algorithm to calculate light intensity.

Any ideas? :slight_smile:

you can use the run_daily function with times you like.
so 4 run daily functions.
use a kwarg in the function to set the % and point them to 1 callback.

do it onve for all the lights you want or reuse the code for every light you want by setting the lights in your apps.yaml

Hi Rene,

Thanks for your help. JFYI your examples and tutorials are the reason I finally decided to give AppDaemon a go.

I dont have much Python experience and am having trouble understaning:

use a kwarg in the function to set the % and point them to 1 callback.

Do you have any examples?

something like:

def init(...):
  self.run_daily(self.callback,runtime, kw_brightness = 100)
def callback(...):
  self.turn_on("light.something", brightness = kwargs["kw_brightness"])

so you set a variable in the run_daily, listen_state, etc. AFTER all needed setting, and you give it a name that isnt used for something already!! (thats why i start those vars with kw_
then you can use it in the callback with kwargs[“kw_the set_var_name”]

What I’ve done:

I have a input.select that has Time Of Day like this:

tod:
  name: Time of day
  options:
    - Morning
    - Day
    - Evening
    - Night

and I have a appdaemon app based on the default advancedMotionLightSensorm, that does something like:

amls hal:
  module: advancedMotionLightSensor
  class: advancedMotionLightSensor
  ...
  input_select: input_select.tod
  lightmapping: {'Morning':30,'Day':99,'Evening':40,'Night':10}

and in python:

self.lightmapping = self.args["lightmapping"]
desired_dimval = self.lightmapping[self.selected_state]
self.turn_on(self.arg_switch,brightness_pct = desired_dimval)

Does this help?

in that case you can just use a listen_state for “input_select.tod” and then set your lights accordingly.

something like:

def init(...):
  self.listen_state(self.callback,"input_select.tod")
def callback(...):
  self.lightmapping = self.args["lightmapping"]
  desired_dimval = self.lightmapping[new]
  self.turn_on(self.arg_switch,brightness_pct = desired_dimval)

as soon as the input_select changes the lighning changes accordingly.

Thanks Rene,

So we can pass variables when we register the callback in the init that we might need to be available in the callback function?

thats true.

you have 2 options to get a variable from the init to the callback.

  1. set the variable as class global by naming it self.variable
  2. transport the variable with the kwargs function.

@kiwinol,

I have something like this, and this is how I did it.

First I created a sensor which I use to determine the “part of day” as follows:

- platform: template
  sensors:
     day_interval:
         friendly_name: "Part of Day"
         value_template: >
            {% if now().hour in range(0, 6) %}
            Midnight
            {% elif now().hour in range(6, 12) %}
            Morning
            {% elif now().hour in range(12, 18) %}
            Afternoon
            {% elif now().hour in range(18, 24) %}
            Evening
            {% endif %}

I did it this way, so I can use it across different things in my system.

Then in Appdaemon u can do the following
apps.yaml

amlshal:
  module: amlshal
  class: advancedMotionLightSensor
  ...
  input_select: input_select.tod
  lightmapping: 
      Morning: 30
      Day: 99
      Evening: 40
      Night: 10

Then for amlshal.py

def init(...):
  self.listen_state(self.callback,self.args['input_select'])
  self.light_mappings = self.args['lightmapping']

def callback(...):
  day_section = self.get_state('sensor.day_interval')
  desired_dimval = self.light_mappings[day_section]
  self.turn_on(self.arg_switch, brightness_pct = desired_dimval)

Hope it helps

i use an app for that too.
because then it is easier to edit the times and periods.
for instance let the evening start at sunset or 1 hour after sunset.
or add a period between night and morning called twilight

@ReneTode,

yeah good point, and it makes changing it easier.

I had done mine a long time ago, before I went main stream into AppD, so haven’t just bothered to change it.

regards

i started working with AD before i had real automations.
and it was short after that that i discovered the option to create sensors. (Andrew didnt even know it was possible :stuck_out_tongue: )
since then i dont have template sensors anymore.
i have almost no configured sensors in HA, they all come from mysensors or from AD.

Wow that’s interesting. So u use mysensors a lot?

yup, i dont have found a way to get away from it.
what do you do when you get a lot off cheap arduinos and a bunch of nrfs for almost nothing?
you cant get a direct wifi connection with that.
so if you have a maingate with nrf, you can connect everything.

i must say that i am thinking about moving all to esp with, mqtt, but what about my arduinos?
and i only have 256 places for all devices in my network. and its filling up quickly.

just a short calculation:
i got a few rooms, so lets count the most important:
livingroom, bedroom, kitchen, mancave, bathroom, second bedroom, hobbyroom, etc.
so lets say we have 10 rooms (its actually more near 25 but just for fun)
so you only have 25 ips for every room.
pc, tv, sat reciever, motion sensors, cover, heating, and a few others and you can get to the max quickly.
so yeah i think ill be using mysensors for a long time.
mostly because if you want to cover a large home (over 10 rooms) with a lot of sensors, you wont get around it, or something simular

Thanks for your explanation and patience I am starting to understand now I just need to get automating :slight_smile:

1 Like

Hi Rene, how does your app for “part of day” that look like?

part of day is included in my AD sensor app.

it sets the state from sensor.part_of_day to a certain state, based on events.

if my wife wakes up, the sensor state goes to “morning”
if i wake up it goes to “day”
if the evening lights go on it goes to “evening”
if i go to bed it goes to “night”

but the basic thing about it is that it uses set_state to change the state from a sensor.

I am having great trouble by making this work. I have a sensor in my configuration file:

sensor:
  - platform: template
    sensors:
      day_interval:
        friendly_name: "Part of day"
        value_template: >
            {% if now().hour in range(0, 6) %}
            Night
            {% elif now().hour in range(6, 18) %}
            Day
            {% elif now().hour in range(18, 22) %}
            Evening
            {% elif now().hour in range(22, 24) %}
            Midnight
            {% endif %}

Then I have made an amlshal.py file:

import appdaemon.plugins.hass.hassapi as hass

class advancedMotionLightSensor(hass.Hass):

def init(...):
  self.listen_state(self.callback,self.args['input_select'])
  self.light_mappings = self.args['lightmapping']

def callback(...):
  day_section = self.get_state('sensor.day_interval')
  desired_dimval = self.light_mappings[day_section]
  self.turn_on(self.arg_switch, brightness_pct = desired_dimval)

And last made in the apps.yaml:

amlshal:
  module: amlshal
  class: advancedMotionLightSensor
  input_select: input_select.tod
  lightmapping: 
      Evening: 170
      Day: 240
      Midnight: 100
      Night: 50

This doesn’t really work, so I might be totally off?

The log returns this:
2018-07-03 21:40:36.567661 INFO hello_world: Hello from AppDaemon
2018-07-03 21:40:36.573377 INFO hello_world: You are now ready to run Apps!
2018-07-03 21:40:36.574050 INFO AppDaemon: Initializing app amlshal using class advancedMotionLightSensor from module amlshal
2018-07-03 21:40:36.577575 WARNING AppDaemon: ------------------------------------------------------------
2018-07-03 21:40:36.578272 WARNING AppDaemon: Unexpected error initializing app: amlshal:
2018-07-03 21:40:36.579589 WARNING AppDaemon: ------------------------------------------------------------
2018-07-03 21:40:36.582170 WARNING AppDaemon: Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 2040, in check_app_updates
self.init_object(app)
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 1561, in init_object
modname = import(app_args[“module”])
File “/config/appdaemon/apps/amlshal.py”, line 5
def init(…):
^
IndentationError: expected an indented block
2018-07-03 21:40:36.582839 WARNING AppDaemon: ------------------------------------------------------------

def needs to be indented in the class. so:

class advancedMotionLightSensor(hass.Hass):

    def init(...):

and that why you get the error. and then off course the app cant start.

That got things a step further :slight_smile:

Now I get this error instead in the log:
2018-07-04 18:37:27.657740 INFO AppDaemon: Reloading Module: /config/appdaemon/apps/amlshal.py
2018-07-04 18:37:27.659464 INFO AppDaemon: Loading App Module: amlshal
2018-07-04 18:37:27.663577 WARNING AppDaemon: ------------------------------------------------------------
2018-07-04 18:37:27.664483 WARNING AppDaemon: Unexpected error loading module: /config/appdaemon/apps/amlshal.py:
2018-07-04 18:37:27.665894 WARNING AppDaemon: ------------------------------------------------------------
2018-07-04 18:37:27.671025 WARNING AppDaemon: Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 1789, in read_app
importlib.reload(self.modules[module_name])
KeyError: ‘amlshal’
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 2015, in check_app_updates
self.read_app(mod[“name”], mod[“reload”])
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 1794, in read_app
self.read_app(file)
File “/usr/lib/python3.6/site-packages/appdaemon/appdaemon.py”, line 1802, in read_app
self.modules[module_name] = importlib.import_module(module_name)
File “/usr/lib/python3.6/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “”, line 994, in _gcd_import
File “”, line 971, in _find_and_load
File “”, line 955, in _find_and_load_unlocked
File “”, line 665, in _load_unlocked
File “”, line 674, in exec_module
File “”, line 781, in get_code
File “”, line 741, in source_to_code
File “”, line 219, in _call_with_frames_removed
File “/config/appdaemon/apps/amlshal.py”, line 5
def init(…):
^
SyntaxError: invalid syntax
2018-07-04 18:37:27.676830 WARNING AppDaemon: Removing associated apps:
2018-07-04 18:37:27.671935 WARNING AppDaemon: ------------------------------------------------------------
2018-07-04 18:37:27.678350 WARNING AppDaemon: amlshal

Now amlshal.py looks like this

import appdaemon.plugins.hass.hassapi as hass

class advancedMotionLightSensor(hass.Hass):

  def init(...):
    self.listen_state(self.callback,self.args['input_select'])
    self.light_mappings = self.args['lightmapping']

  def callback(...):
    day_section = self.get_state('sensor.day_interval')
    desired_dimval = self.light_mappings[day_section]
    self.turn_on(self.arg_switch, brightness_pct = desired_dimval)  

But maybe my starting point is wrong. What I basically would like to do, is by using the sensor “Part of day” and if the lux is below 100 I would like entity id: “light.aeotec_zw111_nano_dimmer_level” to go on at movment by the dimlevel specified in the amlshal part of apps.yaml