LogicMachine Forum
TCP Socket Connection for Legrand - 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 Socket Connection for Legrand (/showthread.php?tid=2068)

Pages: 1 2


RE: TCP Socket Connection for Legrand - a455115 - 20.04.2022

Thank you very much, now it looks much more hopeful. But is there still a problem?




RE: TCP Socket Connection for Legrand - admin - 20.04.2022

Increase socket timeout by changing sock:settimeout(1) to sock:settimeout(5)


RE: TCP Socket Connection for Legrand - a455115 - 21.04.2022

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.


RE: TCP Socket Connection for Legrand - admin - 22.04.2022

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.


RE: TCP Socket Connection for Legrand - a455115 - 26.04.2022

Okay, I get it.

I used the sample TCP code:
Code:
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?


RE: TCP Socket Connection for Legrand - a455115 - 14.06.2022

Hi, I made several attempts to control the MX200 with a script, but unfortunately failed. I have the following commands on the line:

Code:
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:
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



RE: TCP Socket Connection for Legrand - admin - 15.06.2022

Use this. Changing mapping will require full script restart via disable/enable.
Code:
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/documentation/open-web-net-for-myhome/


RE: TCP Socket Connection for Legrand - a455115 - 23.06.2022

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?


RE: TCP Socket Connection for Legrand - admin - 27.06.2022

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:
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()



RE: TCP Socket Connection for Legrand - a455115 - 28.06.2022

(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:
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!


RE: TCP Socket Connection for Legrand - a455115 - 31.08.2022

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:
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



RE: TCP Socket Connection for Legrand - admin - 31.08.2022

Try replacing the parse function with this:
Code:
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.


RE: TCP Socket Connection for Legrand - a455115 - 01.09.2022

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.


RE: TCP Socket Connection for Legrand - a455115 - 07.10.2022

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?


RE: TCP Socket Connection for Legrand - admin - 07.10.2022

Try this code again: https://forum.logicmachine.net/showthread.php?tid=2068&pid=25762#pid25762
Make sure that the password contains only numbers otherwise the script will fail.


RE: TCP Socket Connection for Legrand - a455115 - 11.10.2022

(07.10.2022, 06:40)admin Wrote: Try this code again: https://forum.logicmachine.net/showthread.php?tid=2068&pid=25762#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.