22.06.2022, 10:29
Updated version with an optional timer on/off object and status monitoring. For this to work the dimmer must have a status output active and should report the status as soon as possible (some dimmers have an option to report status when only after a transition). When the script writes its output value it will ignore the status report for 1 second. This can be lowered (line 53) to prevent possible issues when a manual control is performed at the same moment as the scripted control.
Code:
if not client then
timers = {
{
input = '1/1/1', -- binary PIR status
enable = '1/1/2', -- enable timer on/off
output = '1/1/3', -- dimmer control (0..100%)
status = '1/1/4', -- dimmer status (0..100%)
onvaluehigh = 90, -- high output value in %
onvaluelow = 10, -- low output value in %
timeout = 5, -- in seconds
}
}
function setoutputvalue(timer, value)
timer.ignoresec, timer.ignoreusec = os.microtime()
grp.write(timer.output, value, dt.scale)
end
function settimerstate(timer, event)
timer.enabled = busdatatype.decode(event.datahex, dt.bool)
timer.ticks = nil
log('timer enabled', timer.enabled)
end
function setinputvalue(timer, event)
local value = busdatatype.decode(event.datahex, dt.bool)
if not value or not timer.enabled then
return
end
log('pir trigger', timer.statvalue)
if timer.statvalue < timer.onvaluelow then
value = timer.onvaluelow
elseif timer.statvalue < timer.onvaluehigh then
value = timer.onvaluehigh
else
value = nil
end
if not timer.ticks and value then
setoutputvalue(timer, value)
end
timer.ticks = timer.timeout
end
function setstatusvalue(timer, event)
if timer.ignoresec then
local delta = os.udifftime(timer.ignoresec, timer.ignoreusec)
if delta >= 0 and delta <= 1 then
return
end
timer.ignoresec = nil
end
if timer.enabled then
timer.statvalue = busdatatype.decode(event.datahex, dt.scale)
timer.ticks = nil -- stop timer
log('output change', timer.statvalue)
end
end
for _, timer in ipairs(timers) do
timer.statvalue = grp.getvalue(timer.status) or 0
if timer.enable then
timer.enabled = grp.getvalue(timer.enable)
else
timer.enabled = true
end
log('timer init', timer.statvalue, timer.enabled)
end
sender = 'tm'
grp.sender = sender
client = require('localbus').new(0.1)
client:sethandler('groupwrite', function(event)
if event.sender == sender then
return
end
for _, timer in ipairs(timers) do
if event.dst == timer.enable then
settimerstate(timer, event)
elseif event.dst == timer.switch then
setswitchvalue(timer, event)
elseif event.dst == timer.input then
setinputvalue(timer, event)
elseif event.dst == timer.status then
setstatusvalue(timer, event)
end
end
end)
end
client:loop(1)
for _, timer in ipairs(timers) do
if timer.ticks then
timer.ticks = timer.ticks - 1
if timer.ticks == 0 then
log('timer stop', timer.statvalue)
setoutputvalue(timer, timer.statvalue)
timer.ticks = nil
end
end
end