This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Hex manipulation
#1
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:
1234567891011
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����� �
Reply
#2
Hi Buuuuudzik,

Try this:

Code:
1234567891011121314
-- String to HEX strvalue = 'this is my string' result = lmcore.strtohex(strvalue) log(result) -- HEX to String hexvalue = '74686973206973206D7920737472696E67' result = lmcore.hextostr(hexvalue) log(result) -- Remove last 2 chars (or checksum) strvalue = 'this is my string' result = string.sub(strvalue, 0, (string.len(strvalue) -2)) log(result)

BR,

Erwin
Reply
#3
(18.09.2016, 21:31)Erwin van der Zwart Wrote: Hi Buuuuudzik,

Try this:

Code:
1234567891011121314
-- String to HEX strvalue = 'this is my string' result = lmcore.strtohex(strvalue) log(result) -- HEX to String hexvalue = '74686973206973206D7920737472696E67' result = lmcore.hextostr(hexvalue) log(result) -- Remove last 2 chars (or checksum) strvalue = 'this is my string' result = string.sub(strvalue, 0, (string.len(strvalue) -2)) log(result)

BR,

Erwin

Hey Erwin,

thanks for your help but unfortunately it not works probably because I can't use hex in this way:
Code:
1
hexvalue = '74686973206973206D7920737472696E67'


but only in this way:
Code:
1
command = string.char(0xBF,0xF4,0xFA,0xB8,0x43,0xFA,0x00,0x00,0x00,0x04,0xA2)


Is there any way to convert such data to string?

Attached Files Thumbnail(s)
   
Reply
#4
Hi Buuuudzik,


command = string.char(0xBF,0xF4,0xFA,0xB8,0x43,0xFA,0x00,0x00,0x00,0x04,0xA2) is the same as command = 'BFF4FAB843FA00000004A2'

Can you show some more you are trying to achieve as this should work ..

BR,

Erwin
Reply
#5
By default hextostr discards zero bytes, you have to pass a second argument for it to keep zeros. Next two lines result in the same binary string:
Code:
12
c1 = string.char(0xBF,0xF4,0xFA,0xB8,0x43,0xFA,0x00,0x00,0x00,0x04,0xA2) c2 = lmcore.hextostr('BFF4FAB843FA00000004A2', true)

Your script should probably read:
Code:
12
result = lmcore.strtohex(data) log(result)
Reply
#6
I've tried and this is not the same when I will send to RS485:
Code:
1
string.char(0x7F,0xF2,0xFA,0xB8,0x43,0xFA,0x00,0x00,0x00,0xFE,0xFD,0x06,0x5B)

and
Code:
1
'7FF2FAB843FA000000FEFD065B'

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:
12345678
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:
123456789
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.
Reply
#7
Hi Buuuudzik,

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:

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
--------------------------------------------------------------------- -- *********************** START CONNECTION ********************** -- --------------------------------------------------------------------- -- Load Modules require('serial') -- Open connection port = serial.open('/dev/RS485', { baudrate = 4800, parity = 'odd', duplex = 'half', databits = 8, stopbits = 1 }) --------------------------------------------------------------------- -- *********************** START FUNCTIONS *********************** -- --------------------------------------------------------------------- -- 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 ************************ -- --------------------------------------------------------------------- --------------------------------------------------------------------- -- *********************** START WRITE/READ ********************** -- --------------------------------------------------------------------- -- Declare command to send to rotel command = string.char(0xfe, 0x03, 0xa5, 0x10, 0x0a, 0xc2) -- power toggle -- Send command to port and wait for reply or timeout reply = writetoport(port, 1, command)-- Timeout is set to 1 second (default = 0.2) --------------------------------------------------------------------- -- ************************ END WRITE/READ *********************** -- --------------------------------------------------------------------- --------------------------------------------------------------------- -- ************************ START LOGGING ************************ -- --------------------------------------------------------------------- -- Process the reply if reply == "No reply received" then  log(reply) else  --Decode the reply if hex  decoded = str2hex(reply)  log(decoded) end   --------------------------------------------------------------------- -- ************************* END LOGGING ************************* -- --------------------------------------------------------------------- -- Close port port:close() --------------------------------------------------------------------- -- ************************ END CONNECTION *********************** -- ---------------------------------------------------------------------

Hope this helps you..

BR,

Erwin
Reply
#8
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:
12345678910111213141516
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   return res end
Reply
#9
Thanks a lot for Edwin and Admin.

I have a lot of materialWink I've checked if the result from hex calculator is the same as from LM and it's perfectWink
Reply


Forum Jump: