Lua - Dusk Sensor
Introduction
I've been looking for a way to turn on/off the lights in my living room using a KlikAanKlikUit Dusk Sensor (ABST-604) to measure the daylight coming in through the windows. I want my lights to turn on when it's getting dark, cloudy, etc, whenever it's dark enough that i would normally turn on the lights. This Dusk Sensor has a user changable dusk level so it would seem easy. However, when the brightness/darkness outside is nearing the dusk level the Dusk Sensor will repeatly turn on/off/on/off. I'd like to call this a flipstorm, which i want to avoid.
To avoid this flipstorm i only want to turn on/off my living room lights after a certain period and not after each Dusk Sensor state change. Since i want to use the Dusk Sensor for more than just switching my lights on or off, i will use a Virtual Switch called 'State - isDark' to indicate it is Dark or Light outside. Using a seperate switch to indicate it is either Dark or Light outside allows me to use it in other scripts and/or events.
To turn on/off lights you should have the following setup:
- A Kaku ABST-604 Dusk sensor (see Dusk Sensor Setup, for tips how to set it up)
- A Virtual Device called 'State - IsDark' or something similiar
- An Event that turns on / off the lights based on the 'State - IsDark' status.
- This script in the /scripts/lua directory named something like 'script_time_xxx.lua', for example mine is called 'script_time_lastupdate.lua' since this one script holds all my switches that need to be flipstorm friendly.
The Rules
To decide when it is Dark or Light outside i've made the following 4 rules.
- If Dusk Sensor is On, then it is dark enough then i would normally turn on my living room lights.
- If Dusk Sensor is Off, then it is light enough that i would normally turn off my living room lights.
- If Dusk Sensor changes On -> Off (eg: it gets lighter outside) then 'State - IsDark' is Off for at least 5 minutes.
- If Dusk Sensor changes Off -> On (eg: it gets darker outside) then 'State - IsDark' is On for at least 15 minutes.
Rule 3 and 4 are to avoid the flipstorm. The Dusk Sensor will still switch on/off several times, but within these time periods the 'State - IsDark' will not change. You have to decide for yourself if the periods are small/large enough. For me, these work fine if you set the Dusk Level properly.
How it works
To implement the above rules i've tried to make a generic script in which you can implement the above rules. Eventhough i use it for my Dusk Sensor, the script should be generic enough that you can use it for other things by adding extra on_off instructions. I've tried to make it as simple as possible to use the script, so hopefully you only need to change two lines. One at the top which defines the Dusk Sensor and one at the bottom which defines an on_off instruction.
local kaku_dusk_sensor = 'State - Schemer Sensor' -- The name of the Dusk Sensor in Domoticz.
on_off('State - IsDark', 300, is_on(kaku_dusk_sensor), 900, is_off(kaku_dusk_sensor))
The explanation:
- 'local kaku_dusk_sensor ...' defines the device name of the Dusk Sensor.
- 'State - IsDark' is a Virtual Switch that i use to indicate it is dark outside and i want my lights to switch on.
- This script (if you name it script_time_something.lua) will run every minute. It is not a device script, because 'State - IsDark' is updated after a certain period has been elapsed and not when the Dusk Sensor changes it state.
Parameters:
- 'State - IsDark' - the device name of the switch that will be switched on or off.
- 300 - The last update of 'State - IsDark' should have been at least 300 seconds ago before we will change the status to On.
- is_on(kaku_dusk_sensor) - Switch 'State - IsDark' to On, if the Dusk Sensor is On
- 900 - The last update of 'State - IsDark' should have been at least 900 seconds ago before we will change the status to Off.
- is_off(kaku_dusk_sensor) - Switch 'State - IsDark' to Off, if the Dusk Sensor is Off
In other words, regardless if the Dusk Sensor changes it's state (thus avoiding a flip storm).
- If our lights are switched Off, they will at least stay Off for 5 minutes (300 seconds).
- If our lights are switch On, they will at least stay On for 15 minutes (900 seconds).
Dusk Sensor setup
- Setup your Dusk Sensor facing outwards. I have mine mounted on the window facing outside.
- The hour setting should be set to 0.
- Set it to a dusk level when your are SURE you want your lights to turn OFF. If you set it too dark, your lights will turn off too soon in the morning and too late in the afternoon/evening.
- Make sure any Kaku recievers are disconnected from your Dusk Sensor, only the RFXCom should pick it up.
The Script
Put this in <DOMOTICZ_HOME>/scripts/lua/script_time_lastupdate.lua
Remember that you can use more than just the Dusk Sensor is this script by adding more on_off instructions so i use a generic name.
--[[
script_time_lastupdate.lua
@author: Nicky Bulthuis
@since: 2015-01-14
@version: 0.1
A basic LUA script to set a device status after a specific time has been elapsed since the last update.
--]]
local kaku_dusk_sensor = 'State - Schemer Sensor' -- The name of the Dusk Sensor in Domoticz.
--
-- Function to calculate time difference between a timestamp and now in seconds.
--
function timedifference(s)
year = string.sub(s, 1, 4)
month = string.sub(s, 6, 7)
day = string.sub(s, 9, 10)
hour = string.sub(s, 12, 13)
minutes = string.sub(s, 15, 16)
seconds = string.sub(s, 18, 19)
t1 = os.time()
t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
difference = os.difftime (t1, t2)
return difference
end
--
-- Indicate if the flip device is allowed to update.
-- This is to avoid a flip storm. eg: on off on off on off.
--
function may_update(device, timeelapsed)
return otherdevices_lastupdate[device] == nil or timedifference(otherdevices_lastupdate[device]) >= timeelapsed
end
--
-- Switch a device on/off when the timeelapsed has passed and the conditions are true.
--
function on_off(device, timeelapsed_on, condition_on, timeelapsed_off, condition_off)
if condition_on and condition_off then
print('Error: condition_on and condition_off are both true for device: ' .. device)
elseif condition_on and may_update(device, timeelapsed_on) then
if (otherdevices[device] == 'Off') then
commandArray[device]='On'
end
elseif condition_off and may_update(device, timeelapsed_off) then
if (otherdevices[device] == 'On') then
commandArray[device]='Off'
end
end
end
--
-- Returns true if the device status is On.
--
function is_on(device)
return otherdevices[device] == 'On'
end
--
-- Returns true if the device status is Off.
--
function is_off(device)
return otherdevices[device] == 'Off'
end
--
-- Main
--
commandArray = {}
on_off('State - IsDark', 300, is_on(kaku_dusk_sensor), 900, is_off(kaku_dusk_sensor))
return commandArray