This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

TCP/ip connect and maintain connection
#1
I am trying to place a resident script to connect to an ip address, monitor connection and reconnect if connection is lost.
I am reading and watching every tutorial i can find and am slowly getting more understanding but need others help with this.

I am after some guidance in the implementation of a TCP/ip connection to third party device (Symetrix DSP, control protocol same as control4, amx, crestron, lutron).
I have connection working between both the SHAC and the Symetrix DSP, as in I can ping it with a response through the "Network Utilities"
I have full control of Symetrix working through PuTTY terminal and now need to implement scripting to send, and manage received data.

Can anyone share with me scripting that will build this connection, maintain this connection, reconnect if device goes offline then returns online..
I have found multiple examples of this but am not getting much luck with connection or how to monitor if the connection is alive.


Code:
123
local socket = require("socket") local host, port = "192.168.1.246", 48631 local tcp = assert(socket.tcp())


Once i have this connection up and running I need to build scripting to send controls to and receive pushed controls back to update GA's in the SHAC.

Control protocol info from Symetrix document shown below.

The Control Protocol is a text-based (ASCII string) protocol. Commands are sent with simple character strings with terms separated by spaces and completed with a carriage return character <CR> (ASCII code decimal 13). The general form for commands is:
<COMMAND> <PARAMETER1> <PARAMETER2> … <CR>

When in PuTTY if i send the command            CS 1 65535 <CR>        
I get Controller Set "CS" to controller number "1" set to maximum "65535" (all as expected) with a response of ACK.

Can I send this same data through a LUA script? or does it need to be converted to another format?
Reply
#2
Use this resident script (sleep time = 0) as a starting point:
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
-- socket connected if connected then   -- send command   sock:send('CS 1 65535\r')   -- read until one line received or error occured   while true do     char, err = sock:receive(1)     -- error while receiving, timeout or closed socket     if err then       -- remote server closed connection, reconnect       if err == 'closed' then         connected = false         alert('[tcp-sock] connection closed')         os.sleep(1)       end       break     -- end of line, parse buffer     elseif char == '\r' then       data = table.concat(buffer)       log(data)       buffer = {}       -- wait some time before next request       os.sleep(1)       break     -- other char, add to buffer     else       buffer[ #buffer + 1 ] = char     end   end -- first call or previously disconnected else   -- close previous connection when disconnected   if sock then     sock:close()     sock = nil   end   -- create tcp socket   sock = require('socket').tcp()   sock:settimeout(1)   connected, err = sock:connect('192.168.0.9', 80)   -- connect ok, reset buffer   if connected then     alert('[tcp-sock] connection ok')     buffer = {}   -- error while connecting   else     alert('[tcp-sock] connection failed: %s', err)     os.sleep(5)   end end
Reply
#3
Thank you so much, now i know that this will be achievable and I can manage everything from my SHAC.

next question can i place a variable parameter into a sockConfusedend??
as in 

value = GetCBusLevel(0,  127, 10) --0-255

value * (65535/255)

value * 257


example

  -- send command
  sockConfusedend('CS 34 value*257 \r')

this is not working, how would i go about implementing this variable number into the "socket send"
Reply
#4
Like this:
Code:
123
value = GetCBusLevel(0127, 10) command = 'CS 34 ' .. (value * 257) .. '\r' sock:send(command)
Reply
#5
(21.10.2023, 10:56)Erwin van der Zwart Wrote: Like this:
Code:
123
value = GetCBusLevel(0127, 10) command = 'CS 34 ' .. (value * 257) .. ‘\r' sock:send(command)

I'm getting a error

Lua syntax error at line 9: unexpected symbol near '\'

How do I get "value x 257" into "command" so that it can be sent
Reply
#6
(21.10.2023, 22:16)Azar Wrote:
(21.10.2023, 10:56)Erwin van der Zwart Wrote: Like this:
Code:
123
value = GetCBusLevel(0127, 10) command = 'CS 34 ' .. (value * 257) .. ‘\r' sock:send(command)

I'm getting a error

Lua syntax error at line 9: unexpected symbol near '\'

How do I get "value x 257" into "command" so that it can be sent
Hi,
There is an error in the char ` use '.
Best regards Cristian
Reply
#7
(22.10.2023, 10:21)CristianAgata Wrote:
(21.10.2023, 22:16)Azar Wrote:
(21.10.2023, 10:56)Erwin van der Zwart Wrote: Like this:
Code:
123
value = GetCBusLevel(0127, 10) command = 'CS 34 ' .. (value * 257) .. ‘\r' sock:send(command)

I'm getting a error

Lua syntax error at line 9: unexpected symbol near '\'

How do I get "value x 257" into "command" so that it can be sent
Hi,
There is an error in the char ` use '.
Best regards Cristian

Hi Cristian, would you kindly explain in more detail? I'm not sure what you mean! Are you pointing to the end of the second line ? Just prior to the backslash?
Reply
#8
(22.10.2023, 11:45)Azar Wrote:
(22.10.2023, 10:21)CristianAgata Wrote:
(21.10.2023, 22:16)Azar Wrote:
(21.10.2023, 10:56)Erwin van der Zwart Wrote: Like this:
Code:
123
value = GetCBusLevel(0127, 10) command = 'CS 34 ' .. (value * 257) .. ‘\r' sock:send(command)

I'm getting a error

Lua syntax error at line 9: unexpected symbol near '\'

How do I get "value x 257" into "command" so that it can be sent
Hi,
There is an error in the char ` use '.
Best regards Cristian

Hi Cristian, would you kindly explain in more detail? I'm not sure what you mean!°
In your code if I m looking good before the /r' there's this char "`" and it is wrong. You must change with this " ' ".
Best regards Cristian
Reply
#9
Oeps.. responding with iOS on iPhone does that but indeed ‘ must be '

Corrected it in my original post
Reply
#10
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
-- socket connected if connected then       -- Get level of the Volume control group in the Symetrix Control 127 application on the local network value = GetCBusLevel(0127, 10)     -- Convert level to command --command = 'cs 34' ..(value*257).. cr   command = 'CS 34 '..(value * 257).. '\r'       -- send command sock:send (command)   -- read until one line received or error occured   while true do     char, err = sock:receive(1)     -- error while receiving, timeout or closed socket     if err then       -- remote server closed connection, reconnect       if err == 'closed' then         connected = false         alert('[tcp-sock] connection closed')         os.sleep(1)       end       break     -- end of line, parse buffer     elseif char == '\r' then       data = table.concat(buffer)       log(data)       buffer = {}       -- wait some time before next request       os.sleep(1)       break     -- other char, add to buffer     else       buffer[ #buffer + 1 ] = char     end   end -- first call or previously disconnected else   -- close previous connection when disconnected   if sock then     sock:close()     sock = nil   end   -- create tcp socket   sock = require('socket').tcp()   sock:settimeout(1)   connected, err = sock:connect('192.168.1.246', 48631)   -- connect ok, reset buffer   if connected then     alert('[tcp-sock] connection ok')     buffer = {}   -- error while connecting   else     alert('[tcp-sock] connection failed: %s', err)     os.sleep(5)   end end
All is good now, conversion from cbus 255 to control 65535 is working,  
This script continues to send command at every 1 second interval is there any way i can change this so that it only sends socket command apon a new change of cbus level value. similar to an event script that waits for an event before acting?
Reply
#11
Just add a if condition like this:
Code:
12345
if previousvalue ~= value then   -- send command   sock:send (command)   previousvalue == value end
But if the value is not change often i would make it event based, initiate the connection, write the command and close the connection..
Reply
#12
(28.10.2023, 08:25)Erwin van der Zwart Wrote: Just add a if condition like this:
Code:
12345
if previousvalue ~= value then   -- send command   sock:send (command)   previousvalue == value end
But if the value is not change often i would make it event based, initiate the connection, write the command and close the connection..
I've decided to go to an event script but cant get this to work.
Event script by Keyword: Symetrix.
all GA's with keyword "Symetrix" also have there control comand number assigned to them by keyword " SYM=### " I'm trying to get the script to insert the control number into the "CS" Command Send line .
I'm getting a log of

 * string: Error: sym=address tag missing
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
    local value = event.getvalue()     local dest = event.dst     local grps = GetCBusByKW('Symtrix', 'or')     local k, v, alias, net, app, group     local addr = ''     local buffer = {} log(grps)     for k, v in pairs(grps) do       alias = table.concat(v.address, '/')       if alias == dest then         local tags = v.keywords      --log(tags)         local t         for _, t in ipairs(tags) do           local tp = string.split(t, '=')           tp[1] = trim(tp[1])           if tp[2] then             tp[2] = trim(tp[2])             if tp[1] == 'sym' then               addr = tp[2] -- Get device address               break             end           end         end         break       end     end     if addr ~= '' then       -- create tcp socket       local sock = require('socket').tcp()       sock:settimeout(1)       local connected, err = sock:connect('192.168.1.246', 48631)       -- connect ok       if connected then         alert('[tcp-sock] connection ok')       -- error while connecting       else         log('[tcp-sock] connection failed: '..err)         sock:close()         do return end       end       local command = 'CS '..addr..' '..(value * 257).. '\r'       -- send command       sock:send (command)       local sent = socket.gettime()       local timeout = 5       while true do         char, err = sock:receive(1)         -- error while receiving, timeout or closed socket         if err then           -- remote server closed connection           log('[tcp-sock] connection closed'..err)           break         -- end of line, parse buffer         elseif char == '\r' then           local data = table.concat(buffer)           log(data)           break         -- other char, add to buffer         else           buffer[ #buffer + 1 ] = char         end         if socket.gettime() - sent > 5 then           log('Timeout receiving data')           break         end       end       sock:close()     else       log('Error: sym=address tag missing')     end    
Reply
#13
Try using this:
Code:
1234567891011121314
tags = grp.gettags(event.dst) for _, tag in ipairs(tags) do   addr = tag:match('SYM=(%d+)')      if addr then     break   end end log(addr) if addr then   -- send TCP message end

Note that tags are case-sensitive.
Reply


Forum Jump: