Управление освещением
Презентации
Технические решения на LogicMachine
Визуализация
  logicmachine.net.ru    Технические решения на LogicMachine    LogicMachine как TCP сервер для внешних запросов

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'))




Copyright
© Embedded Systems Rus
2019. All Rights Reserved