5
4
from pymodbus.constants import Defaults
6
5
from pymodbus.factory import ClientDecoder
7
from pymodbus.exceptions import *
8
from pymodbus.transaction import *
6
from pymodbus.exceptions import NotImplementedException, ParameterException
7
from pymodbus.exceptions import ConnectionException
8
from pymodbus.transaction import ModbusTransactionManager
9
from pymodbus.transaction import ModbusSocketFramer, ModbusBinaryFramer
10
from pymodbus.transaction import ModbusAsciiFramer, ModbusRtuFramer
9
11
from pymodbus.client.common import ModbusClientMixin
11
13
#---------------------------------------------------------------------------#
15
17
_logger = logging.getLogger(__name__)
17
#---------------------------------------------------------------------------#
18
# Client Producer/Consumer
19
#---------------------------------------------------------------------------#
20
class ModbusTransactionManager:
22
This is a simply pull producer that feeds requests to the modbus client
25
__tid = Defaults.TransactionId
27
def __init__(self, client):
28
''' Sets up the producer to begin sending requests
30
:param client: The client socket wrapper
34
def execute(self, request):
35
''' Starts the producer to send the next request to
36
consumer.write(Frame(request))
39
retries = Defaults.Retries
40
request.transaction_id = self.__getNextTID()
41
_logger.debug("Running transaction %d" % request.transaction_id)
46
self.client._send(self.client.framer.buildPacket(request))
47
# I need to fix this to read the header and the result size,
48
# as this may not read the full result set, but right now
49
# it should be fine...
50
result = self.client._recv(1024)
51
self.client.framer.processIncomingPacket(result, self.__set_result)
53
except socket.error, msg:
55
_logger.debug("Transaction failed. (%s) " % msg)
59
def __set_result(self, message):
60
''' Quick helper that lets me reuse the async framer
62
:param message: The decoded message
64
self.response = message
66
def __getNextTID(self):
67
''' Used internally to handle the transaction identifiers.
68
As the transaction identifier is represented with two
69
bytes, the highest TID is 0xffff
71
tid = (ModbusTransactionManager.__tid + 1) & 0xffff
72
ModbusTransactionManager.__tid = tid
20
#---------------------------------------------------------------------------#
21
# The Synchronous Clients
22
#---------------------------------------------------------------------------#
75
23
class BaseModbusClient(ModbusClientMixin):
77
25
Inteface for a modbus synchronous client. Defined here are all the
97
45
:returns: True if connection succeeded, False otherwise
99
47
raise NotImplementedException("Method not implemented by derived class")
102
50
''' Closes the underlying socket connection
104
raise NotImplementedException("Method not implemented by derived class")
106
54
def _send(self, request):
107
55
''' Sends data on the underlying socket
154
102
def __str__(self):
155
103
''' Builds a string representation of the connection
157
105
:returns: The string representation
159
107
return "Null Transport"
161
110
#---------------------------------------------------------------------------#
162
111
# Modbus TCP Client Transport Implementation
163
112
#---------------------------------------------------------------------------#
176
125
self.socket = None
177
126
BaseModbusClient.__init__(self, ModbusSocketFramer(ClientDecoder()))
179
128
def connect(self):
180
129
''' Connect to the modbus tcp server
182
131
:returns: True if connection succeeded, False otherwise
184
133
if self.socket: return True
221
170
def __str__(self):
222
171
''' Builds a string representation of the connection
224
173
:returns: The string representation
226
175
return "%s:%s" % (self.host, self.port)
228
178
#---------------------------------------------------------------------------#
229
179
# Modbus UDP Client Transport Implementation
230
180
#---------------------------------------------------------------------------#
251
201
if self.socket: return True
253
203
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
254
#self.socket.bind(('localhost', Defaults.Port))
255
except socket.error, msg:
256
_logger.error('Unable to create udp socket')
204
#self.socket.bind((self.host, self.port))
205
except socket.error, ex:
206
_logger.error('Unable to create udp socket %s' % ex)
258
208
return self.socket != None
261
211
''' Closes the underlying socket connection
283
233
def __str__(self):
284
234
''' Builds a string representation of the connection
286
236
:returns: The string representation
288
238
return "%s:%s" % (self.host, self.port)
290
241
#---------------------------------------------------------------------------#
291
242
# Modbus Serial Client Transport Implementation
292
243
#---------------------------------------------------------------------------#
337
288
if self.socket: return True
339
self.socket = serial.Serial(port=self.port, timeout=self.timeout,
290
self.socket = serial.Serial(port=self.port, timeout=self.timeout,
340
291
bytesize=self.bytesize, stopbits=self.stopbits,
341
292
baudrate=self.baudrate, parity=self.parity)
342
293
except serial.SerialException, msg:
343
294
_logger.error(msg)
345
296
return self.socket != None
348
299
''' Closes the underlying socket connection
372
323
def __str__(self):
373
324
''' Builds a string representation of the connection
375
326
:returns: The string representation
377
328
return "%s baud[%s]" % (self.method, self.baudrate)
379
#---------------------------------------------------------------------------#
330
#---------------------------------------------------------------------------#
380
331
# Exported symbols
381
#---------------------------------------------------------------------------#
332
#---------------------------------------------------------------------------#
383
334
"ModbusTcpClient", "ModbusUdpClient", "ModbusSerialClient"