I found the gateway example for HDL Buspro product.https://openrb.com/example-hdl-integrati...rough-lm2/
I am not sure if LM5 can use this script as a tool to connect the HDL product "HDL-MHRCU.433".
Or some modifications need to be taken for this script?
And I can't find out related "Add the following script in Scripting -> Tools -> User function library"
More details about this product" HDL-MHRCU.433 ", please refer to the PDF attachment .
I have tested the script for several times, but still no response from HDL side.
I am not sure if I put the script at the right way and right place---"Add the following script in Scripting -> Tools -> User function library", more details, please refer to picture.
I use HDL buspro tool to search or scan devices, but I can't find the Device ID for LM5 is 254. ID 254 is default for LM5?
I tried again to use LM5 to send switch on/off signal to HDL IP unit (IP Add.=192.168.1.37, Subnet=1 Device=0).
The HDL device (Subnet=1 Device=61) is 8 channels switch module, which also connects to HDL IP unit.
The script user.hdl is copied from example(openrb.com) , and "require('crc16')" is replaced by "crc16 = require('encdec').crc16"
The event-based script also set up according to example(openrb.com) .
14/0/220 is created to test the script.
When I turn on 14/0/220, the following error happens User library hdl:30: bad argument #1 to 'pdecode' (expected 1 argument) stack traceback: [C]: in function 'pdecode' User library hdl:30: in function 'init' User library hdl:99: in function 'encode' User library hdl:137: in function 'chanreg'
I don't know what is the root cause and how to slove this problem.
Try this updated library. Let us know if it works so we can update the example on our website.
Code:
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
Hi I have used the script, it is working fine. How will I get the status (feedack) from buspro (HDL) relay to Logic Machine 5 when I trigger the relay from the HDL Keypad.
Use this script (resident, sleep time = 0) to catch HDL messages. You need to configure your gateway to forward messages to LM. You will have to check opcode and additional field values to determine the HDL packet contents.
Code:
if not sock then
require('user.hdl')
sock = socket.udp()
sock:settimeout(60)
sock:setsockname('*', 6000)
HDL.init()
end
data = sock:receive()
if data then
packet, err = HDL.decode(data)
if packet then
packet.additional = lmcore.strtohex(packet.additional)
log('HDL packet', packet)
else
log('HDL error', err)
end
end
22.06.2025, 09:57 (This post was last modified: 22.06.2025, 09:59 by imprashant.)
Hi I used the above mentioned resident script and I am getting logs when I am Operating the relay channel. But how do I use these logs to update the status group address.
if not sock then
require('user.hdl')
sock = socket.udp()
sock:settimeout(60)
sock:setsockname('*', 6000)
HDL.init()
end
data = sock:receive()
if data then
packet, err = HDL.decode(data)
if packet then
if packet.opcode == HDL.cmd.chanregreply then
channel, _, value = packet.additional:byte(1, 3)
if channel == 1 then
grp.checkupdate('1/1/1', value)
elseif chanel == 2 then
grp.checkupdate('1/1/2', value)
elseif chanel == 3 then
grp.checkupdate('1/1/3', value)
elseif chanel == 4 then
grp.checkupdate('1/1/4', value)
end
end
-- packet.additional = lmcore.strtohex(packet.additional)
-- log('HDL packet', packet)
else
log('HDL error', err)
end
end
If you have multiple HDL relay devices then you need to check packet.srcdevice value to determine the status group address.