@@ -53,7 +53,7 @@ def __init__(self, owner):
5353 host = owner .comm_params .source_address [0 ],
5454 port = owner .comm_params .source_address [1 ],
5555 )
56- super ().__init__ (params , True )
56+ super ().__init__ (params , False )
5757 self .server = owner
5858 self .running = False
5959 self .receive_queue = asyncio .Queue ()
@@ -170,6 +170,7 @@ async def handle(self):
170170 self .comm_params .comm_name ,
171171 )
172172 self .transport_close ()
173+ self .callback_disconnected (exc )
173174 else :
174175 Log .error ("Unknown error occurred {}" , exc )
175176 reset_frame = True # graceful recovery
@@ -252,7 +253,66 @@ def callback_data(self, data: bytes, addr: tuple = None) -> int:
252253# --------------------------------------------------------------------------- #
253254
254255
255- class ModbusTcpServer (ModbusProtocol ):
256+ class ModbusBaseServer (ModbusProtocol ):
257+ """Common functionality for all server classes"""
258+
259+ def __init__ (
260+ self ,
261+ params : CommParams ,
262+ context ,
263+ ignore_missing_slaves ,
264+ broadcast_enable ,
265+ response_manipulator ,
266+ request_tracer ,
267+ identity ,
268+ framer ,
269+ ) -> None :
270+ """Initialize base server."""
271+ super ().__init__ (
272+ params ,
273+ True ,
274+ )
275+ self .loop = asyncio .get_running_loop ()
276+ self .decoder = ServerDecoder ()
277+ self .context = context or ModbusServerContext ()
278+ self .control = ModbusControlBlock ()
279+ self .ignore_missing_slaves = ignore_missing_slaves
280+ self .broadcast_enable = broadcast_enable
281+ self .response_manipulator = response_manipulator
282+ self .request_tracer = request_tracer
283+ self .handle_local_echo = False
284+ if isinstance (identity , ModbusDeviceIdentification ):
285+ self .control .Identity .update (identity )
286+ self .framer = framer
287+ self .serving : asyncio .Future = asyncio .Future ()
288+
289+ def callback_new_connection (self ):
290+ """Handle incoming connect."""
291+ return ModbusServerRequestHandler (self )
292+
293+ async def shutdown (self ):
294+ """Shutdown server."""
295+ await self .server_close ()
296+
297+ async def server_close (self ):
298+ """Close server."""
299+ if not self .serving .done ():
300+ self .serving .set_result (True )
301+ self .transport_close ()
302+
303+ async def serve_forever (self ):
304+ """Start endless loop."""
305+ if self .transport :
306+ raise RuntimeError (
307+ "Can't call serve_forever on an already running server object"
308+ )
309+ await self .transport_listen ()
310+ Log .info ("Server listening." )
311+ await self .serving
312+ Log .info ("Server graceful shutdown." )
313+
314+
315+ class ModbusTcpServer (ModbusBaseServer ):
256316 """A modbus threaded tcp socket server.
257317
258318 We inherit and overload the socket server so that we
@@ -263,7 +323,7 @@ class ModbusTcpServer(ModbusProtocol):
263323 def __init__ (
264324 self ,
265325 context ,
266- framer = None ,
326+ framer = ModbusSocketFramer ,
267327 identity = None ,
268328 address = ("" , 502 ),
269329 ignore_missing_slaves = False ,
@@ -300,60 +360,16 @@ def __init__(
300360 ),
301361 )
302362 params .source_address = address
303-
304363 super ().__init__ (
305364 params ,
306- True ,
365+ context ,
366+ ignore_missing_slaves ,
367+ broadcast_enable ,
368+ response_manipulator ,
369+ request_tracer ,
370+ identity ,
371+ framer ,
307372 )
308- self .decoder = ServerDecoder ()
309- self .framer = framer or ModbusSocketFramer
310- self .context = context or ModbusServerContext ()
311- self .control = ModbusControlBlock ()
312- self .ignore_missing_slaves = ignore_missing_slaves
313- self .broadcast_enable = broadcast_enable
314- self .response_manipulator = response_manipulator
315- self .request_tracer = request_tracer
316- if isinstance (identity , ModbusDeviceIdentification ):
317- self .control .Identity .update (identity )
318-
319- # asyncio future that will be done once server has started
320- self .serving = asyncio .Future ()
321- self .serving_done = asyncio .Future ()
322- # constructors cannot be declared async, so we have to
323- # defer the initialization of the server
324- self .handle_local_echo = False
325-
326- def handle_new_connection (self ):
327- """Handle incoming connect."""
328- return ModbusServerRequestHandler (self )
329-
330- async def serve_forever (self ):
331- """Start endless loop."""
332- if self .transport :
333- raise RuntimeError (
334- "Can't call serve_forever on an already running server object"
335- )
336-
337- await self .transport_listen ()
338- self .serving .set_result (True )
339- Log .info ("Server(TCP) listening." )
340- try :
341- await self .transport .serve_forever ()
342- except asyncio .exceptions .CancelledError :
343- self .serving_done .set_result (False )
344- raise
345- except Exception as exc : # pylint: disable=broad-except
346- Log .error ("Server unexpected exception {}" , exc )
347- self .serving_done .set_result (True )
348- Log .info ("Server graceful shutdown." )
349-
350- async def shutdown (self ):
351- """Shutdown server."""
352- await self .server_close ()
353-
354- async def server_close (self ):
355- """Close server."""
356- self .transport_close ()
357373
358374
359375class ModbusTlsServer (ModbusTcpServer ):
@@ -367,7 +383,7 @@ class ModbusTlsServer(ModbusTcpServer):
367383 def __init__ ( # pylint: disable=too-many-arguments
368384 self ,
369385 context ,
370- framer = None ,
386+ framer = ModbusTlsFramer ,
371387 identity = None ,
372388 address = ("" , 502 ),
373389 sslctx = None ,
@@ -422,7 +438,7 @@ def __init__( # pylint: disable=too-many-arguments
422438 )
423439
424440
425- class ModbusUdpServer (ModbusProtocol ):
441+ class ModbusUdpServer (ModbusBaseServer ):
426442 """A modbus threaded udp socket server.
427443
428444 We inherit and overload the socket server so that we
@@ -433,7 +449,7 @@ class ModbusUdpServer(ModbusProtocol):
433449 def __init__ (
434450 self ,
435451 context ,
436- framer = None ,
452+ framer = ModbusSocketFramer ,
437453 identity = None ,
438454 address = ("" , 502 ),
439455 ignore_missing_slaves = False ,
@@ -468,62 +484,17 @@ def __init__(
468484 reconnect_delay_max = 0.0 ,
469485 timeout_connect = 0.0 ,
470486 ),
471- True ,
487+ context ,
488+ ignore_missing_slaves ,
489+ broadcast_enable ,
490+ response_manipulator ,
491+ request_tracer ,
492+ identity ,
493+ framer ,
472494 )
473495
474- self .loop = asyncio .get_running_loop ()
475- self .decoder = ServerDecoder ()
476- self .framer = framer or ModbusSocketFramer
477- self .context = context or ModbusServerContext ()
478- self .control = ModbusControlBlock ()
479- self .ignore_missing_slaves = ignore_missing_slaves
480- self .broadcast_enable = broadcast_enable
481- self .response_manipulator = response_manipulator
482- self .request_tracer = request_tracer
483- if isinstance (identity , ModbusDeviceIdentification ):
484- self .control .Identity .update (identity )
485- self .stop_serving = self .loop .create_future ()
486- # asyncio future that will be done once server has started
487- self .serving = asyncio .Future ()
488- self .serving_done = asyncio .Future ()
489- self .handle_local_echo = False
490-
491- def handle_new_connection (self ):
492- """Handle incoming connect."""
493- return ModbusServerRequestHandler (self )
494-
495- async def serve_forever (self ):
496- """Start endless loop."""
497- if self .transport :
498- raise RuntimeError (
499- "Can't call serve_forever on an already running server object"
500- )
501- try :
502- await self .transport_listen ()
503- except asyncio .exceptions .CancelledError :
504- self .serving_done .set_result (False )
505- raise
506- except Exception as exc :
507- Log .error ("Server unexpected exception {}" , exc )
508- self .serving_done .set_result (False )
509- raise RuntimeError (exc ) from exc
510- Log .info ("Server(UDP) listening." )
511- self .serving .set_result (True )
512- await self .stop_serving
513- self .serving_done .set_result (True )
514-
515- async def shutdown (self ):
516- """Shutdown server."""
517- await self .server_close ()
518-
519- async def server_close (self ):
520- """Close server."""
521- self .transport_close ()
522- if not self .stop_serving .done ():
523- self .stop_serving .set_result (True )
524-
525496
526- class ModbusSerialServer (ModbusProtocol ):
497+ class ModbusSerialServer (ModbusBaseServer ):
527498 """A modbus threaded serial socket server.
528499
529500 We inherit and overload the socket server so that we
@@ -570,56 +541,15 @@ def __init__(
570541 baudrate = kwargs .get ("baudrate" , 19200 ),
571542 stopbits = kwargs .get ("stopbits" , 1 ),
572543 ),
573- True ,
544+ context ,
545+ kwargs .get ("ignore_missing_slaves" , False ),
546+ kwargs .get ("broadcast_enable" , False ),
547+ kwargs .get ("request_tracer" , None ),
548+ kwargs .get ("response_manipulator" , None ),
549+ kwargs .get ("identity" , None ),
550+ framer ,
574551 )
575-
576- self .loop = asyncio .get_running_loop ()
577552 self .handle_local_echo = kwargs .get ("handle_local_echo" , False )
578- self .ignore_missing_slaves = kwargs .get ("ignore_missing_slaves" , False )
579- self .broadcast_enable = kwargs .get ("broadcast_enable" , False )
580- self .framer = framer or ModbusRtuFramer
581- self .decoder = ServerDecoder ()
582- self .context = context or ModbusServerContext ()
583- self .response_manipulator = kwargs .get ("response_manipulator" , None )
584- self .control = ModbusControlBlock ()
585- if isinstance (identity , ModbusDeviceIdentification ):
586- self .control .Identity .update (identity )
587- self .request_tracer = kwargs .get ("request_tracer" , None )
588- self .server = None
589- self .control = ModbusControlBlock ()
590- identity = kwargs .get ("identity" )
591- if isinstance (identity , ModbusDeviceIdentification ):
592- self .control .Identity .update (identity )
593-
594- async def start (self ):
595- """Start connecting."""
596-
597- def handle_new_connection (self ):
598- """Handle incoming connect."""
599- return ModbusServerRequestHandler (self )
600-
601- async def shutdown (self ):
602- """Terminate server."""
603- self .transport_close ()
604- if self .server :
605- self .server .close ()
606- await asyncio .wait_for (self .server .wait_closed (), 10 )
607- self .server = None
608-
609- async def serve_forever (self ):
610- """Start endless loop."""
611- if self .server :
612- raise RuntimeError (
613- "Can't call serve_forever on an already running server object"
614- )
615- Log .info ("Server(Serial) listening." )
616- await self .transport_listen ()
617- try :
618- await self .transport .serve_forever ()
619- except asyncio .exceptions .CancelledError :
620- raise
621- except Exception as exc : # pylint: disable=broad-except
622- Log .error ("Server unexpected exception {}" , exc )
623553
624554
625555# --------------------------------------------------------------------------- #
@@ -779,7 +709,6 @@ async def StartAsyncSerialServer( # pylint: disable=invalid-name,dangerous-defa
779709 server = ModbusSerialServer (
780710 context , kwargs .pop ("framer" , ModbusAsciiFramer ), identity = identity , ** kwargs
781711 )
782- await server .start ()
783712 await _serverList .run (server , custom_functions )
784713
785714
0 commit comments