~ubuntu-branches/ubuntu/quantal/pymodbus/quantal

« back to all changes in this revision

Viewing changes to pymodbus/bit_read_message.py

  • Committer: Bazaar Package Importer
  • Author(s): W. Martin Borgert
  • Date: 2011-08-17 09:34:29 UTC
  • Revision ID: james.westby@ubuntu.com-20110817093429-cvgff034imbs899m
Tags: upstream-0.9.0
ImportĀ upstreamĀ versionĀ 0.9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Bit Reading Request/Response messages
 
3
--------------------------------------
 
4
 
 
5
"""
 
6
import struct
 
7
from pymodbus.pdu import ModbusRequest
 
8
from pymodbus.pdu import ModbusResponse
 
9
from pymodbus.pdu import ModbusExceptions as merror
 
10
from pymodbus.utilities import pack_bitstring, unpack_bitstring
 
11
 
 
12
class ReadBitsRequestBase(ModbusRequest):
 
13
    ''' Base class for Messages Requesting bit values '''
 
14
 
 
15
    _rtu_frame_size = 8
 
16
 
 
17
    def __init__(self, address, count, **kwargs):
 
18
        ''' Initializes the read request data
 
19
 
 
20
        :param address: The start address to read from
 
21
        :param count: The number of bits after 'address' to read
 
22
        '''
 
23
        ModbusRequest.__init__(self, **kwargs)
 
24
        self.address = address
 
25
        self.count   = count
 
26
 
 
27
    def encode(self):
 
28
        ''' Encodes a request pdu
 
29
 
 
30
        :returns: The encoded pdu
 
31
        '''
 
32
        return struct.pack('>HH', self.address, self.count)
 
33
 
 
34
    def decode(self, data):
 
35
        ''' Decodes a request pdu
 
36
 
 
37
        :param data: The packet data to decode
 
38
        '''
 
39
        self.address, self.count = struct.unpack('>HH', data)
 
40
 
 
41
    def __str__(self):
 
42
        ''' Returns a string representation of the instance
 
43
 
 
44
        :returns: A string representation of the instance
 
45
        '''
 
46
        return "ReadBitRequest(%d,%d)" % (self.address, self.count)
 
47
 
 
48
class ReadBitsResponseBase(ModbusResponse):
 
49
    ''' Base class for Messages responding to bit-reading values '''
 
50
 
 
51
    _rtu_byte_count_pos = 2
 
52
 
 
53
    def __init__(self, values, **kwargs):
 
54
        ''' Initializes a new instance
 
55
 
 
56
        :param values: The requested values to be returned
 
57
        '''
 
58
        ModbusResponse.__init__(self, **kwargs)
 
59
        self.bits = values or []
 
60
 
 
61
    def encode(self):
 
62
        ''' Encodes response pdu
 
63
 
 
64
        :returns: The encoded packet message
 
65
        '''
 
66
        result = pack_bitstring(self.bits)
 
67
        packet = struct.pack(">B", len(result)) + result
 
68
        return packet
 
69
 
 
70
    def decode(self, data):
 
71
        ''' Decodes response pdu
 
72
 
 
73
        :param data: The packet data to decode
 
74
        '''
 
75
        self.byte_count = struct.unpack(">B", data[0])[0]
 
76
        self.bits = unpack_bitstring(data[1:])
 
77
 
 
78
    def setBit(self, address, value=1):
 
79
        ''' Helper function to set the specified bit
 
80
 
 
81
        :param address: The bit to set
 
82
        :param value: The value to set the bit to
 
83
        '''
 
84
        self.bits[address] = (value != 0)
 
85
 
 
86
    def resetBit(self, address):
 
87
        ''' Helper function to set the specified bit to 0
 
88
 
 
89
        :param address: The bit to reset
 
90
        '''
 
91
        self.setBit(address, 0)
 
92
 
 
93
    def getBit(self, address):
 
94
        ''' Helper function to get the specified bit's value
 
95
 
 
96
        :param address: The bit to query
 
97
        :returns: The value of the requested bit
 
98
        '''
 
99
        return self.bits[address]
 
100
 
 
101
    def __str__(self):
 
102
        ''' Returns a string representation of the instance
 
103
 
 
104
        :returns: A string representation of the instance
 
105
        '''
 
106
        return "ReadBitResponse(%d)" % len(self.bits)
 
107
 
 
108
class ReadCoilsRequest(ReadBitsRequestBase):
 
109
    '''
 
110
    This function code is used to read from 1 to 2000(0x7d0) contiguous status
 
111
    of coils in a remote device. The Request PDU specifies the starting
 
112
    address, ie the address of the first coil specified, and the number of
 
113
    coils. In the PDU Coils are addressed starting at zero. Therefore coils
 
114
    numbered 1-16 are addressed as 0-15.
 
115
    '''
 
116
    function_code = 1
 
117
 
 
118
    def __init__(self, address=None, count=None, **kwargs):
 
119
        ''' Initializes a new instance
 
120
 
 
121
        :param address: The address to start reading from
 
122
        :param count: The number of bits to read
 
123
        '''
 
124
        ReadBitsRequestBase.__init__(self, address, count, **kwargs)
 
125
 
 
126
    def execute(self, context):
 
127
        ''' Run a read coils request against a datastore
 
128
 
 
129
        Before running the request, we make sure that the request is in
 
130
        the max valid range (0x001-0x7d0). Next we make sure that the
 
131
        request is valid against the current datastore.
 
132
 
 
133
        :param context: The datastore to request from
 
134
        :returns: The initializes response message, exception message otherwise
 
135
        '''
 
136
        if not (1 <= self.count <= 0x7d0):
 
137
            return self.doException(merror.IllegalValue)
 
138
        if not context.validate(self.function_code, self.address, self.count):
 
139
            return self.doException(merror.IllegalAddress)
 
140
        values = context.getValues(self.function_code, self.address, self.count)
 
141
        return ReadCoilsResponse(values)
 
142
 
 
143
class ReadCoilsResponse(ReadBitsResponseBase):
 
144
    '''
 
145
    The coils in the response message are packed as one coil per bit of
 
146
    the data field. Status is indicated as 1= ON and 0= OFF. The LSB of the
 
147
    first data byte contains the output addressed in the query. The other
 
148
    coils follow toward the high order end of this byte, and from low order
 
149
    to high order in subsequent bytes.
 
150
 
 
151
    If the returned output quantity is not a multiple of eight, the
 
152
    remaining bits in the final data byte will be padded with zeros
 
153
    (toward the high order end of the byte). The Byte Count field specifies
 
154
    the quantity of complete bytes of data.
 
155
    '''
 
156
    function_code = 1
 
157
 
 
158
    def __init__(self, values=None, **kwargs):
 
159
        ''' Intializes a new instance
 
160
 
 
161
        :param values: The request values to respond with
 
162
        '''
 
163
        ReadBitsResponseBase.__init__(self, values, **kwargs)
 
164
 
 
165
class ReadDiscreteInputsRequest(ReadBitsRequestBase):
 
166
    '''
 
167
    This function code is used to read from 1 to 2000(0x7d0) contiguous status
 
168
    of discrete inputs in a remote device. The Request PDU specifies the
 
169
    starting address, ie the address of the first input specified, and the
 
170
    number of inputs. In the PDU Discrete Inputs are addressed starting at
 
171
    zero. Therefore Discrete inputs numbered 1-16 are addressed as 0-15.
 
172
    '''
 
173
    function_code = 2
 
174
 
 
175
    def __init__(self, address=None, count=None, **kwargs):
 
176
        ''' Intializes a new instance
 
177
 
 
178
        :param address: The address to start reading from
 
179
        :param count: The number of bits to read
 
180
        '''
 
181
        ReadBitsRequestBase.__init__(self, address, count, **kwargs)
 
182
 
 
183
    def execute(self, context):
 
184
        ''' Run a read discrete input request against a datastore
 
185
 
 
186
        Before running the request, we make sure that the request is in
 
187
        the max valid range (0x001-0x7d0). Next we make sure that the
 
188
        request is valid against the current datastore.
 
189
 
 
190
        :param context: The datastore to request from
 
191
        :returns: The initializes response message, exception message otherwise
 
192
        '''
 
193
        if not (1 <= self.count <= 0x7d0):
 
194
            return self.doException(merror.IllegalValue)
 
195
        if not context.validate(self.function_code, self.address, self.count):
 
196
            return self.doException(merror.IllegalAddress)
 
197
        values = context.getValues(self.function_code, self.address, self.count)
 
198
        return ReadDiscreteInputsResponse(values)
 
199
 
 
200
class ReadDiscreteInputsResponse(ReadBitsResponseBase):
 
201
    '''
 
202
    The discrete inputs in the response message are packed as one input per
 
203
    bit of the data field. Status is indicated as 1= ON; 0= OFF. The LSB of
 
204
    the first data byte contains the input addressed in the query. The other
 
205
    inputs follow toward the high order end of this byte, and from low order
 
206
    to high order in subsequent bytes.
 
207
 
 
208
    If the returned input quantity is not a multiple of eight, the
 
209
    remaining bits in the final data byte will be padded with zeros
 
210
    (toward the high order end of the byte). The Byte Count field specifies
 
211
    the quantity of complete bytes of data.
 
212
    '''
 
213
    function_code = 2
 
214
 
 
215
    def __init__(self, values=None, **kwargs):
 
216
        ''' Intializes a new instance
 
217
 
 
218
        :param values: The request values to respond with
 
219
        '''
 
220
        ReadBitsResponseBase.__init__(self, values, **kwargs)
 
221
 
 
222
#---------------------------------------------------------------------------# 
 
223
# Exported symbols
 
224
#---------------------------------------------------------------------------# 
 
225
__all__ = [
 
226
    "ReadCoilsRequest", "ReadCoilsResponse",
 
227
    "ReadDiscreteInputsRequest", "ReadDiscreteInputsResponse",
 
228
]