def _probe_characteristics(self, conn, services, timeout=5.0):
        """Probe gatt services for all associated characteristics in a BLE device

        Args:
            conn (int): the connection handle to probe
            services (dict): a dictionary of services produced by probe_services()
            timeout (float): the maximum number of seconds to spend in any single task
        """

        for service in services.values():
            success, result = self._enumerate_handles(conn, service['start_handle'],
                                                      service['end_handle'])

            if not success:
                return False, None

            attributes = result['attributes']

            service['characteristics'] = {}

            last_char = None
            for handle, attribute in attributes.items():
                if attribute['uuid'].hex[-4:] == '0328':
                    success, result = self._read_handle(conn, handle, timeout)
                    if not success:
                        return False, None

                    value = result['data']
                    char = parse_characteristic_declaration(value)
                    service['characteristics'][char['uuid']] = char
                    last_char = char
                elif attribute['uuid'].hex[-4:] == '0229':
                    if last_char is None:
                        return False, None

                    success, result = self._read_handle(conn, handle, timeout)
                    if not success:
                        return False, None

                    value = result['data']
                    assert len(value) == 2
                    value, = unpack("<H", value)

                    last_char['client_configuration'] = {'handle': handle, 'value': value}

        return True, {'services': services}
Probe gatt services for all associated characteristics in a BLE device

        Args:
            conn (int): the connection handle to probe
            services (dict): a dictionary of services produced by probe_services()
            timeout (float): the maximum number of seconds to spend in any single task