~ubuntu-branches/ubuntu/raring/pymodbus/raring-proposed

« back to all changes in this revision

Viewing changes to pymodbus/client/sync.py

  • Committer: Package Import Robot
  • Author(s): W. Martin Borgert
  • Date: 2011-10-26 07:26:28 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20111026072628-fvzyi6tnb8iipomp
Tags: 0.9.0+r175-1
* Update from trunk to get a number of upstream fixes.
* Removed examples/tools/ (not present in previous version
  anyway) from source because there are different licenses
  involved. Needs clarification.
* Dont't install unit tests.
* Debian patches not necessary anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import socket
2
 
import struct
3
2
import serial
4
3
 
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
10
12
 
11
13
#---------------------------------------------------------------------------#
14
16
import logging
15
17
_logger = logging.getLogger(__name__)
16
18
 
17
 
#---------------------------------------------------------------------------#
18
 
# Client Producer/Consumer
19
 
#---------------------------------------------------------------------------#
20
 
class ModbusTransactionManager:
21
 
    '''
22
 
    This is a simply pull producer that feeds requests to the modbus client
23
 
    '''
24
 
 
25
 
    __tid = Defaults.TransactionId
26
 
 
27
 
    def __init__(self, client):
28
 
        ''' Sets up the producer to begin sending requests
29
 
 
30
 
        :param client: The client socket wrapper
31
 
        '''
32
 
        self.client = client
33
 
 
34
 
    def execute(self, request):
35
 
        ''' Starts the producer to send the next request to
36
 
        consumer.write(Frame(request))
37
 
        '''
38
 
        self.response = None
39
 
        retries = Defaults.Retries
40
 
        request.transaction_id = self.__getNextTID()
41
 
        _logger.debug("Running transaction %d" % request.transaction_id)
42
 
 
43
 
        while retries > 0:
44
 
            try:
45
 
                self.client.connect()
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)
52
 
                break;
53
 
            except socket.error, msg:
54
 
                self.client.close()
55
 
                _logger.debug("Transaction failed. (%s) " % msg)
56
 
                retries -= 1
57
 
        return self.response
58
 
 
59
 
    def __set_result(self, message):
60
 
        ''' Quick helper that lets me reuse the async framer
61
 
 
62
 
        :param message: The decoded message
63
 
        '''
64
 
        self.response = message
65
 
 
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
70
 
        '''
71
 
        tid = (ModbusTransactionManager.__tid + 1) & 0xffff
72
 
        ModbusTransactionManager.__tid = tid
73
 
        return tid
74
 
 
 
19
 
 
20
#---------------------------------------------------------------------------#
 
21
# The Synchronous Clients
 
22
#---------------------------------------------------------------------------#
75
23
class BaseModbusClient(ModbusClientMixin):
76
24
    '''
77
25
    Inteface for a modbus synchronous client. Defined here are all the
97
45
        :returns: True if connection succeeded, False otherwise
98
46
        '''
99
47
        raise NotImplementedException("Method not implemented by derived class")
100
 
    
 
48
 
101
49
    def close(self):
102
50
        ''' Closes the underlying socket connection
103
51
        '''
104
 
        raise NotImplementedException("Method not implemented by derived class")
 
52
        pass
105
53
 
106
54
    def _send(self, request):
107
55
        ''' Sends data on the underlying socket
153
101
 
154
102
    def __str__(self):
155
103
        ''' Builds a string representation of the connection
156
 
        
 
104
 
157
105
        :returns: The string representation
158
106
        '''
159
107
        return "Null Transport"
160
108
 
 
109
 
161
110
#---------------------------------------------------------------------------#
162
111
# Modbus TCP Client Transport Implementation
163
112
#---------------------------------------------------------------------------#
175
124
        self.port = port
176
125
        self.socket = None
177
126
        BaseModbusClient.__init__(self, ModbusSocketFramer(ClientDecoder()))
178
 
    
 
127
 
179
128
    def connect(self):
180
129
        ''' Connect to the modbus tcp server
181
 
        
 
130
 
182
131
        :returns: True if connection succeeded, False otherwise
183
132
        '''
184
133
        if self.socket: return True
192
141
                (self.host, self.port, msg))
193
142
            self.close()
194
143
        return self.socket != None
195
 
    
 
144
 
196
145
    def close(self):
197
146
        ''' Closes the underlying socket connection
198
147
        '''
220
169
 
221
170
    def __str__(self):
222
171
        ''' Builds a string representation of the connection
223
 
        
 
172
 
224
173
        :returns: The string representation
225
174
        '''
226
175
        return "%s:%s" % (self.host, self.port)
227
176
 
 
177
 
228
178
#---------------------------------------------------------------------------#
229
179
# Modbus UDP Client Transport Implementation
230
180
#---------------------------------------------------------------------------#
242
192
        self.port = port
243
193
        self.socket = None
244
194
        BaseModbusClient.__init__(self, ModbusSocketFramer(ClientDecoder()))
245
 
    
 
195
 
246
196
    def connect(self):
247
197
        ''' Connect to the modbus tcp server
248
198
 
251
201
        if self.socket: return True
252
202
        try:
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)
257
207
            self.close()
258
208
        return self.socket != None
259
 
    
 
209
 
260
210
    def close(self):
261
211
        ''' Closes the underlying socket connection
262
212
        '''
282
232
 
283
233
    def __str__(self):
284
234
        ''' Builds a string representation of the connection
285
 
        
 
235
 
286
236
        :returns: The string representation
287
237
        '''
288
238
        return "%s:%s" % (self.host, self.port)
289
239
 
 
240
 
290
241
#---------------------------------------------------------------------------#
291
242
# Modbus Serial Client Transport Implementation
292
243
#---------------------------------------------------------------------------#
328
279
        elif method == 'rtu':    return ModbusRtuFramer(ClientDecoder())
329
280
        elif method == 'binary': return ModbusBinaryFramer(ClientDecoder())
330
281
        raise ParameterException("Invalid framer method requested")
331
 
    
 
282
 
332
283
    def connect(self):
333
284
        ''' Connect to the modbus tcp server
334
285
 
336
287
        '''
337
288
        if self.socket: return True
338
289
        try:
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)
344
295
            self.close()
345
296
        return self.socket != None
346
 
    
 
297
 
347
298
    def close(self):
348
299
        ''' Closes the underlying socket connection
349
300
        '''
371
322
 
372
323
    def __str__(self):
373
324
        ''' Builds a string representation of the connection
374
 
        
 
325
 
375
326
        :returns: The string representation
376
327
        '''
377
328
        return "%s baud[%s]" % (self.method, self.baudrate)
378
329
 
379
 
#---------------------------------------------------------------------------# 
 
330
#---------------------------------------------------------------------------#
380
331
# Exported symbols
381
 
#---------------------------------------------------------------------------# 
 
332
#---------------------------------------------------------------------------#
382
333
__all__ = [
383
334
    "ModbusTcpClient", "ModbusUdpClient", "ModbusSerialClient"
384
335
]