LogicMachine Forum
Checksum XOR 4 bytes - Printable Version

+- LogicMachine 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