Get pymodbus to read registers from multiple clients asynchronously

1.3k views Asked by At

I can connect to my modbus slaves using pymodbus and read those connections using the synchronous client. When I attempt to use the asynchronous client with twisted I can read multiple values, and get output from one of the clients and the subsequent one hangs if I don't issue a disconnect, but if I issue a disconnect the client disconnects before the values are returned.

I'm a python novice and this is just me scraping together code from various sources. I'm sure there is a super simple solution. Forgive the code, I'm no programmer. Thanks!!

#!/usr/bin/env python
import logging
from twisted.internet import reactor
from twisted.internet import defer, task
from twisted.internet.endpoints import TCP4ClientEndpoint
from pymodbus.constants import Defaults
from pymodbus.client.async import ModbusClientFactory
import time

logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)


hosts = ['10.3.72.89', '10.3.72.57']

start = time.time()


def show_hreg(response):
    log.debug('1st hreg = {0}'.format(response.getRegister(0)))
    print response.registers

def foo(protocol):
    rlist = []
    r2 = protocol.read_holding_registers(1699, 4, unit=1)
    r2.addCallback(show_hreg)
    r3 = protocol.read_holding_registers(1099, 4, unit=1)
    r3.addCallback(show_hreg)
    r4 = protocol.read_holding_registers(1599, 4, unit=1)
    r4.addCallback(show_hreg)

    rlist.append(r2)
    rlist.append(r3)
    rlist.append(r4)
    results = defer.gatherResults(rlist)
    return results
    #protocol.transport.loseConnection()
    #reactor.callLater(1, protocol.transport.loseConnection)

    #reactor.callLater(1.5, reactor.stop)

def main(reactor, hosts):
    dlist = []
    for server in hosts:
        d = TCP4ClientEndpoint(reactor, server, Defaults.Port)
        protocol = d.connect(ModbusClientFactory())
        protocol.addCallback(foo)
        dlist.append(protocol)

    # finish the process when the "queue" is done
    results = defer.gatherResults(dlist).addCallback(printElapsedTime)
    return results


def printElapsedTime(ignore):
    print "Elapsed Time: %s" % (time.time() - start)


task.react(main, [hosts])
0

There are 0 answers