[script] LUA: Determine LUX average and decide if it's dark or not
Posted: Tuesday 23 January 2018 8:25
Lately i'm busy rewriting all my Lua scripts.
As i'm gradually switching over from 433mhz to Z-Wave devices all my scripts got a bit outdated.
In the past i used to determine the lux status with a KaKu dusk sensor and timer scripts.
Al though those sensors only send a ON/Off signal it suited my needs but still had some miss reading.
Especially when switching seasons where the sun position is changed and time between dark to sunset or sunrise to daytime changes also.
So i always needed to adjust the timers and got a bit fed up with that.
Recently i got myself three Fibaro motion sensors.
And as we know the report lux thresholds.
And since then i used the lux threshold to decide it is dark or not.
Still had some miss reading as we know when a certain light in the room where the motion sensor is located is turned on.
And causes the lux to rise especially in the my living where lux margin are low or hallway where a light is in side of the sensor.
So i decide to take a other approach.
Why not taking all my available lux thresholds and calculate the average and decide if it's dark or not.
I use a function library but below i melted into one script to keep it simple.
How does the script work:
Script contains three functions.
1. timebetween
This function is used to be able to determine time between.
Meaning if defined then something will only trigger between xx:xx and xx:xx hour
2. os.capture
This function is used to be able to capture os.executes.
In this script its used to get sunrise and sunset times available in Domoticz.
3. isdark
This function is used to calculate lux average.
Then according your predefined times determine if its dark or not.
Script also looks in my specific situation if the lux is higher in the hallway.
Because if the light is switched ON then the lux reading average is wrong.
In the end its easy to call if its dark or not.
Simply ask for it in a IF ELSE statement by: if IsDark('true') then
As for the script, normally you don't have to amend function 1 and 2.
Only function 3 needs some amendments to suite your needs.
Like sensor names, max lux threshold, timebetween and such.
As i'm gradually switching over from 433mhz to Z-Wave devices all my scripts got a bit outdated.
In the past i used to determine the lux status with a KaKu dusk sensor and timer scripts.
Al though those sensors only send a ON/Off signal it suited my needs but still had some miss reading.
Especially when switching seasons where the sun position is changed and time between dark to sunset or sunrise to daytime changes also.
So i always needed to adjust the timers and got a bit fed up with that.
Recently i got myself three Fibaro motion sensors.
And as we know the report lux thresholds.
And since then i used the lux threshold to decide it is dark or not.
Still had some miss reading as we know when a certain light in the room where the motion sensor is located is turned on.
And causes the lux to rise especially in the my living where lux margin are low or hallway where a light is in side of the sensor.
So i decide to take a other approach.
Why not taking all my available lux thresholds and calculate the average and decide if it's dark or not.
I use a function library but below i melted into one script to keep it simple.
How does the script work:
Script contains three functions.
1. timebetween
This function is used to be able to determine time between.
Meaning if defined then something will only trigger between xx:xx and xx:xx hour
2. os.capture
This function is used to be able to capture os.executes.
In this script its used to get sunrise and sunset times available in Domoticz.
3. isdark
This function is used to calculate lux average.
Then according your predefined times determine if its dark or not.
Script also looks in my specific situation if the lux is higher in the hallway.
Because if the light is switched ON then the lux reading average is wrong.
In the end its easy to call if its dark or not.
Simply ask for it in a IF ELSE statement by: if IsDark('true') then
As for the script, normally you don't have to amend function 1 and 2.
Only function 3 needs some amendments to suite your needs.
Like sensor names, max lux threshold, timebetween and such.
Code: Select all
--[[
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
@ isdark.lua
@ updated : 1-23-2018
@ Script for calculating average lux between various lux sensors and determine if its dark or not
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
--]]
--
-- **********************************************************
-- Time Between X hours and X hour
-- **********************************************************
--
function timebetween(s,e)
timenow = os.date("*t")
year = timenow.year
month = timenow.month
day = timenow.day
s = s .. ":00"
e = e .. ":00"
shour = string.sub(s, 1, 2)
sminutes = string.sub(s, 4, 5)
sseconds = string.sub(s, 7, 8)
ehour = string.sub(e, 1, 2)
eminutes = string.sub(e, 4, 5)
eseconds = string.sub(e, 7, 8)
t1 = os.time()
t2 = os.time{year=year, month=month, day=day, hour=shour, min=sminutes, sec=sseconds}
t3 = os.time{year=year, month=month, day=day, hour=ehour, min=eminutes, sec=eseconds}
sdifference = os.difftime (t1, t2)
edifference = os.difftime (t1, t3)
isbetween = false
if sdifference >= 0 and edifference <= 0 then
isbetween = true
end
return isbetween
end
--
-- **********************************************************
-- Function to execute os commands and get output
-- **********************************************************
--
function os.capture(cmd, raw)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if raw then return s end
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
s = string.gsub(s, '[\n\r]+', ' ')
return s
end
--
-- **********************************************************
-- Get lux threshold IsDark or IsDay
-- **********************************************************
-- Example: if isdark('true') then
function IsDark(dark)
dark = dark
-- Lux Sensors
local livingroom_lux_sensor = 'Woonkamer - Lux'
local hallway_lux_sensor = 'Gang - Lux'
local upstairs_lux_sensor = 'Overloop - Lux'
-- Define Max/Min Lux threshold
local lux_threshold = 8
-- Get Lux Value
living = tonumber(otherdevices_svalues[livingroom_lux_sensor])
hallway = tonumber(otherdevices_svalues[hallway_lux_sensor])
upstairs = tonumber(otherdevices_svalues[upstairs_lux_sensor])
-- Create table (take in count hallway light ON/OFF to avoid false readings)
if living >= hallway then
sensors={living, hallway, upstairs}
elseif living < hallway then
sensors={living, upstairs}
end
local elements = 0
local sum = 0
local lux = 0
-- Calculate Average
for k,v in pairs(sensors) do
sum = sum + v
elements = elements + 1
end
lux_average = sum / elements
-- Get Sunset
sunset=os.capture("curl 'http://127.0.0.1:8080/json.htm?type=command¶m=getSunRiseSet' | grep 'Sunset' | awk '{print $3}' | sed 's/\"//g' | sed 's/,//g'", false)
sunset = tostring(""..sunset..":00")
-- Get Sunrise
sunrise=os.capture("curl 'http://127.0.0.1:8080/json.htm?type=command¶m=getSunRiseSet' | grep 'Sunrise' | awk '{print $3}' | sed 's/\"//g' | sed 's/,//g'", false)
sunrise = tostring(""..sunrise..":00")
--IsDark_Dawn
if timebetween("00:00:00",""..sunrise.."")
and lux_average >= lux_threshold
then
threshold = 0
end
if timebetween("00:00:00",""..sunrise.."")
and lux_average < lux_threshold
then
threshold = 1
end
--IsDay_Morning
if timebetween(""..sunrise.."","11:59:59")
and lux_average >= lux_threshold
then
threshold = 0
end
if timebetween(""..sunrise.."","11:59:59")
and lux_average < lux_threshold
then
threshold = 0
end
--IsDay_Afternoon
if timebetween("12:00:00",""..sunset.."")
and lux_average >= lux_threshold
then
threshold = 0
end
if timebetween("12:00:00",""..sunset.."")
and lux_average < lux_threshold
then
threshold = 0
end
--IsDark_Dusk
if timebetween(""..sunset.."","23:59:59")
and lux_average >= lux_threshold
then
threshold = 0
end
if timebetween(""..sunset.."","23:59:59")
and lux_average < lux_threshold
then
threshold = 1
end
isdark = false
if threshold == 1 and dark == 'true' then
isdark = true
end
if threshold == 0 and dark == 'false' then
isdark = true
end
return isdark
end
commandArray = {}
if devicechanged[dummy1] == 'On' and otherdevices[dummy2] == 'Off' and IsDark('true')
then
commandArray[dummy2]='On'
print('**********************************************************')
print('Its dark outside')
print('')
print('Lux Living:'..living..'')
print('Lux Hallway:'..hallway..'')
print('Lux Upstairs:'..upstairs..'')
print('------------------')
print('Lux Average:'..lux_average..'')
print('**********************************************************')
end
if devicechanged[dummy1] == 'Off' and otherdevices[dummy2] == 'On' and IsDark('false')
then
commandArray[dummy2]='Off'
print('**********************************************************')
print('Its aint dark anymore')
print('')
print('Lux Living:'..living..'')
print('Lux Hallway:'..hallway..'')
print('Lux Upstairs:'..upstairs..'')
print('------------------')
print('Lux Average:'..lux_average..'')
print('**********************************************************')
end
return commandArray