code: def _probe_characteristics(self, conn, services, timeout=5.0):
          
  
          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}
docs: 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