18.09.2016, 14:35 (This post was last modified: 18.09.2016, 14:36 by buuuudzik.)
Hello,
maybe do you know functions for hex<->string conversion? I am preparing a full integration with Somfy blinds via RS485 and I want receive some data. After this I must delete last 2 bytes(checksum) and inverse all other bytes.
I've tried used this function which I've found in some forum:
Code:
function string.fromhex(str)
return (str:gsub('..', function (cc)
return string.char(tonumber(cc, 16))
end))
end
function string.tohex(str)
return (str:gsub('.', function (c)
return string.format('%02X', string.byte(c))
end))
end
but unfortunately after using string.fromhex(str) for data from the serial port I have such error:
bad argument #1 to '?' (number expected, got nil)
and this is raw data from the serial port when I've log it via log(data)
string: O�C��C����� �
Only first way works good second not.
This is my task:
I am preparing:
1) sending commands to somfy rts transmitter without feedback(and it works nice),
2) sending commands to somfy with a feedback message. (to do)
This is a function prepared on this forum:
Code:
function sendSOMFY(command)
require('serial')
port = serial.open('/dev/RS485', { baudrate = 4800, parity = 'odd', duplex = 'half', databits = 8, stopbits = 1 })
port:flush()
port:write(command)
port:close()
sleep(0.1)
end
I must prepare also reading data after sending command GET. But I don't know how many chars will be sended. I've tried this:
Code:
function send_receiveSOMFY(command)
require('serial')
port = serial.open('/dev/RS485', { baudrate = 4800, parity = 'odd', duplex = 'half', databits = 8, stopbits = 1 })
port:flush()
port:write(command)
data = port:read(20, 1)
port:close()
sleep(0.1)
end
And also in this function is some problem. But this is second thing. When I receive a data from device I must:
1. Delete last 2 bytes which are the checksum.
2. Inverse all bytes.
Here is a script i use for other devices, here is a function to read a line without knowing the lenght, also another HEX function you might want to use:
-- Function to read until carier return is received or timeout
function readline(port, timeout)
local char, buf
buf = {}
while true do
char = port:read(1, timeout or 0.2)
-- error (timeout) or newline, stop
if char == nil or char == '\n' then
break
-- ignore cr char
elseif char ~= '\r' then
table.insert(buf, char)
end
end
return table.concat(buf)
end
-- Function to write to port and return a reply
function writetoport(port, timeout, command)
-- Write data to port as HEX
port:write(command)
-- Call function to read data
line = readline(port, timeout)
if #line > 0 then
return line
else
return "No reply received"
end
end
-- Function to decode hex string value to readable string format
function str2hex(str)
raw_len = string.len(str)
i = 1
while i <= raw_len do
current_hexvalue = '0x' .. string.format("%02x", string.byte(str, i))
if value then
value = value .. ', ' .. current_hexvalue
else
value = current_hexvalue
end
i = i + 1
end
return value
end
---------------------------------------------------------------------
-- ************************ END FUNCTIONS ************************ --
---------------------------------------------------------------------
Of course second one does not work because '7F' == string.char(0x37, 0x46). If you want to send hex string as binary you have to convert it using lmcore.hextostr(str, true) or use string.char.
If by inversion you mean binary XOR, then your function should look like this:
Code:
function convert(str)
local res, byte
res = ''
-- discard last 2 bytes
for i = 1, #str - 2 do
-- get single byte
byte = str:byte(i, i)
-- invert
byte = bit.bxor(byte, 0xFF)
-- add to result
res = res .. string.char(byte)
end