def test_read_io_data(self): """ XBee class should properly read and parse incoming IO data """ # Build IO data # One sample, ADC 0 enabled # DIO 1,3,5,7 enabled header = b'\x01\x02\xAA' # First 7 bits ignored, DIO8 low, DIO 0-7 alternating # ADC0 value of 255 sample = b'\x00\xAA\x00\xFF' data = header + sample # Wrap data in frame # RX frame data rx_io_resp = b'\x83\x00\x01\x28\x00' device = Serial() device.set_read_data(b'\x7E\x00\x0C' + rx_io_resp + data + b'\xfd') xbee = XBee(device, io_loop=self._patch_io) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = {'id': 'rx_io_data', 'source_addr': b'\x00\x01', 'rssi': b'\x28', 'options': b'\x00', 'samples': [{'dio-1': True, 'dio-3': True, 'dio-5': True, 'dio-7': True, 'adc-0': 255}] } self.assertEqual(info, expected_info)
def test_is_remote_response_parsed_as_io(self): """ I/O data in a Remote AT response for an IS command is parsed. """ # Build IO data # One sample, ADC 0 enabled # DIO 1,3,5,7 enabled header = b'\x01\x02\xAA' # First 7 bits ignored, DIO8 low, DIO 0-7 alternating # ADC0 value of 255 sample = b'\x00\xAA\x00\xFF' data = header + sample device = Serial() device.set_read_data(APIFrame( data=b'\x97D\x00\x13\xa2\x00@oG\xe4v\x1aIS\x00' + data).output() ) xbee = XBee(device, io_loop=self._patch_io) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = {'id': 'remote_at_response', 'frame_id': b'D', 'source_addr_long': b'\x00\x13\xa2\x00@oG\xe4', 'source_addr': b'v\x1a', 'command': b'IS', 'status': b'\x00', 'parameter': [{'dio-1': True, 'dio-3': True, 'dio-5': True, 'dio-7': True, 'adc-0': 255}]} self.assertEqual(info, expected_info)
def test_read_at(self): """ read and parse a parameterless AT command """ device = Serial() device.set_read_data(b'\x7E\x00\x05\x88DMY\x01\x8c') xbee = XBee(device, io_loop=self._patch_io) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = {'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01'} self.assertEqual(info, expected_info)
def test_read_rx_with_close_brace(self): """ An rx data frame including a close brace must be read properly. """ device = Serial() device.set_read_data(APIFrame(b'\x81\x01\x02\x55\x00{test=1}').output()) xbee = XBee(device, io_loop=self._patch_io) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = {'id': 'rx', 'source_addr': b'\x01\x02', 'rssi': b'\x55', 'options': b'\x00', 'rf_data': b'{test=1}'} self.assertEqual(info, expected_info)
def test_empty_frame_ignored(self): """ If an empty frame is received from a device, it must be ignored. """ device = Serial() device.set_read_data(b'\x7E\x00\x00\xFF\x7E\x00\x05\x88DMY\x01\x8c') xbee = XBee(device, io_loop=self._patch_io) xbee._process_input(None, None) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = {'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01'} self.assertEqual(info, expected_info)
def test_read_at_params_in_escaped_mode(self): """ read and parse an AT command with a parameter in escaped API mode """ device = Serial() device.set_read_data(b'~\x00\t\x88DMY\x01}^}]}1}3m') xbee = XBee(device, escaped=True, io_loop=self._patch_io) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = {'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01', 'parameter': b'\x7E\x7D\x11\x13'} self.assertEqual(info, expected_info)
def test_read_at(self): """ read and parse a parameterless AT command """ device = Serial() device.set_read_data(b'\x7E\x00\x05\x88DMY\x01\x8c') xbee = XBee(device) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01' } self.assertEqual(info, expected_info)
def test_is_remote_response_parsed_as_io(self): """ I/O data in a Remote AT response for an IS command is parsed. """ # Build IO data # One sample, ADC 0 enabled # DIO 1,3,5,7 enabled header = b'\x01\x02\xAA' # First 7 bits ignored, DIO8 low, DIO 0-7 alternating # ADC0 value of 255 sample = b'\x00\xAA\x00\xFF' data = header + sample device = Serial() device.set_read_data( APIFrame(data=b'\x97D\x00\x13\xa2\x00@oG\xe4v\x1aIS\x00' + data).output()) xbee = XBee(device) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'remote_at_response', 'frame_id': b'D', 'source_addr_long': b'\x00\x13\xa2\x00@oG\xe4', 'source_addr': b'v\x1a', 'command': b'IS', 'status': b'\x00', 'parameter': [{ 'dio-1': True, 'dio-3': True, 'dio-5': True, 'dio-7': True, 'adc-0': 255 }] } self.assertEqual(info, expected_info)
def test_empty_frame_ignored(self): """ If an empty frame is received from a device, it must be ignored. """ device = Serial() device.set_read_data(b'\x7E\x00\x00\xFF\x7E\x00\x05\x88DMY\x01\x8c') xbee = XBee(device) xbee._process_input(None, None) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01' } self.assertEqual(info, expected_info)
def test_read_at_params_in_escaped_mode(self): """ read and parse an AT command with a parameter in escaped API mode """ device = Serial() device.set_read_data(b'~\x00\t\x88DMY\x01}^}]}1}3m') xbee = XBee(device, escaped=True) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01', 'parameter': b'\x7E\x7D\x11\x13' } self.assertEqual(info, expected_info)
def test_read_at_params(self): """ read and parse an AT command with a parameter """ device = Serial() device.set_read_data(b'\x7E\x00\x08\x88DMY\x01\x00\x00\x00\x8c') xbee = XBee(device, io_loop=self._patch_io) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'at_response', 'frame_id': b'D', 'command': b'MY', 'status': b'\x01', 'parameter': b'\x00\x00\x00' } self.assertEqual(info, expected_info)
def test_read_rx_with_close_brace_escaped(self): """ An escaped rx data frame including a close brace must be read properly. """ device = Serial() device.set_read_data( APIFrame(b'\x81\x01\x02\x55\x00{test=1}', escaped=True).output()) xbee = XBee(device, escaped=True) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'rx', 'source_addr': b'\x01\x02', 'rssi': b'\x55', 'options': b'\x00', 'rf_data': b'{test=1}' } self.assertEqual(info, expected_info)
def test_read_io_data(self): """ XBee class should properly read and parse incoming IO data """ # Build IO data # One sample, ADC 0 enabled # DIO 1,3,5,7 enabled header = b'\x01\x02\xAA' # First 7 bits ignored, DIO8 low, DIO 0-7 alternating # ADC0 value of 255 sample = b'\x00\xAA\x00\xFF' data = header + sample # Wrap data in frame # RX frame data rx_io_resp = b'\x83\x00\x01\x28\x00' device = Serial() device.set_read_data(b'\x7E\x00\x0C' + rx_io_resp + data + b'\xfd') xbee = XBee(device) xbee._process_input(None, None) info = yield xbee.wait_read_frame() expected_info = { 'id': 'rx_io_data', 'source_addr': b'\x00\x01', 'rssi': b'\x28', 'options': b'\x00', 'samples': [{ 'dio-1': True, 'dio-3': True, 'dio-5': True, 'dio-7': True, 'adc-0': 255 }] } self.assertEqual(info, expected_info)
def test_read_empty_string(self): """ Reading an empty string must not cause a crash Occasionally, the serial port fails to read properly, and returns an empty string. In this event, we must not crash. """ class BadReadDevice(Serial): def __init__(self, bad_read_index, data): self.read_id = 0 self.bad_read_index = bad_read_index super(BadReadDevice, self).__init__() self.set_read_data(data) def inWaiting(self): return 1 def read(self, length=1): if self.read_id == self.bad_read_index: self.read_id += 1 return '' else: self.read_id += 1 return super(BadReadDevice, self).read() badDevice = BadReadDevice(1, b'\x7E\x00\x05\x88DMY\x01\x8c') xbee = XBee(badDevice, io_loop=self._patch_io) try: xbee._process_input(None, None) yield xbee.wait_read_frame() except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() self.fail("".join(traceback.format_exception( exc_type, exc_value, exc_traceback )))
def test_read_empty_string(self): """ Reading an empty string must not cause a crash Occasionally, the serial port fails to read properly, and returns an empty string. In this event, we must not crash. """ class BadReadDevice(Serial): def __init__(self, bad_read_index, data): self.read_id = 0 self.bad_read_index = bad_read_index super(BadReadDevice, self).__init__() self.set_read_data(data) def inWaiting(self): return 1 def read(self, length=1): if self.read_id == self.bad_read_index: self.read_id += 1 return '' else: self.read_id += 1 return super(BadReadDevice, self).read() badDevice = BadReadDevice(1, b'\x7E\x00\x05\x88DMY\x01\x8c') xbee = XBee(badDevice) try: xbee._process_input(None, None) yield xbee.wait_read_frame() except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() self.fail("".join( traceback.format_exception(exc_type, exc_value, exc_traceback)))