Задача:
Создать двухсторонний обмен данными между пультами 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