Задача
- Установить TCP соединение с внешним TCP сервером – Denon Home Theater
- Читать данные из Denon Home Theater и показывать на визуализации:
— объект «boolean», показывающий статус вкл/выкл Denon Home Theater
— объект «string» в котором хранится имя радиостанции, которая сейчас играет
Резидентный скрипт
- Добавьте следующий программный код в резидентный скрипт.
-- первый вызов
if not ready then
require('socket')
warningclosed = true
warningfailed = true
warningerrors = true
warningtimeou = true
denonstatus = false
lastdatareceived = nil
-- функция разбора команд
function parse(data)
if data == 'PWON' then
denonstatus = true
elseif data == 'PWSTANDBY' then
denonstatus = false
elseif string.sub(data, 1, 4) == 'NSE0' then
grp.write('5/2/2', string.sub(data, 5))
elseif string.sub(data, 1, 4) == 'NSE1' then
grp.write('5/2/3', string.sub(data, 5))
else
-- логируем информацию, которую не обрабатываем, но она используется в системе
log(data)
end
-- проверяем изменился ли статус Denon и если да, то посылаем на шину новое
-- значение объекта
currentdenonstatus = grp.getvalue('5/2/1')
if currentdenonstatus ~= denonstatus then
grp.write('5/2/1', denonstatus)
end
end
ready = true
end
-- если клиент существует соединение с клиентом
if connected then
-- мы должны послать запрос статуса , чтобы убедится что socket не закрыт
-- но так как Denon посылает PWON каждую секунду автоматически, то в запросе
-- нет необходимости
--client:send('PW?\r')
while true do
char, err = client:receive(1)
if char ~= nil then
lastdatareceived = os.time()
warningclosed = true
warningfailed = true
warningerrors = true
warningtimeou = true
else
now = os.time()
deltatime = now - lastdatareceived
end
-- если произошла ошибка во время получения данных, произошел timeout или
-- был закрыт socket
if err then
-- удаленный сервер закрыл соединение, переподключаемся
if err == 'closed' then
connected = false
if warningclosed then alert('[tcp-client] connection closed') end
warningclosed = false
sleep(1)
elseif err == 'timeout' then
connected = false
if warningtimeou then alert('[tcp-client] connection timeout') end
warningtimeou = false
sleep(1)
elseif warningerrors then alert('[tcp-client] connection failed: %s', err)
warningerrors = false
end
break
-- конец полученной строки, разбираем ее (buffer)
elseif char == '\r' then
data = table.concat(buffer)
parse(data)
buffer = {}
-- ждем некоторое время перед следующим запросом
--sleep(1)
break
-- другие символы, добавляем в буфер (buffer)
else
table.insert(buffer, char)
end
end
-- первый вызов или предыдущее соединение было закрыто
else
-- закрываем предыдущее соединение когда отключаемся
if client then
client:close()
client = nil
end
-- создаем tcp клиента
client = socket.tcp()
client:settimeout(5)
connected, err = client:connect('172.16.1.111', 23)
-- если соединение установлено, очищаем буфер (buffer)
if connected then
lastdatareceived = os.time()
warningclosed = true
warningfailed = true
warningerrors = true
warningtimeou = true
alert('[tcp-client] connection ok')
buffer = {}
sleep(5)
-- если произошли ошибки при соединении
else
if warningfailed then alert('[tcp-client] connection failed (conn): %s', err) end
warningfailed = false
sleep(5)
end
end
Вывод на LogicMachine
- TCP статусы соединения – OK, closed, timeout, failed
- логируем не обрабатываемую информацию, используемую системой
Значения объектов