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.

LM Lutron telnet listener
#1
hello everyone!!

I made function (with Admin's big help), which will show you what Lutron send by telnet
I have lutron Homework QS

create user libruary "lutron"
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142
local socket = require("socket") local user = 'default' local password = 'default' function lutron_connect()     local tcp = assert(socket.tcp())  tcp:settimeout(31)     local res, err = tcp:connect('192.168.0.105', 23)  if res then    return tcp  else    tcp:close()    return nil, err  end end function lutron_login()  local tcp, tcp_err = lutron_connect()  if not tcp then    return nil,  tcp_err  end  tcp:receive(7)  tcp:send(user..'\r\n')     tcp:receive(10)  tcp:send(password..'\r\n')  local res = tcp:receive(9)  if res == nil or res == 'bad login' then    tcp:close()    return nil, res  end  return tcp end   function lutron_receive(tcp) res, err = tcp:receive()  if not res then    tcp:close()    return nil, err  end  return res end

and resident script
Code:
12345678910111213
require('user.lutron')   tcp, err = lutron_login() if not tcp then  log('no connection to device', err) end while tcp do  res, err = lutron_receive(tcp)  log(res,err)    if (res == nil) then      return    end end
Reply
#2
some additions for that case
Lutron message parser
For example I shall show you how to receive setpoint temperature from Lutron panel/switch
Let’s write all messages from Lutron to knx group address
Change resident script
Code:
123456789101112131415
require('user.lutron')   tcp, err = lutron_login() if not tcp then  log('no connection to device', err) end while tcp do  res, err = lutron_receive(tcp)  --log(res,err)    if (res == nil) then      return     else       grp.write('15/1/1', res)    end end
From Lutron we receive a lot of messages when we change setpoint
For example, this 4 message we will receive twice, when we will change setpoint:
~HVAC,11,78,26,26 – i dont know what is it
~HVAC,11,18,79,0,0 – setpoint in Fahrenheit
~HVAC,11,19,26,0,0 -- setpoint in Celsius degree
~HVAC,11,10,26,26 -- i dont know what is it
 
Let’s see, what we have in  setpoint in Celsius degree
~HVAC,11,19,26,0,0
~HVAC – status from device
11 – device id, which send this message
19 – type of information (Celsius degree in this example)
26 - Celsius degree
0,0 – some other parameters
To parse this message and write temperature to knx address create event based script for message group address (15/1/1)
Code:
12345678910111213141516171819202122
--lutron parser -- get string temp = event.getvalue() -- convert sting to table temp = string.split(temp, ',') -- if comand type is ~HVAC let's move forward if temp[1] == '~HVAC' then     -- if device id = id of our panel let's move forward     if temp[2] == '11' then -- be carefull, temp[2] is string, not number         -- if in message is celsius degree         if temp[3] == '19' then             -- convert temperature from string to number             temp = tonumber(temp[4])             -- check current value of setpoint, to not to write the same value             cur_temp = grp.getvalue('lutron_temp_setpoint')             if temp~=cur_temp then                 -- write walue to temp address                 grp.write('lutron_temp_setpoint', temp)             end         end     end end
To write value from LM to Lutron create event script for setpoint object

Code:
123456789
require('user.lutron') value = event.getvalue() -- round setmoint to integer value = math.floor(value)   tcp, err = lutron_login() if not tcp then  log('no connection to device', err) end tcp:send('#HVAC,11,19,'..value..',0,0\r\n')
to read some data from lutron use next script (resident in my case)
Code:
123456789101112131415
require('user.lutron') --Подключаемся и делаем запрос tcp, err = lutron_login() if not tcp then  log('no connection to device', err) else   -- send some request  tcp:send('?HVAC,11,15\r\n')   -- and receive answer  x = tcp:receive()   -- log answer, or write it to message address  log(x)  tcp:close() end
Reply
#3
Hi AEK,

We did this Lutron link 2 years ago on a big project.

Keep in mind to send a telegam once every x period otherwise the TCP connection will be closed (after 12 hours i believe) by Lutron.

We included a mechanisme to request date or time every hour from the Lutron server to keep the connection alive.

BR,

Erwin
Reply
#4
(12.10.2016, 14:15)Erwin van der Zwart Wrote: Hi AEK,

We did this Lutron link 2 years ago on a big project.

Keep in mind to send a telegam once every x period otherwise the TCP connection will be closed (after 12 hours i believe) by Lutron.

We included a mechanisme to request date or time every hour from the Lutron server to keep the connection alive.

BR,

Erwin

Hi, Erwin!
thanks for your advice.
there will be request of current temperature every N minutes in our case, so I think there will be no problem.

if you did this 2 years ago, could you post your code here to?
I'm not programmer, so i understand my code only partially Smile
Reply
#5
Hi Erwin,
is it possible to have some suggestion about Lutron integration? In the next week I will have to integrate it.
Let me know if it could be possible.
Thanks.
Reply
#6
(02.02.2017, 17:44)Domoticatorino Wrote: Hi Erwin,
is it possible to have some suggestion about Lutron integration? In the next week I will have to integrate it.
Let me know if it could be possible.
Thanks.

I am integrating knx keypad and lutron controller using Logic Machine, I am able to send command but how do I get the status message from lutron please help.
Reply
#7
What kind of status do you want to get? Do you already know the required status request message that should be sent to Lutron?
Reply
#8
(14.11.2022, 16:36)admin Wrote: What kind of status do you want to get? Do you already know the required status request message that should be sent to Lutron?

I just want to get On/off status and brightness value. No, how to send the required status to lutron? Please guide.
Reply
#9
Which commands are you using for control? The status command is similar but it begins with ? instead of # and the last parameter (value) is skipped. This example parses HVAC query: https://forum.logicmachine.net/showthrea...97#pid2197
You will need a separate resident script for status queries.
Reply
#10
(21.11.2022, 08:12)admin Wrote: Which commands are you using for control? The status command is similar but it begins with ? instead of # and the last parameter (value) is skipped. This example parses HVAC query: https://forum.logicmachine.net/showthrea...97#pid2197
You will need a separate resident script for status queries.

I am using this event based script to send command, can you please share the resident script for the same.

require('user.lutron')
tcp, err = lutron_login()
if not tcp then
  log('no connection to device', err)
end
tcpConfusedend('#DEVICE,10,6,3\r\n')
Reply
#11
Try this, no guarantees that it will work because we don't have any Lutron devices to test. Check Logs for any errors if the script does not work.
Adjust each query call as needed. First argument is the query request (without \r\n, it's added automatically), second argument is the status group address where the new value is written.
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
require('user.lutron') sock, err = lutron_login() if not sock then   log('no connection to device', err)   os.sleep(5) end function close(err)   sock:close()   sock = nil   log('receive failed', err) end function query(req, out)   if not sock then     return   end   sock:send(req .. '\r\n')   local res, err = sock:receive()   if not res then     return close(err)   end   if res:sub(1, 1) ~= '~' then     return close('invalid reply ' .. res)   end   if res:sub(2, #req) ~= req:sub(2) then     return close('invalid reply ' .. res)   end   local val = res:sub(#req + 2)   val = tonumber(val)   if val then     grp.checkupdate(out, val)   end end while sock do   query('?DEVICE,10,6,3', '1/1/1')   query('?DEVICE,10,1,2', '1/1/2')   query('?DEVICE,10,3,4', '1/1/3')   if sock then     os.sleep(5) -- delay between each poll cycle   else     break   end end
Reply
#12
(22.11.2022, 12:29)admin Wrote: Try this, no guarantees that it will work because we don't have any Lutron devices to test. Check Logs for any errors if the script does not work.
Adjust each query call as needed. First argument is the query request (without \r\n, it's added automatically), second argument is the status group address where the new value is written.
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
require('user.lutron') sock, err = lutron_login() if not sock then   log('no connection to device', err)   os.sleep(5) end function close(err)   sock:close()   sock = nil   log('receive failed', err) end function query(req, out)   if not sock then     return   end   sock:send(req .. '\r\n')   local res, err = sock:receive()   if not res then     return close(err)   end   if res:sub(1, 1) ~= '~' then     return close('invalid reply ' .. res)   end   if res:sub(2, #req) ~= req:sub(2) then     return close('invalid reply ' .. res)   end   local val = res:sub(#req + 2)   val = tonumber(val)   if val then     grp.checkupdate(out, val)   end end while sock do   query('?DEVICE,10,6,3', '1/1/1')   query('?DEVICE,10,1,2', '1/1/2')   query('?DEVICE,10,3,4', '1/1/3')   if sock then     os.sleep(5) -- delay between each poll cycle   else     break   end end

The script you have shared worked, but sometimes it goes into the sleep mode or update the status very late. Also How do I get the brightness status through this script. I am using the event based script to send the brightness value command to lutron. Please guide

require('user.lutron')
tcp, err = lutron_login()
if not tcp then
  log('no connection to device', err)
end
value = event.getvalue()
value = math.floor(value)
 
tcpConfusedend('#OUTPUT,151,1,'..value..'\r\n')
Reply
#13
What is the resident script sleep time set to?
For outputs use this query format:
Code:
1
query('?OUTPUT,151,1', '1/1/151')
Reply
#14
(29.11.2022, 10:14)admin Wrote: What is the resident script sleep time set to?
For outputs use this query format:
Code:
1
query('?OUTPUT,151,1', '1/1/151')

Sleep Interval for script is set to 0,

while sock do
  query('?OUTPUT,151,1', '0/0/2')
  query('?OUTPUT,151,1', '0/0/4')

I am using this but I it is updating the ON/OFF status only in the script but not giving me the value.  First One is for ON/OFF status and second one is for the BR value, '0/0/2' is 1-bit object and '0/0/4' is 1byte Scale object.
Reply
#15
Add logging to the query function like this and post what you get in Logs tab:
Code:
12345678910111213141516171819202122232425262728
function query(req, out)   if not sock then     return   end   sock:send(req .. '\r\n')   local res, err = sock:receive()   if not res then     return close(err)   end   if res:sub(1, 1) ~= '~' then     return close('invalid reply ' .. res)   end   if res:sub(2, #req) ~= req:sub(2) then     return close('invalid reply ' .. res)   end   local val = res:sub(#req + 2)   log('response', req, out, val)   val = tonumber(val)   if val then     grp.checkupdate(out, val)   end end
Reply
#16
(29.11.2022, 10:35)admin Wrote: Add logging to the query function like this and post what you get in Logs tab:
Code:
12345678910111213141516171819202122232425262728
function query(req, out)   if not sock then     return   end   sock:send(req .. '\r\n')   local res, err = sock:receive()   if not res then     return close(err)   end   if res:sub(1, 1) ~= '~' then     return close('invalid reply ' .. res)   end   if res:sub(2, #req) ~= req:sub(2) then     return close('invalid reply ' .. res)   end   local val = res:sub(#req + 2)   log('response', req, out, val)   val = tonumber(val)   if val then     grp.checkupdate(out, val)   end end
Lutron Status 29.11.2022 16:17:17
* arg: 1
  * string: receive failed
* arg: 2
  * string: invalid reply QNET> ~OUTPUT,151,1,11.00
Lutron Status 29.11.2022 16:17:17
* arg: 1
  * string: receive failed
* arg: 2
  * string: invalid reply NET>
Lutron Status 29.11.2022 16:17:17
* arg: 1
  * string: receive failed
* arg: 2
  * string: invalid reply NET>
Lutron Status 29.11.2022 16:17:18
* arg: 1
  * string: receive failed
* arg: 2
  * string: invalid reply QNET> ~OUTPUT,151,1,11.00
Lutron Status 29.11.2022 16:17:18
* arg: 1
  * string: receive failed
* arg: 2
  * string: invalid reply QNET> ~OUTPUT,151,1,11.00
Lutron Status 29.11.2022 16:17:18
* arg: 1
  * string: no connection to device
* arg: 2
  * nil
Lutron Status 29.11.2022 16:17:23
* arg: 1
  * string: receive failed
* arg: 2
  * string: invalid reply QNET> ~OUTPUT,151,1,11.00
Reply
#17
Try this query function:
Code:
12345678910111213141516171819202122232425262728293031
function query(req, out)   if not sock then     return   end   sock:send(req .. '\r\n')   local res, err = sock:receive()   if not res then     return close(err)   end   local pos = res:find('~')   if not pos then     return close('invalid reply1 ' .. res)   end   res = res:sub(pos)   if res:sub(2, #req) ~= req:sub(2) then     return close('invalid reply2 ' .. res)   end   local val = res:sub(#req + 2)   log('response', req, out, val)   val = tonumber(val)   if val then     grp.checkupdate(out, val)   end end
Reply
#18
(29.11.2022, 11:01)admin Wrote: Try this query function:
Code:
12345678910111213141516171819202122232425262728293031
function query(req, out)   if not sock then     return   end   sock:send(req .. '\r\n')   local res, err = sock:receive()   if not res then     return close(err)   end   local pos = res:find('~')   if not pos then     return close('invalid reply1 ' .. res)   end   res = res:sub(pos)   if res:sub(2, #req) ~= req:sub(2) then     return close('invalid reply2 ' .. res)   end   local val = res:sub(#req + 2)   log('response', req, out, val)   val = tonumber(val)   if val then     grp.checkupdate(out, val)   end end
Now this is working great, but still sometimes are status update is immediate, but  many times it is taking significant amount of time to update.
Reply
#19
You can lower the sleep time between polling cycles by modifying this line (currently it's 5 seconds):
Code:
1
    os.sleep(5) -- delay between each poll cycle
Reply
#20
(29.11.2022, 11:16)admin Wrote: You can lower the sleep time between polling cycles by modifying this line (currently it's 5 seconds):
Code:
1
    os.sleep(5) -- delay between each poll cycle

I have made it 1 second. Now it is working fine, I hope it will work when I add more data points.
Thank You Very much for your support.
Reply


Forum Jump: