13.12.2023, 08:03
(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()