Posts: 10
Threads: 2
Joined: Oct 2023
Reputation:
0
19.10.2023, 03:49
(This post was last modified: 19.10.2023, 03:51 by Azar.)
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: 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?
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
Use this resident script (sleep time = 0) as a starting point:
Code: -- 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
Posts: 10
Threads: 2
Joined: Oct 2023
Reputation:
0
21.10.2023, 09:40
(This post was last modified: 21.10.2023, 09:56 by Azar.)
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 sock end??
as in
value = GetCBusLevel(0, 127, 10) --0-255
value * (65535/255)
value * 257
example
-- send command
sock end('CS 34 value*257 \r')
this is not working, how would i go about implementing this variable number into the "socket send"
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
21.10.2023, 10:56
(This post was last modified: 22.10.2023, 12:07 by Erwin van der Zwart.)
Like this:
Code: value = GetCBusLevel(0, 127, 10)
command = 'CS 34 ' .. (value * 257) .. '\r'
sock:send(command)
Posts: 10
Threads: 2
Joined: Oct 2023
Reputation:
0
21.10.2023, 22:16
(This post was last modified: 22.10.2023, 07:09 by Azar.)
(21.10.2023, 10:56)Erwin van der Zwart Wrote: Like this:
Code: value = GetCBusLevel(0, 127, 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
Posts: 306
Threads: 59
Joined: Dec 2019
Reputation:
13
(21.10.2023, 22:16)Azar Wrote: (21.10.2023, 10:56)Erwin van der Zwart Wrote: Like this:
Code: value = GetCBusLevel(0, 127, 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
Posts: 10
Threads: 2
Joined: Oct 2023
Reputation:
0
22.10.2023, 11:45
(This post was last modified: 22.10.2023, 11:49 by Azar.)
(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: value = GetCBusLevel(0, 127, 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?
Posts: 306
Threads: 59
Joined: Dec 2019
Reputation:
13
(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: value = GetCBusLevel(0, 127, 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
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
22.10.2023, 11:53
(This post was last modified: 22.10.2023, 12:07 by Erwin van der Zwart.)
Oeps.. responding with iOS on iPhone does that but indeed ‘ must be '
Corrected it in my original post
Posts: 10
Threads: 2
Joined: Oct 2023
Reputation:
0
Code: -- socket connected
if connected then
-- Get level of the Volume control group in the Symetrix Control 127 application on the local network
value = GetCBusLevel(0, 127, 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?
Posts: 1764
Threads: 6
Joined: Jul 2015
Reputation:
117
28.10.2023, 08:25
(This post was last modified: 28.10.2023, 08:27 by Erwin van der Zwart.)
Just add a if condition like this:
Code: 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..
Posts: 10
Threads: 2
Joined: Oct 2023
Reputation:
0
(28.10.2023, 08:25)Erwin van der Zwart Wrote: Just add a if condition like this:
Code: 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: 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
Posts: 7758
Threads: 42
Joined: Jun 2015
Reputation:
447
Try using this:
Code: 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.
|