2
2
Implementation of a Modbus Client Using Twisted
3
3
--------------------------------------------------
7
from twisted.internet import reactor, protocol
8
from pymodbus.client.async import ModbusClientProtocol
10
def printResult(result):
11
print "Result: %d" % result.bits[0]
14
result = client.write_coil(1, True)
15
result.addCallback(printResult)
16
reactor.callLater(1, reactor.stop)
18
defer = protocol.ClientCreator(reactor, ModbusClientProtocol
19
).connectTCP("localhost", 502)
20
defer.addCallback(process)
24
from twisted.internet import reactor
7
25
from pymodbus.client.async import ModbusClientFactory
8
from pymodbus.bit_read_message import ReadCoilsRequest
11
requests = [ ReadCoilsRequest(0,99) ]
12
p = reactor.connectTCP("localhost", 502, ModbusClientFactory(requests))
28
factory = reactor.connectTCP("localhost", 502, ModbusClientFactory())
14
31
if __name__ == "__main__":
15
reactor.callLater(1, clientTest)
32
reactor.callLater(1, process)
19
35
from collections import deque
21
from twisted.internet import reactor, defer, protocol
36
from twisted.internet import defer, protocol
23
37
from pymodbus.factory import ClientDecoder
24
38
from pymodbus.exceptions import ConnectionException
25
from pymodbus.transaction import ModbusSocketFramer
39
from pymodbus.transaction import ModbusSocketFramer, ModbusTransactionManager
26
40
from pymodbus.client.common import ModbusClientMixin
28
42
#---------------------------------------------------------------------------#
32
46
_logger = logging.getLogger(__name__)
34
48
#---------------------------------------------------------------------------#
49
# A manager for the transaction identifiers
50
#---------------------------------------------------------------------------#
51
_manager = ModbusTransactionManager()
54
#---------------------------------------------------------------------------#
55
# Connected Client Protocols
36
56
#---------------------------------------------------------------------------#
37
57
class ModbusClientProtocol(protocol.Protocol, ModbusClientMixin):
39
59
This represents the base modbus client protocol. All the application
40
60
layer code is deferred to a higher level wrapper.
44
63
def __init__(self, framer=None):
45
64
''' Initializes the framer module
47
66
:param framer: The framer to use for the protocol
49
68
self.framer = framer or ModbusSocketFramer(ClientDecoder())
50
self._requests = deque() # link queue to tid
69
self._requests = deque() # link queue to tid
51
70
self._connected = False
53
72
def connectionMade(self):
70
89
:param data: The data returned from the server
72
self.framer.processIncomingPacket(data, self._callback)
91
def _callback(reply): # todo errback/callback
93
self._requests.popleft().callback(reply)
95
self.framer.processIncomingPacket(data, _callback)
74
97
def execute(self, request):
75
98
''' Starts the producer to send the next request to
76
99
consumer.write(Frame(request))
78
request.transaction_id = self.__getNextTID()
101
request.transaction_id = _manager.getNextTID()
79
102
#self.handler[request.transaction_id] = request
80
103
packet = self.framer.buildPacket(request)
81
104
self.transport.write(packet)
82
105
return self._buildResponse()
84
def _callback(self, reply):
85
''' The callback to call with the response message
87
:param reply: The decoded response message
89
# todo errback/callback
91
self._requests.popleft().callback(reply)
93
107
def _buildResponse(self):
94
108
''' Helper method to return a deferred response
95
109
for the current request.
103
117
self._requests.append(d)
106
def __getNextTID(self):
107
''' Used to retrieve the next transaction id
108
:return: The next unique transaction id
110
As the transaction identifier is represented with two
111
bytes, the highest TID is 0xffff
113
..todo:: Remove this and use the transaction manager
115
tid = (ModbusClientProtocol.__tid + 1) & 0xffff
116
ModbusClientProtocol.__tid = tid
119
120
#----------------------------------------------------------------------#
120
121
# Extra Functions
121
122
#----------------------------------------------------------------------#
125
126
# self.retry -= 1
127
128
#---------------------------------------------------------------------------#
129
# Not Connected Client Protocol
130
#---------------------------------------------------------------------------#
131
class ModbusUdpClientProtocol(protocol.DatagramProtocol, ModbusClientMixin):
133
This represents the base modbus client protocol. All the application
134
layer code is deferred to a higher level wrapper.
138
def __init__(self, framer=None):
139
''' Initializes the framer module
141
:param framer: The framer to use for the protocol
143
self.framer = framer or ModbusSocketFramer(ClientDecoder())
144
self._requests = deque() # link queue to tid
146
def datagramReceived(self, data, (host, port)):
147
''' Get response, check for valid message, decode result
149
:param data: The data returned from the server
151
def _callback(reply): # todo errback/callback
153
self._requests.popleft().callback(reply)
155
_logger.debug("Datagram from: %s:%d" % (host, port))
156
self.framer.processIncomingPacket(data, _callback)
158
def execute(self, request):
159
''' Starts the producer to send the next request to
160
consumer.write(Frame(request))
162
request.transaction_id = _manager.getNextTID()
163
#self.handler[request.transaction_id] = request
164
packet = self.framer.buildPacket(request)
165
self.transport.write(packet)
166
return self._buildResponse()
168
def _buildResponse(self):
169
''' Helper method to return a deferred response
170
for the current request.
172
:returns: A defer linked to the latest request
175
self._requests.append(d)
179
#---------------------------------------------------------------------------#
128
180
# Client Factories
129
181
#---------------------------------------------------------------------------#
130
182
class ModbusClientFactory(protocol.ReconnectingClientFactory):
133
185
protocol = ModbusClientProtocol
135
#---------------------------------------------------------------------------#
187
#---------------------------------------------------------------------------#
136
188
# Exported symbols
137
#---------------------------------------------------------------------------#
189
#---------------------------------------------------------------------------#
139
"ModbusClientProtocol", "ModbusClientFactory",
191
"ModbusClientProtocol", "ModbusUdpClientProtocol",
192
"ModbusClientFactory",