3

PLC の modbus サーバーからいくつかのコイル/レジスタを読み取るテスト コードを作成しました。1 つのリクエストを呼び出すと、コードが機能します。ケーブルを抜いた後、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()
4

1 に答える 1

1

私はあなたのコードをテストしましたが、あなたの要求の 1 つをコメントアウトした後、コードが動作するように見えたときに、タイミング関連の赤いニシンを見たことがあると思います。呼び出されていない場所で見られる動作についてclientConnectionLostは、ねじれた FAQ で説明されています:なぜ connectionLost メソッドが呼び出されないのですか?

TCP のタイムアウトに常に依存できるとは限らないため、独自のプロトコル固有のタイムアウトを作成する必要があります。コードを修正する簡単な方法は、これをreadメソッドの最後に追加することです。

self.timeout = reactor.callLater(5, self.transport.abortConnection)

5秒待ってから接続を中止します。また、リクエストが次のように正常に完了したときに、このタイムアウトをキャンセルする必要があります。

self.timeout.cancel()

もう一度requestFetched呼び出す前に、メソッドで。read

于 2016-04-13T12:35:09.110 に答える