Программирование ARM nRF5 SDK: модуль Database Discovery Tue, January 25 2022  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

nRF5 SDK: модуль Database Discovery Печать
Добавил(а) microsin   

Модуль Database Discovery обрабатывает распознавание служб у серверов GATT (т. е. у периферийных устройств BLE). Когда клиент (устройство BLE Central) соединяется с пиром, на котором работает требуемый сервер, необходимо распознавание службы (service discovery) чтобы гарантировать, что клиент взаимодействует с характеристиками сервера, используя корректные дескрипторы атрибутов (attributes handles). Service discovery также важно потому, что BLE адвертайзинг не требует, чтобы были объявлены (advertised) все службы. Чтобы узнать, что служба присутствует на устройстве пира, Вы можете выполнить service discovery. Этот модуль может использоваться для многих типовых сценариев распознавания, и для всех реализаций клиента в SDK.

Модуль Database Discovery найдет зарегистрированные сервисы на пире, вместе с характеристиками каждой службы.

На пире будет осуществляться поиск только следующих дескрипторов:

• Client Characteristic Configuration
• Characteristic Extended Properties
• Characteristic User Description
• Report Reference

На пире не будет осуществляться поиск никаких служб, кроме первичной службы (primary Service).

[Конфигурация Database Discovery Module]

Конфигурация задается количеством служб и характеристик, которые должны быть обнаружены, от этого зависит необходимое количество выделяемой памяти. Устанавливаются следующие параметры времени компиляции:

BLE_DB_DISCOVERY_MAX_SRV. Это макроопределение задает максимальное количество распознаваемых служб. По умолчанию установлено 6.

BLE_GATT_DB_MAX_CHARS. Это макроопределение задает максимальное количество распознаваемых характеристик на службу. По умолчанию установлено 5.

Эти определения изначально настроены так, чтобы они подходили для большинства примеров из SDK, но их значения можно увеличить или уменьшить в зависимости от требований приложения (чем больше значения, тем больше памяти будет зарезервировано). Если на устройстве пира большее количество характеристик, чем задано BLE_GATT_DB_MAX_CHARS, то будут распознаны только первые характеристики, все остальные будут игнорированы.

[Использование Database Discovery Module]

Регистрация идентификаторов UUID. Сначала модуль должен быть инициализирован вызовом функции ble_db_discovery_init, который в качестве параметра принимает адрес функции обработчика событий (event handler). Пример реализации:

/**@brief Функция для обработки событий database discovery.
 *
 * @details Это callback-функция для обработки событий из модуля DataBase Discovery.
 *          В зависимости от UUID, которые распознаны, эта функция должна перенаправить
 *          события в их соответствующие службы.
 *
 * @param[in] p_event  Указатель на событие database discovery.
 */
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
   ble_hrs_on_db_disc_evt(&m_ble_hrs_c, p_evt);   
   SaveCharacteristics(p_evt);
}
 
/**
 * @brief Инициализация Database discovery. */
static void db_discovery_init(void)
{
   ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
   APP_ERROR_CHECK(err_code);
}

После этого Вы можете регистрировать UUID-ы, которые нужно искать в базах данных пиров BLE (серверов BLE) с помощью вызовов ble_db_discovery_evt_register. Пример регистрации UUID для поиска Heart Rate Service:

uint32_t ble_hrs_c_init(ble_hrs_c_t * p_ble_hrs_c,
                        ble_hrs_c_init_t * p_ble_hrs_c_init)
{
   uint32_t err_code;
 
   VERIFY_PARAM_NOT_NULL(p_ble_hrs_c);
   VERIFY_PARAM_NOT_NULL(p_ble_hrs_c_init);
 
   ble_uuid_t hrs_uuid;
 
   hrs_uuid.type = BLE_UUID_TYPE_BLE;
   hrs_uuid.uuid = BLE_UUID_HEART_RATE_SERVICE;
 
   p_ble_hrs_c->evt_handler                 = p_ble_hrs_c_init->evt_handler;
   p_ble_hrs_c->conn_handle                 = BLE_CONN_HANDLE_INVALID;
   p_ble_hrs_c->peer_hrs_db.hrm_cccd_handle = BLE_GATT_HANDLE_INVALID;
   p_ble_hrs_c->peer_hrs_db.hrm_handle      = BLE_GATT_HANDLE_INVALID;
 
   err_code = app_timer_create(&m_read_timer_id,
                               APP_TIMER_MODE_SINGLE_SHOT,
                               read_timeout_handler);
   APP_ERROR_CHECK(err_code);
   return ble_db_discovery_evt_register(&hrs_uuid);
}

Реализации клиентов служб (Service Clients) в примерах SDK будут регистрировать UUID-ы сервера, с которым необходимо установить взаимодействие, тем самым устанавливается пара пиров BLE - сервер и клиент BLE (они же BLE Peripheral и BLE Central соответственно). Когда все нужные службы зарегистрированы, то можно запустить ble_db_discovery_start, чтобы начать распознавание служб (discovery) на имеющемся соединении. Каждый распознанный UUID вызовет обработчик события распознавания (discovery event handler) с типом события BLE_DB_DISCOVERY_COMPLETE. Это событие содержит дескрипторы (handles) и идентификаторы (UUID-ы) распознанной службы.

Event Handler. В обработчике события (discovery event handler) перенаправьте поступившие события discovery в модули клиента путем вызова их функций "on_db_disc_evt". Например, клиент датчика сердцебиения (Heart Rate Service Client, пример ble_peripheral\ble_app_hrs) имеет в своем составе функцию ble_hrs_on_db_disc_evt:

void ble_hrs_on_db_disc_evt(ble_hrs_c_t * p_ble_hrs_c,
                            const ble_db_discovery_evt_t * p_evt)
{
   // Проверка: была ли распознана Heart Rate Service.
   if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
       p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_HEART_RATE_SERVICE &&
       p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE)
   {
      // Поиск CCCD Handle характеристики Heart Rate Measurement.
      uint32_t i;
 
      ble_hrs_c_evt_t evt;
 
      evt.evt_type    = BLE_HRS_C_EVT_DISCOVERY_COMPLETE;
      evt.conn_handle = p_evt->conn_handle;
 
      for (i = 0; i < p_evt->params.discovered_db.char_count; i++)
      {
         if (p_evt->params.discovered_db.charateristics[i].characteristic.uuid.uuid ==
             BLE_UUID_HEART_RATE_MEASUREMENT_CHAR)
         {
            // Найдена характеристика Heart Rate. Сохранение CCCD handle и break.
            evt.params.peer_db.hrm_cccd_handle =
               p_evt->params.discovered_db.charateristics[i].cccd_handle;
            evt.params.peer_db.hrm_handle =
               p_evt->params.discovered_db.charateristics[i].characteristic.handle_value;
            break;
         }
      }
 
      umsg("Heart Rate Service discovered at peer.\n");
      // Если экземпляр был назначен перед db_discovery, то назначаем db_handles.
      if (p_ble_hrs_c->conn_handle != BLE_CONN_HANDLE_INVALID)
      {
         if ((p_ble_hrs_c->peer_hrs_db.hrm_cccd_handle == BLE_GATT_HANDLE_INVALID)&&
             (p_ble_hrs_c->peer_hrs_db.hrm_handle == BLE_GATT_HANDLE_INVALID))
         {
            p_ble_hrs_c->peer_hrs_db = evt.params.peer_db;
         }
      }
      p_ble_hrs_c->evt_handler(p_ble_hrs_c, &evt);
   }
}

Это позволяет модулям клиента принять решение, относятся ли к ним распознанные атрибуты. Если это те атрибуты, которые нужны, то модуль клиента может вызывать свои события оповещения о завершении распознавания ("discovery complete" events). Например, Heart Rate Service Client вызовет событие BLE_HRS_C_EVT_DISCOVERY_COMPLETE, основываясь на событии BLE_DB_DISCOVERY_COMPLETE, которое было перенаправлено из discovery event handler.

Назначение дескрипторов (handles). В обработчике событий Вашего модуля клиента (такого как hrs_c_evt_handler в примере BLE Heart Rate Collector) у Вас есть теперь все корректные дескрипторы атрибутов службы, с которой необходимо взаимодействовать. Эти дескрипторы должны быть связаны с экземпляром клиента, который нужно использовать на этом подключении. Большинство реализаций клиентов в примерах SDK имеют функцию "handles_assign", чтобы устанавливать подобную взаимосвязь. Например, у клиента HRS есть соответствующая функция ble_hrs_c_handles_assign:

/**@brief     Функция для назначения дескрипторов handles для этого экземпляра hrs_c.
 *
 * @details   Вызовите эту функцию, когда установлен линк с пиром, чтобы связать
 *            этот линк с этим экземпляром модуля. Это дает возможность обработать
 *            несколько линков, и связать каждый линк с частным экземпляром
 *            в этом модуле. Дескриптор соединения (conn_handle) и дескрипторы
 *            атрибутов (attribute handles) будут предоставлены из события
 *            завершения распознавания службы @ref BLE_HRS_C_EVT_DISCOVERY_COMPLETE.
 *
 * @param[in] p_ble_hrs_c        Указатель на структуру heart rate client, связанную
 *                               с экземпляром клиента (Heart Rate Client Instance).
 * @param[in] conn_handle        Дескриптор соединения, связанного с указанным
 *                               экземпляром клинента (Heart Rate Client Instance).
 * @param[in] p_peer_hrs_handles Дескрипторы атрибутов (attribute handles) для
 *                               сервера HRS, с которым этот HRS_C client должен
 *                               взаимодействовать.
 */
uint32_t ble_hrs_c_handles_assign(ble_hrs_c_t * p_ble_hrs_c,
                                  uint16_t conn_handle,
                                  const hrs_db_t * p_peer_hrs_handles)
{
   VERIFY_PARAM_NOT_NULL(p_ble_hrs_c);
 
   p_ble_hrs_c->conn_handle = conn_handle;
   if (p_peer_hrs_handles != NULL)
   {
      p_ble_hrs_c->peer_hrs_db = *p_peer_hrs_handles;
   }
   return NRF_SUCCESS;
}

Примечание: процедура назначения дескрипторов может потребовать дополнительной логики, в зависимости от целей, установленных для приложения. Например, если Ваше приложение рассчитано на несколько подключений, и/или несколько экземпляров клиентов и служб (приложение может работать либо как клиент, либо как сервер, либо может реализовать и клиент, и сервер BLE одновременно).

[Ссылки]

1. nRF5 SDK v12 Database Discovery Module site:nordicsemi.com.

 

Добавить комментарий


Защитный код
Обновить

Top of Page