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.

Checksum XOR 4 bytes
#1
Hello. Please tell me how you can summarize 4 bytes with the XOR operation. I have 5 bytes should have this amount
Code:
addr = {'0x01','0x03','0x05','0x07','0x09','0x0b','0x0d','0x0f','0x11','0x13','0x15','0x17','0x19','0x1b','0x1d','0x1f','0x21'}
checksum = {'0xd3','0xd1','0xd7','0xd5','0xdb','0xd9','0xdf','0xdd','0xc3','0xc1','0xc7','0xc5','0xcb','0xc9','0xcf','0xcd','0xf3'}
for i=1,17,1 do
   command = string.char(0x04,0x04,addr[i],0xd2,checksum[i])
   reply = writetoport(port, 0.2, command)
   decoded = str2hex(reply)
   log('Device address: eA'.. i-1 .. ', Result: ' .. decoded)
end

I have 17 devices, 3 bytes is the address of the device, which changes, respectively, and the XOR checksum will also change
Reply
#2
Use bit.bxor() and don't use quotes around numbers because not all functions will convert strings to numbers automatically.
Code:
function encode(...)
  local checksum = bit.bxor(...)
  return string.char(...) .. string.char(checksum)
end

addrs = {0x01,0x03,0x05,0x07,0x09,0x0b,0x0d,0x0f,0x11,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21}

for _, addr in ipairs(addrs) do
  command = encode(0x04,0x04,addr,0xd2)
  reply = writetoport(port, 0.2, command)
  decoded = str2hex(reply)
  log('Device address: eA'.. i-1 .. ', Result: ' .. decoded)
end
Reply
#3
(21.12.2021, 13:49)admin Wrote: Use bit.bxor() and don't use quotes around numbers because not all functions will convert strings to numbers automatically.
Code:
function encode(...)
  local checksum = bit.bxor(...)
  return string.char(...) .. string.char(checksum)
end

addrs = {0x01,0x03,0x05,0x07,0x09,0x0b,0x0d,0x0f,0x11,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21}

for _, addr in ipairs(addrs) do
  command = encode(0x04,0x04,addr,0xd2)
  reply = writetoport(port, 0.2, command)
  decoded = str2hex(reply)
  log('Device address: eA'.. i-1 .. ', Result: ' .. decoded)
end
Thanks for the help Smile
Reply
#4
Please tell me more, how can I make a script that sends a request to rs232, after execution it starts up again, I tried to make a resident script with an interval of 0 so it does not have time to read data from the port
Reply
#5
Can you describe your task in more detail? Protocol description would be helpful as well.
The main rule with serial ports is that only a single script can access the port. For reading you can set read length to -1 to skip waiting and read only the data that is already buffered by the driver.
Reply
#6
(22.12.2021, 08:00)admin Wrote: Can you describe your task in more detail? Protocol description would be helpful as well.
The main rule with serial ports is that only a single script can access the port. For reading you can set read length to -1 to skip waiting and read only the data that is already buffered by the driver.

Good afternoon. I need to constantly poll the room presence sensors through the rs232 port, on average, all sensors are polled once every 2.5 seconds. I transfer the result of the survey to group addresses. My script is hovering at the bottom
Code:
if not port then
require('serial')
    port, err = serial.open('/dev/RS232', {baudrate = 38400, databits = 8, stopbits = 1, parity = 'none', duplex = 'full'})
    if port then
    port:flush()
  else
    log('Error open port in: ' .. err)
  end
end

function readline(port, timeout)
  local char, buf
  buf = {}
  while true do
    char = port:read(1, timeout or 0.2)
    if char == nil or char == '\n' then
      break 
    elseif char ~= '\r' then
      table.insert(buf, char)
    end
  end
  return table.concat(buf)
end

function writetoport(port, timeout, command)
  port:write(command)
  line = readline(port, timeout)
  if #line > 0 then
      return line
  else
    return "No reply received"
  end
end

function str2hex(str)
    raw_len = string.len(str)
    i = 1
      value = ''
  while i <= raw_len do
    if value then
      if i == 4 then
              value = string.byte(str, i)
      end
    else
      value = string.byte(str, i)
    end
    i = i + 1
  end
  return value
end

function encode(...)
  local checksum = bit.bxor(...)
  return string.char(...) .. string.char(checksum)
end

addrs = {0x01,0x03,0x05,0x07,0x09,0x0b,0x0d,0x0f,0x11,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23}

local sum = 0

for _, addr in ipairs(addrs) do
  command = encode(0x04,0x04,addr,0xc8)
  reply = writetoport(port, 0.1, command)
  decoded = str2hex(reply)
  if grp.getvalue('37/3/'.. sum)~=decoded then
        grp.update('37/3/'.. sum, decoded)
  end
  sum = sum + 1
end

value = event.getvalue()
if value == true then
    grp.update(event.dst, false)
elseif value == false then
    grp.update(event.dst, true)
end

At the end, I check the state of the address where the script is and run it anew when the request is received.
Reply
#7
This should be done via a resident script. Maybe add a small delay before each poll. You can also add port:flush() before writing and reading to clear the buffered data if there is anything left there.
Reply
#8
(22.12.2021, 08:45)admin Wrote: This should be done via a resident script. Maybe add a small delay before each poll. You can also add port:flush() before writing and reading to clear the buffered data if there is anything left there.
I did thanks as advised, created a resident script with an interval of 3 seconds, and made the difference as a delay so that the script could finish the request, although I think I will remove the delay. The skrp is executed in an average of 2.5 seconds, and the difference in the interval of 3 seconds minus the query execution time will compensate for the pause after the execution of the script

Attached Files Thumbnail(s)
   
Reply


Forum Jump: