| 
		
	
	
	
		
	Posts: 137 
	Threads: 29 
	Joined: May 2016
	
 Reputation: 
3 
	
		
		
		05.01.2017, 08:08 
(This post was last modified: 07.01.2017, 10:57 by Habib.
 Edit Reason: add solved Tag
)
		
	 
		Hi,
 at moment I search for a way to get a total sum of all Lights in my house with state on. The same I have for opened windows and it works for me, but I think my way is not much elegenat.
 
 I have create one KNX Object for the sum count total. Then I created on each windows object an event which gets the value from the total sum and add or substract the total value (+1 or -1).
 That works because are only few windows (19) and the action on that is very slow. But if I try to do it for my downlights on the same way it doesn't works.
 
 I have 110 Downlights in my house and each of them has its own status object. I have done that, because I use many different scenes and wants to have in all ways the exact visualisiation. In my living room I have 30 downlights and If I do the calculation in that way I described before, It calculates every times wrong.
 
 In next step I reverted that and put the calculation in the event script of the event trigger (switch/button) and do the calculation for the whole group (+3 or +24 and so on). But it doesn't work also. In some cases it works, in other combination not...
 
 My idea is now to create a functionality to get the status of all tagged objects (maybe tag: "downlight status") on every 2 minutes. but the disadvantage is, that I have much more traffic and CPU/Bus load.
 
 What is the best way to do such functionality?
 
 Thank you forwards
 
 BR
 Habib
 
		
	 
	
	
	
		
	Posts: 942 
	Threads: 161 
	Joined: Jul 2015
	
 Reputation: 
33 
	
		
		
		05.01.2017, 11:31 
(This post was last modified: 07.01.2017, 11:40 by buuuudzik.)
		
	 
		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
		
	 
	
	
	
		
	Posts: 137 
	Threads: 29 
	Joined: May 2016
	
 Reputation: 
3 
	
	
		Hi buuuudzik,
 wow, thx. A ready solution? I will try it at weekend.
 A resident script with 0s. Produce it not to much CPU load?
 
		
	 
	
	
	
		
	Posts: 942 
	Threads: 161 
	Joined: Jul 2015
	
 Reputation: 
33 
	
	
		No, because there is a variable updatedelay=0,5s(you can change this for more) so the effect is that this script has interval more than 0,5s.
 But be careful with number of group addresses which are calculated by this script. I think the sum of 100-200 shouldn't be a problem but more and more can produce some weard beahaviour(in your case bad number of lamps which are switched on and number of whole lamps).
 
		
	 
	
	
	
		
	Posts: 411 
	Threads: 103 
	Joined: Oct 2016
	
 Reputation: 
9 
	
	
		HiIn my project I have > 500 bulbs. My experience is the better way is to use two layers in these calculations. First layer (aka kitchen, bedroom) where every room contains less than 10 lights is calculated in per event based scripts. The second layer is calculated just from the first layer's results as a resident task.
 
 I use DALI gateways. I experimented with DALI cumulative feedback but the result was unreliable. The reason was DALI sends not one but few other cumulative feedback according to DALI program and DALI bus state. And from time to time it happened on KNX bus the first telegram outran the second telegram.
 
LM5Lp, firmware: 2018.08.22 and  2021.12.15, FlashSYS v2, ARMv7 Processor rev 5 (v7l), kernel 4.4.151 and 4.4.259
 
		
	 
	
	
	
		
	Posts: 200 
	Threads: 60 
	Joined: Jun 2015
	
 Reputation: 
7 
	
	
		Hi,
 I do a similar thing, individual lights are tagged to rooms,  the rooms are tagged to a floor or areas,  the floors\areas are tagged to the whole house \ apartment. That works great.  That way you get a status at all of the levels.
 
 Thanks
 
 Roger
 
		
	 
	
	
	
		
	Posts: 137 
	Threads: 29 
	Joined: May 2016
	
 Reputation: 
3 
	
		
		
		07.01.2017, 09:49 
(This post was last modified: 07.01.2017, 09:49 by Habib.)
		
	 
		Hi,
 @buuuudzik
 it works great for me. What I don't understand is, why the "OR" logic don't works...
 AND and AVERAGE works, so I made a simple quick&dirty mod and added a forth object "COUNT" and modified for that the function avarage to get the amount of lights which are in state on.
 
 I understand that script in that way, that I can use one script for each room, or sum of windows and so on, for each value I will count. Is that correct?
 For example I count with Tag "Spots" all my Downlights which I tagged... If I want to count open windows, I take another copy of that script and Tag all my windows status objects with "windows", and I will get a value for opened windows. ...
 
		
	 
	
	
	
		
	Posts: 200 
	Threads: 60 
	Joined: Jun 2015
	
 Reputation: 
7 
	
	
		Hi, 
I have also applied this with temperatures too,  the following will average Celsius temps and then convert it to Fahrenheit.
 
 Code: -- Temperature AVERAGE valuecalc['tempavg'] = 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
 end
 end
 if count > 0 then
 result = result / count
 local fahren= math.floor(((result * 9 / 5 + 32) * 10^2) + 0.5) / (10^2)
 grp.checkupdate(group.output, fahren)
 end
 end
Thanks,
 
Roger
	
		
	 
	
	
	
		
	Posts: 942 
	Threads: 161 
	Joined: Jul 2015
	
 Reputation: 
33 
	
	
		But event scripts can be not a good solution when there is some change of whole room or much more when there is whole floor change. Then there are a lot of unnecessary serial calculations of every event. With this resident script you can also prepare some layers and I use also such solutions. 
More on this forum about this task(more about OR calculations but also universal):
http://forum.logicmachine.net/showthread...l+statuses
http://forum.logicmachine.net/showthread...l+statuses
		
	 
	
	
	
		
	Posts: 137 
	Threads: 29 
	Joined: May 2016
	
 Reputation: 
3 
	
	
		@buuuudzikdid you mean me with your answer? If yes, you missunderstood me. I use multiple resident scripts to count for different groups. I agree with you, taht event based scripts for an global stat is not a good idea. That was the reason for this thread.
 
 Thank you very much :-)
 
		
	 
	
	
	
		
	Posts: 942 
	Threads: 161 
	Joined: Jul 2015
	
 Reputation: 
33 
	
	
		 (07.01.2017, 11:32)Habib Wrote:  @buuuudzikdid you mean me with your answer? If yes, you missunderstood me. I use multiple resident scripts to count for different groups. I agree with you, taht event based scripts for an global stat is not a good idea. That was the reason for this thread.
 
 Thank you very much :-)
 
This was only an exchange of some experience with this complex subject that everybody should have whole background of this subject(Preparing the elegant solution for calculating central statuses). 
 
But for this script recommended is to using only 1 with whole groups(Kitchen, Livingroom, 1Floor etc.).  I updated this script a few minute ago because I saw that there was no sum function     Now there is. Please check.
	 
		
	 
	
	
	
		
	Posts: 137 
	Threads: 29 
	Joined: May 2016
	
 Reputation: 
3 
	
	
		that's great :-) I have adopted your new version. I think the functionality should be part of the original installation.
 
		
	 
	
	
	
		
	Posts: 942 
	Threads: 161 
	Joined: Jul 2015
	
 Reputation: 
33 
	
		
		
 07.01.2017, 18:57 
(This post was last modified: 07.01.2017, 19:00 by buuuudzik.) 
		First version was prepared by Edgars so he can everything. I agree with you but I think it should be not a script but a special app with simple editor. Another think is that this version is simpler to change for suit it to specific solutions.
	 
		
	 |