Class: ModBus::Client

Inherits:
Object
  • Object
show all
Includes:
Errors
Defined in:
lib/rmodbus/client.rb

Direct Known Subclasses

TCPClient

Constant Summary collapse

CONNECTION_RETRIES =

Number of times to retry on connection and read timeouts

10
READ_RETRIES =
10

Instance Method Summary collapse

Instance Method Details

#mask_write_register(addr, and_mask, or_mask) ⇒ Object

Write *current value & and_mask | or mask in addr register

Return self



193
194
195
196
# File 'lib/rmodbus/client.rb', line 193

def mask_write_register(addr, and_mask, or_mask)
  query("\x16" + addr.to_bytes + and_mask.to_bytes + or_mask.to_bytes)
  self  
end

#query(pdu) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/rmodbus/client.rb', line 198

def query(pdu)    
  send_pdu(pdu)

  tried = 0
  begin
    timeout(1, ModBusTimeout) do
      pdu = read_pdu
    end
  rescue ModBusTimeout => err
    tried += 1
    retry unless tried >= READ_RETRIES
    raise ModBusTimeout.new, 'Timed out during read attempt'
  end

  if pdu[0].to_i >= 0x80
    case pdu[1].to_i
      when 1
        raise IllegalFunction.new, "The function code received in the query is not an allowable action for the server"  
      when 2
        raise IllegalDataAddress.new, "The data address received in the query is not an allowable address for the server"
      when 3
        raise IllegalDataValue.new, "A value contained in the query data field is not an allowable value for server"
      when 4
        raise SlaveDeviceFailure.new, "An unrecoverable error occurred while the server was attempting to perform the requested action"
      when 5
        raise Acknowledge.new, "The server has accepted the request and is processing it, but a long duration of time will be required to do so"
      when 6
        raise SlaveDeviceBus.new, "The server is engaged in processing a long duration program command"
      when 8
        raise MemoryParityError.new, "The extended file area failed to pass a consistency check"
      else
        raise ModBusException.new, "Unknown error"
    end
  end
  pdu[2..-1]
end

#read_coils(addr, ncoils) ⇒ Object

Read value ncoils coils starting with addr

Return array of their values



99
100
101
# File 'lib/rmodbus/client.rb', line 99

def read_coils(addr, ncoils)
  query("\x1" + addr.to_bytes + ncoils.to_bytes).to_array_bit[0..ncoils-1]
end

#read_discret_inputs(addr, ncoils) ⇒ Object

Deprecated version of read_discrete_inputs



111
112
113
114
# File 'lib/rmodbus/client.rb', line 111

def read_discret_inputs(addr, ncoils)
  warn "[DEPRECATION] `read_discret_inputs` is deprecated.  Please use `read_discrete_inputs` instead."
  read_discrete_inputs(addr, ncoils)
end

#read_discrete_inputs(addr, ncoils) ⇒ Object

Read value ncoils discrete inputs starting with addr

Return array of their values



106
107
108
# File 'lib/rmodbus/client.rb', line 106

def read_discrete_inputs(addr, ncoils)
  query("\x2" + addr.to_bytes + ncoils.to_bytes).to_array_bit[0..ncoils-1]
end

#read_holding_registers(addr, nreg) ⇒ Object

Read value nreg holding registers starting with addr

Return array of their values



119
120
121
# File 'lib/rmodbus/client.rb', line 119

def read_holding_registers(addr, nreg) 
  query("\x3" + addr.to_bytes + nreg.to_bytes).to_array_int16
end

#read_input_registers(addr, nreg) ⇒ Object

Read value nreg input registers starting with addr

Return array of their values



126
127
128
# File 'lib/rmodbus/client.rb', line 126

def read_input_registers(addr, nreg)
  query("\x4" + addr.to_bytes + nreg.to_bytes).to_array_int16
end

#write_multiple_coils(addr, val) ⇒ Object

Write val in coils starting with addr

val it is array of bits

Return self



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rmodbus/client.rb', line 157

def write_multiple_coils(addr, val)
  nbyte = ((val.size-1) >> 3) + 1
  sum = 0
  (val.size - 1).downto(0) do |i|
    sum = sum << 1
    sum |= 1 if val[i] > 0
  end
   
  s_val = ""
  nbyte.times do
    s_val << (sum & 0xff).chr
    sum >>= 8 
  end

  query("\xf" + addr.to_bytes + val.size.to_bytes + nbyte.chr + s_val)
  self
end

#write_multiple_registers(addr, val) ⇒ Object

Write val in registers starting with addr

val it is array of integer

Return self



180
181
182
183
184
185
186
187
188
# File 'lib/rmodbus/client.rb', line 180

def write_multiple_registers(addr, val)
  s_val = ""
  val.each do |reg|
    s_val << reg.to_bytes
  end

  query("\x10" + addr.to_bytes + val.size.to_bytes + (val.size * 2).chr + s_val)
  self
end

#write_single_coil(addr, val) ⇒ Object

Write val in addr coil

if val lager 0 write 1

Return self



135
136
137
138
139
140
141
142
# File 'lib/rmodbus/client.rb', line 135

def write_single_coil(addr, val)
  if val == 0
    query("\x5" + addr.to_bytes + 0.to_bytes)
  else
    query("\x5" + addr.to_bytes + 0xff00.to_bytes) 
  end
  self
end

#write_single_register(addr, val) ⇒ Object

Write val in addr register

Return self



147
148
149
150
# File 'lib/rmodbus/client.rb', line 147

def write_single_register(addr, val)
  query("\x6" + addr.to_bytes + val.to_bytes)
  self
end