Skip to content

Commit 17e21a3

Browse files
hgonzaleDigidiescalo
authored andcommitted
operating_mode: fix packet reader function to correctly escape the bytes
- Transformed _unescape_data() method to public. - Removed all unnecesary calls to unescape_data() from create_packet methods. - Replaced __read_next_packet() method by a search in the xbee packet queue. Signed-off-by: Héctor González <[email protected]> Signed-off-by: Diego Escalona <[email protected]>
1 parent e102693 commit 17e21a3

File tree

9 files changed

+125
-128
lines changed

9 files changed

+125
-128
lines changed

digi/xbee/devices.py

+13-38
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017, Digi International Inc.
1+
# Copyright 2017, 2018, 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
@@ -24,7 +24,6 @@
2424

2525
from digi.xbee.packets.cellular import TXSMSPacket
2626
from digi.xbee.models.accesspoint import AccessPoint, WiFiEncryptionType
27-
from digi.xbee.models.atcomm import SpecialByte
2827
from digi.xbee.models.hw import HardwareVersion
2928
from digi.xbee.models.mode import OperatingMode, APIOutputMode, IPAddressingMode
3029
from digi.xbee.models.address import XBee64BitAddress, XBee16BitAddress, XBeeIMEIAddress
@@ -34,7 +33,6 @@
3433
from digi.xbee.models.status import ATCommandStatus, TransmitStatus, PowerLevel, \
3534
ModemStatus, CellularAssociationIndicationStatus, WiFiAssociationIndicationStatus, AssociationIndicationStatus,\
3635
NetworkDiscoveryStatus
37-
from digi.xbee.packets import factory
3836
from digi.xbee.packets.aft import ApiFrameType
3937
from digi.xbee.packets.common import ATCommPacket, TransmitPacket, RemoteATCommandPacket, ExplicitAddressingPacket
4038
from digi.xbee.packets.network import TXIPv4Packet
@@ -108,6 +106,8 @@ def __init__(self, local_xbee_device=None, serial_port=None, sync_ops_timeout=_D
108106
self._protocol = None
109107
self._node_id = None
110108

109+
self._packet_listener = None
110+
111111
self._log.addHandler(logging.NullHandler())
112112

113113
self.__generic_lock = threading.Lock()
@@ -1055,13 +1055,14 @@ def _get_packet_by_id(self, frame_id):
10551055
ValueError: if ``frame_id`` is less than 0 or greater than 255.
10561056
TimeoutException: if there was not any XBee packet matching the provided frame ID that could be read.
10571057
"""
1058-
operating_mode = OperatingMode.API_MODE if self.is_remote() else self._operating_mode
10591058
if not (0 <= frame_id <= 255):
10601059
raise ValueError("Frame ID must be between 0 and 255.")
1061-
packet_read = factory.build_frame(self.__read_next_packet(), operating_mode)
1062-
while not packet_read.needs_id() or packet_read.frame_id != frame_id:
1063-
packet_read = factory.build_frame(self.__read_next_packet(), operating_mode)
1064-
return packet_read
1060+
1061+
queue = self._packet_listener.get_queue()
1062+
1063+
packet = queue.get_by_id(frame_id, XBeeDevice.TIMEOUT_READ_PACKET)
1064+
1065+
return packet
10651066

10661067
@staticmethod
10671068
def __is_api_packet(xbee_packet):
@@ -1079,31 +1080,6 @@ def __is_api_packet(xbee_packet):
10791080
return False
10801081
return True
10811082

1082-
def __read_next_packet(self):
1083-
"""
1084-
Reads the next XBee packet. Starts to read when finds the start delimiter.
1085-
The last byte read is the checksum.
1086-
1087-
If there is something in the COM port buffer before the
1088-
start delimiter, this method discards it.
1089-
1090-
Returns:
1091-
:class:XBeePacket: the next XBee packet read.
1092-
1093-
Raises:
1094-
TimeoutException: if it could not read any new XBee packet.
1095-
"""
1096-
xbee_packet = bytearray(1)
1097-
xbee_packet[0] = self._serial_port.read_byte()
1098-
while xbee_packet[0] != SpecialByte.HEADER_BYTE.code:
1099-
xbee_packet[0] = self._serial_port.read_byte()
1100-
packet_length = self._serial_port.read_bytes(2)
1101-
xbee_packet += packet_length
1102-
length = utils.length_to_int(packet_length)
1103-
xbee_packet += self._serial_port.read_bytes(length)
1104-
xbee_packet.append(self._serial_port.read_byte())
1105-
return xbee_packet
1106-
11071083
def __get_log(self):
11081084
"""
11091085
Returns the XBee device log.
@@ -1147,7 +1123,7 @@ class XBeeDevice(AbstractXBeeDevice):
11471123
Timeout to wait when resetting the module.
11481124
"""
11491125

1150-
_TIMEOUT_READ_PACKET = 3 # seconds
1126+
TIMEOUT_READ_PACKET = 3 # seconds
11511127
"""
11521128
Timeout to read packets.
11531129
"""
@@ -1203,7 +1179,6 @@ def __init__(self, port, baud_rate, data_bits=serial.EIGHTBITS, stop_bits=serial
12031179

12041180
self._network = XBeeNetwork(self)
12051181

1206-
self._packet_listener = None
12071182
self.__packet_queue = None
12081183
self.__data_queue = None
12091184
self.__explicit_queue = None
@@ -2463,7 +2438,7 @@ def send_packet(self, packet, sync=False):
24632438
24642439
This method can be synchronous or asynchronous.
24652440
2466-
If is synchronous, this method will discards all response
2441+
If is synchronous, this method will discard all response
24672442
packets until it finds the one that has the appropriate frame ID,
24682443
that is, the sent packet's frame ID.
24692444
@@ -3481,7 +3456,7 @@ def send_ip_data_broadcast(self, dest_port, data):
34813456
return self.send_ip_data(IPv4Address(self.BROADCAST_IP), dest_port, IPProtocol.UDP, data)
34823457

34833458
@AbstractXBeeDevice._before_send_method
3484-
def read_ip_data(self, timeout=XBeeDevice._TIMEOUT_READ_PACKET):
3459+
def read_ip_data(self, timeout=XBeeDevice.TIMEOUT_READ_PACKET):
34853460
"""
34863461
Reads new IP data received by this XBee device during the
34873462
provided timeout.
@@ -3512,7 +3487,7 @@ def read_ip_data(self, timeout=XBeeDevice._TIMEOUT_READ_PACKET):
35123487
return self.__read_ip_data_packet(timeout)
35133488

35143489
@AbstractXBeeDevice._before_send_method
3515-
def read_ip_data_from(self, ip_addr, timeout=XBeeDevice._TIMEOUT_READ_PACKET):
3490+
def read_ip_data_from(self, ip_addr, timeout=XBeeDevice.TIMEOUT_READ_PACKET):
35163491
"""
35173492
Reads new IP data received from the given IP address during the
35183493
provided timeout.

digi/xbee/packets/base.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017, Digi International Inc.
1+
# Copyright 2017, 2018, 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
@@ -229,7 +229,7 @@ def _escape_data(data):
229229
return esc_data
230230

231231
@staticmethod
232-
def _unescape_data(data):
232+
def unescape_data(data):
233233
"""
234234
Un-escapes the provided bytearray data.
235235
@@ -482,15 +482,13 @@ def create_packet(raw, operating_mode=OperatingMode.API_MODE):
482482
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
483483
raise InvalidOperatingModeException(operating_mode + " is not supported.")
484484

485-
unesc_raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
485+
XBeeAPIPacket._check_api_packet(raw, min_length=GenericXBeePacket.__MIN_PACKET_LENGTH)
486486

487-
XBeeAPIPacket._check_api_packet(unesc_raw, min_length=GenericXBeePacket.__MIN_PACKET_LENGTH)
488-
489-
if unesc_raw[3] != ApiFrameType.GENERIC.code:
487+
if raw[3] != ApiFrameType.GENERIC.code:
490488
raise InvalidPacketException("Wrong frame type, expected: " + ApiFrameType.GENERIC.description +
491489
". Value: " + ApiFrameType.GENERIC.code)
492490

493-
return GenericXBeePacket(unesc_raw[4:-1])
491+
return GenericXBeePacket(raw[4:-1])
494492

495493
def _get_api_packet_spec_data(self):
496494
"""

digi/xbee/packets/cellular.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017, Digi International Inc.
1+
# Copyright 2017, 2018, 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
@@ -83,13 +83,12 @@ def create_packet(raw, operating_mode):
8383
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
8484
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
8585

86-
_raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
87-
88-
XBeeAPIPacket._check_api_packet(_raw, min_length=RXSMSPacket.__MIN_PACKET_LENGTH)
89-
if _raw[3] != ApiFrameType.RX_SMS.code:
86+
XBeeAPIPacket._check_api_packet(raw, min_length=RXSMSPacket.__MIN_PACKET_LENGTH)
87+
88+
if raw[3] != ApiFrameType.RX_SMS.code:
9089
raise InvalidPacketException("This packet is not an RXSMSPacket")
9190

92-
return RXSMSPacket(_raw[4:23].decode("utf8").replace("\0", ""), _raw[24:-1].decode("utf8"))
91+
return RXSMSPacket(raw[4:23].decode("utf8").replace("\0", ""), raw[24:-1].decode("utf8"))
9392

9493
def needs_id(self):
9594
"""
@@ -252,13 +251,12 @@ def create_packet(raw, operating_mode):
252251
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
253252
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
254253

255-
_raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
256-
257254
XBeeAPIPacket._check_api_packet(raw, min_length=TXSMSPacket.__MIN_PACKET_LENGTH)
258-
if _raw[3] != ApiFrameType.TX_SMS.code:
255+
256+
if raw[3] != ApiFrameType.TX_SMS.code:
259257
raise InvalidPacketException("This packet is not a TXSMSPacket")
260258

261-
return TXSMSPacket(_raw[4], _raw[6:25].decode("utf8").replace("\0", ""), _raw[26:-1].decode("utf8"))
259+
return TXSMSPacket(raw[4], raw[6:25].decode("utf8").replace("\0", ""), raw[26:-1].decode("utf8"))
262260

263261
def needs_id(self):
264262
"""

digi/xbee/packets/common.py

+1-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017, Digi International Inc.
1+
# Copyright 2017, 2018, 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
@@ -91,7 +91,6 @@ def create_packet(raw, operating_mode):
9191
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
9292
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
9393

94-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
9594
XBeeAPIPacket._check_api_packet(raw, min_length=ATCommPacket.__MIN_PACKET_LENGTH)
9695

9796
if raw[3] != ApiFrameType.AT_COMMAND.code:
@@ -253,8 +252,6 @@ def create_packet(raw, operating_mode):
253252
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
254253
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
255254

256-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
257-
258255
XBeeAPIPacket._check_api_packet(raw, min_length=ATCommResponsePacket.__MIN_PACKET_LENGTH)
259256

260257
if raw[3] != ApiFrameType.AT_COMMAND_RESPONSE.code:
@@ -441,8 +438,6 @@ def create_packet(raw, operating_mode):
441438
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
442439
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
443440

444-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
445-
446441
XBeeAPIPacket._check_api_packet(raw, min_length=ReceivePacket.__MIN_PACKET_LENGTH)
447442

448443
if raw[3] != ApiFrameType.RECEIVE_PACKET.code:
@@ -678,8 +673,6 @@ def create_packet(raw, operating_mode):
678673
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
679674
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
680675

681-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
682-
683676
XBeeAPIPacket._check_api_packet(raw, min_length=RemoteATCommandPacket.__MIN_PACKET_LENGTH)
684677

685678
if raw[3] != ApiFrameType.REMOTE_AT_COMMAND_REQUEST.code:
@@ -937,8 +930,6 @@ def create_packet(raw, operating_mode):
937930
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
938931
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
939932

940-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
941-
942933
XBeeAPIPacket._check_api_packet(raw, min_length=RemoteATCommandResponsePacket.__MIN_PACKET_LENGTH)
943934

944935
if raw[3] != ApiFrameType.REMOTE_AT_COMMAND_RESPONSE.code:
@@ -1211,8 +1202,6 @@ def create_packet(raw, operating_mode):
12111202
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
12121203
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
12131204

1214-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
1215-
12161205
XBeeAPIPacket._check_api_packet(raw, min_length=TransmitPacket.__MIN_PACKET_LENGTH)
12171206

12181207
if raw[3] != ApiFrameType.TRANSMIT_REQUEST.code:
@@ -1463,8 +1452,6 @@ def create_packet(raw, operating_mode):
14631452
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
14641453
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
14651454

1466-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
1467-
14681455
XBeeAPIPacket._check_api_packet(raw, min_length=TransmitStatusPacket.__MIN_PACKET_LENGTH)
14691456

14701457
if raw[3] != ApiFrameType.TRANSMIT_STATUS.code:
@@ -1663,8 +1650,6 @@ def create_packet(raw, operating_mode):
16631650
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
16641651
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
16651652

1666-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
1667-
16681653
XBeeAPIPacket._check_api_packet(raw, min_length=ModemStatusPacket.__MIN_PACKET_LENGTH)
16691654

16701655
if raw[3] != ApiFrameType.MODEM_STATUS.code:
@@ -1799,8 +1784,6 @@ def create_packet(raw, operating_mode):
17991784
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
18001785
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
18011786

1802-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
1803-
18041787
XBeeAPIPacket._check_api_packet(raw, min_length=IODataSampleRxIndicatorPacket.__MIN_PACKET_LENGTH)
18051788

18061789
if raw[3] != ApiFrameType.IO_DATA_SAMPLE_RX_INDICATOR.code:
@@ -2150,7 +2133,6 @@ def create_packet(raw, operating_mode):
21502133
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
21512134
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
21522135

2153-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
21542136
XBeeAPIPacket._check_api_packet(raw, min_length=ExplicitAddressingPacket.__MIN_PACKET_LENGTH)
21552137

21562138
if raw[3] != ApiFrameType.EXPLICIT_ADDRESSING.code:
@@ -2511,7 +2493,6 @@ def create_packet(raw, operating_mode):
25112493
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
25122494
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
25132495

2514-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
25152496
XBeeAPIPacket._check_api_packet(raw, min_length=ExplicitRXIndicatorPacket.__MIN_PACKET_LENGTH)
25162497

25172498
if raw[3] != ApiFrameType.EXPLICIT_RX_INDICATOR.code:

digi/xbee/packets/devicecloud.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2017, Digi International Inc.
1+
# Copyright 2017, 2018, 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
@@ -90,7 +90,6 @@ def create_packet(raw, operating_mode):
9090
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
9191
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
9292

93-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
9493
XBeeAPIPacket._check_api_packet(raw, min_length=DeviceRequestPacket.__MIN_PACKET_LENGTH)
9594

9695
if raw[3] != ApiFrameType.DEVICE_REQUEST.code:
@@ -312,7 +311,6 @@ def create_packet(raw, operating_mode):
312311
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
313312
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
314313

315-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
316314
XBeeAPIPacket._check_api_packet(raw, min_length=DeviceResponsePacket.__MIN_PACKET_LENGTH)
317315

318316
if raw[3] != ApiFrameType.DEVICE_RESPONSE.code:
@@ -469,7 +467,6 @@ def create_packet(raw, operating_mode):
469467
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
470468
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
471469

472-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
473470
XBeeAPIPacket._check_api_packet(raw, min_length=DeviceResponseStatusPacket.__MIN_PACKET_LENGTH)
474471

475472
if raw[3] != ApiFrameType.DEVICE_RESPONSE_STATUS.code:
@@ -585,7 +582,6 @@ def create_packet(raw, operating_mode):
585582
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
586583
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
587584

588-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
589585
XBeeAPIPacket._check_api_packet(raw, min_length=FrameErrorPacket.__MIN_PACKET_LENGTH)
590586

591587
if raw[3] != ApiFrameType.FRAME_ERROR.code:
@@ -719,7 +715,6 @@ def create_packet(raw, operating_mode):
719715
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
720716
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
721717

722-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
723718
XBeeAPIPacket._check_api_packet(raw, min_length=SendDataRequestPacket.__MIN_PACKET_LENGTH)
724719

725720
if raw[3] != ApiFrameType.SEND_DATA_REQUEST.code:
@@ -939,7 +934,6 @@ def create_packet(raw, operating_mode):
939934
if operating_mode != OperatingMode.ESCAPED_API_MODE and operating_mode != OperatingMode.API_MODE:
940935
raise InvalidOperatingModeException(operating_mode.name + " is not supported.")
941936

942-
raw = XBeeAPIPacket._unescape_data(raw) if operating_mode == OperatingMode.ESCAPED_API_MODE else raw
943937
XBeeAPIPacket._check_api_packet(raw, min_length=SendDataResponsePacket.__MIN_PACKET_LENGTH)
944938

945939
if raw[3] != ApiFrameType.SEND_DATA_RESPONSE.code:

0 commit comments

Comments
 (0)