我正在尝试在一个扭曲的应用程序中使用最近引入 的类,该应用程序使用. 我觉得我的问题与我使用的 modbus 协议无关,因为我使用较低级别的扭曲 API 创建了很多其他工作原型;但是这个新的看起来完全符合我的需求,因此应该减少我的代码足迹并保持它的整洁,如果我能让它工作的话。twisted.application.internet.ClientService
pymodbus
ClientService
我的测试显示ClientService
手柄重新连接,正如预期的那样,我可以轻松访问第一个连接Protocol
。我遇到的问题是获取Protocol
重新连接的后续对象。这是我遇到问题的代码的简化版本:
from twisted.application import internet, service
from twisted.internet.protocol import ClientFactory
from twisted.internet import reactor, endpoints
from pymodbus.client.async import ModbusClientProtocol
class ModbusPollingService(internet.ClientService):
def __init__(self, addrstr, numregs=5):
self.numregs=numregs
internet.ClientService.__init__(self,
endpoints.clientFromString(reactor, addrstr),
ClientFactory.forProtocol(ModbusClientProtocol))
def startService(self):
internet.ClientService.startService(self)
self._pollWhenConnected()
def _pollWhenConnected(self):
d = self.whenConnected()
d.addCallback(self._connected)
d.addErrback(self._connfail)
def _connected(self, p):
self._log.debug("connected: {p}", p=p)
self._mbp = p
self._poll()
return True
def _connfail(self, failstat):
self._log.failure('connection failure', failure=failstat)
self._mbp = None
self._pollWhenConnected()
def _poll(self):
self._log.debug("poll: {n}", n=self.numregs)
d = self._mbp.read_holding_registers(0, self.numregs)
d.addCallback(self._regs)
d.addErrback(self._connfail)
def _regs(self, res):
self._log.debug("regs: {r}", r=res.registers)
# Do real work of dealing storing registers here
reactor.callLater(1, self._poll)
return res
application = service.Application("ModBus Polling Test")
mbpollsvc = ModbusPollingService('tcp:127.0.0.1:502')
mbpollsvc.setServiceParent(application)
当连接失败(无论出于何种原因)errback
时,deferred
返回的 fromread_holding_registers()
被调用,目的是我的服务可以放弃它Protocol
并返回等待回调返回新连接的状态Protocol
......whenConnected()
但是似乎正在发生的是 ClientService 还没有意识到连接已死,并返回给我相同的断开连接的协议,给我一个完整的日志:
2016-05-05 17:28:25-0400 [-] connected: <pymodbus.client.async.ModbusClientProtocol object at 0x000000000227b558>
2016-05-05 17:28:25-0400 [-] poll: 5
2016-05-05 17:28:25-0400 [-] connection failure
Traceback (most recent call last):
Failure: pymodbus.exceptions.ConnectionException: Modbus Error: [Connection] Client is not connected
2016-05-05 17:28:25-0400 [-] connected: <pymodbus.client.async.ModbusClientProtocol object at 0x000000000227b558>
2016-05-05 17:28:25-0400 [-] poll: 5
2016-05-05 17:28:25-0400 [-] connection failure
Traceback (most recent call last):
Failure: pymodbus.exceptions.ConnectionException: Modbus Error: [Connection] Client is not connected
还是很相似,注意重复的 ModbusClientProtocol 对象地址。
我很确定我可能只是为这个 API 选择了一个糟糕的模式,但是我已经迭代了一些不同的可能性,比如创建我自己的,Protocol
并且完全Factory
基于ModbusClientProtocol
和处理该类中的轮询机制;但是通过持久性配置和机制来存储轮询数据感觉有点混乱,似乎在 ClientService 级别或更高级别处理这个是一种更清洁的方法,但我无法找到跟踪的最佳方法当前连接的协议。我想我真正想要的是在扩展轮询情况下使用该类的最佳实践建议。ClientService