~ubuntu-branches/ubuntu/precise/pymodbus/precise

« back to all changes in this revision

Viewing changes to pymodbus/payload.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
'''
 
2
Modbus Payload Builders
 
3
------------------------
 
4
 
 
5
A collection of utilities for building and decoding
 
6
modbus messages payloads.
 
7
'''
 
8
from struct import pack, unpack
 
9
from pymodbus.constants import Endian
 
10
 
 
11
 
 
12
class PayloadBuilder(object):
 
13
    '''
 
14
    A utility that helps build payload messages to be
 
15
    written with the various modbus messages. It really is just
 
16
    a simple wrapper around the struct module, however it saves
 
17
    time looking up the format strings. What follows is a simple
 
18
    example::
 
19
 
 
20
        builder = PayloadBuilder(endian=Endian.Little)
 
21
        builder.add_8bit_uint(1)
 
22
        builder.add_16bit_uint(2)
 
23
        payload = builder.tostring()
 
24
    '''
 
25
 
 
26
    def __init__(self, payload=None, endian=Endian.Little):
 
27
        ''' Initialize a new instance of the payload builder
 
28
 
 
29
        :param payload: Raw payload data to initialize with
 
30
        :param endian: The endianess of the payload
 
31
        '''
 
32
        self._payload = payload or []
 
33
        self._endian  = endian
 
34
 
 
35
    def reset(self):
 
36
        ''' Reset the payload buffer
 
37
        '''
 
38
        self._payload = []
 
39
 
 
40
    def tostring(self):
 
41
        ''' Return the payload buffer as a string
 
42
 
 
43
        :returns: The payload buffer as a string
 
44
        '''
 
45
        return ''.join(self._payload)
 
46
 
 
47
    def tolist(self):
 
48
        ''' Return the payload buffer as a list
 
49
 
 
50
        :returns: The payload buffer as a list
 
51
        '''
 
52
        return self._payload
 
53
 
 
54
    def add_8bit_uint(self, value):
 
55
        ''' Adds a 8 bit unsigned int to the buffer
 
56
 
 
57
        :param value: The value to add to the buffer
 
58
        '''
 
59
        fstring = self._endian + 'B'
 
60
        self._payload.append(pack(fstring, value))
 
61
 
 
62
    def add_16bit_uint(self, value):
 
63
        ''' Adds a 16 bit unsigned int to the buffer
 
64
 
 
65
        :param value: The value to add to the buffer
 
66
        '''
 
67
        fstring = self._endian + 'H'
 
68
        self._payload.append(pack(fstring, value))
 
69
 
 
70
    def add_32bit_uint(self, value):
 
71
        ''' Adds a 32 bit unsigned int to the buffer
 
72
 
 
73
        :param value: The value to add to the buffer
 
74
        '''
 
75
        fstring = self._endian + 'I'
 
76
        self._payload.append(pack(fstring, value))
 
77
 
 
78
    def add_64bit_uint(self, value):
 
79
        ''' Adds a 64 bit unsigned int to the buffer
 
80
 
 
81
        :param value: The value to add to the buffer
 
82
        '''
 
83
        fstring = self._endian + 'Q'
 
84
        self._payload.append(pack(fstring, value))
 
85
 
 
86
    def add_8bit_int(self, value):
 
87
        ''' Adds a 8 bit signed int to the buffer
 
88
 
 
89
        :param value: The value to add to the buffer
 
90
        '''
 
91
        fstring = self._endian + 'b'
 
92
        self._payload.append(pack(fstring, value))
 
93
 
 
94
    def add_16bit_int(self, value):
 
95
        ''' Adds a 16 bit signed int to the buffer
 
96
 
 
97
        :param value: The value to add to the buffer
 
98
        '''
 
99
        fstring = self._endian + 'h'
 
100
        self._payload.append(pack(fstring, value))
 
101
 
 
102
    def add_32bit_int(self, value):
 
103
        ''' Adds a 32 bit signed int to the buffer
 
104
 
 
105
        :param value: The value to add to the buffer
 
106
        '''
 
107
        fstring = self._endian + 'i'
 
108
        self._payload.append(pack(fstring, value))
 
109
 
 
110
    def add_64bit_int(self, value):
 
111
        ''' Adds a 64 bit signed int to the buffer
 
112
 
 
113
        :param value: The value to add to the buffer
 
114
        '''
 
115
        fstring = self._endian + 'q'
 
116
        self._payload.append(pack(fstring, value))
 
117
 
 
118
    def add_32bit_float(self, value):
 
119
        ''' Adds a 32 bit float to the buffer
 
120
 
 
121
        :param value: The value to add to the buffer
 
122
        '''
 
123
        fstring = self._endian + 'f'
 
124
        self._payload.append(pack(fstring, value))
 
125
 
 
126
    def add_64bit_float(self, value):
 
127
        ''' Adds a 64 bit float(double) to the buffer
 
128
 
 
129
        :param value: The value to add to the buffer
 
130
        '''
 
131
        fstring = self._endian + 'd'
 
132
        self._payload.append(pack(fstring, value))
 
133
 
 
134
    def add_string(self, value):
 
135
        ''' Adds a string to the buffer
 
136
 
 
137
        :param value: The value to add to the buffer
 
138
        '''
 
139
        fstring = self._endian + 's'
 
140
        for c in value:
 
141
            self._payload.append(pack(fstring, c))
 
142
 
 
143
 
 
144
class PayloadDecoder(object):
 
145
    '''
 
146
    A utility that helps decode payload messages from a modbus
 
147
    reponse message.  It really is just a simple wrapper around
 
148
    the struct module, however it saves time looking up the format
 
149
    strings. What follows is a simple example::
 
150
 
 
151
        decoder = PayloadDecoder(self.little_endian_payload)
 
152
        first   = decoder.decode_8bit_uint()
 
153
        second  = decoder.decode_16bit_uint()
 
154
    '''
 
155
 
 
156
    def __init__(self, payload, endian=Endian.Little):
 
157
        ''' Initialize a new payload decoder
 
158
 
 
159
        :param payload: The payload to decode with
 
160
        :param endian: The endianess of the payload
 
161
        '''
 
162
        self._payload = payload
 
163
        self._pointer = 0x00
 
164
        self._endian  = endian
 
165
 
 
166
    def reset(self):
 
167
        ''' Reset the decoder pointer back to the start
 
168
        '''
 
169
        self._pointer = 0x00
 
170
 
 
171
    def decode_8bit_uint(self):
 
172
        ''' Decodes a 8 bit unsigned int from the buffer
 
173
        '''
 
174
        self._pointer += 1
 
175
        fstring = self._endian + 'B'
 
176
        handle = self._payload[self._pointer - 1:self._pointer]
 
177
        return unpack('B', handle)[0]
 
178
 
 
179
    def decode_16bit_uint(self):
 
180
        ''' Decodes a 16 bit unsigned int from the buffer
 
181
        '''
 
182
        self._pointer += 2
 
183
        fstring = self._endian + 'H'
 
184
        handle = self._payload[self._pointer - 2:self._pointer]
 
185
        return unpack(fstring, handle)[0]
 
186
 
 
187
    def decode_32bit_uint(self):
 
188
        ''' Decodes a 32 bit unsigned int from the buffer
 
189
        '''
 
190
        self._pointer += 4
 
191
        fstring = self._endian + 'I'
 
192
        handle = self._payload[self._pointer - 4:self._pointer]
 
193
        return unpack(fstring, handle)[0]
 
194
 
 
195
    def decode_64bit_uint(self):
 
196
        ''' Decodes a 64 bit unsigned int from the buffer
 
197
        '''
 
198
        self._pointer += 8
 
199
        fstring = self._endian + 'Q'
 
200
        handle = self._payload[self._pointer - 8:self._pointer]
 
201
        return unpack(fstring, handle)[0]
 
202
 
 
203
    def decode_8bit_int(self):
 
204
        ''' Decodes a 8 bit signed int from the buffer
 
205
        '''
 
206
        self._pointer += 1
 
207
        fstring = self._endian + 'b'
 
208
        handle = self._payload[self._pointer - 1:self._pointer]
 
209
        return unpack(fstring, handle)[0]
 
210
 
 
211
    def decode_16bit_int(self):
 
212
        ''' Decodes a 16 bit signed int from the buffer
 
213
        '''
 
214
        self._pointer += 2
 
215
        fstring = self._endian + 'h'
 
216
        handle = self._payload[self._pointer - 2:self._pointer]
 
217
        return unpack(fstring, handle)[0]
 
218
 
 
219
    def decode_32bit_int(self):
 
220
        ''' Decodes a 32 bit signed int from the buffer
 
221
        '''
 
222
        self._pointer += 4
 
223
        fstring = self._endian + 'i'
 
224
        handle = self._payload[self._pointer - 4:self._pointer]
 
225
        return unpack(fstring, handle)[0]
 
226
 
 
227
    def decode_64bit_int(self):
 
228
        ''' Decodes a 64 bit signed int from the buffer
 
229
        '''
 
230
        self._pointer += 8
 
231
        fstring = self._endian + 'q'
 
232
        handle = self._payload[self._pointer - 8:self._pointer]
 
233
        return unpack(fstring, handle)[0]
 
234
 
 
235
    def decode_32bit_float(self):
 
236
        ''' Decodes a 32 bit float from the buffer
 
237
        '''
 
238
        self._pointer += 4
 
239
        fstring = self._endian + 'f'
 
240
        handle = self._payload[self._pointer - 4:self._pointer]
 
241
        return unpack(fstring, handle)[0]
 
242
 
 
243
    def decode_64bit_float(self):
 
244
        ''' Decodes a 64 bit float(double) from the buffer
 
245
        '''
 
246
        self._pointer += 8
 
247
        fstring = self._endian + 'd'
 
248
        handle = self._payload[self._pointer - 8:self._pointer]
 
249
        return unpack(fstring, handle)[0]
 
250
 
 
251
    def decode_string(self, size=1):
 
252
        ''' Decodes a string from the buffer
 
253
 
 
254
        :param size: The size of the string to decode
 
255
        '''
 
256
        self._pointer += size
 
257
        return self._payload[self._pointer - size:self._pointer]
 
258
 
 
259
#---------------------------------------------------------------------------#
 
260
# Exported Identifiers
 
261
#---------------------------------------------------------------------------#
 
262
__all__ = ["PayloadBuilder", "PayloadDecoder"]