This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

HDL Buspro gateway integration with LM5
#7
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
Reply


Messages In This Thread
RE: HDL Buspro gateway integration with LM5 - by admin - 25.10.2023, 06:36

Forum Jump: