Задача
При каждом изменении значения объекта ’1/1/1′, посылаем TCP сообщения всем подсоединенным внешним TCP клиентам.
UDP клиентская функция
Функция должна быть добавлена в Скрипты –> Общие функции (Scripting -> Common functions).
Эта функция получает в качестве параметра переменную «текстовая строка» и посылает ее UDP серверу, который в свою очередь рассылает ее всем подсоединенным клиентам по TCP.
function udpsend(message)
require('socket')
local client = socket.udp()
-- upd client ready, send to local port 23456
if client then
client:sendto(message, '127.0.0.1', 23456)
client:close()
end
end
Резидентный скрипт – реализация сервера
Добавим следующий резидентный скрипт с значением параметра Sleep interval, равным «0».
Далее необходимо описать TCP и UDP сервер. После того, как TCP пошлет сообщение “HELLO”, а TCP сервер/LogicMachine пришлет ответ “HELLO YOU TOO”, соединение будет установлено.
-- init server handler
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()
alert('[server] data from %s:%d - %s', ip, port, data)
-- send reply
if data == 'HELLO' then
sock:send('HELLO TO YOU\r\n')
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 12345
tcpserver = socket.bind('*', 12345)
-- 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 23456
udpserver = socket.udp()
udpserver:setsockname('127.0.0.1', 23456)
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
for id, sock in pairs(clients) do
sock:send(message .. '\r\n')
end
end
copas.step(0.1)
end
Программа обработки событий
Событийный скрипт, основанный на событии будет отслеживать объект ’1/1/1′. В случае включения объекта ( лампы) будет послано сообщение “Lamp is ON” всем TCP клиентам, которые в данный момент подключены к TCP серверу LogicMachine. В случае же выключения объекта будет передано сообщение – “Lamp is OFF”.
value = event.getvalue()
udpsend('Lamp is ' .. (value and 'ON' or 'OFF'))