@@ -240,7 +240,7 @@ class ReconnectingAsyncioModbusTcpClient(object):
240240 #: Maximum delay in milli seconds before reconnect is attempted.
241241 DELAY_MAX_MS = 1000 * 60 * 5
242242
243- def __init__ (self , protocol_class = None , loop = None ):
243+ def __init__ (self , protocol_class = None , loop = None , ** kwargs ):
244244 """
245245 Initialize ReconnectingAsyncioModbusTcpClient
246246 :param protocol_class: Protocol used to talk to modbus device.
@@ -257,6 +257,7 @@ def __init__(self, protocol_class=None, loop=None):
257257 self .connected = False
258258 #: Reconnect delay in milli seconds.
259259 self .delay_ms = self .DELAY_MIN_MS
260+ self ._proto_args = kwargs
260261
261262 def reset_delay (self ):
262263 """
@@ -296,7 +297,7 @@ def _create_protocol(self):
296297 """
297298 Factory function to create initialized protocol instance.
298299 """
299- protocol = self .protocol_class ()
300+ protocol = self .protocol_class (** self . _proto_args )
300301 protocol .factory = self
301302 return protocol
302303
@@ -353,7 +354,7 @@ async def _reconnect(self):
353354class AsyncioModbusTcpClient (object ):
354355 """Client to connect to modbus device over TCP/IP."""
355356
356- def __init__ (self , host = None , port = 502 , protocol_class = None , loop = None ):
357+ def __init__ (self , host = None , port = 502 , protocol_class = None , loop = None , ** kwargs ):
357358 """
358359 Initializes Asyncio Modbus Tcp Client
359360 :param host: Host IP address
@@ -372,6 +373,7 @@ def __init__(self, host=None, port=502, protocol_class=None, loop=None):
372373 self .port = port
373374
374375 self .connected = False
376+ self ._proto_args = kwargs
375377
376378 def stop (self ):
377379 """
@@ -387,7 +389,7 @@ def _create_protocol(self):
387389 """
388390 Factory function to create initialized protocol instance.
389391 """
390- protocol = self .protocol_class ()
392+ protocol = self .protocol_class (** self . _proto_args )
391393 protocol .factory = self
392394 return protocol
393395
@@ -441,27 +443,34 @@ class ReconnectingAsyncioModbusTlsClient(ReconnectingAsyncioModbusTcpClient):
441443 """
442444 Client to connect to modbus device repeatedly over TLS."
443445 """
444- def __init__ (self , protocol_class = None , loop = None , framer = None ):
446+ def __init__ (self , protocol_class = None , loop = None , framer = None , ** kwargs ):
445447 """
446448 Initialize ReconnectingAsyncioModbusTcpClient
447449 :param protocol_class: Protocol used to talk to modbus device.
448450 :param loop: Event loop to use
449451 """
450452 self .framer = framer
451- ReconnectingAsyncioModbusTcpClient .__init__ (self , protocol_class , loop )
453+ ReconnectingAsyncioModbusTcpClient .__init__ (self , protocol_class , loop , ** kwargs )
452454
453- async def start (self , host = 'localhost' , port = 802 , sslctx = None ,
454- certfile = None , keyfile = None , password = None , ** kwargs ):
455+ async def start (self , host , port = 802 , sslctx = None , server_hostname = None ):
455456 """
456457 Initiates connection to start client
457- :param host: The host to connect to (default localhost)
458- :param port: Port to connect
459- :param sslctx:The SSLContext to use for TLS (default None and auto create)
460- :param certfile: The optional client's cert file path for TLS server request
461- :param keyfile: The optional client's key file path for TLS server request
462- :param password: The password for for decrypting client's private key file
458+ :param host:
459+ :param port:
460+ :param sslctx:
461+ :param server_hostname:
462+ :return:
463463 """
464- self .sslctx = sslctx_provider (sslctx , certfile , keyfile , password )
464+ self .sslctx = sslctx
465+ if self .sslctx is None :
466+ self .sslctx = ssl .create_default_context ()
467+ # According to MODBUS/TCP Security Protocol Specification, it is
468+ # TLSv2 at least
469+ self .sslctx .options |= ssl .OP_NO_TLSv1_1
470+ self .sslctx .options |= ssl .OP_NO_TLSv1
471+ self .sslctx .options |= ssl .OP_NO_SSLv3
472+ self .sslctx .options |= ssl .OP_NO_SSLv2
473+ self .server_hostname = server_hostname
465474 return await ReconnectingAsyncioModbusTcpClient .start (self , host , port )
466475
467476 async def _connect (self ):
@@ -484,7 +493,7 @@ def _create_protocol(self):
484493 """
485494 Factory function to create initialized protocol instance.
486495 """
487- protocol = self .protocol_class (framer = self .framer )
496+ protocol = self .protocol_class (framer = self .framer , ** self . _proto_args )
488497 protocol .transaction = FifoTransactionManager (self )
489498 protocol .factory = self
490499 return protocol
@@ -500,7 +509,7 @@ class ReconnectingAsyncioModbusUdpClient(object):
500509 #: Maximum delay in milli seconds before reconnect is attempted.
501510 DELAY_MAX_MS = 1000 * 60 * 5
502511
503- def __init__ (self , protocol_class = None , loop = None ):
512+ def __init__ (self , protocol_class = None , loop = None , ** kwargs ):
504513 """
505514 Initializes ReconnectingAsyncioModbusUdpClient
506515 :param protocol_class: Protocol used to talk to modbus device.
@@ -517,6 +526,7 @@ def __init__(self, protocol_class=None, loop=None):
517526 self .port = 0
518527
519528 self .connected = False
529+ self ._proto_args = kwargs
520530 self .reset_delay ()
521531
522532 def reset_delay (self ):
@@ -565,7 +575,7 @@ def _create_protocol(self, host=None, port=0):
565575 """
566576 Factory function to create initialized protocol instance.
567577 """
568- protocol = self .protocol_class ()
578+ protocol = self .protocol_class (** self . _proto_args )
569579 protocol .host = host
570580 protocol .port = port
571581 protocol .factory = self
@@ -629,7 +639,7 @@ class AsyncioModbusUdpClient(object):
629639 Client to connect to modbus device over UDP.
630640 """
631641
632- def __init__ (self , host = None , port = 502 , protocol_class = None , loop = None ):
642+ def __init__ (self , host = None , port = 502 , protocol_class = None , loop = None , ** kwargs ):
633643 """
634644 Initializes Asyncio Modbus UDP Client
635645 :param host: Host IP address
@@ -648,6 +658,7 @@ def __init__(self, host=None, port=502, protocol_class=None, loop=None):
648658 self .port = port
649659
650660 self .connected = False
661+ self ._proto_args = kwargs
651662
652663 def stop (self ):
653664 """
@@ -666,7 +677,7 @@ def _create_protocol(self, host=None, port=0):
666677 """
667678 Factory function to create initialized protocol instance.
668679 """
669- protocol = self .protocol_class ()
680+ protocol = self .protocol_class (** self . _proto_args )
670681 protocol .host = host
671682 protocol .port = port
672683 protocol .factory = self
@@ -832,31 +843,30 @@ async def init_tcp_client(proto_cls, loop, host, port, **kwargs):
832843 :return:
833844 """
834845 client = ReconnectingAsyncioModbusTcpClient (protocol_class = proto_cls ,
835- loop = loop )
846+ loop = loop , ** kwargs )
836847 await client .start (host , port )
837848 return client
838849
839850
840- async def init_tls_client ( proto_cls , loop , host , port , sslctx = None ,
841- certfile = None , keyfile = None , password = None ,
842- framer = None , ** kwargs ):
851+ @ asyncio . coroutine
852+ def init_tls_client ( proto_cls , loop , host , port , sslctx = None ,
853+ server_hostname = None , framer = None , ** kwargs ):
843854 """
844855 Helper function to initialize tcp client
845856 :param proto_cls:
846857 :param loop:
847858 :param host:
848859 :param port:
849860 :param sslctx:
850- :param certfile: The optional client's cert file path for TLS server request
851- :param keyfile: The optional client's key file path for TLS server request
852- :param password: The password for for decrypting client's private key file
861+ :param server_hostname:
853862 :param framer:
854863 :param kwargs:
855864 :return:
856865 """
857866 client = ReconnectingAsyncioModbusTlsClient (protocol_class = proto_cls ,
858- loop = loop , framer = framer )
859- await client .start (host , port , sslctx , certfile , keyfile , password )
867+ loop = loop , framer = framer ,
868+ ** kwargs )
869+ await client .start (host , port , sslctx , server_hostname )
860870 return client
861871
862872
@@ -871,6 +881,6 @@ async def init_udp_client(proto_cls, loop, host, port, **kwargs):
871881 :return:
872882 """
873883 client = ReconnectingAsyncioModbusUdpClient (protocol_class = proto_cls ,
874- loop = loop )
884+ loop = loop , ** kwargs )
875885 await client .start (host , port )
876886 return client
0 commit comments