Python Pymodbus/Twisted异步客户端重新连接

Python Pymodbus/Twisted异步客户端重新连接,python,tcp,twisted,modbus,modbus-tcp,Python,Tcp,Twisted,Modbus,Modbus Tcp,我编写了一个测试代码,从PLC的modbus服务器读取一些线圈/寄存器。当我调用一个请求时,代码就起作用了。我拔下电缆,然后Twisted调用clientConnectionLost函数,这样当我插回电缆时,我的客户端将重新连接。如果我执行多个请求,如下面的代码中所示,则处理中断,什么也不会发生。我不知道是什么引起了这个问题 #!/usr/bin/env python from PyQt4 import QtCore, QtGui from twisted.internet import re

我编写了一个测试代码,从PLC的modbus服务器读取一些线圈/寄存器。当我调用一个请求时,代码就起作用了。我拔下电缆,然后Twisted调用clientConnectionLost函数,这样当我插回电缆时,我的客户端将重新连接。如果我执行多个请求,如下面的代码中所示,则处理中断,什么也不会发生。我不知道是什么引起了这个问题

#!/usr/bin/env python

from PyQt4 import QtCore, QtGui
from twisted.internet import reactor, protocol,defer
from pymodbus.constants import Defaults
from pymodbus.client.async import ModbusClientProtocol

from time import sleep

def logger():
    import logging
    logging.basicConfig()
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)

logger()

class MyModbusClientProtocol(ModbusClientProtocol):

    def connectionMade(self):
        ModbusClientProtocol.connectionMade(self)
        print 'Connected'
        self.read()

    def read(self):
        deferred = self.read_coils(0,1999)
        deferred.addCallbacks(self.requestFetched,self.requestNotFetched)
        deferred = self.read_holding_registers(0,124)
        deferred.addCallbacks(self.requestFetched,self.requestNotFetched)

    def requestNotFetched(self,error):
        print error
        sleep(0.5)

    def requestFetched(self,response):
        try:
            print ("Fetched %d" % response.getRegister(1))
        except:
            print ("Fetched %d" % response.getBit(1))

        self.factory.counter += 1
        if self.factory.counter == 2:
            self.factory.counter = 0
            reactor.callLater(0,self.read)

class MyModbusClientFactory(protocol.ClientFactory):
    """A factory.

    A new protocol instance will be created each time we connect to the server.
    """
    def __init__(self):
        self.counter = 0

    def buildProtocol(self, addr):
        p = MyModbusClientProtocol()
        p.factory = self
        return p

    def clientConnectionLost(self, connector, reason):
        print "connection lost:", reason
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print "connection failed:", reason
        connector.connect()

if __name__ == "__main__":

    factoryinstance = MyModbusClientFactory()

    reactor.connectTCP("192.168.2.69", 502, factoryinstance)

    reactor.run()

我已经测试了您的代码,并且相信您已经看到了一个与时间相关的麻烦,当您的代码在注释了您的一个请求后被认为是有效的。twisted常见问题解答中介绍了您看到的未调用
clientConnectionLost
的行为:

您需要做的是创建自己的特定于协议的超时,因为您不能总是依赖TCP的超时来实现对您有利的工作。修复代码的一个简单方法是将其添加到
read
方法的末尾:

self.timeout = reactor.callLater(5, self.transport.abortConnection)
这将在等待5秒后中止连接。当您的请求通过以下方式成功完成时,您还需要取消此超时:

self.timeout.cancel()

在再次调用
read
之前,请使用
requestFetched
方法。

我在理解您描述的问题时遇到了一些问题。您是说如果发出两个请求,然后拔下电缆,
clientConnectionLost
不会被调用吗?这与您只发出一个请求然后拔下电缆的行为形成对比,这确实会导致调用
clientConnectionLost
?是的,这就是问题所在,您问的两个问题就是两种情况。稍后,我将使用reactor call在循环中读取服务器。我正在测试拔掉电缆的重新连接能力。使用一个延迟回调就可以了。两个或多个延迟回调不起作用。