update value of object - rocfusion - 06.07.2023
Hi,
Is there an grp. script command that will update the value of an object that does not write to the TP or IP bus under any condition. It ONLY changes the value of the object no matter the value of the object. I know you have grp.update and grp.checkupdate.
When you have resident scripts that should change other objects on the event that an groupwrite telegram has been sent to that object AND they also act as the status object. These scripts will continuously run. Both grp.update and grp.checkupate send back a groupwrite telegram. Is there something else just to change the value, without messing with the underlying DB.
Many thanks
Roger
RE: update value of object - admin - 07.07.2023
Can you provide an example of what you are trying to achieve?
RE: update value of object - rocfusion - 07.07.2023
Hi
I have the following resident script running, to give the status of a group of lights ( room ). The second script is an event script for controlling that group of lights. Now right now I have to use a separate object which responds with the status.
Code: if not client then
-- each group has 3 fields:
-- tag - status object tag
-- output - status output object
-- mode - calculate mode (and/or/avg)
groups = {
{ tag= 'cinema', output= '5/2/5', mode= 'avg' },
{ tag= 'living', output= '5/3/5', mode= 'avg' },
{ tag= 'kitchen', output= '5/4/5', mode= 'avg' },
{ tag= 'master', output= '5/5/5', mode= 'avg' }
}
-- time to wait between last telegram from any status in group and update
updatedelay = 0.5
-- 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 = {}
-- Temperature AVERAGE value
calc['tempavg'] = function(group)
local result, count, value = 0, 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)* 9 / 5) + 32
local fahren= math.floor(result+0.5)
grp.checkupdate(group.output, fahren)
end
end
-- AVERAGE value
calc['avg'] = function(group)
local result, count, switch, value = 0, 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
if value > 0 then
count = count + 1
end
-- boolean true is 100%, false is 0%
elseif type(value) == 'boolean' then
if toboolean(value) then
-- result = result + ( result / count )
switch = switch + 1
end
end
end
if count > 0 then
if result > 0 then
result = math.floor(result / count + 0.5)
end
grp.checkupdate(group.output, result)
elseif switch > 0 then
grp.checkupdate(group.output, 100)
else
grp.checkupdate(group.output, 0)
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.25 })
client:sethandler('groupwrite', eventhandler)
end
tsec, tusec = os.microtime()
client:step()
delta = os.udifftime(tsec, tusec)
-- 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
Event script
Code: if (event.type=='groupread') then
grp.response(event.dst,grp.getvalue(event.dst))
elseif (event.type=='groupwrite') then
grp.write('0/2/104',grp.getvalue(event.dst),dt.scale)
grp.write('0/2/105',grp.getvalue(event.dst),dt.scale)
if(event.getvalue()==0) then
grp.write('0/0/107',false,dt.bool)
else
grp.write('0/0/107',true,dt.bool)
end
end
RE: update value of object - Daniel - 10.07.2023
When you use Virtual groups then the value is not sent to TP or IP. For normal objects write will send to TP and IP , where update will send to IP but not to TP.
RE: update value of object - admin - 10.07.2023
You can also use grp.sender / event.sender to block event script execution when a different script changed the value. See this: https://forum.logicmachine.net/showthread.php?tid=4516&pid=29215#pid29215
|