Как callback функция вызова может отозвать себя. Например, функция подключения отменяется при наличии нового подключения

В дополнение к моему предыдущему вопросу здесь

Может ли кто-нибудь помочь мне понять, как отзывается функция обратного вызова? Функция подключения, функция отключения.

Источник пользовательского кода UUID BLE здесь

Другим примером является BLEUART с функциями обратного вызова:

/*************************************************** ****************************
Это пример для наших модулей Bluefruit LE на базе nRF52.

Возьмите один сегодня в магазине Adafruit!

Adafruit вкладывает время и ресурсы, предоставляя этот открытый исходный код,
пожалуйста, поддержите Adafruit и оборудование с открытым исходным кодом, купив
продукты от Adafruit!

Лицензия MIT, см. ЛИЦЕНЗИЯ для получения дополнительной информации
Весь текст выше и экран-заставка ниже должны быть включены в
любое перераспределение
******************************************************* *******************/

/*
* Этот скетч демонстрирует центральный API(). Дополнительный голубой плод
* для демонстрации требуется bleuart в качестве периферийного устройства.
*/
#include <bluefruit.h>

BLEClientBas  clientBas;  // клиент батареи
BLEClientDis  clientDis;  // клиент информации об устройстве
BLEClientUart clientUart; // блюарт-клиент

void setup()
{
  Serial.begin(115200);
// в то время как ( !Serial ) задержка (10); // для nrf52840 с родным usb

  Serial.println("Bluefruit52 Central BLEUART Example");
  Serial.println("-----------------------------------\n");
  
  // Инициализируем Bluefruit с максимальным количеством соединений, как Peripheral = 0, Central = 1
  // Использование SRAM, необходимое для SoftDevice, резко возрастет с увеличением количества подключений
  Bluefruit.begin(0, 1);
  
  Bluefruit.setName("Bluefruit52 Central");

  // Настроить клиент батареи
  clientBas.begin();  

  // Настраиваем DIS-клиент
  clientDis.begin();

  // Инициируем службу BLE Central Uart
  clientUart.begin();
  clientUart.setRxCallback(bleuart_rx_callback);

  // Увеличить скорость мигания, чтобы он отличался от режима рекламы PrPh
  Bluefruit.setConnLedInterval(250);

  // Обратные вызовы для Central
  Bluefruit.Central.setConnectCallback(connect_callback);
  Bluefruit.Central.setDisconnectCallback(disconnect_callback);

  /* Start Central Scanning
   * - Enable auto scan if disconnected
   * - Interval = 100 ms, window = 80 ms
   * - Don't use active scan
   * - Start(timeout) with timeout = 0 will scan forever (until connected)
   */
  Bluefruit.Scanner.setRxCallback(scan_callback);
  Bluefruit.Scanner.restartOnDisconnect(true);
  Bluefruit.Scanner.setInterval(160, 80); // в единицах 0,625 мс
  Bluefruit.Scanner.useActiveScan(false);
  Bluefruit.Scanner.start(0);                   // // 0 = Не останавливать сканирование через n секунд
}

/**
 * Callback invoked when scanner pick up an advertising data
 * @param report Structural advertising data
 */
void scan_callback(ble_gap_evt_adv_report_t* report)
{
  // Проверяем, содержит ли реклама сервис BleUart
  if ( Bluefruit.Scanner.checkReportForService(report, clientUart) )
  {
    Serial.print("BLE UART service detected. Connecting ... ");

    // Подключиться к устройству с сервисом bleuart в рекламе
    Bluefruit.Central.connect(report);
  }else
  {      
    // Для Softdevice v6: после получения отчета сканер будет приостановлен
    // Нам нужно вызвать Scanner возобновление(), чтобы продолжить сканирование
    Bluefruit.Scanner.resume();
  }
}

/**
 * Callback invoked when an connection is established
 * @param conn_handle
 */
void connect_callback(uint16_t conn_handle)
{
  Serial.println("Connected");

  Serial.print("Dicovering Device Information ... ");
  if ( clientDis.discover(conn_handle) )
  {
    Serial.println("Found it");
    char buffer[32+1];
    
    // прочитать и распечатать Производитель
    memset(buffer, 0, sizeof(buffer));
    if ( clientDis.getManufacturer(buffer, sizeof(buffer)) )
    {
      Serial.print("Manufacturer: ");
      Serial.println(buffer);
    }

    // прочитать и распечатать номер модели
    memset(buffer, 0, sizeof(buffer));
    if ( clientDis.getModel(buffer, sizeof(buffer)) )
    {
      Serial.print("Model: ");
      Serial.println(buffer);
    }

    Serial.println();
  }else
  {
    Serial.println("Found NONE");
  }

  Serial.print("Dicovering Battery ... ");
  if ( clientBas.discover(conn_handle) )
  {
    Serial.println("Found it");
    Serial.print("Battery level: ");
    Serial.print(clientBas.read());
    Serial.println("%");
  }else
  {
    Serial.println("Found NONE");
  }

  Serial.print("Discovering BLE Uart Service ... ");
  if ( clientUart.discover(conn_handle) )
  {
    Serial.println("Found it");

    Serial.println("Enable TXD's notify");
    clientUart.enableTXD();

    Serial.println("Ready to receive from peripheral");
  }else
  {
    Serial.println("Found NONE");
    
    // отключаемся, так как не можем найти сервис bleuart
    Bluefruit.disconnect(conn_handle);
  }  
}

/**
 * Callback invoked when a connection is dropped
 * @param conn_handle
 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
 */
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;
  
  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
}

/**
 * Callback invoked when uart received data
 * @param uart_svc Reference object to the service where the data 
 * arrived. In this example it is clientUart
 */
void bleuart_rx_callback(BLEClientUart& uart_svc)
{
  Serial.print("[RX]: ");
  
  while ( uart_svc.available() )
  {
    Serial.print( (char) uart_svc.read() );
  }

  Serial.println();
}

void loop()
{
  if ( Bluefruit.Central.connected() )
  {
    // Пока не обнаружено
    if ( clientUart.discovered() )
    {
      // Обнаруженные средства в рабочем состоянии
      // Получаем последовательный ввод и отправляем на периферию
      if ( Serial.available() )
      {
        delay(2); // немного задержать приход всех символов
        
        char str[20+1] = { 0 };
        Serial.readBytes(str, 20);
        
        clientUart.print( str );
      }
    }
  }
}

Следующее помогает установить функции обратного вызова:

clientUart.setRxCallback(bleuart_rx_callback);
...
Bluefruit.Central.setConnectCallback(connect_callback);
...
Bluefruit.Central.setDisconnectCallback(disconnect_callback);

Отслеживание найденных библиотек:

void BLEPeriph::setConnectCallback( ble_connect_callback_t fp )
{
  _connect_cb = fp;
}

void BLEPeriph::setDisconnectCallback( ble_disconnect_callback_t fp )
{
  _disconnect_cb = fp;
}

Но я не могу понять, как это инициализирует вызов функции соединения или отключения при получении нового соединения или разрыва соединения соответственно.

, 👍0


1 ответ


Лучший ответ:

0

Все, что делает назначение функции обратного вызова, — это связывает внутренний указатель с функцией, которую вы предоставляете.

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

Таким образом, _connect_cb и connect_callback() — это одно и то же. Каждый раз, когда ожидается использование connect_callback(), вместо этого используется _connect_cb().

По сути, это просто создание внутреннего псевдонима для вашего кода, а затем использование этого псевдонима для вызова вашего кода, когда это необходимо.

,

Хорошо, я очистил часть назначения указателя, и _connect_cb присвоил значение функции connect_callback(). Но мне нужно уточнить еще одну вещь: где я вызвал _connect_cb в своем основном коде? Когда есть новое соединение, оно само отменяется. Итак, я хочу знать, определено ли это где-то в библиотеке?, @Just doin Gods work

Вы ничего не называете. В этом весь смысл обратного вызова — его вызывает библиотека. Где-то в библиотеке будет вызов _connect_cb()., @Majenko

@JustdoinGodswork, вы вызываете функции BLE в цикле(). любой из них может вызвать обратный вызов, @Juraj

Хорошо, я попробую поискать connect_cb() в библиотеках., @Just doin Gods work