4

を使用して単純な modbus-tcp ポーリングを行うねじれたアプリケーションで、最近導入され たクラスを利用しようとしています。私の問題は、私が使用している modbus プロトコルとは何の関係もないと感じています。低レベルのツイスト API を使用して、他にもかなりの数の実用的なプロトタイプを作成したからです。しかし、この新しいものは私のニーズにぴったり合っているように見えるので、コードのフットプリントを削減し、機能させることができればきれいに保つ必要があります.twisted.application.internet.ClientServicepymodbusClientService

私のテスト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を待つ状態に戻ることができます...しかし、どう思われますか起こっているのは、ClientService が接続が切断されたことをまだ認識しておらず、同じ切断されたプロトコルを返し、次のようなログが表示されることです。ProtocolwhenConnected()

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

4

2 に答える 2

0

ポーリングに応答して私が見ることができる場所で self.transport.loseConnection() を呼び出していないため、ツイストが知る限り、実際には切断されていません。後で、古いトランスポートで何もするのをやめたときかもしれませんが、それまでに物事を見失っています。

于 2016-09-03T02:53:35.907 に答える