HDL integration with KNX through LM2
Example: HDL integration with KNX through Logic Machine 2
Task
Control HDL protocol-based dimmer and relay according to KNX objects value change.
Note! Using Logic Machine 2 you can create also HDL to Modbus, or HDL to BACnet, or EnOcean to HDL gateway etc.
Add HDL function in LM2
Add the following script in Scripting -> Tools -> User function library
- local socket = require('socket')
- local crc16 = require('encdec').crc16
- local ifinfo = require('ifinfo')
-
- HDL = {
- -- destination ip
- dstip = '192.168.0.2',
- -- packet constant data
- magic = 'HDLMIRACLE',
- lcode = string.char(0xAA, 0xAA),
- -- source device settings
- srcsubnet = 1,
- srcdevice = 254,
- devicetype = 0xFFFE,
- -- command types
- cmd = {
- chanreg = 0x0031, -- single channel regulate
- chanregreply = 0x0032, -- single channel regulate answerback
- chanstat = 0x0033, -- read status of single channel targets
- chanstatreply = 0x0034, -- single channel targets status answerback
- }
- }
-
- HDL.init = function()
- local info, chunk, chunks
-
- info = ifinfo()
-
- if not info or not info.eth0 then
- error('cannot get interface info')
- end
-
- -- ip header
- HDL.iphdr = ''
- -- broadcast address
- HDL.bcast = info.eth0.bcast
-
- -- split ip address into chunks
- chunks = info.eth0.inetaddr:split('.')
-
- -- add ip address chunks
- for i = 1, 4 do
- chunk = tonumber(chunks[ i ])
- HDL.iphdr = HDL.iphdr .. string.char(chunk)
- end
- end
-
- HDL.decode = function(packet)
- local len, data, src, crc
-
- -- primary header
- if packet:sub(5, 14) ~= HDL.magic then
- return nil, 'magic'
- end
-
- -- leading code
- if packet:sub(15, 16) ~= HDL.lcode then
- return nil, 'lcode'
- end
-
- -- get data length and check against
- len = packet:byte(17)
- if len and len + 16 ~= packet:len() then
- return nil, 'len'
- end
-
- -- get packet data and check crc
- data = packet:sub(17, len + 14)
- crc = packet:byte(len + 15) * 0x100 + packet:byte(len + 16)
- if crc16(data) ~= crc then
- return nil, 'crc'
- end
-
- -- return parsed packet
- return {
- srcip = string.format('%d.%d.%d.%d', packet:byte(1, 4)),
- srcsubnet = packet:byte(18),
- srcdevice = packet:byte(19),
- devicetype = (packet:byte(20) * 0x100 + packet:byte(21)),
- opcode = (packet:byte(22) * 0x100 + packet:byte(23)),
- dstsubnet = packet:byte(24),
- dstdevice = packet:byte(25),
- additional = packet:sub(26, len + 14)
- }
- end
-
- HDL.word = function(v)
- return string.char(bit.band(bit.rshift(v, 8), 0xFF), bit.band(v, 0xFF))
- end
-
- HDL.encode = function(cmd, dstsubnet, dstdevice, extra)
- local packet, len, crc, data
-
- -- perform init if required
- if not HDL.iphdr then
- HDL.init()
- end
-
- -- start packet: ip, magic and leading code
- packet = { HDL.iphdr, HDL.magic, HDL.lcode }
- -- base data
- data = string.char(HDL.srcsubnet, HDL.srcdevice) ..
- HDL.word(HDL.devicetype) ..
- HDL.word(cmd) ..
- string.char(dstsubnet, dstdevice)
-
- -- add extra data parameters
- if type(extra) == 'string' then
- data = data .. extra
- end
-
- -- calculate length and crc
- len = string.char(data:len() + 3)
- crc = crc16(len .. data)
-
- table.insert(packet, len)
- table.insert(packet, data)
- table.insert(packet, HDL.word(crc))
-
- return table.concat(packet)
- end
-
- HDL.send = function(packet)
- local client = socket.udp()
- client:sendto(packet, HDL.dstip, 6000)
- end
-
- HDL.chanreg = function(dstsubnet, dstdevice, chan, value, delay)
- local extra, packet
- delay = delay or 0
-
- if type(value) == 'boolean' then
- value = value and 100 or 0
- end
-
- extra = string.char(chan, value) .. HDL.word(delay)
- packet = HDL.encode(HDL.cmd.chanreg, dstsubnet, dstdevice, extra)
-
- HDL.send(packet)
- end
Change HDL parameters in the function to correct ones
By default IP of HDL controller is 192.168.1.7 (dstip), the address of Logic Machine in HDL network is 1.254 (srcsubnet and srcdevice).
Change HDL dimmer value on each KNX object value change
- Add new object in Object menu
- Add Event-based script which will monitor newly created object
- In Scripting Editor specify the following code for this script
- local value = dpt.decode(event.datahex, dt.scale)
- HDL.chanreg(1, 12, 1, value, 1)
- HDL.chanreg(dstsubnet, dstdevice, chan, value, delay)
- dstsubnet – device subnet
- dstdevice – device address
- chan – channel number (1..n)
- value – value (0..100, or true / false)
- delay – transition time or delay in seconds (0..65535), by default is 0
- Add new object in Object menu
- Add Event-based script which will monitor newly created object
- In Scripting Editor specify the following code for this script
- local value = dpt.decode(event.datahex, dt.bool)
- HDL.chanreg(1, 11, 1, value)
Function description to control dimmer or relay module:
Parameters:
Test Dimmer program: if you change the value for object 4/1/1 in Objects menu with Set Value, it will automatically change dimmer state in HDL network
Change HDL network’s relay state on each KNX object value change
Test the Relay program: if you change the value for object 4/1/2 in Objects menu with Set Value, it will automatically change the relay state in HDL network.