Управление освещением
    Презентации
    Технические решения на LogicMachine
    Визуализация
      evika.ru    Технические решения на LogicMachine    Управление устройствами HDL из KNX, используя LogicMachine

    Управление устройствами HDL из KNX, используя LogicMachine

    Задача: Управлять устройствами HDL (диммером и реле) из сети KNX

    ПРИМЕЧАНИЕ: Использование LogicMachine позволит вам управлять HDL-устройствами также из сети Modbus, BACnet, или EnOcean.

    В настоящий момент реализована поддержка только объектов типа 05.001 scale и битовых.

    ШАГ 1 — Нужно добавить поддержку протокола HDL в LogicMachine

    Пожалуйста, свяжитесь с компанией EVIKA для получения специального обновления и интеграции протокола HDL в ваш LogicMachine. Получив файл с обновлением, добавьте его через меню Network configuration -> System -> Packages.
    ШАГ 2 — Нужно добавить программный код функции HDL в LogicMachine

    Добавьте пользовательскую библиотеку (проверьте) с именем «HDL» через меню Scripting -> User libraries:

    HDL = {
      -- destination ip
      dstip = '192.168.10.250',
      -- packet constant data
      magic = 'HDLMIRACLE',
      -- leading code
      lcode = string.char(0xAA, 0xAA),
      -- source device settings
      srcsubnet = 1,
      srcdevice = 254,
      devicetype = 0xFFFE,
      -- command types
      cmd = {
        scene = 0x0002, -- scene select
        scenereply = 0x0003, -- scene select answerback
        sequence = 0x001A, -- sequence select
        sequencereply = 0x001B, -- sequence select answerback
        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()
      require('json')
      require('encdec')
      require('socket')
     
      local ip, chunk, chunks, data
      -- read interface data
      data = json.pdecode(io.readproc('if-json'))
     
      if not data or not data.eth0 then
        error('cannot get interface data')
      end
     
      -- ip header
      HDL.iphdr = ''
      -- broadcast address
      HDL.bcast = data.eth0.bcast
      -- source ip
      HDL.srcip = data.eth0.inetaddr
     
      -- split ip address into chunks
      chunks = HDL.srcip: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 encdec.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 = encdec.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.sendcmd = function(cmd, dstsubnet, dstdevice, a, b, c)
      local extra, packet
     
      extra = string.char(a, b) .. HDL.word(c or 0)
      packet = HDL.encode(HDL.cmd.chanreg, dstsubnet, dstdevice, extra)
     
      HDL.send(packet)
    end
     
    HDL.chanreg = function(dstsubnet, dstdevice, chan, value, delay)
      if type(value) == 'boolean' then
        value = value and 100 or 0
      end
     
      HDL.sendcmd(HDL.cmd.chanreg, dstsubnet, dstdevice, chan, value, delay)
    end
     
    HDL.sequence = function(dstsubnet, dstdevice, area, value)
      HDL.sendcmd(HDL.cmd.sequence, dstsubnet, dstdevice, area, value)
    end
     
    HDL.scene = function(dstsubnet, dstdevice, area, scene)
      HDL.sendcmd(HDL.cmd.scene, dstsubnet, dstdevice, area, scene)
    end

    ШАГ 3 — Измените параметры настройки сети HDL в соответствии с Вашими требованиями
    В приведённой выше программе IP адрес HDL контроллера задан как 192.168.1.7 (dstip), адрес LogicMachine в сети HDL 1.254 (srcsubnet и srcdevice).
    Найдите строки программы в начале текста библиотеки, где соответствующим переменным присваиваются значения, и скорректируйте их:
    HDL = {
      -- destination ip
      dstip = '192.168.1.7',

    lcode = string.char(0xAA, 0xAA),
      -- source device settings
      srcsubnet = 1,
      srcdevice = 254,
      devicetype = 0xFFFE,

    ШАГ 4 — Нужно добавить резидентную часть программы поддержки функции HDL/strong>

    Добавьте резидентный скрипт (проверьте) через меню Scripting -> Resident с любым именем, например «HDL_Resident». Установите параметр Sleep interval = 0 и активируйте скрипт.

    if not knxclient then
      require('user.hdl')
      require('genohm-scada.eibdgm')
     
      HDL.init()
     
      hdltoknx = {}
      knxtohdl = {}
      datatypes = {}
      knxvalues = {}
     
      -- get all tagged objects and set mapping
      for _, object in ipairs(grp.tag('HDL')) do
        local address, dt
     
        address = unpack(object.name:split(' '))
     
        hdltoknx[ address ] = object.id
        knxtohdl[ object.id ] = address:split('/')
     
        dt = tonumber(object.datatype) or 0
        if dt >= 1000 then
          dt = math.floor(dt / 1000)
        end
     
        datatypes[ object.id ] = dt
      end
     
      -- hdl connection
      hdlclient = socket.udp()
      hdlclient:settimeout(0.1)
      hdlclient:setsockname(HDL.bcast, 6000)
     
      -- knx group write handler
      function knxgroupwrite(event)
        local value, address, delay
     
        -- check if address is mapped
        address = knxtohdl[ event.dstraw ]
     
        -- set new channel value
        if address then
          if datatypes[ event.dstraw ] == dt.bool then
            value = knxdatatype.decode(event.datahex, dt.bool)
            delay = 0
          else
            value = knxdatatype.decode(event.datahex, dt.scale)
            delay = 1
          end
     
          HDL.chanreg(address[ 1 ], address[ 2 ], address[ 3 ], value, delay)
        end
      end
     
      -- check for incoming data and update knx
      function hdludpread()
        local data, packet, address, chan, value, id, datatype, sendvalue
        data = hdlclient:receive()
     
        -- read timeout
        if not data then
          return
        end
     
        packet = HDL.decode(data)
        -- errorneus data or wront packet opcode
        if not packet or packet.opcode ~= HDL.cmd.chanregreply then
          return
        end
     
        chan = packet.additional:byte(1)
        value = packet.additional:byte(3)
        address = string.format('%d/%d/%d', packet.srcsubnet, packet.srcdevice, chan)
     
        id = hdltoknx[ address ]
        if id and knxvalues[ id ] ~= value then
          if datatypes[ id ] == dt.bool then
            datatype = dt.bool
            sendvalue = value > 0
          else
            datatype = dt.scale
            sendvalue = value
          end
     
          grp.update(id, sendvalue, datatype)
          knxvalues[ id ] = value
        end
      end
     
      -- knx connection
      knxclient = eibdgm:new()
      knxclient:sethandler('groupwrite', knxgroupwrite)
    end
     
    -- main loop
    knxclient:step()
    hdludpread()

    ШАГ 5 — Изменение значения диммера HDL в соответствии с изменением значения объекта KNX

    Определим объект для управления на вкладке Object
    Имя объекта должно содержать в начале строку, определяющую HDL адрес.
    Среди тэгов должна присутствовать строка: HDL

    К объекту нужно привязать Event-based скрипт, который будет отслеживать его изменения.

    Разместим следующий код:

    local value = dpt.decode(event.datahex, dt.scale)
    HDL.chanreg(1, 12, 1, value, 1)

    Описание функции, управляющей диммиром или реле HDL :

    HDL.chanreg(dstsubnet, dstdevice, chan, value, delay)

    Параметры:

    • dstsubnet – device subnet (подсеть устройства )
    • dstdevice – device address (адрес устройства)
    • chan – номер канала (1..n)
    • value – значение (0..100, или true / false)
    • delay – время задержки в секундах (0..65535), по умолчанию 0

    Проверка программы: Если вы поменяете значение объекта с групповым адресом 4/1/1 во вкладке Objects через пункт меню Set Value, этим автоматически измените значение соответствующего диммера в сети HDL.
    ШАГ 6 — Изменение значения реле HDL в соответствии с изменением значения объекта KNX

    Добавим новый объект во вкладке Object.

    Добавим скрипт, обрабатывающий события, который будет отслеживать изменения ранее созданного объекта.

    Откроем скрипт на редактирование и добавим следующий код:

    local value = dpt.decode(event.datahex, dt.bool)
     HDL.chanreg(1, 11, 1, value))

    Проверка программы: Если вы поменяете значение объекта с групповым адресом 4/1/2 во вкладке Objects через пункт меню Set Value, этим вы автоматически измените значение соответствующего реле в сети HDL

     




    Copyright © Evika.ru 2017
    All Rights Reserved