I'm new to the forum and lua scripting. I read some examples but didn't find anything suitable for my case.
I need to check multiple KNX addresses to determine a state change from 0 to 1. Specifically, I have the following logic: group/function/device. The number of devices varies for each group, but always starts at 11 and increases by 10.
If the state of address 1/2/11 or any of the addresses 1/2/X becomes 1, I need to change the state of all devices of type 1/3/Y and 1/5/Z. For example, if the address 1/2/11 is 1, then the addresses 1/3/11, 1/3/21, 1/3/31...(up to the number of objects entered) will change to 0, and the addresses 1/5/18, 1/5/28, 1/5/38...(up to the number of objects entered) will also change to 0. In other words, if any device from group 1 and function 2 has a state of 1, then all devices with functions 3 and 5 will change to a state of 0. If all devices from group 1 with function 2 have a state of 0 and control is allowed (the control address is X/2/0 for each group), then all devices with functions 3 and 5 will change to a state of 1.
What is the best practice for implementing this logic? I assume a resident script with a sleep of 0 is necessary, but with tags or first checking if the addresses exist, then using a for loop. Which solution will be most efficient and reliable for operation?
It is important to note that the groups range from 1 to 60, and the devices range from 11 to 161, always increasing by 10.
Use an event script mapped to a tag that all the input objects also have. Don't tag output objects with the same tag or you will get an infinite loop.
event.dstraw variable can be used to calculate output group addresses.
This example will write an inverse binary value to a group address with the next middle address (A/B/C -> A/B+1/C).
Code:
123
value = event.getvalue()
addr = event.dstraw + 256grp.write(addr, notvalue)
You also need to clearly define your algorithm. If you say there are 60 input groups then there will be an overlap when writing to the output groups.
This would lead to the possibility of many errors, can't it be done with a resident script that monitors states and processes events? I tried to write something similar, but apparently I don't understand the system's workings very well and it doesn't work for me.
client:loop(1) will exit after 1 second, you need this to keep the loop running:
Code:
123
whiletruedoclient:loop(1)
end
At the moment your code is very inefficient. Writing to any group address will cause the script to go through a big array checking each entry if it matches. Use group addresses as table keys to quickly check if it belongs to a certain group or not:
Code:
12345678
localgroup_ids = {}
-- fill group address -> group id mapping table on init
...
localaddress = event.dstlocalgroup_id = group_ids[ address ]
ifgroup_idthen-- perform some actions hereend
Use grp.getvalue() to get the initial object value and cache them into a table, then update the values that you get from the event. For binary values change the event value decoding and all other checks to use true/false instead of numbers:
Code:
1
localvalue = tonumber(event.datahex, 16) ~= 0-- 0 is false, all other values are true
I think I have a global issue in the code, because it works once and doesn't work another time. Is there a way to monitor the resources and load of the LM? Is it better as a practice to mark the variables with tags as an option?
Yes, I added a while true loop, there are no errors in the log, but it still doesn't work. I assume my approach is wrong, but I don't know what the correct method is to traverse so many addresses.
Use this as a starting point and fill in the blanks
1. inputgroup maps group address to group id. groupobjects contains group address to value map for each group id. If object is not found then it won't be added.
Try this. If something is not working add log() calls to check what the values are in the called functions. pcall is not needed as grp functions do not stop execution in case of an error, they simply return nil. grp.checkwrite does not write to non-existing objects so checking if object exists beforehand is not needed.
Thank you very much!
It works flawlessly! The code looks quite simple and works perfectly. It's different when you know the system in detail. Do you have any more detailed documentation that I can read to understand how the system works?
It's impossible to document all possible scripting features so just ask if you can't find certain information.
There are many examples in this forum. Also check these links for docs and examples: https://openrb.com/docs/ https://openrb.com/all-examples/
Thank you very much for the information! I think I've already started to get my bearings.
Is there any way I can monitor CPU and ram usage to determine how efficient the script is?
29.05.2023, 08:55 (This post was last modified: 29.05.2023, 08:56 by AISystem.)
What is the difference between what it says about CPU in the bottom corner https://ibb.co/r0vyDRX and what is in System load https://ibb.co/MDmrFck , what are the recommended values?
CPU/IO shows the whole system load average: https://en.wikipedia.org/wiki/Load_(computing)
System load app shows the CPU/RAM consumption for each process separately. If your resident script constantly consumes around 40% CPU then most likely it needs some optimization.
The script does not use group monitoring at all. client:loop(1) is more or less the same as os.sleep(1) in this case.
You have more than a hundred of grp.getvalue() calls each second. Instead of constantly polling values you should only react when the values change as in the previous script.