Logic Machine Forum
Hex manipulation - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Hex manipulation (/showthread.php?tid=392)



Hex manipulation - buuuudzik - 18.09.2016

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����� �


RE: Hex manipulation - Erwin van der Zwart - 18.09.2016

Hi Buuuuudzik,

Try this:

Code:
-- 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


RE: Hex manipulation - buuuudzik - 19.09.2016

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

Try this:

Code:
-- 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:
hexvalue = '74686973206973206D7920737472696E67'


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


Is there any way to convert such data to string?


RE: Hex manipulation - Erwin van der Zwart - 19.09.2016

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


RE: Hex manipulation - admin - 19.09.2016

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:
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:
result = lmcore.strtohex(data)
log(result)



RE: Hex manipulation - buuuudzik - 19.09.2016

I've tried and this is not the same when I will send to RS485:
Code:
string.char(0x7F,0xF2,0xFA,0xB8,0x43,0xFA,0x00,0x00,0x00,0xFE,0xFD,0x06,0x5B)

and
Code:
'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:
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.


RE: Hex manipulation - Erwin van der Zwart - 19.09.2016

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:
---------------------------------------------------------------------
-- *********************** 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


RE: Hex manipulation - admin - 19.09.2016

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

  return res
end



RE: Hex manipulation - buuuudzik - 19.09.2016

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