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

LM5_N
LM-Wall_N
DALI_N
Vita_N

LogicMachine как TCP сервер для внешних запросов

Задача

При каждом изменении значения объекта ’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'))