Module: ModBus::Server

Included in:
RTUServer, RTUViaTCPServer, TCPServer
Defined in:
lib/rmodbus/server.rb

Overview

Module for implementation ModBus server

Constant Summary

Funcs =
[1,2,3,4,5,6,15,16]

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#coilsObject

Returns the value of attribute coils



21
22
23
# File 'lib/rmodbus/server.rb', line 21

def coils
  @coils
end

#discrete_inputsObject

Returns the value of attribute discrete_inputs



21
22
23
# File 'lib/rmodbus/server.rb', line 21

def discrete_inputs
  @discrete_inputs
end

#holding_registersObject

Returns the value of attribute holding_registers



21
22
23
# File 'lib/rmodbus/server.rb', line 21

def holding_registers
  @holding_registers
end

#input_registersObject

Returns the value of attribute input_registers



21
22
23
# File 'lib/rmodbus/server.rb', line 21

def input_registers
  @input_registers
end

#uidObject

Returns the value of attribute uid



21
22
23
# File 'lib/rmodbus/server.rb', line 21

def uid
  @uid
end

Instance Method Details

#exec_req(req, coils, discrete_inputs, holding_registers, input_registers) ⇒ Object (private)



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
90
# File 'lib/rmodbus/server.rb', line 29

def exec_req(req, coils, discrete_inputs, holding_registers, input_registers)
  func = req.getbyte(0)

  unless Funcs.include?(func)
    params = { :err => 1 }
  end

  case func
    when 1
      params = parse_read_func(req, coils, 2000)
      if params[:err] == 0
        val = coils[params[:addr],params[:quant]].pack_to_word
        pdu = func.chr + val.size.chr + val
      end
    when 2
      params = parse_read_func(req, discrete_inputs, 2000)
      if params[:err] == 0
        val = discrete_inputs[params[:addr],params[:quant]].pack_to_word
        pdu = func.chr + val.size.chr + val
      end
    when 3
      params = parse_read_func(req, holding_registers)
      if params[:err] == 0
        pdu = func.chr + (params[:quant] * 2).chr + holding_registers[params[:addr],params[:quant]].pack('n*')
      end
    when 4
      params = parse_read_func(req, input_registers)
      if params[:err] == 0
        pdu = func.chr + (params[:quant] * 2).chr + input_registers[params[:addr],params[:quant]].pack('n*')
      end
    when 5
      params = parse_write_coil_func(req)
      if params[:err] == 0
        coils[params[:addr]] = params[:val]
        pdu = req
      end
    when 6
      params = parse_write_register_func(req)
      if params[:err] == 0
        holding_registers[params[:addr]] = params[:val]
        pdu = req
      end
    when 15
      params = parse_write_multiple_coils_func(req)
      if params[:err] == 0
        coils[params[:addr],params[:quant]] = params[:val][0,params[:quant]]
        pdu = req[0,5]
      end
    when 16
      params = parse_write_multiple_registers_func(req)
      if params[:err] == 0
        holding_registers[params[:addr],params[:quant]] = params[:val][0,params[:quant]]
        pdu = req[0,5]
      end
  end

  if params[:err] == 0
    pdu
  else
    pdu = (func | 0x80).chr + params[:err].chr
  end
end

#parse_read_func(req, field, quant_max = 0x7d) ⇒ Object (private)



92
93
94
95
96
97
98
99
100
101
# File 'lib/rmodbus/server.rb', line 92

def parse_read_func(req, field, quant_max=0x7d)
  quant = req[3,2].unpack('n')[0]

  return { :err => 3} unless quant <= quant_max

  addr = req[1,2].unpack('n')[0]
  return { :err => 2 } unless addr + quant <= field.size

  return { :err => 0, :quant => quant, :addr => addr }
end

#parse_write_coil_func(req) ⇒ Object (private)



103
104
105
106
107
108
109
110
111
112
# File 'lib/rmodbus/server.rb', line 103

def parse_write_coil_func(req)
  addr = req[1,2].unpack('n')[0]
  return { :err => 2 } unless addr <= @coils.size

  val = req[3,2].unpack('n')[0]
  return { :err => 3 } unless val == 0 or val == 0xff00

  val = 1 if val == 0xff00
  return { :err => 0, :addr => addr, :val => val }
end

#parse_write_multiple_coils_func(req) ⇒ Object (private)



123
124
125
126
127
128
129
130
# File 'lib/rmodbus/server.rb', line 123

def parse_write_multiple_coils_func(req)
  params = parse_read_func(req, @coils)

  if params[:err] == 0
    params = {:err => 0, :addr => params[:addr], :quant => params[:quant], :val => req[6,params[:quant]].unpack_bits }
  end
  params
end

#parse_write_multiple_registers_func(req) ⇒ Object (private)



132
133
134
135
136
137
138
139
# File 'lib/rmodbus/server.rb', line 132

def parse_write_multiple_registers_func(req)
  params = parse_read_func(req, @holding_registers)

  if params[:err] == 0
    params = {:err => 0, :addr => params[:addr], :quant => params[:quant], :val => req[6,params[:quant] * 2].unpack('n*')}
  end
  params
end

#parse_write_register_func(req) ⇒ Object (private)



114
115
116
117
118
119
120
121
# File 'lib/rmodbus/server.rb', line 114

def parse_write_register_func(req)
   addr = req[1,2].unpack('n')[0]
   return { :err => 2 } unless addr <= @holding_registers.size

   val = req[3,2].unpack('n')[0]

   return { :err => 0, :addr => addr, :val => val }
end