Pymodbus/Twisted 异步客户端重新连接
Posted
技术标签:
【中文标题】Pymodbus/Twisted 异步客户端重新连接【英文标题】:Pymodbus/Twisted Asynchronous Client Reconnecting 【发布时间】:2015-01-26 20:54:44 【问题描述】:我编写了一个测试代码,它从 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()
【问题讨论】:
我在处理您所描述的问题时遇到了一些麻烦。你是说如果你发出两个请求然后拔掉电缆,clientConnectionLost
不会被调用?这与您仅发出一个请求然后拔下电缆时的行为形成对比,这确实会导致调用clientConnectionLost
?
是的,这就是问题所在,你问的两个问题,就是两种情况。我正在使用reactor callLater 循环读取服务器。我正在通过拔下电缆测试重新连接能力。使用一个延迟回调起作用。两个或多个延迟回调不起作用。
【参考方案1】:
我已经测试了您的代码,并且相信您已经看到了与时间相关的红鲱鱼,当您的代码在注释掉您的一个请求后可以正常工作时。您看到的未调用 clientConnectionLost
的行为包含在扭曲的常见问题解答中:Why isn't my connectionLost method called?
您需要做的是创建自己的协议特定超时,因为您不能总是依赖 TCP 的超时来为您服务。修复代码的一种简单方法是将其添加到 read
方法的末尾:
self.timeout = reactor.callLater(5, self.transport.abortConnection)
这将在等待 5 秒后中止连接。当您的请求成功完成后,您还需要取消此超时:
self.timeout.cancel()
在您再次调用您的read
之前,在您的requestFetched
方法中。
【讨论】:
以上是关于Pymodbus/Twisted 异步客户端重新连接的主要内容,如果未能解决你的问题,请参考以下文章
.NET Core的ZooKeeper异步客户端(支持断线重连永久watcher递归操作并且能跨平台)
Android MQTT 客户端无法重新连接到 ActiveMQ