Class: Modbus
- Inherits:
-
Object
- Object
- Modbus
- Defined in:
- lib/modbus.rb,
lib/modbus/adu.rb,
lib/modbus/request.rb,
lib/modbus/response.rb,
lib/modbus/exception.rb,
lib/modbus/tcp_header.rb
Defined Under Namespace
Classes: ExceptionPDU, RequestPDU, ResponsePDU, TCPHeader
Constant Summary collapse
- CODES =
{ read_coils: 0x01, read_inputs: 0x02, read_holding_registers: 0x03, read_input_registers: 0x04, write_coil: 0x05, write_register: 0x06, write_multiple_coils: 0x0F, write_multiple_registers: 0x10, # Serial only read_exception_status: 0x07, diagnostics: 0x08, get_event_counter: 0x0B, get_event_log: 0x0C, get_server_id: 0x11, # unsupported read_file_record: 0x14, write_file_record: 0x15, mask_write_register: 0x16, read_write_registers: 0x17, read_fifo_queue: 0x17, encapsulated_interface_transport: 0x2B, canopen_general_request: 0x0D, read_device_identification: 0x0E }
- READ_CODES =
[0x01, 0x02, 0x03, 0x04].freeze
- WRITE_CODES =
[0x05, 0x06].freeze
- MULTIPLE_CODES =
[0x0F, 0x10].freeze
- EXCEPTIONS =
{ 0x01 => 'illegal function', 0x02 => 'illegal data address', 0x03 => 'illegal data value', 0x04 => 'server device failure', 0x05 => 'acknowledge', # processing will take some time, no need to retry 0x06 => 'server device busy', 0x08 => 'memory parity error', 0x0A => 'gateway path unavailable', 0x0B => 'gateway device failed to respond' }
Instance Method Summary collapse
-
#initialize ⇒ Modbus
constructor
A new instance of Modbus.
-
#read(data) ⇒ Object
Decodes an ADU from wire format and sets the attributes of this object.
- #write_coils(address, *values) ⇒ Object
- #write_registers(address, *values) ⇒ Object
Constructor Details
#initialize ⇒ Modbus
Returns a new instance of Modbus.
43 44 45 |
# File 'lib/modbus.rb', line 43 def initialize @transaction = 0 end |
Instance Method Details
#read(data) ⇒ Object
Decodes an ADU from wire format and sets the attributes of this object.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/modbus.rb', line 50 def read(data) @buffer ||= String.new @buffer << data error = nil loop do # not enough data in buffer to know the length break if @buffer.bytesize < 6 header = TCPHeader.new header.read(@buffer[0..5]) # the headers unit identifier is included in the length total_length = header.request_length + 6 # Extract just the request from the buffer break if @buffer.bytesize < total_length request = @buffer.slice!(0...total_length) function_code = request.getbyte(7) # Yield the complete responses begin if function_code <= 0x80 response = ResponsePDU.new response.read(request[6..-1]) else # Error response response = ExceptionPDU.new response.read(request[6..-1]) function_code = function_code - 0x80 end yield ADU.new header, function_code, response rescue => e error = e end end raise error if error end |
#write_coils(address, *values) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/modbus.rb', line 101 def write_coils(address, *values) values = values.flatten if values.length > 1 write_multiple_coils(address, *values) else adu = request_adu :write_coil request = adu.pdu request.put.address = address.to_i request.put.data = values.first ? 0xFF00 : 0x0 adu end end |
#write_registers(address, *values) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/modbus.rb', line 115 def write_registers(address, *values) values = values.flatten.map! { |value| value.to_i } if values.length > 1 adu = request_adu :write_multiple_registers request = adu.pdu request.put_multiple.address = address.to_i request.put_multiple.quantity = values.length request.put_multiple.data = values.pack('n*') adu else adu = request_adu :write_register request = adu.pdu request.put.address = address.to_i request.put.data = values.first adu end end |