Skip to content

Commit 5f528ee

Browse files
committed
api output mode: deprecate get/set API output mode methods
These methods are using an enumeration with absolute values for the 'AO' setting, when it is compose bit per bit. Each bit of the 'AO' value enables a different option. Use those bits instead of full values with all the possible combinations. Signed-off-by: Tatiana Leon <tatiana.leon@digi.com>
1 parent 0344bee commit 5f528ee

7 files changed

Lines changed: 228 additions & 26 deletions

File tree

digi/xbee/devices.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,7 @@ def set_dio_change_detection(self, io_lines_set):
11791179
flags[0] = flags[0] | ((1 << i) - 8)
11801180
self.set_parameter(ATStringCommand.IC.command, flags)
11811181

1182+
@utils.deprecated("1.3", details="Use :meth:`get_api_output_mode_value`")
11821183
def get_api_output_mode(self):
11831184
"""
11841185
Returns the API output mode of the XBee device.
@@ -1201,6 +1202,37 @@ def get_api_output_mode(self):
12011202
"""
12021203
return APIOutputMode.get(self.get_parameter(ATStringCommand.AO.command)[0])
12031204

1205+
def get_api_output_mode_value(self):
1206+
"""
1207+
Returns the API output mode of the XBee.
1208+
1209+
The API output mode determines the format that the received data is
1210+
output through the serial interface of the XBee.
1211+
1212+
Returns:
1213+
Bytearray: the parameter value.
1214+
1215+
Raises:
1216+
TimeoutException: if the response is not received before the read timeout expires.
1217+
XBeeException: if the XBee device's serial port is closed.
1218+
InvalidOperatingModeException: if the XBee device's operating mode is not API or
1219+
ESCAPED API. This method only checks the cached value of the operating mode.
1220+
ATCommandException: if the response is not as expected.
1221+
OperationNotSupportedException: if it is not supported by the current protocol.
1222+
1223+
.. seealso::
1224+
| :class:`digi.xbee.models.mode.APIOutputModeBit`
1225+
"""
1226+
if self.get_protocol() not in (XBeeProtocol.ZIGBEE, XBeeProtocol.DIGI_MESH,
1227+
XBeeProtocol.DIGI_POINT, XBeeProtocol.XLR,
1228+
XBeeProtocol.XLR_DM):
1229+
raise OperationNotSupportedException(
1230+
message="Operation not supported for the current protocol (%s)"
1231+
% self.get_protocol().description)
1232+
1233+
return self.get_parameter(ATStringCommand.AO.command)
1234+
1235+
@utils.deprecated("1.3", details="Use :meth:`set_api_output_mode_value`")
12041236
def set_api_output_mode(self, api_output_mode):
12051237
"""
12061238
Sets the API output mode of the XBee device.
@@ -1221,6 +1253,39 @@ def set_api_output_mode(self, api_output_mode):
12211253
"""
12221254
self.set_parameter(ATStringCommand.AO.command, bytearray([api_output_mode.code]))
12231255

1256+
def set_api_output_mode_value(self, api_output_mode):
1257+
"""
1258+
Sets the API output mode of the XBee.
1259+
1260+
Args:
1261+
api_output_mode (Integer): new API output mode options. Calculate this value using
1262+
the method
1263+
:meth:`digi.xbee.models.mode.APIOutputModeBit.calculate_api_output_mode_value`
1264+
with a set of :class:`digi.xbee.models.mode.APIOutputModeBit`.
1265+
1266+
Raises:
1267+
TimeoutException: if the response is not received before the read timeout expires.
1268+
XBeeException: if the XBee device's serial port is closed.
1269+
InvalidOperatingModeException: if the XBee device's operating mode is not API or ESCAPED API. This
1270+
method only checks the cached value of the operating mode.
1271+
ATCommandException: if the response is not as expected.
1272+
OperationNotSupportedException: if it is not supported by the current protocol.
1273+
1274+
.. seealso::
1275+
| :class:`digi.xbee.models.mode.APIOutputModeBit`
1276+
"""
1277+
if api_output_mode is None:
1278+
raise ValueError("API output mode cannot be None")
1279+
1280+
if self.get_protocol() not in (XBeeProtocol.ZIGBEE, XBeeProtocol.DIGI_MESH,
1281+
XBeeProtocol.DIGI_POINT, XBeeProtocol.XLR,
1282+
XBeeProtocol.XLR_DM):
1283+
raise OperationNotSupportedException(
1284+
message="Operation not supported for the current protocol (%s)"
1285+
% self.get_protocol().description)
1286+
1287+
self.set_parameter(ATStringCommand.AO.command, bytearray([api_output_mode]))
1288+
12241289
def enable_bluetooth(self):
12251290
"""
12261291
Enables the Bluetooth interface of this XBee device.

digi/xbee/models/mode.py

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017, Digi International Inc.
1+
# Copyright 2017-2019, Digi International Inc.
22
#
33
# This Source Code Form is subject to the terms of the Mozilla Public
44
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -13,6 +13,8 @@
1313
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

1515
from enum import Enum, unique
16+
17+
from digi.xbee.models.protocol import XBeeProtocol
1618
from digi.xbee.util import utils
1719

1820

@@ -147,6 +149,98 @@ def get(cls, code):
147149
APIOutputMode.__doc__ += utils.doc_enum(APIOutputMode)
148150

149151

152+
@unique
153+
class APIOutputModeBit(Enum):
154+
"""
155+
Enumerates the different API output mode bit options. The API output mode
156+
establishes the way data will be output through the serial interface of an XBee.
157+
158+
| Inherited properties:
159+
| **name** (String): the name (id) of this APIOutputModeBit.
160+
| **value** (String): the value of this APIOutputModeBit.
161+
"""
162+
163+
EXPLICIT = (0x01, "Output in Native/Explicit API format")
164+
UNSUPPORTED_ZDO_PASSTHRU = (0x02, "Unsupported ZDO request pass-through")
165+
SUPPORTED_ZDO_PASSTHRU = (0x04, "Supported ZDO request pass-through")
166+
BINDING_PASSTHRU = (0x08, "Binding request pass-through")
167+
168+
def __init__(self, code, description):
169+
self.__code = code
170+
self.__description = description
171+
172+
def __get_code(self):
173+
"""
174+
Returns the code of the APIOutputModeBit element.
175+
176+
Returns:
177+
Integer: the code of the APIOutputModeBit element.
178+
"""
179+
return self.__code
180+
181+
def __get_description(self):
182+
"""
183+
Returns the description of the APIOutputModeBit element.
184+
185+
Returns:
186+
String: the description of the APIOutputModeBit element.
187+
"""
188+
return self.__description
189+
190+
@classmethod
191+
def get(cls, code):
192+
"""
193+
Returns the APIOutputModeBit for the given code.
194+
195+
Args:
196+
code (Integer): the code corresponding to the API output mode to get.
197+
198+
Returns:
199+
:class:`.OperatingMode`: the APIOutputModeBit with the given code, ``None``
200+
if there is not an APIOutputModeBit with that code.
201+
"""
202+
for item in cls:
203+
if code == item.code:
204+
return item
205+
206+
return None
207+
208+
@classmethod
209+
def calculate_api_output_mode_value(cls, protocol, options):
210+
"""
211+
Calculates the total value of a combination of several option bits for the
212+
given protocol.
213+
214+
Args:
215+
protocol (:class:`digi.xbee.models.protocol.XBeeProtocol`): The ``XBeeProtocol``
216+
to calculate the value of all the given API output options.
217+
options: Collection of option bits to get the final value.
218+
219+
Returns:
220+
Integer: The value to be configured in the module depending on the given
221+
collection of option bits and the protocol.
222+
"""
223+
if not options:
224+
return 0
225+
226+
if protocol == XBeeProtocol.ZIGBEE:
227+
return sum(op.code for op in options)
228+
elif protocol in (XBeeProtocol.DIGI_MESH, XBeeProtocol.DIGI_POINT,
229+
XBeeProtocol.XLR, XBeeProtocol.XLR_DM):
230+
return sum(op.code for op in options if lambda option: option != cls.EXPLICIT)
231+
232+
return 0
233+
234+
code = property(__get_code)
235+
"""Integer. The API output mode bit code."""
236+
237+
description = property(__get_description)
238+
"""String: The API output mode bit description."""
239+
240+
241+
APIOutputModeBit.__doc__ += utils.doc_enum(APIOutputModeBit)
242+
243+
150244
@unique
151245
class IPAddressingMode(Enum):
152246
"""

digi/xbee/models/zdo.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from digi.xbee.devices import XBeeDevice, RemoteXBeeDevice
1919
from digi.xbee.exception import XBeeException, OperationNotSupportedException
2020
from digi.xbee.models.address import XBee64BitAddress, XBee16BitAddress
21-
from digi.xbee.models.mode import APIOutputMode
21+
from digi.xbee.models.mode import APIOutputModeBit
2222
from digi.xbee.models.options import TransmitOptions
2323
from digi.xbee.models.protocol import Role, XBeeProtocol
2424
from digi.xbee.models.status import TransmitStatus
@@ -262,9 +262,16 @@ def __prepare_device(self):
262262
xb = self._xbee.get_local_xbee_device()
263263

264264
try:
265-
self.__saved_ao = xb.get_api_output_mode()
265+
self.__saved_ao = xb.get_api_output_mode_value()
266266

267-
xb.set_api_output_mode(APIOutputMode.EXPLICIT)
267+
# Do not configure AO if it is already
268+
if utils.is_bit_enabled(self.__saved_ao[0], 0):
269+
self.__saved_ao = None
270+
return
271+
272+
value = APIOutputModeBit.calculate_api_output_mode_value(self._xbee.get_protocol(),
273+
{APIOutputModeBit.EXPLICIT})
274+
xb.set_api_output_mode_value(value)
268275

269276
except XBeeException as e:
270277
raise XBeeException("Could not prepare XBee for ZDO: " + str(e))
@@ -283,7 +290,7 @@ def __restore_device(self):
283290
xb = self._xbee.get_local_xbee_device()
284291

285292
try:
286-
xb.set_api_output_mode(self.__saved_ao)
293+
xb.set_api_output_mode_value(self.__saved_ao[0])
287294
except XBeeException as e:
288295
self._error = "Could not restore XBee after ZDO: " + str(e)
289296

doc/user_doc/communicating_with_xbee_devices.rst

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -676,18 +676,42 @@ receive data in application layer, or explicit, data format.
676676

677677
To receive data in explicit format, you must first configure the data output
678678
mode of the receiver XBee device to explicit format using the
679-
``set_api_output_mode`` method.
680-
681-
+----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
682-
| Method | Description |
683-
+========================================+======================================================================================================================================================================================================================================================================================================================+
684-
| **get_api_output_mode()** | Returns the API output mode of the data received by the XBee device. |
685-
+----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
686-
| **set_api_output_mode(APIOutputMode)** | Specifies the API output mode of the data received by the XBee device. The mode can be one of the following: |
687-
| | * **APIOutputMode.NATIVE**: The data received by the device will be output as standard received data and it must be read using standard data-reading methods. It does not matter if the data sent by the remote device was sent in standard or explicit format. |
688-
| | * **APIOutputMode.EXPLICIT**: The data received by the device will be output as explicit received data and it must be read using explicit data-reading methods. It does not matter if the data sent by the remote device was sent in standard or explicit format. |
689-
| | * **APIOutputMode.EXPLICIT_ZDO_PASSTHRU**: The data received by the device will be output as explicit received data, like the **APIOutputMode.EXPLICIT** option. In addition, this mode also outputs as explicit data ZigBee Device Object (ZDO) packets received by the XBee module through the serial interface. |
690-
+----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
679+
``set_api_output_mode_value`` method.
680+
681+
+----------------------------------------+----------------------------------------------------------------------------------------------+
682+
| Method | Description |
683+
+========================================+==============================================================================================+
684+
| **get_api_output_mode_value()** | Returns the API output mode of the data received by the XBee device. |
685+
+----------------------------------------+----------------------------------------------------------------------------------------------+
686+
| **set_api_output_mode_value(Integer)** | Specifies the API output mode of the data received by the XBee device. Calculate the mode |
687+
| | with the method `calculate_api_output_mode_value` with a set of `APIOutputModeBit`. |
688+
+----------------------------------------+----------------------------------------------------------------------------------------------+
689+
690+
**Set API output mode**
691+
692+
.. code:: python
693+
694+
[...]
695+
696+
# Instantiate a ZigBee device object.
697+
device = ZigBeeDevice("COM1", 9600)
698+
device.open()
699+
700+
# Set explicit output mode
701+
mode = APIOutputModeBit.calculate_api_output_mode_value(device.get_protocol(),
702+
{APIOutputModeBit.EXPLICIT})
703+
device.set_api_output_mode_value(mode)
704+
705+
# Set native output mode
706+
mode = 0
707+
device.set_api_output_mode_value(mode)
708+
709+
# Set explicit plus unsupported ZDO request pass-through
710+
mode = APIOutputModeBit.calculate_api_output_mode_value(device.get_protocol(),
711+
{APIOutputModeBit.EXPLICIT, APIOutputModeBit.UNSUPPORTED_ZDO_PASSTHRU})
712+
device.set_api_output_mode_value(mode)
713+
714+
[...]
691715
692716
Once you have configured the device to receive data in explicit format, you can
693717
read it using one of the following mechanisms provided by the XBee device

examples/communication/explicit/ReceiveExplicitDataPollingSample/ReceiveExplicitDataPollingSample.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

1515
from digi.xbee.devices import ZigBeeDevice
16-
from digi.xbee.models.mode import APIOutputMode
16+
from digi.xbee.models.mode import APIOutputModeBit
1717
from digi.xbee.util import utils
1818

1919
# TODO: Replace with the serial port where your local module is connected to.
@@ -32,7 +32,9 @@ def main():
3232
try:
3333
device.open()
3434

35-
device.set_api_output_mode(APIOutputMode.EXPLICIT)
35+
device.set_api_output_mode_value(
36+
APIOutputModeBit.calculate_api_output_mode_value(
37+
device.get_protocol(), {APIOutputModeBit.EXPLICIT}))
3638

3739
device.flush_queues()
3840

examples/communication/explicit/ReceiveExplicitDataSample/ReceiveExplicitDataSample.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

1515
from digi.xbee.devices import ZigBeeDevice
16-
from digi.xbee.models.mode import APIOutputMode
16+
from digi.xbee.models.mode import APIOutputModeBit
1717
from digi.xbee.util import utils
1818

1919
# TODO: Replace with the serial port where your local module is connected to.
@@ -32,7 +32,9 @@ def main():
3232
try:
3333
device.open()
3434

35-
device.set_api_output_mode(APIOutputMode.EXPLICIT)
35+
device.set_api_output_mode_value(
36+
APIOutputModeBit.calculate_api_output_mode_value(
37+
device.get_protocol(), {APIOutputModeBit.EXPLICIT}))
3638

3739
def explicit_data_callback(explicit_xbee_message):
3840
print("From %s >> %s"

functional_tests/configuration/get_set_api_output_mode.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,21 @@
1313
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

1515
from digi.xbee.devices import XBeeDevice
16-
from digi.xbee.models.mode import APIOutputMode
16+
from digi.xbee.models.mode import APIOutputModeBit
17+
from digi.xbee.models.protocol import XBeeProtocol
1718

1819
# TODO: Replace with the serial port where your local module is connected to.
1920
PORT = "COM1"
2021
# TODO: Replace with the baud rate of your local module.
2122
BAUD_RATE = 9600
2223

24+
NATIVE = 0
25+
EXPLICIT = APIOutputModeBit.calculate_api_output_mode_value(XBeeProtocol.ZIGBEE,
26+
{APIOutputModeBit.EXPLICIT})
27+
EXPLICIT_ZDO_PASSTHRU = APIOutputModeBit.calculate_api_output_mode_value(
28+
XBeeProtocol.ZIGBEE,
29+
{APIOutputModeBit.EXPLICIT, APIOutputModeBit.UNSUPPORTED_ZDO_PASSTHRU})
30+
2331

2432
def main():
2533

@@ -32,10 +40,10 @@ def main():
3240
try:
3341
device.open()
3442

35-
for api_output_mode in [APIOutputMode.EXPLICIT, APIOutputMode.EXPLICIT_ZDO_PASSTHRU, APIOutputMode.NATIVE]:
36-
device.set_api_output_mode(api_output_mode)
37-
ao_mode = device.get_api_output_mode()
38-
assert (ao_mode == api_output_mode)
43+
for api_output_mode in [EXPLICIT, EXPLICIT_ZDO_PASSTHRU, NATIVE]:
44+
device.set_api_output_mode_value(api_output_mode)
45+
ao_mode = device.get_api_output_mode_value()
46+
assert (ao_mode[0] == api_output_mode)
3947

4048
print("Test finished successfully")
4149

0 commit comments

Comments
 (0)