@@ -65,6 +65,11 @@ def _execute(self, request):
6565 try :
6666 context = self .factory .store [request .unit_id ]
6767 response = request .execute (context )
68+ except NoSuchSlaveException , ex :
69+ _logger .debug ("requested slave does not exist: %s; %s" , ex , traceback .format_exc () )
70+ if self .factory .ignore_missing_slaves :
71+ return # the client will simply timeout waiting for a response
72+ response = request .doException (merror .GatewayNoResponse )
6873 except Exception , ex :
6974 _logger .debug ("Datastore unable to fulfill request: %s" % ex )
7075 response = request .doException (merror .SlaveFailure )
@@ -96,7 +101,7 @@ class ModbusServerFactory(ServerFactory):
96101
97102 protocol = ModbusTcpProtocol
98103
99- def __init__ (self , store , framer = None , identity = None ):
104+ def __init__ (self , store , framer = None , identity = None , ** kwargs ):
100105 ''' Overloaded initializer for the modbus factory
101106
102107 If the identify structure is not passed in, the ModbusControlBlock
@@ -105,13 +110,14 @@ def __init__(self, store, framer=None, identity=None):
105110 :param store: The ModbusServerContext datastore
106111 :param framer: The framer strategy to use
107112 :param identity: An optional identify structure
108-
113+ :param ignore_missing_slaves: True to not send errors on a request to a missing slave
109114 '''
110115 self .decoder = ServerDecoder ()
111116 self .framer = framer or ModbusSocketFramer
112117 self .store = store or ModbusServerContext ()
113118 self .control = ModbusControlBlock ()
114119 self .access = ModbusAccessControl ()
120+ self .ignore_missing_slaves = kwargs .get ('ignore_missing_slaves' , Defaults .IgnoreMissingSlaves )
115121
116122 if isinstance (identity , ModbusDeviceIdentification ):
117123 self .control .Identity .update (identity )
@@ -123,7 +129,7 @@ def __init__(self, store, framer=None, identity=None):
123129class ModbusUdpProtocol (protocol .DatagramProtocol ):
124130 ''' Implements a modbus udp server in twisted '''
125131
126- def __init__ (self , store , framer = None , identity = None ):
132+ def __init__ (self , store , framer = None , identity = None , ** kwargs ):
127133 ''' Overloaded initializer for the modbus factory
128134
129135 If the identify structure is not passed in, the ModbusControlBlock
@@ -132,13 +138,14 @@ def __init__(self, store, framer=None, identity=None):
132138 :param store: The ModbusServerContext datastore
133139 :param framer: The framer strategy to use
134140 :param identity: An optional identify structure
135-
141+ :param ignore_missing_slaves: True to not send errors on a request to a missing slave
136142 '''
137143 framer = framer or ModbusSocketFramer
138144 self .framer = framer (decoder = ServerDecoder ())
139145 self .store = store or ModbusServerContext ()
140146 self .control = ModbusControlBlock ()
141147 self .access = ModbusAccessControl ()
148+ self .ignore_missing_slaves = kwargs .get ('ignore_missing_slaves' , Defaults .IgnoreMissingSlaves )
142149
143150 if isinstance (identity , ModbusDeviceIdentification ):
144151 self .control .Identity .update (identity )
@@ -163,6 +170,11 @@ def _execute(self, request, addr):
163170 try :
164171 context = self .store [request .unit_id ]
165172 response = request .execute (context )
173+ except NoSuchSlaveException , ex :
174+ _logger .debug ("requested slave does not exist: %s; %s" , ex , traceback .format_exc () )
175+ if self .ignore_missing_slaves :
176+ return # the client will simply timeout waiting for a response
177+ response = request .doException (merror .GatewayNoResponse )
166178 except Exception , ex :
167179 _logger .debug ("Datastore unable to fulfill request: %s" % ex )
168180 response = request .doException (merror .SlaveFailure )
@@ -187,38 +199,40 @@ def _send(self, message, addr):
187199#---------------------------------------------------------------------------#
188200# Starting Factories
189201#---------------------------------------------------------------------------#
190- def StartTcpServer (context , identity = None , address = None , console = False ):
202+ def StartTcpServer (context , identity = None , address = None , console = False , ** kwargs ):
191203 ''' Helper method to start the Modbus Async TCP server
192204
193205 :param context: The server data context
194206 :param identify: The server identity to use (default empty)
195207 :param address: An optional (interface, port) to bind to.
196208 :param console: A flag indicating if you want the debug console
209+ :param ignore_missing_slaves: True to not send errors on a request to a missing slave
197210 '''
198211 from twisted .internet import reactor
199212
200213 address = address or ("" , Defaults .Port )
201214 framer = ModbusSocketFramer
202- factory = ModbusServerFactory (context , framer , identity )
215+ factory = ModbusServerFactory (context , framer , identity , ** kwargs )
203216 if console : InstallManagementConsole ({'factory' : factory })
204217
205218 _logger .info ("Starting Modbus TCP Server on %s:%s" % address )
206219 reactor .listenTCP (address [1 ], factory , interface = address [0 ])
207220 reactor .run ()
208221
209222
210- def StartUdpServer (context , identity = None , address = None ):
223+ def StartUdpServer (context , identity = None , address = None , ** kwargs ):
211224 ''' Helper method to start the Modbus Async Udp server
212225
213226 :param context: The server data context
214227 :param identify: The server identity to use (default empty)
215228 :param address: An optional (interface, port) to bind to.
229+ :param ignore_missing_slaves: True to not send errors on a request to a missing slave
216230 '''
217231 from twisted .internet import reactor
218232
219233 address = address or ("" , Defaults .Port )
220234 framer = ModbusSocketFramer
221- server = ModbusUdpProtocol (context , framer , identity )
235+ server = ModbusUdpProtocol (context , framer , identity , ** kwargs )
222236
223237 _logger .info ("Starting Modbus UDP Server on %s:%s" % address )
224238 reactor .listenUDP (address [1 ], server , interface = address [0 ])
@@ -235,6 +249,7 @@ def StartSerialServer(context, identity=None,
235249 :param port: The serial port to attach to
236250 :param baudrate: The baud rate to use for the serial device
237251 :param console: A flag indicating if you want the debug console
252+ :param ignore_missing_slaves: True to not send errors on a request to a missing slave
238253 '''
239254 from twisted .internet import reactor
240255 from twisted .internet .serialport import SerialPort
@@ -244,7 +259,7 @@ def StartSerialServer(context, identity=None,
244259 console = kwargs .get ('console' , False )
245260
246261 _logger .info ("Starting Modbus Serial Server on %s" % port )
247- factory = ModbusServerFactory (context , framer , identity )
262+ factory = ModbusServerFactory (context , framer , identity , ** kwargs )
248263 if console : InstallManagementConsole ({'factory' : factory })
249264
250265 protocol = factory .buildProtocol (None )
0 commit comments