Module: ModBus::RTU
- Included in:
- RTUClient, RTUServer, RTUSlave, RTUViaTCPClient, RTUViaTCPServer, RTUViaTCPSlave
- Defined in:
- lib/rmodbus/rtu.rb
Constant Summary
- CHUNK_SIZE =
1500- CrcHiTable =
[ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40]
- CrcLoTable =
[ 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40]
Instance Method Summary (collapse)
- - (Object) clean_input_buff private
-
- (Object) crc16(msg)
private
Calc CRC16 for massage.
- - (Object) read_rtu_pdu private
- - (Object) read_rtu_request(io) private
-
- (Object) read_rtu_response(io)
private
We have to read specific amounts of numbers of bytes from the network depending on the function code and content.
- - (Object) send_rtu_pdu(pdu) private
- - (Object) serv_rtu_requests(io, &blk) private
Instance Method Details
- (Object) clean_input_buff (private)
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/rmodbus/rtu.rb', line 49 def clean_input_buff win_platform = RUBY_PLATFORM.include? "mingw" begin # Read up to CHUNK_SIZE bytes of trash. if win_platform # non-blocking reads are not supported by Windows @io.readpartial(CHUNK_SIZE) else @io.read_nonblock(CHUNK_SIZE) end rescue Errno::EAGAIN # Ignore the fact we couldn't read. rescue Exception => e raise e unless win_platform && e.is_a?(EOFError) # EOFError means we are done end end |
- (Object) crc16(msg) (private)
Calc CRC16 for massage
136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/rmodbus/rtu.rb', line 136 def crc16(msg) crc_lo = 0xff crc_hi = 0xff msg.unpack('c*').each do |byte| i = crc_hi ^ byte crc_hi = crc_lo ^ CrcHiTable[i] crc_lo = CrcLoTable[i] end return ((crc_hi << 8) + crc_lo) end |
- (Object) read_rtu_pdu (private)
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/rmodbus/rtu.rb', line 76 def read_rtu_pdu msg = read_rtu_response(@io) log "Rx (#{msg.size} bytes): " + logging_bytes(msg) if msg.getbyte(0) == @uid return msg[1..-3] if msg[-2,2].unpack('n')[0] == crc16(msg[0..-3]) log "Ignore package: don't match CRC" else log "Ignore package: don't match uid ID" end loop do #waite timeout sleep(0.1) end end |
- (Object) read_rtu_request(io) (private)
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/rmodbus/rtu.rb', line 93 def read_rtu_request(io) # Read the slave_id and function code msg = io.read(2) # If msg is nil, then our client never sent us anything and it's time to disconnect return if msg.nil? function_code = msg.getbyte(1) if [1, 2, 3, 4, 5, 6].include?(function_code) # read 6 more bytes and return the message total message msg += io.read(6) elsif [15, 16].include?(function_code) # Read in first register, register count, and data bytes msg += io.read(5) # Read in however much data we need to + 2 CRC bytes msg += io.read(msg.getbyte(6) + 2) else raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}" end log "Server RX (#{msg.size} bytes): #{logging_bytes(msg)}" msg end |
- (Object) read_rtu_response(io) (private)
We have to read specific amounts of numbers of bytes from the network depending on the function code and content
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rmodbus/rtu.rb', line 23 def read_rtu_response(io) # Read the slave_id and function code msg = nil while msg.nil? msg = io.read(2) end function_code = msg.getbyte(1) case function_code when 1,2,3,4 then # read the third byte to find out how much more # we need to read + CRC msg += io.read(1) msg += io.read(msg.getbyte(2)+2) when 5,6,15,16 then # We just read in an additional 6 bytes msg += io.read(6) when 22 then msg += io.read(8) when 0x80..0xff then msg += io.read(3) else raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}" end end |
- (Object) send_rtu_pdu(pdu) (private)
66 67 68 69 70 71 72 73 74 |
# File 'lib/rmodbus/rtu.rb', line 66 def send_rtu_pdu(pdu) msg = @uid.chr + pdu msg << crc16(msg).to_word clean_input_buff @io.write msg log "Tx (#{msg.size} bytes): " + logging_bytes(msg) end |
- (Object) serv_rtu_requests(io, &blk) (private)
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rmodbus/rtu.rb', line 118 def serv_rtu_requests(io, &blk) loop do # read the RTU message msg = read_rtu_request(io) # If there is no RTU message, we're done serving this client break if msg.nil? if msg.getbyte(0) == @uid and msg[-2,2].unpack('n')[0] == crc16(msg[0..-3]) pdu = yield msg resp = @uid.chr + pdu resp << crc16(resp).to_word log "Server TX (#{resp.size} bytes): #{logging_bytes(resp)}" io.write resp end end end |