Author Topic: Most efficient way to use luup.call_timer for motion based automatic lighting  (Read 1976 times)

Offline chrisbirkinshaw

  • Sr. Newbie
  • *
  • Posts: 23
  • Karma: +0/-0
I have created the code below, however am worried it is not very efficient.

The basic flow is:

1. Motion detected
2. If light is off then turn it on
3. Trigger timer passing tripped time as data
4. When timer ends test whether motion has been tripped again since the time was called
5. If motion was not tripped since the timer was called then switch light off

However, this means I have lots of parallel timer threads running, as a new one is created every time motion is detected.

Would it be more efficient to have a loop that runs every second and evaluates LastTrip timestamps for all motion detectors and turns off lights if they detector was not tripped for some time? I would call the loop function once on startup then have a timer at the end to call itself after a 1 sec delay.

Current code snippet is below.

Thanks,

Chris

Code: [Select]
function setup_watchers()
core_log("Setting up watchers")
luup.variable_watch("livingroom_motion", MOTION_SID, "Tripped", LIVINGROOM_MOTION)
end

function livingroom_motion()
  local tripped = luup.variable_get(MOTION_SID, "Tripped", LIVINGROOM_MOTION)
  if (tripped == "1") then
core_log("Livingroom motion detected")
local this_trip =  os.time()
local last_trip = luup.variable_get( MOTION_SID, "LastTrip", LIVINGROOM_MOTION) or this_trip
local day = luup.variable_get(DAY_NIGHT_SID, "Status", DAY_NIGHT)
local receiver_power = luup.variable_get(SW_SID, "Status", LIVINGROOM_RECEIVER)
local receiver_input = luup.variable_get(INPUT_SID, "Input", LIVINGROOM_RECEIVER)
local transport_state = luup.variable_get(AV_TRANSPORT_SID, "TransportState", SONOS)
local dimmer_status = luup.variable_get(DIMMER_SID, "LoadLevelStatus", LIVINGROOM_LIGHT)
local house_mode =  luup.variable_get(VCONTAINER_SID, "Variable1", HOUSE_VARS)

luup.variable_set(MOTION_SID, "LastTrip", this_trip, LIVINGROOM_MOTION)

-- activate lights if night and home and not already on and av off or set to music
core_log("house_mode=" .. house_mode .. ", dimmer_status=" .. dimmer_status .. ", day=" .. day .. ", receiver_power=" .. receiver_power .. ", receiver_input=" .. receiver_input)
if (house_mode == "Home") and (day == "0") and (receiver_power == "0" or (receiver_power == "1" and receiver_input == MUSIC_INPUT)) then
if (dimmer_status == "0") then
core_log("Setting Livingroom light dim level to 100%")
luup.call_action( DIMMER_SID, "SetLoadLevelTarget", { newLoadlevelTarget = LIVINGROOM_LEVEL}, LIVINGROOM_LIGHT)
end
      luup.call_timer("livingroom_lights_off", 1, LIGHTS_DELAY, "", this_trip)
end

-- activate music if sonos playing and home amp not already on
core_log("house_mode=" .. house_mode .. ", transport_state=" .. transport_state .. ", receiver_power=" .. receiver_power)
if (house_mode == "Home") and (transport_state == "PLAYING") then
if (receiver_power == "0") then
core_log("Running Livingroom music on scene")
luup.call_action(HA_SID, "RunScene", {SceneNum = LIVINGROOM_MUSIC_ON}, 0)
end
luup.call_timer("livingroom_music_off", 1, MUSIC_DELAY, "", this_trip)
end
  end
end

function livingroom_lights_off(this_trip)
core_log("Livingroom lights off called by timer")
local last_trip = luup.variable_get( MOTION_SID, "LastTrip", LIVINGROOM_MOTION)
local dimmer_status = luup.variable_get(DIMMER_SID, "LoadLevelStatus", LIVINGROOM_LIGHT)

core_log("this_trip=" .. this_trip .. ", last_trip=" .. last_trip)
-- Only turn off if the sensor was not tripped again after the timer was called and the light is still on
if (this_trip == last_trip) then
core_log("Turning livingroom light off")
luup.call_action( DIMMER_SID, "SetLoadLevelTarget", { newLoadlevelTarget = "0"}, LIVINGROOM_LIGHT)
end
end

function livingroom_music_off(this_trip)
core_log("Livingroom music off called by timer")
local last_trip = luup.variable_get( MOTION_SID, "LastTrip", LIVINGROOM_MOTION)
local receiver_power = luup.variable_get(SW_SID, "Status", LIVINGROOM_RECEIVER)
local receiver_input = luup.variable_get(INPUT_SID, "Input", LIVINGROOM_RECEIVER)

core_log("this_trip=" .. this_trip .. ", last_trip=" .. last_trip .. ", receiver_power= " .. receiver_power .. ", receiver_input=" .. receiver_input)
-- Only turn off if the sensor was not tripped again after the timer was called and the amp is still powered up and on the music input
if (this_trip == last_trip) and (receiver_power == "1") and (receiver_input == MUSIC_INPUT) then
speak("turning off music in the living room")
core_log("Running livingroom music off scene")
luup.call_action(HA_SID, "RunScene", {SceneNum = LIVINGROOM_MUSIC_OFF}, 0)
end
end

Offline PJJP

  • Full Member
  • ***
  • Posts: 149
  • Karma: +2/-0
Did you ever find a more efficient method for this? Or did you just stick with it? How's it working?

Offline chrisbirkinshaw

  • Sr. Newbie
  • *
  • Posts: 23
  • Karma: +0/-0
In practice it seems to work with no issues.

Chris

Offline Eilskov

  • Newbie
  • *
  • Posts: 8
  • Karma: +0/-0
I know this is old, but please show how you set AV_TRANSPORT_SID

Offline Tillsy

  • Full Member
  • ***
  • Posts: 207
  • Karma: +12/-4
I did this entirely differently:

1. Set up an association between the motion sensor and the light relay
2. Configured settings on motion sensor so that it activates for the time I want, stays active if more motion detected, etc.
3. For thoroughness, set a scene in Vera that kicks in when the light is detected as on and to do a delay turn off of the light

In practise only #1 and #2 happen, as the sensor obviously activates with motion and for as long as it is activated it also activates the light.  It automatically turns off again when no motion.  #3 is simply a fallback in case it were manually turned on and for some reason no movement ended up happening that would otherwise cause it to then turn off.

Furthermore as this is a passage way I have actually put a Fibaro dimmer there and set it to retain the brightness level.  At night I have a scene that sets the brightness to 5%, by day 100%.

Offline mrmaceurope

  • Newbie
  • *
  • Posts: 10
  • Karma: +0/-0
Hi Chris,

Would you say that it's fast enough?

I'm asking since I have Associated my PIR and Dimmer from Fibaro to communicate directly instead of through my controller and to be that seems to be a lot faster. However the drawback is that that I am not able to control the light directly, rather I need to kind of overrule the direct communication, which I actually haven't done in this case, since it a hallway where the direct setup works fine. So same setup as Tillsy, though I don't use my VERA controller currently, instead I have converted to Telldus http://telldus.com.

Anyhow, would be great to hear you feedback, since I'm considering implementing LUA if it means taking back control to the Controller? :)

In practice it seems to work with no issues.

Chris