Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
Hi,
i want to know if it is possible to create an event loop, like https://forum.logicmachine.net/showthread.php?tid=2670
to include a tcp connection to have callback function on server:read from tcp port etc
I already have a working tcp script in resident script but i want to make it more economical on cpu etc,
i am communicating to alarm panel so i want to receive pir triggered events etc
Many Thanks.
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
Do you have some extra communication in the script? You won't get any improvements on CPU usage if you're only reading from TCP and updating object values.
Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
22.09.2020, 05:27
(This post was last modified: 22.09.2020, 20:25 by benanderson_475.)
(21.09.2020, 07:24)admin Wrote: Do you have some extra communication in the script? You won't get any improvements on CPU usage if you're only reading from TCP and updating object values.
What is the best way to achieve what i need?
Below is what i currently have in resident script, i need to log out and log in every 15 min to maintain connectivity, and also have object event script sending to udp server in this script to send the client:write() to alarm to activate outputs, i was thinking as i currently use mqtt with https://forum.logicmachine.net/showthread.php?tid=2670
i can utilize the local bus in the event loop without the need to have an additional event script as well as having the on_timer function in the above link running the login/out function every 900 sec.
is it advisable to use the event loop?
Code: --log in--
function log_in()
ip, port = "192.168.1.61", 1918
client = assert(require('socket').tcp())
client:connect(ip, port);
client:settimeout(0.5);
log("Connecting to Alarm at ip:" .. ip .. ' port: '.. tostring(port)..' at '.. os.date("%H:%M:%S"));
-- log("logging Out of alarm")
client:send(string.char(0x49,0x43,0x08,0x00,0x00,0x00,0x00,0x03))
-- log("logging In")
client:send(string.char(0x49,0x43,0x0D,0x00,0x00,0x00,0x00,0x02,0x01,0x02,0x03,0x04,0xFF))
-- log("Setting alarm timeout")
client:send(string.char(0x49,0x43,0x0A,0x00,0x00,0x00,0x00,0x04,0x70,0x17))
-- log("Turning alarm events on")
client:send(string.char(0x49,0x43,0x0A,0x00,0x00,0x00,0x00,0x06,0x01,0x01))
end
log_in_time = os.time() + 900
log_in()
while true do
--re log out/in after 15min --
if os.time() > log_in_time then
client:close()
log_in()
log_in_time = os.time() + 900
end
--udp server for recieving commands from event script
if not server then
server = require('socket').udp()
server:settimeout(1)
server:setsockname('127.0.0.1', 5432)
log("Udp Server:5432 Recived message")
end
cmd = server:receive()
if cmd then
if cmd == "Gate_Lock" then
client:send(string.char(0x49,0x43,0x0C,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x0A))
end
if cmd == "Gate_UnLock" then
client:send(string.char(0x49,0x43,0x0C,0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,0x0A))
end
end
--recieving data--
rx = client:receive()
function to_bool(state)
if state == 'Opened' then
return true, state
end
if state == 'Closed' then
return false, state
end
end
if rx then
rx = string.gsub(rx, ".", function(value) return string.format('%02X', string.byte(value))end)
msg = string.sub(rx, 19)
data_type = string.sub(rx, 13,16)
-- loghex(msg)
msg = string.gsub(msg, '%x%x', function(value) return string.char(tonumber(value, 16)) end)
log(msg)
t = string.split(msg, ' ')
-- Zone name is always in t[2]
if t[2] == 'Zone_1' then
-- Zone state is always in t[4]
state = to_bool(t[4])
grp.write('1/1/1', state)
end
end
end
Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
@admin any suggestion as above, what do you recommend?
Many Thanks
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
You can use selectfds to check if there's data in udp/tcp socket or when tcp socket is closed.
Code: --log in--
function log_in()
local ip, port = "192.168.1.61", 1918
client = assert(require('socket').tcp())
client:connect(ip, port)
client:settimeout(0.5)
log("Connecting to Alarm at ip:" .. ip .. ' port: '.. tostring(port)..' at '.. os.date("%H:%M:%S"))
-- log("logging Out of alarm")
client:send(string.char(0x49,0x43,0x08,0x00,0x00,0x00,0x00,0x03))
-- log("logging In")
client:send(string.char(0x49,0x43,0x0D,0x00,0x00,0x00,0x00,0x02,0x01,0x02,0x03,0x04,0xFF))
-- log("Setting alarm timeout")
client:send(string.char(0x49,0x43,0x0A,0x00,0x00,0x00,0x00,0x04,0x70,0x17))
-- log("Turning alarm events on")
client:send(string.char(0x49,0x43,0x0A,0x00,0x00,0x00,0x00,0x06,0x01,0x01))
end
log_in_time = os.time() + 900
log_in()
--udp server for recieving commands from event script
if not server then
server = require('socket').udp()
server:setsockname('127.0.0.1', 5432)
end
sfd = socket.fdmaskset(server:getfd(), 'r')
cfd = socket.fdmaskset(client:getfd(), 'r')
while true do
res, sstat, cstat = socket.selectfds(10, sfd, cfd)
if res then
if sstat then
cmd = server:receive()
if cmd then
log("udp server message", cmd)
end
end
if cstat then
rx, err = client:receive()
if rx then
log("tcp client message", rx)
else
log_in_time = 0
log("tcp client error", err)
end
end
end
if os.time() > log_in_time then
client:close()
log_in()
log_in_time = os.time() + 900
end
end
Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
Thanks for this, this is what i am after although after a short amount of time it stops reading, i don't get any error in the log, so i insert
log( _, sstat, cstat) after _, sstat, cstat = socket.selectfds(10, sfd, cfd)
when arg 1 is nill, after this i don't receive any command from the client:receive() until i stop and start the script etc
see attached log screenshot
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
I've modified the example to check select result before checking if any fds are ready.
Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
All is well now, Thanks admin
|