Logic Machine Forum
Checksum XOR 4 bytes - 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: Checksum XOR 4 bytes (/showthread.php?tid=3764)



Checksum XOR 4 bytes - sashhun - 21.12.2021

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


RE: Checksum XOR 4 bytes - admin - 21.12.2021

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



RE: Checksum XOR 4 bytes - sashhun - 21.12.2021

(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


RE: Checksum XOR 4 bytes - sashhun - 21.12.2021

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


RE: Checksum XOR 4 bytes - admin - 22.12.2021

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.


RE: Checksum XOR 4 bytes - sashhun - 22.12.2021

(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.


RE: Checksum XOR 4 bytes - admin - 22.12.2021

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.


RE: Checksum XOR 4 bytes - sashhun - 22.12.2021

(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