Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
Thank you very much, now it looks much more hopeful. But is there still a problem?
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
Increase socket timeout by changing sock:settimeout(1) to sock:settimeout(5)
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
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.
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
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.
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
26.04.2022, 13:52
(This post was last modified: 27.04.2022, 06:13 by a455115.)
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?
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
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
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
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/documentat...or-myhome/
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
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?
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
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()
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
(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!
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
31.08.2022, 07:32
(This post was last modified: 31.08.2022, 08:04 by a455115.)
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
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
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.
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
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.
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
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?
Posts: 7773
Threads: 42
Joined: Jun 2015
Reputation:
447
Try this code again: https://forum.logicmachine.net/showthrea...2#pid25762
Make sure that the password contains only numbers otherwise the script will fail.
Posts: 95
Threads: 16
Joined: Aug 2019
Reputation:
0
(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.
|