nRF52832 BLE «conn_handle» для отключения текущих подключенных устройств
Я работаю над модулем Adafruit nRF52832 Bluefruit . Я хочу, чтобы соединение BLE отключалось с помощью функции и могло вызываться при необходимости. Но проблема в том, что для функции отключения требуется "conn_handle" для отключения от текущего подключенного Клиента.
Может ли кто-нибудь помочь мне найти, где я могу получить "conn_handle" подключенного клиента?
/**
* Обратный вызов вызывается при разрыве соединения
* @param conn_handle
* @param reason is a BLE_HCI_STATUS_CODE который можно найти в ble_hci.h.
*/
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void) conn_handle;
(void) reason;
connection_num--;
// Пометить идентификатор как недействительный
int id = findConnHandle(conn_handle);
// Несуществующее соединение, что-то пошло не так, DBG !!!
if ( id < 0 ) return;
// Пометить дескриптор подключения как недействительный
prphs[id].conn_handle = BLE_CONN_HANDLE_INVALID;
Serial.print(prphs[id].name);
Serial.println(" disconnected!");
}
Приведенный ниже полный код предназначен для "Central Bleuart Multi"-
/*************************************************** ****************************
Это пример для наших модулей Bluefruit LE на базе nRF52.
Возьмите один сегодня в магазине Adafruit!
Adafruit вкладывает время и ресурсы, предоставляя этот открытый исходный код,
пожалуйста, поддержите Adafruit и оборудование с открытым исходным кодом, купив
продукты от Adafruit!
Лицензия MIT, см. ЛИЦЕНЗИЯ для получения дополнительной информации
Весь текст выше и экран-заставка ниже должны быть включены в
любое перераспределение
************************************* ************* *******************/
/* Этот скетч демонстрирует центральный API(), который позволяет вам подключаться
* к нескольким периферийным платам (Bluefruit nRF52 в периферийном режиме или
* любые платы Bluefruit nRF51).
*
* Одна или несколько плат Bluefruit, сконфигурированных как периферийные устройства с
* Для этой демонстрации требуется запущенный сервис bleuart.
*
* Этот скетч будет:
* - Чтение данных из последовательного порта HW (обычно последовательный порт USB, доступный
* например, через Serial Monitor) и отправлять любые входящие данные на
* все остальные периферийные устройства, подключенные к центральному устройству.
* - Пересылать любые входящие сообщения bleuart с периферийного устройства на все
* другие подключенные устройства.
*
* Рекомендуется давать каждой периферийной плате отдельное имя, чтобы
* чтобы легче различать отдельные устройства.
*
* Объяснение дескриптора подключения
* -----------------------------
* Общее количество подключений BLE_MAX_CONNECTION (20)
*
* «Дескриптор соединения» — это целое число, присвоенное SoftDevice.
* (собственный стек BLE Nordic). Каждое соединение получит свое
* числовой дескриптор, начинающийся от 0 до BLE_MAX_CONNECTION-1, в зависимости от порядка
* соединения(й).
*
* - Например, если наша центральная плата сначала подключается к мобильному телефону (работает как периферийное устройство),
* затем подключается к другой плате Bluefruit, работающей в периферийном режиме, затем
* дескриптор подключения мобильного телефона равен 0, а дескриптор Bluefruit
* плата равна 1 и так далее.
*/
/* ШАБЛОНЫ СВЕТОДИОДОВ
* ------------
* LED_RED — изменение шаблона мигания в зависимости от количества подключений.
* LED_BLUE - постоянно мигает при сканировании
*/
#include <bluefruit.h>
// Структура, содержащая информацию о периферии
typedef struct
{
char name[16+1];
uint16_t conn_handle;
// Каждому prph нужна собственная клиентская служба bleuart
BLEClientUart bleuart;
} prph_info_t;
/* Peripheral info array (one per peripheral device)
*
* There are 'BLE_MAX_CONNECTION' central connections, but the
* the connection handle can be numerically larger (for example if
* the peripheral role is also used, such as connecting to a mobile
* device). As such, we need to convert connection handles <-> the array
* index where appropriate to prevent out of array accesses.
*
* Note: One can simply declares the array with BLE_MAX_CONNECTION and use connection
* handle as index directly with the expense of SRAM.
*/
prph_info_t prphs[BLE_MAX_CONNECTION];
// Программный таймер для мигания КРАСНОГО светодиода
SoftwareTimer blinkTimer;
uint8_t connection_num = 0; // для моргания
void setup()
{
Serial.begin(115200);
while ( !Serial ) delay(10); // для nrf52840 с родным usb
// Инициализируем blinkTimer на 100 мс и запускаем его
blinkTimer.begin(100, blink_timer_callback);
blinkTimer.start();
Serial.println("Bluefruit52 Central Multi BLEUART Example");
Serial.println("-----------------------------------------\n");
// Инициализируем Bluefruit с максимальным числом одновременных подключений: Peripheral = 0, Central = 4
// Использование SRAM, требуемое SoftDevice, будет увеличиваться с увеличением количества подключений
Bluefruit.begin(0, 4);
// Имя набора
Bluefruit.setName("Bluefruit52 Central");
// Запускаем периферийный пул
for (uint8_t idx=0; idx<BLE_MAX_CONNECTION; idx++)
{
// Недействительный дескриптор соединения
prphs[idx].conn_handle = BLE_CONN_HANDLE_INVALID;
// Все услуги BLE Central Uart
prphs[idx].bleuart.begin();
prphs[idx].bleuart.setRxCallback(bleuart_rx_callback);
}
// Обратные вызовы для 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
* - Filter only accept bleuart service in advertising
* - Don't use active scan (used to retrieve the optional scan response adv packet)
* - Start(0) = will scan forever since no timeout is given
*/
Bluefruit.Scanner.setRxCallback(scan_callback);
Bluefruit.Scanner.restartOnDisconnect(true);
Bluefruit.Scanner.setInterval(160, 80); // в единицах 0,625 мс
Bluefruit.Scanner.filterUuid(BLEUART_UUID_SERVICE);
Bluefruit.Scanner.useActiveScan(false); // Не запрашивать данные ответа сканирования
Bluefruit.Scanner.start(0); // 0 = Не останавливать сканирование через n секунд
}
/**
* Callback invoked when scanner picks up an advertising packet
* @param report Structural advertising data
*/
void scan_callback(ble_gap_evt_adv_report_t* report)
{
// Поскольку мы настраиваем сканер с помощью filterUuid()
// Обратный вызов сканирования вызывается только для устройства с объявленным сервисом bleuart
// Подключаемся к устройству с сервисом bleuart в рекламном пакете
Bluefruit.Central.connect(report);
}
/**
* Callback invoked when an connection is established
* @param conn_handle
*/
void connect_callback(uint16_t conn_handle)
{
// Находим доступный идентификатор для использования
int id = findConnHandle(BLE_CONN_HANDLE_INVALID);
// Eeek: Превышено количество подключений!!!
if ( id < 0 ) return;
prph_info_t* peer = &prphs[id];
peer->conn_handle = conn_handle;
Bluefruit.Connection(conn_handle)->getPeerName(peer->name, sizeof(peer->name)-1);
Serial.print("Connected to ");
Serial.println(peer->name);
Serial.print("Discovering BLE UART service ... ");
if ( peer->bleuart.discover(conn_handle) )
{
Serial.println("Found it");
Serial.println("Enabling TXD characteristic's CCCD notify bit");
peer->bleuart.enableTXD();
Serial.println("Continue scanning for more peripherals");
Bluefruit.Scanner.start(0);
Serial.println("Enter some text in the Serial Monitor to send it to all connected peripherals:");
} else
{
Serial.println("Found ... NOTHING!");
// отключаемся, так как не можем найти сервис bleuart
Bluefruit.disconnect(conn_handle);
}
connection_num++;
}
/**
* 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;
connection_num--;
// Пометить идентификатор как недействительный
int id = findConnHandle(conn_handle);
// Несуществующее соединение, что-то пошло не так, DBG !!!
if ( id < 0 ) return;
// Пометить дескриптор подключения как недействительный
prphs[id].conn_handle = BLE_CONN_HANDLE_INVALID;
Serial.print(prphs[id].name);
Serial.println(" disconnected!");
}
/**
* Callback invoked when BLE UART data is received
* @param uart_svc Reference object to the service where the data
* arrived.
*/
void bleuart_rx_callback(BLEClientUart& uart_svc)
{
// uart_svc — это prphs[conn_handle].bleuart
uint16_t conn_handle = uart_svc.connHandle();
int id = findConnHandle(conn_handle);
prph_info_t* peer = &prphs[id];
// Печать имени отправителя
Serial.printf("[From %s]: ", peer->name);
// Чтение и передача на все периферийные устройства
while ( uart_svc.available() )
{
// MTU по умолчанию с дополнительным байтом для конца строки
char buf[20+1] = { 0 };
if ( uart_svc.read(buf,sizeof(buf)-1) )
{
Serial.println(buf);
sendAll(buf);
}
}
}
/**
* Helper function to send a string to all connected peripherals
*/
void sendAll(const char* str)
{
Serial.print("[Send to All]: ");
Serial.println(str);
for(uint8_t id=0; id < BLE_MAX_CONNECTION; id++)
{
prph_info_t* peer = &prphs[id];
if ( peer->bleuart.discovered() )
{
peer->bleuart.print(str);
}
}
}
void loop()
{
// Сначала проверяем, подключены ли мы к какой-либо периферии
if ( Bluefruit.Central.connected() )
{
// MTU по умолчанию с дополнительным байтом для конца строки
char buf[20+1] = { 0 };
// Чтение из HW Serial (обычно USB Serial) и отправка на все периферийные устройства
if ( Serial.readBytes(buf, sizeof(buf)-1) )
{
sendAll(buf);
}
}
}
/**
* Find the connection handle in the peripheral array
* @param conn_handle Connection handle
* @return array index if found, otherwise -1
*/
int findConnHandle(uint16_t conn_handle)
{
for(int id=0; id<BLE_MAX_CONNECTION; id++)
{
if (conn_handle == prphs[id].conn_handle)
{
return id;
}
}
return -1;
}
/**
* Software Timer callback is invoked via a built-in FreeRTOS thread with
* minimal stack size. Therefore it should be as simple as possible. If
* a periodically heavy task is needed, please use Scheduler.startLoop() to
* create a dedicated task for it.
*
* More information http://www.freertos.org/RTOS-software-timer.html
*/
void blink_timer_callback(TimerHandle_t xTimerID)
{
(void) xTimerID;
// Период последовательности 10 раз (1 секунда).
// КРАСНЫЙ светодиод будет переключаться первые 2*n раз (вкл./выкл.) и останется выключенным до конца периода
// Где n = номер соединения
static uint8_t count = 0;
if ( count < 2*connection_num ) digitalToggle(LED_RED);
if ( count % 2 && digitalRead(LED_RED)) digitalWrite(LED_RED, LOW); // выпуск №98
count++;
if (count >= 10) count = 0;
}
Исходный код GitHub
Я хочу вызвать эту функцию отключения, но не знаю, где взять conn_handle. Если у кого-то есть какие-либо идеи, пожалуйста, помогите мне.
Я уже пробовал заходить в библиотеки; лучшее, что он показывает, это просто определение функции обратного вызова:
1: Bluefruit.Central.setDisconnectCallback(disconnect_callback);
2: void BLECentral::setDisconnectCallback( ble_disconnect_callback_t fp )
{
_disconnect_cb = fp;
}
3: class BLECentral
{
...
private:
ble_disconnect_callback_t _disconnect_cb;
}
4: typedef void (*ble_disconnect_callback_t ) (uint16_t conn_hdl, uint8_t reason);
Это все, что я получил об этой функции отключения в разных библиотеках в соответствии с определением, но ничего не связанного с conn_handle.
1 ответ
Лучший ответ:
Не знаю, правильно это или нет, но это работает.
Когда установлено новое соединение, "connect" отзывается с помощью "conn_handle" как его аргумент. Если кто-то знает, расскажите, пожалуйста, как эта функция отзывает себя.
Но я создал глобальную переменную uint16_t conn_handle
uint16_t g_conn_handle;
void connect_callback(uint16_t conn_handle)
{
g_conn_handle=conn_handle;
// Находим доступный идентификатор для использования
int id = findConnHandle(BLE_CONN_HANDLE_INVALID);
// Иек: Exc
...
Теперь я могу вызвать функцию Disconnect с этой глобальной переменной g_conn_handle
.
- Как callback функция вызова может отозвать себя. Например, функция подключения отменяется при наличии нового подключения
- Как отправить ключи, отличные от ASCII, через соединение BLE HID с помощью Adafruit nRF52 Feather?
- Использование SoC nRF52 в качестве РЧ-радио
- Как записать с клиентского узла на серверный узел в пользовательскую службу BLE?
- C++ против языка Arduino?
- avrdude ser_open() can't set com-state
- Как читать и записывать EEPROM в ESP8266
- Float печатается только 2 десятичных знака после запятой