2014-11-28 3 views
2

Я написал тестовый код, который считывает некоторые катушки/регистры с сервера Modbus PLC. Когда я вызываю один запрос, код работает. Я отключил кабель, затем Twisted вызывает функцию clientConnectionLost, чтобы мой клиент снова подключился, когда я подключил кабель. Если я выполняю несколько запросов, как в приведенном ниже коде, обработка перерывов, ничего не происходит. Я не знаю, что вызывает проблему.Подсоединение Pymodbus/Twisted Asynchronous Client

#!/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() 
+0

У меня есть небольшая проблема после описанной проблемы. Вы говорите, что если вы выдаете два запроса, а затем отсоединяете кабель, 'clientConnectionLost' не вызывается? Это в отличие от поведения, когда вы выдаете только один запрос, а затем отсоединяете кабель, что вызывает вызов 'clientConnectionLost'? –

+0

Да, это проблема, два вопроса, которые вы задали, - это две ситуации. Я читаю сервер в цикле с реактором callLater. Я тестирую возможность повторного подключения с отсоединением кабеля. С одним отложенным обратным вызовом. Два или более отложенных обратных вызовов не работают. – Poseidon

ответ

1

Я проверил ваш код и верить, что вы видели связанные газораспределительный красной сельди когда ваш код был замечен на работу после того, как закомментировать одну из ваших запросов. Поведение, которое вы видите, где clientConnectionLost не называется покрыта скрученной FAQ: Why isn't my connectionLost method called?

Что вам нужно сделать, это создать свой собственный протокол конкретный тайм-аут, как вы не можете всегда полагаться на тайм-ауты TCP, чтобы работать в вашу пользу. Простой способ исправить код можно было бы добавить это к концу вашего метода read:

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

Какой будет прервать соединение через 5 секунд ждать. Кроме того, необходимо отменить этот тайм-аут, когда ваши запросы успешно завершены с:

self.timeout.cancel() 

в методе requestFetched, прежде чем вы называете read снова.

Смежные вопросы