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

    LogicMachine, как шлюз между контроллерами RTI и сетью KNX

    Задача:

    Создать двухсторонний обмен данными между пультами RTI T2-Cs+ и устройствами в сети KNX.

    Драйвер для контроллера XP-6:

    Обмен данными с LogicMachine со стороны контроллера XP-6 осуществляется с помощью драйвера (LogicMachine.rtidriver). В настройках драйвера необходимо указать IP адрес LogicMachine и задать групповые адреса, состояние которых будет отображаться на пультах.

    Скрипт для LogicMachine:

    Функция должна быть добавлена в Скрипты -> Пользовательские библиотеки (Scripting -> User libraries).

    function updatestring(number)
    -- обновление строк
      if number == '1' then
        local value = grp.getvalue('3/0/1') --запрос температуры в помещении
        local t = tostring(value)
        return string.format('%.1f', t) --преобразуем в строку для отображения на панели.
      end
    -- Номера строк лежат в диапазоне от 1 до 250
    end
     
    function updatebutton(number)
      return false
    end
     
    function pushbutton(number)
      -- обработка нажатия кнопки
      if number == '1' then
        local value = grp.getvalue('3/0/2')    
        if value < 37 then
          value = value + 0.1 -- Меняем температуру в помещении
        end
        grp.write('3/0/4', value)
     
        elseif number == '2' then
        local value = grp.getvalue('3/0/2')
        if value > 7 then
          value = value - 0.1 -- Меняем температуру в помещении
        end
        grp.write('3/0/4', value)
      end
    -- Номера кнопок лежат в диапазоне от 1 до 250
    end
     
    function sendstring(address,value)
      local t = tostring(value)
      local number = nil
      if address == '3/0/1' then
        number = 1
      end
      if number then
        udpsend("STRING",number,"STRING",string.format('%.1f', t))
      end
    end
     
    function sendaddress(address,datatype,value)
      udpsend("WRITEADDRESS",address,datatype,value)
    end
     
    function udpsend(command,address,datatype,value)
      require('socket')    
     
      local client = socket.udp()
      local message = '#RTI_Control#@'..command..'@%%'..address..'%%$'..datatype..
    '$~'..value..'~\r\n'
     
      -- upd client ready, send to local port 12345
      if client then
        client:sendto(message, '127.0.0.1', 12345)
        client:close()
      end
    end

    Резидентный скрипт – реализация сервера:

    Добавим следующий скрипт в Скрипты –> Резидентные  (Scripting -> Resident) со значением параметра Интервал запуска (Sleep interval), равным «0»:

    if not ready then
      require('copas')
     
      -- list of client sockets
      clients = {}
     
      -- incoming data handler
      function datahandler(sock, data)
        local ip, port
        ip, port = sock:getpeername()
     
        _,_,command,address,datatype,value = string.find(data, 
    "^#RTI_Control#@([^@]+)@%%([^%%]+)%%%$([^%$]*)%$~([^~]*)~")
     
        -- send reply
        if value == 'HELLO' then
          sock:send('#RTI_Control#@HEARTBEAT@%SYSTEM%$STRING$~HELLO TO YOU~\r\n')
        end
        if command == 'BUTTON' then
          --Нажали кнопку. Вызываем функцию, обработки нажатий.
          pushbutton(address, value)
        end
        if command == 'WRITEADDRESS' then
          --Записываем полученное значение в групповой адрес.
          grp.write(address, value)
        end
        if command == 'READSTRING' then
          --Запрос значения строки.
          value = updatestring(address)
          if value ~= nil then
            udpsend("UPDATESTRING",address,"STRING",value)
          end
        end
        if command == 'READBUTTON' then
          --Запрос состояния кнопки.
          value = updatebutton(address)
          if value ~= nil then
            udpsend("UPDATEBUTTON",address,"BOOLEAN",value)
          end
        end
        if command == 'READADDRESS' then
          --Запрос состояния группового адреса.
          value = grp.getvalue(address)
          if value ~= nil then
            if type(value) == 'boolean' and datatype == 'BOOLEAN' then
              udpsend("UPDATEADDRESS",address,"BOOLEAN",(value and 1 or 0))
            elseif type(value) == 'integer' and datatype == 'INTEGER' then
              udpsend("UPDATEADDRESS",address,"INTEGER",value)
            end
          end
        end
      end
     
      -- connection handler
      function connhandler(sock)
      -- enable keep-alive to check for disconnect events
        sock:setoption('keepalive', true)
     
        local ip, port, data, err, id
     
        -- get ip and port from socket
        ip, port = sock:getpeername()
     
        -- client id
        id = string.format('%s:%d', ip, port)
     
        alert('[server] connection from %s', id)
     
        -- save socket reference
        clients[ id ] = sock
     
        -- main reader loop
        while true do
          -- wait for single line of data (until \n, \r is ignored)
          data, err = copas.receive(sock, '*l')
     
          -- error while receiving
          if err then
            alert('[server] closed connection from %s:%d', ip, port)
            -- remove socket reference
            clients[ id ] = nil
            return
          end
     
          -- handle data frame
          datahandler(sock, data)
        end
      end
     
      -- bind to port 6789
      tcpserver = socket.bind('*', 6789)
     
      -- error while binding, try again later
      if not tcpserver then
        os.sleep(5)
        error('[server] error: cannot bind')
      end
     
      -- set server connection handler
      copas.addserver(tcpserver, connhandler)
     
      -- create local udp server on port 12345
      udpserver = socket.udp()
      udpserver:setsockname('127.0.0.1', 12345)
      udpserver:settimeout(0.1)
     
      ready = true
    end
     
    -- perform server tasks for one second (5 x (0.1 + 0.1))
    for i = 1, 5 do
      message = udpserver:receive()
     
      -- got message from udp, send to all active clients
      if message then
        --alert(message)
        for id, sock in pairs(clients) do
          sock:send(message .. '\r\n')
        end
      end
     
      copas.step(0.1)
    end

    От RTI контроллера могут быть получены следующие команды:
    • «BUTTON» — контроллер сообщает, что нажата кнопка. В данном примере будет вызвана функция pushbutton(address, value). Номера кнопок (address) лежат в диапазоне от 1 до 250. Значение value = 1 означает, что кнопку нажали, а value = 0 – отпустили.
    • «WRITEADDRESS» — контроллер сообщает, что нужно изменить значение группового адреса.
    • «READSTRING» — запрос содержания строки. В данном примере строка возвращается через функцию updatestring(address).
    • «READBUTTON» — запрос состояния кнопки. В данном примере состояние кнопки определяется через функцию updatebutton(address).
    • «READADDRESS» — запрос состояния адреса.

    Программа обработки событий:

    Скрипт, основанный на событии, будет отслеживать объект ’1/0/1′. В случае включения объекта (лампы) будет послано сообщение “ON” всем контроллерам, которые в данный момент подключены к LogicMachine. В случае же выключения объекта будет передано сообщение – “OFF”.

    address = event.dst
    value = event.getvalue()
    sendaddress(address,'BOOLEAN',(value and 'ON' or 'OFF'))

    Скрипт, основанный на событии, будет отслеживать объект ’1/1/1′. В случае изменения температуры в помещении будет послана строка, содержащая значение температуры всем контроллерам, которые в данный момент подключены к LogicMachine.

    address = event.dst
    local value = event.getvalue()
    alert('address = %s, value = %s', address, value)
    local t = tostring(value)
    alert('t = %s', value)
    sendstring(address, string.format('%.1f', t))

    Демодрайвер Rti предоставлен Красовским Алексеем (скачать)
    Для получения полной версии драйвера обращайтесь по:
    e-mail:kao@itservice-vrn.ru
    тел.: +7(920)211-78-90




    Copyright
    © Embedded Systems Rus
    2017. All Rights Reserved