Posts: 23
Threads: 7
Joined: Aug 2017
Reputation:
0
Hi,
I want to send command for sauna control over RS485
Comand list
How need to look my command in LM?
Code: require('serial')
port = serial.open('/dev/RS485-1', { baudrate = 57600, parity = 'none', duplex = 'half', databits = 8, stopbits = 1 })
port:flush()
log = port:write (info)
port:close()
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Code: port:write('set sauna on\r')
port:write('set sauna val 70\r')
Posts: 23
Threads: 7
Joined: Aug 2017
Reputation:
0
This is correct that I done in resident for reading:
Code: require('serial')
port = serial.open('/dev/RS485-1', { baudrate = 57600, parity = 'none', duplex = 'half', databits = 8, stopbits = 1 })
port:flush()
grp.write('32/2/2', port:write(('get sauna val\r'), 'uint16'))
port:close()
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
If you want to query status periodically then things get more complicated. You need to have a single resident script which will handle both reading and writing because you cannot have multiple scripts accessing serial port at the same time.
You also need to parse the response because the reply will contain some additional characters.
This should log raw response of temperature value.
Code: function readack()
local line = {}
while true do
local char, err = port:read(1, 5)
if char == nil then
return nil, err
elseif char == ';' then
break
else
line[ #line + 1 ] = char
end
end
return table.concat(line)
end
port:write('get sauna val\r')
res, err = readack()
log(res, err)
Posts: 23
Threads: 7
Joined: Aug 2017
Reputation:
0
Ok connection is working maybe you know why I get not correct value?
Posts: 23
Threads: 7
Joined: Aug 2017
Reputation:
0
Evrithing is good its working code:
Code: require('serial')
port = serial.open('/dev/RS485-1', { baudrate = 57600, parity = 'none', duplex = 'half', databits = 8, stopbits = 1 })
port:flush()
function readack()
local line = {}
while true do
local char, err = port:read(1, 5)
if char == nil then
return nil, err
elseif char == ';' then
break
else
line[ #line + 1 ] = char
end
end
return table.concat(line)
end
port:write('get sauna\r')
res, err = readack()
log(res, err)
port:close()
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
Hi.
I get response timeout when running this script in wiser knx. is there any difference for RS-485 port?
I´ve tested this script over here and also with
This:
Code: require('serial')
local port, errorMsg = serial.open('/dev/RS485', { baudrate = 57600, parity = 'none', duplex = 'half', databits = 8, stopbits = 1 })
-- Kontrollera om porten öppnades framgångsrikt
if not port then
log("Kunde inte öppna porten: " .. (errorMsg or "Okänt fel"))
return
end
port:flush()
-- Funktion för att läsa svar från bastun
local function readack()
local line = {}
while true do
local char, err = port:read(1, 5)
if char == nil then
return nil, err
elseif char == ';' then
break
else
table.insert(line, char)
end
end
return table.concat(line)
end
-- Kontrollera om bastun ska vara PÅ eller AV
local bastuState = grp.getvalue('37/1/1')
if bastuState then
port:write('set sauna on\r')
else
port:write('set sauna off\r')
end
-- Ställ in bastutemperaturen baserat på KNX-gruppadressen, värde mellan 30-110 grader
local temperature = grp.getvalue('37/1/3')
port:write('set sauna val ' .. temperature .. '\r')
-- Läs tillbaka värdet från bastun
port:write('get sauna val\r')
local res, err = readack()
if res then
log("Sauna värde: " .. res)
grp.checkwrite('37/1/0', res) -- Skriver bastustatus till angiven adress
grp.checkwrite('37/1/4', res) -- Skriver tillbaka temperaturstatus till den nya gruppadressen
else
log("Fel vid läsning av bastu värde: " .. (err or "Okänt fel"))
end
-- Stäng porten
port:close()
Anone who can see something wrong in this script?
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Script should call readack() after every command (both set and get). But this won't cause last readack() to return timeout. Something is wrong on the communication level. Try swapping A/B and see if GND is connected.
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
(06.10.2023, 12:43)admin Wrote: Script should call readack() after every command (both set and get). But this won't cause last readack() to return timeout. Something is wrong on the communication level. Try swapping A/B and see if GND is connected.
Thanks this helped.
Now runs thhis script and its working.
Code: require('serial')
local port, errorMsg = serial.open('/dev/RS485', { baudrate = 57600, parity = 'none', duplex = 'half', databits = 8, stopbits = 1 })
if not port then
log("Kunde inte öppna porten: " .. (errorMsg or "Okänt fel"))
return
end
port:flush()
-- Funktion för att läsa svar från bastun
local function readack()
local line = {}
local crlf_received = false
while not crlf_received do
local char, err = port:read(1, 5)
if char == nil then
return nil, err
elseif char == '\r' then
-- Ignorerar CR och väntar på LF
elseif char == '\n' then
crlf_received = true
else
table.insert(line, char)
end
end
local response = table.concat(line)
if string.sub(response, -1) == ';' then
response = string.sub(response, 1, -2) -- Ta bort semikolon i slutet
end
return response
end
-- Loggar och skickar kommandon till bastustyrningen, läser sedan svaret
local function sendAndRead(command)
log("Skickat kommando: " .. command)
port:write(command .. '\r\n')
return readack()
end
-- Kontrollera om bastun ska vara PÅ eller AV och läs svar
local bastuState = grp.getvalue('37/1/1')
sendAndRead(bastuState and 'set sauna on' or 'set sauna off')
-- Ställ in bastutemperaturen baserat på KNX-gruppadressen och läs svar
local temperature = grp.getvalue('37/1/3')
local tempResponse = sendAndRead('set sauna val ' .. temperature)
if tempResponse then
log("Svar på temperaturinställning: " .. tempResponse)
-- Uppdatera KNX-gruppadressen med det utlästa värdet
grp.checkwrite('37/1/4', temperature)
end
-- Läs bastuns nuvarande status
local currentStatus = sendAndRead('get sauna')
if currentStatus then
local status = string.match(currentStatus, "SAUNA%s(%w+)")
if status then
log("Bastuns nuvarande status: " .. status)
local knxStatus = (status == "on") and 1 or 0
grp.checkwrite('37/1/0', knxStatus)
else
log("Kunde inte tolka bastuns nuvarande status från svaret: " .. currentStatus)
end
end
-- Stäng porten
port:close()
Build on more functions for the sauna with following script and with the new one it does not work, is there any solution you can see?
Code: require('serial')
local port, errorMsg = serial.open('/dev/RS485', { baudrate = 57600, parity = 'none', duplex = 'half', databits = 8, stopbits = 1 })
if not port then
log("Kunde inte öppna porten: " .. (errorMsg or "Okänt fel"))
return
end
port:flush()
-- Funktion för att läsa svar från bastun
local function readack()
local line = {}
local crlf_received = false
while not crlf_received do
local char, err = port:read(1, 5)
if char == nil and err then
log("Läsfel: " .. err)
return nil, err
elseif char == '\r' or char == '\n' then
-- Hanterar CR, LF och potentiellt icke-skrivbara tecken
if char == '\n' then
crlf_received = true
end
elseif char then
table.insert(line, char)
end
end
local response = table.concat(line)
log("Mottaget svar: " .. response)
if string.sub(response, -1) == ';' then
response = string.sub(response, 1, -2)
end
return response
end
-- Loggar och skickar kommandon till bastustyrningen, läser sedan svaret
local function sendAndRead(command)
log("Skickat kommando: " .. command)
port:write(command .. '\r\n')
return readack()
end
-- Hantera Timer-status (starta/stoppa)
local function handleTimerStatus()
local timerStatus = grp.getvalue('37/1/5')
local response = sendAndRead(timerStatus and 'set timer on' or 'set timer off')
if response then
local status = string.match(response, "timer%s(%w+);")
grp.checkwrite('37/1/6', status == "on" and 1 or 0)
end
end
-- Sätta tid för Timer och hämta dess status
local function setAndQueryTimerTime()
local timerTime = grp.getvalue('37/1/7')
sendAndRead('set timer val ' .. timerTime)
local timerTimeResponse = sendAndRead('get timer val')
if timerTimeResponse then
local timeValue = string.match(timerTimeResponse, "timer%s(%d+);")
grp.checkwrite('37/1/8', tonumber(timeValue))
end
end
-- Hantera Userprogram
local function handleUserProgram()
local userProgram = grp.getvalue('37/1/9')
local response = sendAndRead(userProgram and 'set user-prog on' or 'set user-prog off')
if response then
local status = string.match(response, "user%-prog%s(%w+);")
grp.checkwrite('37/1/10', status == "on" and 1 or 0)
end
local programNumber = grp.getvalue('37/1/11')
local programResponse = sendAndRead('set user-prog val ' .. programNumber)
if programResponse then
local currentProgram = string.match(programResponse, "user%-prog%s(%d+);")
grp.checkwrite('37/1/12', tonumber(currentProgram))
end
end
-- Hämta bastu Control Unit Status
local function getControlUnitStatus()
local response = sendAndRead('get status')
if response then
-- Matcha statusen efter "STATUS " utan att kräva ett semikolon i slutet
local status = string.match(response, "STATUS%s(%w+)")
if status then
-- Skickar statussvaret som en textsträng till KNX-gruppadressen
grp.checkwrite('37/1/20', "Bastu " .. status)
else
log("Kunde inte tolka Control Unit status från svaret: " .. response)
end
end
end
-- Anropa funktionerna
handleTimerStatus()
setAndQueryTimerTime()
handleUserProgram()
getControlUnitStatus()
-- Stäng porten
port:close()
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Do you get anything in logs? Any response from the readack() function?
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
Gets this in my log, sorry for the swedish text in log
Bastu Status REV 13.12.2023 09:25:16
* string: Skickat kommando: set timer val 240
Bastu Status REV 13.12.2023 09:25:16
* string: Mottaget svar: TIMER 240min ;
Bastu Status REV 13.12.2023 09:25:16
* string: Skickat kommando: get timer val
Bastu Status REV 13.12.2023 09:25:16
* string: Mottaget svar: TIMER 240min ;
Bastu Status REV 13.12.2023 09:25:16
* string: Skickat kommando: set user-prog val 1
Bastu Status REV 13.12.2023 09:25:16
* string: Mottaget svar: USER-PROG 1 ;
Bastu Status REV 13.12.2023 09:25:16
* string: Skickat kommando: get status
Bastu Status REV 13.12.2023 09:25:16
* string: Mottaget svar: STATUS OK;
The sauna activates with one relay but directly shuts off.
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
The response is uppercase so your regexp won't work because it's lowercase. Use 'USER%-PROG%s+(%d+)' for user program detection and 'TIMER%s+(%w+)' for timer. Modify other regexps in a similar way.
Posts: 92
Threads: 16
Joined: Jan 2020
Reputation:
2
Okey, now gets this in Log.
Bastu Status REV 13.12.2023 09:52:22
* string: Skickat kommando: set timer val 240
Bastu Status REV 13.12.2023 09:52:22
* string: Mottaget svar: TIMER 240min ;
Bastu Status REV 13.12.2023 09:52:22
* string: Skickat kommando: get timer val
Bastu Status REV 13.12.2023 09:52:22
* string: Mottaget svar: �TIMER 240min ;
Bastu Status REV 13.12.2023 09:52:22
* string: Skickat kommando: set user-prog off
Bastu Status REV 13.12.2023 09:52:22
* string: Mottaget svar: USER-PROG off;
Bastu Status REV 13.12.2023 09:52:22
* string: Skickat kommando: set user-prog val 1
Bastu Status REV 13.12.2023 09:52:22
* string: Mottaget svar: USER-PROG 1 ;
Bastu Status REV 13.12.2023 09:52:22
* string: Skickat kommando: get status
Bastu Status REV 13.12.2023 09:52:22
* string: Mottaget svar: STATUS OK;
Posts: 7764
Threads: 42
Joined: Jun 2015
Reputation:
447
Post you current script. What exactly is not working after the regexp changes?
|