This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

[solved] Most efficient way to get sum of all light states?
#2
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.

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
Reply


Messages In This Thread
RE: Most efficient way to get sum of all light states? - by buuuudzik - 05.01.2017, 11:31

Forum Jump: