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 Socket Connection for Legrand
#21
Thank you very much, now it looks much more hopeful. But is there still a problem?

Reply
#22
Increase socket timeout by changing sock:settimeout(1) to sock:settimeout(5)
Reply
#23
Thank you administrator!

So already in the alarms the connection is ok.

How do I see the messages from the bus in LM? Because at the moment I only have * # * 1 ##, but not what's going on online. My goal is to transfer all lamps and thermostats to LM for easier and more beautiful operation. That is, I need to be able to read and change their condition.

I apologize for the stupid questions, but I'm still new to writing scripts.
Reply
#24
After the connection is open you need to call read and parse the incoming data. For sending commands a separate script might be needed because there are two session types - command (*99*0##) and event (*99*1##). Unfortunately it's quite hard to make a full example without being able to test it on a real device.
Reply
#25
Okay, I get it.

I used the sample TCP code:
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
function read(sock)   local buf = {}   while true do     local ch, err = sock:receive(1)     if ch then       local pr = buf[ #buf ]       buf[ #buf + 1 ] = ch       if ch == '#' and pr == '#' then         break       end     else       return nil, err     end   end   local ret = table.concat(buf)   log(ret)   return ret end -- init socket if not sock then   require('socket')   sock, err = socket.connect('192.168.1.247', 20000)   -- set timeout to 1 second   if sock then     sock:settimeout(1)   -- error opening connection, log error and wait before reconnecting    else     error(err)     sleep(5)   end end -- socket handler if sock then    sock:send('*99*1##')       --data = sock:receive(14)    res, err = read(sock)       --sock:send('*#1*12##') -- log('check') -- sock:send('*1*1*12##')   -- got data, log it   if data then     log(data)   end end

 and I'm currently getting this:
* # 4 * 1 * 0 * 0229 ## in log.
Which means that the temperature of thermostat 1 is 22.9 degrees. How to separate the digit with the code 1 to be address 32/1/1 and write the value 22.9 in it? How do I separate receiving and sending commands so that it works properly?
Reply
#26
Hi, I made several attempts to control the MX200 with a script, but unfortunately failed. I have the following commands on the line:

Code:
12345678910111213
MH200 26.04.2022 19:53:58     * string: *1*9*11##    90%           MH200 26.04.2022 19:54:15     * string: *1*1000#0*11##    OK           MH200 26.04.2022 19:54:15     * string: *1*0*11##    OFF

could you help me to bind them in a script so that I can recognize them on arrival and bind them to the respective objects and accordingly if the value of the object changes I send the command back to the gateway?
This is the code I use to get them in the log:
Code:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
function read(sock)   local buf = {}   while true do     local ch, err = sock:receive(1)     if ch then       local pr = buf[ #buf ]       buf[ #buf + 1 ] = ch       if ch == '#' and pr == '#' then         break       end     else       return nil, err     end   end   local ret = table.concat(buf)   log(ret)   return ret end -- init socket if not sock then   require('socket')   sock, err = socket.connect('192.168.1.247', 20000)   -- set timeout to 1 second   if sock then     sock:settimeout(1)   -- error opening connection, log error and wait before reconnecting    else     error(err)     sleep(5)   end end -- socket handler if sock then    sock:send('*99*1##')    res, err = read(sock)     if data then     log(data)   end end
Reply
#27
Use this. Changing mapping will require full script restart via disable/enable.
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
if not sock then   mapping = {     ['11'] = '1/1/11',   }   function parselighting(what, where)     local addr = mapping[ where ]     what = tonumber(what) or -1     if addr and 0 <= what and what <= 10 then       grp.checkwrite(addr, what * 10)     end   end   function parse(msg)     local who, what, where = unpack(msg:split('*'))     who = tonumber(who)     -- lighting     if who == 1 then       parselighting(what, where)     end   end   function read(sock)     local buf = {}     while true do       local ch, err = sock:receive(1)       if ch then         local pr = buf[ #buf ]         buf[ #buf + 1 ] = ch         if ch == '#' and pr == '#' then           break         end       else         return nil, err       end     end     if #buf > 0 and buf[ 1 ] == '*' then       return table.concat(buf, '', 2, #buf - 2)     end   end   sock = require('socket').tcp()   sock:settimeout(1)   res, err = sock:connect('192.168.1.247', 20000)   if res then     sock:send('*99*1##')   else     log('connect failed', err)     sock:close()     sock = nil     os.sleep(1)   end end -- socket handler if sock then       res, err = read(sock)   if res then     parse(res)   elseif err == 'closed' then     sock:close()     sock = nil   end end

This example partially implements parsing of lighting type messages (off and dimming).
Docs for all types: https://developer.legrand.com/documentat...or-myhome/
Reply
#28
Thank you so much!

 It works perfectly, but now how can I send commands to the gateway when changing the object in a logic machine?
Reply
#29
You need a separate socket connection for commands. You also need to send another init sequence: *99*0##.
This example should control light point 11 by converting 0..100% value to 0..10. There's some extra logging to check if the message flow is correct. Remove it when the script is working properly.
Code:
1234567891011121314151617181920212223242526
value = event.getvalue() value = math.ceil(value / 10) cmd = '*1*' .. value .. '*11##' sock = require('socket').tcp() sock:settimeout(1) res, err = sock:connect('192.168.1.247', 20000) if res then   sock:send('*99*0##')      res, err = sock:receive(6) -- receive ACK   log('receive 1', res, err)   res, err = sock:send(cmd)   log('send', res, err)   res, err = sock:receive(6) -- receive result ACK/NACK   log('receive 2', res, err) else   log('connect failed', err) end sock:close()
Reply
#30
(27.06.2022, 12:15)admin Wrote: You need a separate socket connection for commands. You also need to send another init sequence: *99*0##.
This example should control light point 11 by converting 0..100% value to 0..10. There's some extra logging to check if the message flow is correct. Remove it when the script is working properly.
Code:
1234567891011121314151617181920212223242526
value = event.getvalue() value = math.ceil(value / 10) cmd = '*1*' .. value .. '*11##' sock = require('socket').tcp() sock:settimeout(1) res, err = sock:connect('192.168.1.247', 20000) if res then   sock:send('*99*0##')     res, err = sock:receive(6) -- receive ACK   log('receive 1', res, err)   res, err = sock:send(cmd)   log('send', res, err)   res, err = sock:receive(6) -- receive result ACK/NACK   log('receive 2', res, err) else   log('connect failed', err) end sock:close()

Works perfectly!

Thank you very much for the help!
Reply
#31
Hello Admin,

Would you help me to refactor the code so that it can use all the features of Open web net ? I tried to redo it myself for the temperature, but I'm sure it's not the right way since the string is different there.

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
if not sock then   mappingtemp = {     ['1'] = '1/1/1',     ['2'] = '1/1/2',   }   mapping = {         ['3'] = '1/1/3',     ['4'] = '1/1/4',     ['5'] = '1/1/5',     ['6'] = '1/1/6',     ['7'] = '1/1/7',     ['8'] = '1/1/8',     ['9'] = '1/1/9',     ['10'] = '1/1/10',     ['11'] = '1/1/11',     ['12'] = '1/1/12',     ['13'] = '1/1/13',     ['14'] = '1/1/14',     ['15'] = '1/1/15',     ['16'] = '1/1/16',     ['17'] = '1/1/17',     ['22'] = '1/1/22',     ['23'] = '1/1/23',     ['51'] = '1/1/51',     ['0215'] = '1/1/52',   }      function parselighting(what, where)     log("Ok")     local addr = mapping[ where ]     what = tonumber(what) or -1     if addr and 0 <= what and what <= 10 then       grp.checkwrite(addr, what)     end   end           function parsetemperature(where, value)     local addr = mappingtemp[ where ]     log(where)     value = tonumber(value) or -1     if addr and 0 <= value and value <= 4050 then       value = value * 0.1       grp.checkwrite(addr, value)       log("done",value)     end   end             function parse(msg)     log (msg)     length = string.len(msg)         if length == 11 then     log("length",length)     local who, where, dimension, value = unpack(msg:split('*'))     if who == "#4" then     who = string.sub(who,2,2)     who = tonumber(who)     parsetemperature(where, value) end     end      if length == 6 then       log("length",length)        local who, what, where = unpack(msg:split('*'))             who = tonumber(who)        -- lighting         if who == 1 then       parselighting(what, where)       log(what)       log(where)     end   end       end   function read(sock)     local buf = {}     while true do       local ch, err = sock:receive(1)       if ch then         local pr = buf[ #buf ]         buf[ #buf + 1 ] = ch         if ch == '#' and pr == '#' then           break         end       else         return nil, err       end     end     if #buf > 0 and buf[ 1 ] == '*' then       return table.concat(buf, '', 2, #buf - 2)     end   end   sock = require('socket').tcp()   sock:settimeout(1)   res, err = sock:connect('192.168.1.195', 20000)   if res then     sock:send('*99*1##')   else     log('connect failed', err)     sock:close()     sock = nil     os.sleep(1)   end end -- socket handler if sock then      res, err = read(sock)   if res then     log(res)     parse(res)   elseif err == 'closed' then     sock:close()     sock = nil   end end
Reply
#32
Try replacing the parse function with this:
Code:
123456789101112
function parse(msg)   local chunks = msg:split('*')   local who = table.remove(chunks, 1)   if who == '#1' then     local what, where = unpack(chunks)     parselighting(what, where)   elseif who == '#4' then     local where, dimension, value = unpack(chunks)     parsetemperature(where, value)   end end
If it does not work then provide logs of the received messages.
Reply
#33
Thanks Admin!

With a slight modification it works perfectly. But I have another problem - the system runs fast for about a day and then starts responding after about 10 seconds (turning on the lights with the first code). I try with OpenWebNet_Client from my PC and it works fast. When I changed the IP on the MH200N it worked quickly again for about a day. Restarting LM or anything else makes no difference. The only difference is that through OpenWebNet_Client I log in with a password, and LM is on a password-free IP. Could there be some communication left open that would initiate the delay? Do you have any other idea? I know it's hard when you don't have access to a working installation, but at least if you could give me some pointers on how and where to look for it.
Reply
#34
Hi Admin,

I still have no progress on the case. Can you help me refactor the code so that I can log in with a username and password?
Reply
#35
Try this code again: https://forum.logicmachine.net/showthrea...2#pid25762
Make sure that the password contains only numbers otherwise the script will fail.
Reply
#36
(07.10.2022, 06:40)admin Wrote: Try this code again: https://forum.logicmachine.net/showthrea...2#pid25762
Make sure that the password contains only numbers otherwise the script will fail.

Hello,

The code works! It manages to log in, now I have to combine it with the other one so that it can also control the lighting.
Reply


Forum Jump: