def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()
        self.backend.start()
예제 #2
0
 def test_reset_and_reconnect(self):
     self.backend.stop()
     self.backend = BGAPIBackend(
         serial_port=self.mock_device.serial_port_name,
         receive_queue_timeout=0.001)
     self.mock_device.mocked_serial.write = mock.MagicMock()
     self.mock_device.mocked_serial.read = mock.MagicMock()
     self.mock_device.mocked_serial.read.side_effect = [None] + [
         serial.serialutil.SerialException] * MAX_CONNECTION_ATTEMPTS
     with self.assertRaises(NotConnectedError):
         self.backend.start()
     self.assertEquals(MAX_CONNECTION_ATTEMPTS + 1,
                       self.mock_device.mocked_serial.read.call_count)
     self.assertTrue(self.mock_device.mocked_serial.write.called)
예제 #3
0
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()
        self.backend.start()
예제 #4
0
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()

        self.time_patcher = mock.patch('pygatt.backends.bgapi.bgapi.time')
        self.time_patcher.start()

        self.timeout_patcher = mock.patch(
            'pygatt.backends.bgapi.bgapi._timed_out')
        timed_out = self.timeout_patcher.start()
        timed_out.return_value = True

        self.backend.start()
예제 #5
0
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()

        self.time_patcher = mock.patch('pygatt.backends.bgapi.bgapi.time')
        self.time_patcher.start()

        self.timeout_patcher = mock.patch(
            'pygatt.backends.bgapi.bgapi._timed_out')
        timed_out = self.timeout_patcher.start()
        timed_out.return_value = True

        self.backend.start()
class BGAPIDeviceTests(unittest.TestCase):
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()
        self.backend.start()

    def tearDown(self):
        self.mock_device.stop()
        # TODO if we call stop without staging another disconnect packet, the
        # bglib explodes because of a packet == None and you get a runaway
        # process. what we can do about that?
        self.mock_device.stage_disconnect_packets(True, False)
        self.backend.stop()

    def _connect(self):
        self.mock_device.stage_connect_packets(self.address,
                                               ['connected', 'completed'])
        return self.backend.connect(self.address_string)

    def test_disconnect_when_connected(self):
        device = self._connect()
        # test disconnect (connected, not fail)
        self.mock_device.stage_disconnect_packets(True, False)
        device.disconnect()

    def test_char_read(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets(
            [uuid_char, handle_char, uuid_desc, handle_desc])
        # Test char_read
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(0, 0x00, expected_value)
        value = device.char_read(UUID(uuid_char))
        eq_(bytearray(expected_value), value)

    def test_char_write(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets(
            [uuid_char, handle_char, uuid_desc, handle_desc])
        # Test char_write
        value = [0xF0, 0x0F, 0x00]
        self.mock_device.stage_char_write_packets(0, value)
        device.char_write(UUID(uuid_char), bytearray(value))

    def test_bond(self):
        device = self._connect()
        self.mock_device.stage_bond_packets(
            self.address, ['connected', 'encrypted', 'parameters_change'])
        device.bond()

    def test_get_rssi(self):
        device = self._connect()
        # Test get_rssi
        self.mock_device.stage_get_rssi_packets()
        eq_(-80, device.get_rssi())

    def test_discover_characteristics(self):
        device = self._connect()

        uuid_char = UUID('01234567-0123-0123-0123-0123456789AB')
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678

        self.mock_device.stage_discover_characteristics_packets(
            [str(uuid_char), handle_char, uuid_desc, handle_desc])
        characteristics = device.discover_characteristics()
        eq_(characteristics[uuid_char].handle, handle_char)
        eq_(characteristics[uuid_char].descriptors[uuid16_to_uuid(0x2902)],
            handle_desc)
예제 #7
0
class BGAPIDeviceTests(unittest.TestCase):
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()
        self.backend.start()

    def tearDown(self):
        self.mock_device.stop()
        # TODO if we call stop without staging another disconnect packet, the
        # bglib explodes because of a packet == None and you get a runaway
        # process. what we can do about that?
        self.mock_device.stage_disconnect_packets(True, False)
        self.backend.stop()

    def _connect(self):
        self.mock_device.stage_connect_packets(
            self.address, ['connected', 'completed'])
        return self.backend.connect(self.address_string)

    def test_disconnect_when_connected(self):
        device = self._connect()
        # test disconnect (connected, not fail)
        self.mock_device.stage_disconnect_packets(True, False)
        device.disconnect()

    def test_char_read(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets([
            uuid_char, handle_char,
            uuid_desc, handle_desc])
        # Test char_read
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(
            0, 0x00, expected_value)
        value = device.char_read(UUID(uuid_char))
        eq_(bytearray(expected_value), value)

    def test_char_write(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets([
            uuid_char, handle_char,
            uuid_desc, handle_desc])
        # Test char_write
        value = [0xF0, 0x0F, 0x00]
        self.mock_device.stage_char_write_packets(0, value)
        device.char_write(UUID(uuid_char), bytearray(value))

    def test_bond(self):
        device = self._connect()
        self.mock_device.stage_bond_packets(
            self.address, ['connected', 'encrypted', 'parameters_change'])
        device.bond()

    def test_get_rssi(self):
        device = self._connect()
        # Test get_rssi
        self.mock_device.stage_get_rssi_packets()
        eq_(-80, device.get_rssi())

    def test_discover_characteristics(self):
        device = self._connect()

        uuid_char = UUID('01234567-0123-0123-0123-0123456789AB')
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678

        self.mock_device.stage_discover_characteristics_packets([
            str(uuid_char), handle_char,
            uuid_desc, handle_desc])
        characteristics = device.discover_characteristics()
        eq_(characteristics[uuid_char].handle, handle_char)
        eq_(characteristics[uuid_char].descriptors[uuid16_to_uuid(0x2902)],
            handle_desc)
예제 #8
0
class BGAPIBackendTests(unittest.TestCase):
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()
        self.backend.start()

    def tearDown(self):
        self.mock_device.stop()
        # TODO if we call stop without staging another disconnect packet, the
        # bglib explodes because of a packet == None and you get a runaway
        # process. what we can do about that?
        self.mock_device.stage_disconnect_packets(True, False)
        self.backend.stop()

    def _connect(self):
        self.mock_device.stage_connect_packets(
            self.address, ['connected', 'completed'])
        return self.backend.connect(self.address_string)

    def test_connect(self):
        self._connect()

    def test_connect_already_connected(self):
        device = self._connect()
        another_device = self.backend.connect(self.address_string)
        eq_(device, another_device)

    def test_scan_and_get_devices_discovered(self):
        # Test scan
        scan_responses = []
        addr_0 = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        scan_responses.append({
            'rssi': -80,
            'packet_type': 0,
            'bd_addr': addr_0,
            'addr_type': 0x00,
            'bond': 0xFF,
            'data': [0x07, 0x09, ord('H'), ord('e'), ord('l'),
                     ord('l'), ord('o'), ord('!')]
        })
        self.mock_device.stage_scan_packets(scan_responses=scan_responses)
        devs = self.backend.scan(timeout=.5)
        eq_('Hello!', devs[0]['name'])
        eq_(-80, devs[0]['rssi'])

    def test_clear_bonds(self):
        # Test delete stored bonds
        self.mock_device.stage_clear_bonds_packets(
            [0x00, 0x01, 0x02, 0x03, 0x04])
        self.backend.clear_bond()

    def test_clear_bonds_disconnect(self):
        """clear_bonds shouldn't abort if disconnected."""
        # Test delete stored bonds
        self.mock_device.stage_clear_bonds_packets(
            [0x00, 0x01, 0x02, 0x03, 0x04], disconnects=True)
        self.backend.clear_bond()
예제 #9
0
class BGAPIDeviceTests(unittest.TestCase):
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()

        self.time_patcher = mock.patch('pygatt.backends.bgapi.bgapi.time')
        self.time_patcher.start()

        self.timeout_patcher = mock.patch(
            'pygatt.backends.bgapi.bgapi._timed_out')
        timed_out = self.timeout_patcher.start()
        timed_out.return_value = True

        self.backend.start()

    def tearDown(self):
        self.time_patcher.stop()
        self.timeout_patcher.stop()
        self.mock_device.stop()
        # TODO if we call stop without staging another disconnect packet, the
        # bglib explodes because of a packet == None and you get a runaway
        # process. what we can do about that?
        self.mock_device.stage_disconnect_packets(True, False)
        self.backend.stop()

    def _connect(self):
        self.mock_device.stage_connect_packets(
            self.address, ['connected', 'completed'])
        device = self.backend.connect(self.address_string)
        self.assertNotEqual(None, device)
        return device

    def test_disconnect_when_connected(self):
        device = self._connect()
        # test disconnect (connected, not fail)
        self.mock_device.stage_disconnect_packets(True, False)
        device.disconnect()

    def test_char_read(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets([
            uuid_char, handle_char,
            uuid_desc, handle_desc])
        # Test char_read
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(
            handle_char, 0x00, expected_value)
        value = device.char_read(UUID(uuid_char))
        eq_(bytearray(expected_value), value)

        # Test ignore of packet with wrong handle
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(
            0, 0x00, expected_value)
        self.mock_device.stage_char_read_packets(
            handle_char, 0x00, expected_value)
        value = device.char_read(UUID(uuid_char))
        eq_(bytearray(expected_value), value)

    def test_read_nonstandard_4byte_char(self):
        device = self._connect()
        uuid_char = 0x03ea
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets([
            "03ea", handle_char,
            uuid_desc, handle_desc])

        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(
            handle_char, 0x00, expected_value)
        value = device.char_read(UUID(str(uuid16_to_uuid(uuid_char))))
        eq_(bytearray(expected_value), value)

    @raises(ExpectedResponseTimeout)
    def test_read_timeout_wrong_handle(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets([
            uuid_char, handle_char,
            uuid_desc, handle_desc])
        # Test char_read
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(
            0, 0x00, expected_value)
        device.char_read(UUID(uuid_char))

    def test_char_write(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets([
            uuid_char, handle_char,
            uuid_desc, handle_desc])
        # Test char_write request
        value = [0xF0, 0x0F, 0x00]
        self.mock_device.stage_char_write_packets(0, value)
        device.char_write(UUID(uuid_char), bytearray(value), True)

        # Test char_write command
        value = [0xF0, 0x0F, 0x00]
        self.mock_device.stage_char_write_command_packets(0, value)
        device.char_write(UUID(uuid_char), bytearray(value), False)

    def test_bond(self):
        device = self._connect()
        self.mock_device.stage_bond_packets(
            self.address, ['connected', 'encrypted', 'parameters_change'])
        device.bond()

    def test_get_rssi(self):
        device = self._connect()
        # Test get_rssi
        self.mock_device.stage_get_rssi_packets()
        eq_(-80, device.get_rssi())

    def test_discover_characteristics(self):
        device = self._connect()

        uuid_char = UUID('01234567-0123-0123-0123-0123456789AB')
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678

        self.mock_device.stage_discover_characteristics_packets([
            str(uuid_char), handle_char,
            uuid_desc, handle_desc])
        characteristics = device.discover_characteristics()
        eq_(characteristics[uuid_char].handle, handle_char)
        eq_(characteristics[uuid_char].descriptors[uuid16_to_uuid(0x2902)],
            handle_desc)
예제 #10
0
class BGAPIDeviceTests(unittest.TestCase):
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()

        self.time_patcher = mock.patch('pygatt.backends.bgapi.bgapi.time')
        self.time_patcher.start()

        self.timeout_patcher = mock.patch(
            'pygatt.backends.bgapi.bgapi._timed_out')
        timed_out = self.timeout_patcher.start()
        timed_out.return_value = True

        self.backend.start()

    def tearDown(self):
        self.time_patcher.stop()
        self.timeout_patcher.stop()
        self.mock_device.stop()
        # TODO if we call stop without staging another disconnect packet, the
        # bglib explodes because of a packet == None and you get a runaway
        # process. what we can do about that?
        self.mock_device.stage_disconnect_packets(True, False)
        self.backend.stop()

    def _connect(self):
        self.mock_device.stage_connect_packets(self.address,
                                               ['connected', 'completed'])
        device = self.backend.connect(self.address_string)
        self.assertNotEqual(None, device)
        return device

    def test_disconnect_when_connected(self):
        device = self._connect()
        # test disconnect (connected, not fail)
        self.mock_device.stage_disconnect_packets(True, False)
        device.disconnect()

    def test_char_read(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets(
            [uuid_char, handle_char, uuid_desc, handle_desc])
        # Test char_read
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(handle_char, 0x00,
                                                 expected_value)
        value = device.char_read(UUID(uuid_char))
        eq_(bytearray(expected_value), value)

        # Test ignore of packet with wrong handle
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(0, 0x00, expected_value)
        self.mock_device.stage_char_read_packets(handle_char, 0x00,
                                                 expected_value)
        value = device.char_read(UUID(uuid_char))
        eq_(bytearray(expected_value), value)

    def test_read_nonstandard_4byte_char(self):
        device = self._connect()
        uuid_char = 0x03ea
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets(
            ["03ea", handle_char, uuid_desc, handle_desc])

        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(handle_char, 0x00,
                                                 expected_value)
        value = device.char_read(UUID(str(uuid16_to_uuid(uuid_char))))
        eq_(bytearray(expected_value), value)

    @raises(ExpectedResponseTimeout)
    def test_read_timeout_wrong_handle(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets(
            [uuid_char, handle_char, uuid_desc, handle_desc])
        # Test char_read
        expected_value = [0xBE, 0xEF, 0x15, 0xF0, 0x0D]
        self.mock_device.stage_char_read_packets(0, 0x00, expected_value)
        device.char_read(UUID(uuid_char))

    def test_char_write(self):
        device = self._connect()
        uuid_char = '01234567-0123-0123-0123-0123456789AB'
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678
        self.mock_device.stage_discover_characteristics_packets(
            [uuid_char, handle_char, uuid_desc, handle_desc])
        # Test char_write request
        value = [0xF0, 0x0F, 0x00]
        self.mock_device.stage_char_write_packets(0, value)
        device.char_write(UUID(uuid_char), bytearray(value), True)

        # Test char_write command
        value = [0xF0, 0x0F, 0x00]
        self.mock_device.stage_char_write_command_packets(0, value)
        device.char_write(UUID(uuid_char), bytearray(value), False)

    def test_bond(self):
        device = self._connect()
        self.mock_device.stage_bond_packets(
            self.address, ['connected', 'encrypted', 'parameters_change'])
        device.bond()

    def test_get_rssi(self):
        device = self._connect()
        # Test get_rssi
        self.mock_device.stage_get_rssi_packets()
        eq_(-80, device.get_rssi())

    def test_discover_characteristics(self):
        device = self._connect()

        uuid_char = UUID('01234567-0123-0123-0123-0123456789AB')
        handle_char = 0x1234
        uuid_desc = '2902'
        handle_desc = 0x5678

        self.mock_device.stage_discover_characteristics_packets(
            [str(uuid_char), handle_char, uuid_desc, handle_desc])
        characteristics = device.discover_characteristics()
        eq_(characteristics[uuid_char].handle, handle_char)
        eq_(characteristics[uuid_char].descriptors[uuid16_to_uuid(0x2902)],
            handle_desc)
예제 #11
0
class BGAPIBackendTests(unittest.TestCase):
    def setUp(self):
        self.mock_device = MockBGAPISerialDevice()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name,
            receive_queue_timeout=0.001)

        self.address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        self.address_string = ":".join("%02x" % b for b in self.address)

        self.mock_device.stage_run_packets()

        self.time_patcher = mock.patch('pygatt.backends.bgapi.bgapi.time')
        self.time_patcher.start()

        self.timeout_patcher = mock.patch(
            'pygatt.backends.bgapi.bgapi._timed_out')
        timed_out = self.timeout_patcher.start()
        timed_out.return_value = True

        self.backend.start()

    def tearDown(self):
        self.time_patcher.stop()
        self.timeout_patcher.stop()
        self.mock_device.stop()
        # TODO if we call stop without staging another disconnect packet, the
        # bglib explodes because of a packet == None and you get a runaway
        # process. what we can do about that?
        self.mock_device.stage_disconnect_packets(True, False)
        self.backend.stop()

    def _connect(self):
        self.mock_device.stage_connect_packets(
            self.address, ['connected', 'completed'])
        return self.backend.connect(self.address_string)

    def test_connect(self):
        self._connect()

    def test_connect_already_connected(self):
        device = self._connect()
        another_device = self.backend.connect(self.address_string)
        eq_(device, another_device)

    def test_serial_port_connection_failure(self):
        self.mock_device.mocked_serial.read = mock.MagicMock()
        self.mock_device.mocked_serial.read.side_effect = (
            serial.serialutil.SerialException)
        with self.assertRaises(NotConnectedError):
            self.backend.start()

    def test_reset_and_reconnect(self):
        self.backend.stop()
        self.backend = BGAPIBackend(
            serial_port=self.mock_device.serial_port_name,
            receive_queue_timeout=0.001)
        self.mock_device.mocked_serial.write = mock.MagicMock()
        self.mock_device.mocked_serial.read = mock.MagicMock()
        self.mock_device.mocked_serial.read.side_effect = [None] + [
            serial.serialutil.SerialException] * MAX_CONNECTION_ATTEMPTS
        with self.assertRaises(NotConnectedError):
            self.backend.start()
        self.assertEquals(MAX_CONNECTION_ATTEMPTS + 1,
                          self.mock_device.mocked_serial.read.call_count)
        self.assertTrue(self.mock_device.mocked_serial.write.called)

    def test_scan_and_get_devices_discovered(self):
        # Test scan
        scan_responses = []
        addr_0 = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB]
        scan_responses.append({
            'rssi': -80,
            'packet_type': 0,
            'bd_addr': addr_0,
            'addr_type': 0x00,
            'bond': 0xFF,
            'data': [0x07, 0x09, ord('H'), ord('e'), ord('l'),
                     ord('l'), ord('o'), ord('!')]
        })
        self.mock_device.stage_scan_packets(scan_responses=scan_responses)
        devs = self.backend.scan(timeout=.5)
        eq_('Hello!', devs[0]['name'])
        eq_(-80, devs[0]['rssi'])

    def test_clear_bonds(self):
        # Test delete stored bonds
        self.mock_device.stage_clear_bonds_packets(
            [0x00, 0x01, 0x02, 0x03, 0x04])
        self.backend.clear_bond()

    def test_clear_bonds_disconnect(self):
        """clear_bonds shouldn't abort if disconnected."""
        # Test delete stored bonds
        self.mock_device.stage_clear_bonds_packets(
            [0x00, 0x01, 0x02, 0x03, 0x04], disconnects=True)
        self.backend.clear_bond()