Hi Habib,
this is a script for central status calculations from forum with a little update of sum function.
output - how many lamps are switched on from tagged
counter - how many lamps are tagged for sum
This should be Resident script 0s.
this is a script for central status calculations from forum with a little update of sum function.
output - how many lamps are switched on from tagged
counter - how many lamps are tagged for sum
This should be Resident script 0s.
Code:
if not client then
-- each group has 3 or 4 fields:
-- tag - status object tag
-- output - status output object
-- mode - calculate mode (and/or/avg/sum)
-- counter - calculate number of light which are tagged(only sum function)
groups = {
--samples
-- { tag = 'my_group_and', output = '4/0/0', mode = 'and' },
-- { tag = 'my_group_or', output = '4/0/1', mode = 'or' },
-- { tag = 'my_group_avg', output = '4/0/2', mode = 'avg' },
-- { tag = 'my_group_sum', output = '4/0/3', mode = 'sum', counter = '4/0/4' },
--mean temperature
{ tag = 'Lamp', output = '8/2/37', mode = 'sum', counter = '8/2/25' },
--number of lights which are switched on
{ tag = 'Kitchen_L_sum', output = '0/0/64', mode = 'sum', counter = '0/0/65' },
{ tag = 'Livingroom_L_sum', output = '0/0/64', mode = 'sum', counter = '0/0/65' },
{ tag = 'Garderobe_L_sum', output = '0/0/64', mode = 'sum', counter = '0/0/65' },
{ tag = 'Hall_L_sum', output = '0/0/64', mode = 'sum', counter = '0/0/65' },
{ tag = 'Floor1_L_sum', output = '0/0/64', mode = 'sum', counter = '0/0/65' },
}
-- time to wait between last telegram from any status in group and update
updatedelay = 0.5
timeout = updatedelay / 2
-- object value cache
values = {}
-- object datatype cache
datatypes = {}
-- send update only when value changes
grp.checkupdate = function(alias, value)
if values[ alias ] ~= value then
grp.update(alias, value)
end
end
calc = {}
-- AVERAGE value
calc['avg'] = function(group)
local result, count, value = 0, 0
for _, address in ipairs(group.objects) do
value = values[ address ]
-- number must be in [0..100] range
if type(value) == 'number' then
result = result + value
count = count + 1
-- boolean true is 100%, false is 0%
elseif type(value) == 'boolean' then
if toboolean(value) then
result = result + 100
end
count = count + 1
end
end
if count > 0 then
result = math.floor(result / count + 0.5)
grp.checkupdate(group.output, result)
end
end
-- SUM value
calc['sum'] = function(group)
local result, count, value = 0, 0
for _, address in ipairs(group.objects) do
value = values[ address ]
-- number must be in [0..100] range
if value then
result = result + 1
end
count = count + 1
end
if count > 0 then
grp.checkupdate(group.output, result)
grp.checkupdate(group.counter, count)
end
end
-- AND gate
calc['and'] = function(group)
local result = true
for _, address in ipairs(group.objects) do
result = result and toboolean(values[ address ])
end
grp.checkupdate(group.output, result)
end
-- OR gate
calc['or'] = function(group)
local result = false
for _, address in ipairs(group.objects) do
result = result or toboolean(values[ address ])
end
grp.checkupdate(group.output, result)
end
-- prepare each group
for _, group in ipairs(groups) do
object = grp.find(group.output)
-- cache output status object value and datatype
values[ object.address ] = object.data
datatypes[ object.address ] = object.datatype
group.output = object.address
-- group input status object list
group.objects = {}
-- find all status objects and cache values and datatypes
objects = grp.tag(group.tag)
for _, object in ipairs(objects) do
values[ object.address ] = object.data
datatypes[ object.address ] = object.datatype
table.insert(group.objects, object.address)
end
-- force update on first run
group.timer = 0
-- calc function reference
group.fn = calc[ group.mode ]
end
-- handle group writes
function eventhandler(event)
local dst, datatype
dst = event.dst
datatype = datatypes[ event.dst ]
-- unknown object, stop
if not datatype then
return
end
values[ dst ] = dpt.decode(event.datahex, datatype)
-- check if any group needs to be updated
for _, group in ipairs(groups) do
for _, address in ipairs(group.objects) do
if address == dst then
group.timer = updatedelay
end
end
end
end
require('genohm-scada.eibdgm')
client = eibdgm:new({ timeout = 0.1 })
client:sethandler('groupwrite', eventhandler)
end
delta = 0
repeat
tsec, tusec = os.microtime()
client:step()
tdelta = os.udifftime(tsec, tusec)
-- clock jump
if tdelta < 0 then
delta = timeout
else
delta = delta + tdelta
end
until delta >= timeout
-- check if any group has an active timer
for _, group in ipairs(groups) do
timer = group.timer
if timer then
timer = timer - delta
-- timer expired, run calc function
if timer <= 0 then
group.fn(group)
timer = nil
end
group.timer = timer
end
end