LogicMachine Forum
Tcp script event loop - Printable Version

+- LogicMachine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Tcp script event loop (/showthread.php?tid=2858)



Tcp script event loop - benanderson_475 - 21.09.2020

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.


RE: Tcp script event loop - admin - 21.09.2020

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.


RE: Tcp script event loop - benanderson_475 - 22.09.2020

(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 



RE: Tcp script event loop - benanderson_475 - 28.09.2020

@admin any suggestion as above, what do you recommend?
Many Thanks


RE: Tcp script event loop - admin - 28.09.2020

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



RE: Tcp script event loop - benanderson_475 - 29.09.2020

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




RE: Tcp script event loop - admin - 29.09.2020

I've modified the example to check select result before checking if any fds are ready.


RE: Tcp script event loop - benanderson_475 - 30.09.2020

All is well now, Thanks admin