Горячая линия Embedded System Rus:8-800-775-06-34 (звонок по России бесплатный)

LM5_N
LM-Wall_N
DALI_N
Vita_N

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

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

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

В настоящий момент реализована поддержка только объектов типа 05.001 scale и битовых.
ШАГ 1 — Нужно добавить программный код функции HDL в LogicMachine

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

require("apps")
require('json')
require('encdec')
require('socket')

-----------------------------------------------------------------

function data_print(data)
    local str = ''
    for index, value in pairs(data) do
        c = string.format('%02X', value)
        str = str .. ' ' .. c
    end
    return str
end

HDL = {
    -- if true then using ip interface else using RS485 interface
    use_ip = true,
    -- destination ip
    dstip = '192.168.1.7',
    -- 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
        universalswitch = 0xE01C,
        universalswitchreply = 0xE01D,
        curtainswitch = 0xE3E0,
        curtainswitchreply = 0xE3E1,
        broadcasttemperature = 0xE3E5,
        readtemperature = 0xE3E7,
        readtemperaturereply = 0xE3E8,
        readtemperaturenew = 0x1948,
        readtemperaturenewreply = 0x1949,
        readstatus = 0x1604, -- Влажность запрос
        readstatusreply = 0x1605, -- Влажность ответ
        panelreadstatus = 0xE3DA,
        panelreadstatusreply = 0xE3DB,
        readfloorheatingstatus = 0x1944,
        readfloorheatingstatusreply = 0x1945

    }
}

function bytes_to_float(b4, b3, b2, b1)
    local ffi = require('ffi')
    local fl = ffi.new('float[1]')
    local ch = ffi.new('unsigned char[4]', b4, b3, b2, b1)
    ffi.copy(fl, ch, 4)
    return fl[0]
end

HDL.init = function()

    local ip, chunk, chunks, data
    -- read interface data
    vv = io.readproc('if-json')
    data = json.pdecode(vv)

    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)
    tt = {packet:byte(1, packet:len())}
    -- log('decode',data_print(tt))

    if HDL.use_ip then
        pack = packet:sub(15)
        local t1 = {}
        t1 = HDL.decode_base(pack)
        t1.srcip = string.format('%d.%d.%d.%d', packet:byte(1, 4))
        return t1
    else
        return HDL.decode_base(packet)
    end
end

HDL.decode_base = function(packet)
    local len, data, src, crc

    tt = {packet:byte(1, packet:len())}
    -- log('decode_base',data_print(tt))

    -- leading code
    if packet:sub(1, 2) ~= HDL.lcode then return nil, 'lcode' end

    -- get data length and check against
    len = packet:byte(3)
    if len and len + 2 ~= packet:len() then return nil, 'len' end

    -- get packet data and check crc
    data = packet:sub(3, len)
    crc = packet:byte(len + 1) * 0x100 + packet:byte(len + 2)

    if encdec.crc16(data) ~= crc then return nil, 'crc' end

    -- return parsed packet
    return {

        srcsubnet = packet:byte(4),
        srcdevice = packet:byte(5),
        devicetype = (packet:byte(6) * 0x100 + packet:byte(7)),
        opcode = (packet:byte(8) * 0x100 + packet:byte(9)),
        dstsubnet = packet:byte(10),
        dstdevice = packet:byte(11),
        additional = packet:sub(12, len)
    }
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

    log('encode', cmd, dstsubnet, dstdevice, extra)

    -- perform init if required
    if not HDL.iphdr then HDL.init() end

    packet = {}
    if HDL.use_ip then
        -- start packet: ip, magic and leading code
        packet = {HDL.iphdr, HDL.magic, HDL.lcode}
    else
        packet = {HDL.lcode}
    end

    -- 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)
    tt = {packet:byte(1, packet:len())}
    log('send', data_print(tt))

    if HDL.use_ip then
        local client = socket.udp()
        client:sendto(packet, HDL.dstip, 6000)
    else
        log('write port', HDL.port:write(packet))
    end
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(cmd, dstsubnet, dstdevice, extra)

    HDL.send(packet)
end

HDL.sendcmd1 = function(cmd, dstsubnet, dstdevice, a)
    local extra, packet

    extra = string.char(a)
    packet = HDL.encode(cmd, dstsubnet, dstdevice, extra)

    HDL.send(packet)
end

HDL.chanreg = function(dstsubnet, dstdevice, chan, value, delay)
    if type(value) == 'boolean' then value = value and 255 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

HDL.universal_switch = function(dstsubnet, dstdevice, id, value)
    HDL.sendcmd(HDL.cmd.universalswitch, dstsubnet, dstdevice, id, channel,
                value)
end

HDL.curtain_switch = function(dstsubnet, dstdevice, switch, status)

    -- if Curtain no. < 17 then 0 = STOP, 1 = OPEN, 2 = CLOSE 
    -- if Curtain no. = 17 then 0-100% percent
    HDL.sendcmd(HDL.cmd.curtainswitch, dstsubnet, dstdevice, switch, status)
end

HDL.readtemperature = function(dstsubnet, dstdevice, chan)
    HDL.sendcmd1(HDL.cmd.readtemperature, dstsubnet, dstdevice, chan, 0)
end

HDL.readtemperaturenew = function(dstsubnet, dstdevice, chan)
    HDL.sendcmd1(HDL.cmd.readtemperaturenew, dstsubnet, dstdevice, chan, 0)
end

HDL.readstatus = function(dstsubnet, dstdevice, chan)
    HDL.sendcmd1(HDL.cmd.readstatus, dstsubnet, dstdevice, chan, 0)
end

HDL.chanregreply = function(chan, value)
    local extra, packet

    extra = string.char(chan, 0xF8, value, chan)
    packet = HDL.encode(HDL.cmd.chanregreply, 255, 255, extra)
    HDL.send(packet)
end

HDL.scenereply = function(area, scene)
    local extra, packet

    log('scenereply', area, scene)

    extra = string.char(area, scene, 1, 1)
    packet = HDL.encode(HDL.cmd.scenereply, 255, 255, extra)
    HDL.send(packet)
end

HDL.sequencereply = function(area, seq)
    local extra, packet

    log('sequencereply', area, seq)

    extra = string.char(area, seq)
    packet = HDL.encode(HDL.cmd.sequencereply, 255, 255, extra)
    HDL.send(packet)
end

HDL.universalswitchreply = function(id, value)

    local extra, packet

    if value > 0 then value = 1 end

    --  log({cmd = 'universalswitchreply into', channel =channel, value = value, subnet =  packet.srcsubnet,devid = packet.srcdevice})
    log('universalswitchreply into', id, value)

    extra = string.char(id, value)
    packet = HDL.encode(HDL.cmd.universalswitchreply, 255, 255, extra)
    log('switchreply', packet)
    HDL.send(packet)
end

HDL.curtainswitchreply = function(dstsubnet, dstdevice, switch, status)

    -- if Curtain no. < 17 then 0 = STOP, 1 = OPEN, 2 = CLOSE 
    -- if Curtain no. = 17 then 0-100% percent
    HDL.sendcmd(HDL.cmd.curtainswitchreply, dstsubnet, dstdevice, switch, status)
end

HDL.panelreadstatus = function(dstsubnet, dstdevice, chan)
    HDL.sendcmd1(HDL.cmd.panelreadstatus, dstsubnet, dstdevice, chan, 0)
end

HDL.parse = function(packet)
    --   log('parse')

    if packet.opcode == HDL.cmd.chanreg then
        channel = packet.additional:byte(1)
        value = packet.additional:byte(2)

        log('chanreg')

        for index, rec in ipairs(hdltoknx) do
            if packet.dstsubnet == rec.hdl_net and packet.dstdevice ==
                rec.hdl_dev and channel == rec.channel and packet.opcode ==
                rec.type then
                log('chanreg found', rec, value)
                grp.write(rec.knx_obj, value)
                HDL.chanregreply(channel, value)
                return
            end
        end
    elseif packet.opcode == HDL.cmd.chanregreply then
        channel = packet.additional:byte(1)
        err = packet.additional:byte(2)
        value = packet.additional:byte(3)

        log({
            cmd = 'chanregreply',
            channel = channel,
            value = value,
            subnet = packet.srcsubnet,
            devid = packet.srcdevice
        })

        for index, rec in ipairs(hdltoknx) do
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.hdl_dev and channel == rec.channel and packet.opcode ==
                rec.type then
                log('chanregreply found', rec, value)
                if err == 0xF8 then -- F8 F8 = Success, F5 = Fail
                    grp.write(rec.knx_obj, value)
                end
                return
            end
        end
    elseif packet.opcode == HDL.cmd.scene then
        area = packet.additional:byte(1)
        scene = packet.additional:byte(2)

        log('scene', area, scene)

        for index, rec in ipairs(hdltoknx) do
            if packet.dstsubnet == rec.hdl_net and packet.dstdevice ==
                rec.hdl_dev and area == rec.area and packet.opcode == rec.type then
                log('scene found', rec.knx_obj, scene)
                grp.write(rec.knx_obj, scene)
                HDL.scenereply(area, scene)
                return
            end
        end

    elseif packet.opcode == HDL.cmd.sequence then
        area = packet.additional:byte(1)
        seq = packet.additional:byte(2)

        log('sequence', area, seq)

        for index, rec in ipairs(hdltoknx) do
            if packet.dstsubnet == rec.hdl_net and packet.dstdevice ==
                rec.hdl_dev and area == rec.area and packet.opcode == rec.type then
                log('sequence found', rec.knx_obj, seq)
                grp.write(rec.knx_obj, seq)
                HDL.sequencereply(area, seq)
                return
            end
        end

    elseif packet.opcode == HDL.cmd.universalswitch then
        channel = packet.additional:byte(1)
        value = packet.additional:byte(2)
        -- log('universalswitch debug',packet.additional, #packet.additional, channel, value)
        -- log('universalswitch',channel,value, packet.dstsubnet, packet.dstdevice, packet)
        log({
            cmd = 'universalswitch',
            channel = channel,
            value = value,
            subnet = packet.dstsubnet,
            devid = packet.dstdevice
        })
        for index, rec in ipairs(hdltoknx) do
            -- log(packet.dstsubnet == rec.hdl_net,packet.dstdevice , rec.hdl_dev, packet.dstdevice == rec.hdl_dev, channel == rec.channel, packet.opcode == rec.type)
            if packet.dstsubnet == rec.hdl_net and packet.dstdevice ==
                rec.hdl_dev and channel == rec.channel and packet.opcode ==
                rec.type then
                log('universalswitch found', rec.knx_obj, value, channel)
                grp.write(rec.knx_obj, value)
                log(channel, value)
                HDL.universalswitchreply(channel, value)
                return
            end
        end

    elseif packet.opcode == HDL.cmd.broadcasttemperature then
        channel = packet.additional:byte(1)
        value = packet.additional:byte(2)

        log('broadcasttemperature', channel, value, packet.srcsubnet,
            packet.srcdevice)
        for index, rec in ipairs(hdltoknx) do
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.hdl_dev and packet.opcode == rec.type and channel ==
                rec.channel then
                log('broadcasttemperature found', rec.knx_obj, value)
                grp.write(rec.knx_obj, value)
                return
            end
        end

    elseif packet.opcode == HDL.cmd.readtemperaturereply then
        channel = packet.additional:byte(1)
        value = packet.additional:byte(2)

        value = bit.band(value, 63)
        sign = bit.band(value, 64)

        if sign == 1 then value = -1 * value end

        log('readtemperaturereply', channel, value, packet.srcsubnet,
            packet.srcdevice)
        for index, rec in ipairs(hdltoknx) do
            -- if packet.srcsubnet == rec.hdl_net and packet.srcdevice == rec.hdl_dev and packet.opcode == rec.type and channel == rec.channel then
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.srcdevice and packet.opcode == rec.type and channel ==
                rec.channel then
                log('readtemperaturereply found', rec.knx_obj, value)
                log('readtemperaturereply')
                grp.write(rec.knx_obj, value)
                return
            end
        end
    elseif packet.opcode == HDL.cmd.readtemperaturenewreply then
        channel = packet.additional:byte(1)
        b1 = packet.additional:byte(2)
        b2 = packet.additional:byte(3)
        b3 = packet.additional:byte(4)
        b4 = packet.additional:byte(5)

        value = bytes_to_float(b1, b2, b3, b4)
        log('readtemperaturenewreply', channel, value, packet.srcsubnet,
            packet.srcdevice)
        for index, rec in ipairs(hdltoknx) do
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.hdl_dev and packet.opcode == rec.type and channel ==
                rec.channel then
                log('readtemperaturereply found', rec.knx_obj, value)
                grp.write(rec.knx_obj, value)
                return
            end
        end
    elseif packet.opcode == HDL.cmd.readstatusreply then

        channel = packet.additional:byte(1)
        b1 = packet.additional:byte(2) -- success or fail (f8 or f5)
        b2 = packet.additional:byte(3) -- temp 0-80 (-20-60 C)
        b3 = packet.additional:byte(4) -- brightness
        b4 = packet.additional:byte(5) -- hum
        b5 = packet.additional:byte(6) -- air
        b6 = packet.additional:byte(7) -- gas
        b7 = packet.additional:byte(8) -- motion sensor
        b8 = packet.additional:byte(9) -- dry contact 1
        b9 = packet.additional:byte(10) -- dry contact 2
        b10 = packet.additional:byte(11) -- UV switch 1
        b11 = packet.additional:byte(12) -- UV switch 1
        value = packet.additional:byte(5)

        -- log({cmd = 'readstatusreply',channel = channel,value ={b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11},subnet = packet.srcsubnet,devid = packet.srcdevice})
        log({
            cmd = 'readstatusreply',
            channel = channel,
            value = {b4},
            subnet = packet.srcsubnet,
            devid = packet.srcdevice
        })
        for index, rec in ipairs(hdltoknx) do
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.hdl_dev and packet.opcode == rec.type and channel ==
                rec.channel then
                log('readstatusreply found', rec.knx_obj, value)
                grp.write(rec.knx_obj, value, dt.uint16)
                return
            end
        end

    elseif packet.opcode == HDL.cmd.panelreadstatusreply then
        values = {}
        for i = 1, #packet.additional do
            table.insert(values, packet.additional:byte(i))
        end
        channel = values[1]
        value = values[2]
        for index, rec in pairs(hdltoknx) do
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.hdl_dev and packet.opcode == rec.type and channel ==
                rec.channel then
                log('panelreadstatusreply found', rec.knx_obj, value)
                alert('panelreadstatusreply to knx')
                grp.write(rec.knx_obj, value, dt.uint16)
                return
            end
        end
        log('panelreadstatusreply', values, packet.srcsubnet, packet.srcdevice)

    elseif packet.opcode == HDL.cmd.readfloorheatingstatusreply then
        values = {}

        for i = 1, #packet.additional do
            table.insert(values, packet.additional:byte(i))
        end
        for index, rec in pairs(hdltoknx) do
            if packet.srcsubnet == rec.hdl_net and packet.srcdevice ==
                rec.hdl_dev and packet.opcode == rec.type then
                log('readfloorheatingstatusreply found', rec.knx_obj, value)
                -- alert('readfloorheatingstatusreply to kx')
                grp.write(rec.knx_obj, values[rec.channel], dt.uint16)
                return
            end
        end
        log('readfloorheatingstatusreply', values, packet.srcsubnet,
            packet.srcdevice)
    end

end

ШАГ 2 — Измените параметры настройки сети 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,

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

Добавьте два резидентных скрипта (проверьте) через меню Scripting -> Resident с любым именем, например «HDL to KNX» и «KNX to HDL», установите параметр Sleep interval = 0 и пока не активируйте скрипт. Как видно из названия, скрипты будут отвечать за одно из направлений связи, т.е. KNX -> HDL и HDL -> KNX. Скрипт «HDLtoKNX» отвечает за связь команд от конкретных устройств с групповыми адресами KNX.

hdltoknx[1] = {
    hdl_net = 1, -- сеть 
    hdl_dev = 3, -- устройство
    type = HDL.cmd.chanreg, -- команда
    channel = 1, -- канал
    knx_obj = '1/1/1' -- адрес KNX
}

Здесь мы задаём связь с устройством по адресу 1.3, его командой chanreg канала 1 с групповым адресом 1/1/1. Обратите внимание, что указывается индекс в таблице — [1], эти индексы должны обязательно идти подряд, иначе не все команды будут обрабатываться. Код резидентного скрипта HDLtoKNX ниже:

require('user.hdl')

hdltoknx = {}

hdltoknx[1] = {
    hdl_net = 1,
    hdl_dev = 3,
    type = HDL.cmd.chanreg,
    channel = 1,
    knx_obj = '1/1/1'
}
hdltoknx[2] = {
    hdl_net = 1,
    hdl_dev = 5,
    type = HDL.cmd.universalswitch,
    channel = 14,
    knx_obj = '1/1/2'
}
hdltoknx[3] = {
    hdl_net = 1,
    hdl_dev = 5,
    type = HDL.cmd.readtemperaturereply,
    channel = 1,
    knx_obj = '1/1/3'
}

-- 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 false end

    -- log('пакет получен')

    packet, err = HDL.decode(data)

    if packet == nil then log('ошибка пакета', err) end

    chan = packet.additional:byte(1)
    value = packet.additional:byte(2)
    -- logger = string.format('src: %d.%d.%d dest: %d.%d value: %d cmd: %02X', packet.srcsubnet, packet.srcdevice, chan, packet.dstsubnet, packet.dstdevice,value or 'not value', packet.opcode)

    -- log('hdl read',logger)

    HDL.parse(packet)

    return true
end

-- hdl connection
if hdlclient == nil then

    log('init HDL2KNX')

    hdlclient = socket.udp()
    hdlclient:settimeout(30)
    hdlclient:setsockname('*', 6000)

    HDL.init()

end

b = true

while b do
    b = hdludpread()
    os.sleep(0.05)
end

os.sleep(0.3)
-- log('конец скрипта HDL2KNX')

Структура скрипта KNXtoHDL схожа с HDLtoKNX. Мы задаём групповой адрес, значения которого будут отправляться определенной командой на заданный канал заданного устройства.

knxtohdl[1] = {
    knx_obj = 'gost-1', -- knx адрес
    hdl_net = 1, -- сеть
    hdl_dev = 3, -- устройство
    type = HDL.cmd.chanreg, -- команда
    channel = 1 -- канал
}
require('user.hdl')

knxtohdl = {}

knxtohdl[1] = {
    knx_obj = '2/2/2',
    hdl_net = 1,
    hdl_dev = 3,
    type = HDL.cmd.chanreg,
    channel = 1
}
knxtohdl[2] = {
    knx_obj = '3/3/3',
    hdl_net = 1,
    hdl_dev = 5,
    type = HDL.cmd.universalswitch,
    channel = 1
}
knxtohdl[3] = {
    knx_obj = '4/4/4',
    hdl_net = 1,
    hdl_dev = 5,
    type = HDL.cmd.readtemperature,
    channel = 1
}

function getknxupdate()

    -- mydata will be set to a predefined value (e.g. 127) when data was not found
    tm = storage.get('hdl_sync_time', 0)
    cur_time = os.time()
    storage.set('hdl_sync_time', cur_time)

    for index, rec in pairs(knxtohdl) do

        obj = grp.find(rec.knx_obj)

        if obj == nil then log('object not found', rec.knx_obj) end

        if obj and obj.updatetime >= tm then
            value = nil
            log(
                'knx obj ' .. rec.knx_obj .. ' value: ' .. tostring(obj.value) ..
                    ' last time: ' .. tm .. ' objtime: ' .. obj.updatetime ..
                    ' curtime: ' .. cur_time)

            if rec.type == HDL.cmd.chanreg then
                if obj.datatype == dt.bool or obj.datatype == dt.boolean or
                    obj.datatype == dt.switch then
                    if obj.value then
                        value = 100
                    else
                        value = 0
                    end
                else
                    value = knxdatatype.decode(obj.value, dt.scale)
                end

                log('chanreg', rec.hdl_net, rec.hdl_dev, rec.channel, value,
                    rec.delay or 0)

                HDL.chanreg(rec.hdl_net, rec.hdl_dev, rec.channel, value,
                            rec.delay or 0)
                return
            elseif rec.type == HDL.cmd.scene then
                value = knxdatatype.decode(obj.value, dt.scale)

                log('scene', rec.hdl_net, rec.hdl_dev, rec.area, value)
                HDL.scene(rec.hdl_net, rec.hdl_dev, rec.area, value)
                return
            elseif rec.type == HDL.cmd.sequence then
                log('sequence', rec.hdl_net, rec.hdl_dev, rec.area)
                HDL.sequence(rec.hdl_net, rec.hdl_dev, rec.area, 1)
            elseif rec.type == HDL.cmd.readtemperature then
                log('readtemperature', rec.hdl_net, rec.hdl_dev, rec.channel)
                HDL.readtemperature(rec.hdl_net, rec.hdl_dev, rec.channel)
                return
            elseif rec.type == HDL.cmd.readtemperaturenew then
                log('readtemperaturenew', rec.hdl_net, rec.hdl_dev, rec.channel)
                HDL.readtemperaturenew(rec.hdl_net, rec.hdl_dev, rec.channel)
                return
            elseif rec.type == HDL.cmd.universalswitch then

                if obj.value == true then
                    value = 255
                else
                    value = 0
                end

                log('universalswitch', rec.hdl_net, rec.hdl_dev, rec.channel,
                    value, rec.delay)
                HDL.universal_switch(rec.hdl_net, rec.hdl_dev, rec.channel,
                                     value)
                return
            end
        end

    end

end

getknxupdate()

os.sleep(0.3)
-- log('конец скрипта KNX2HDL')

После того, как вы создадите и сконфигурируете оба скрипта, можете их активировать и вся связь будет работать в автоматическом режиме.