Uso de BLE do Seeed Studio XIAO nRF54L15 Sense
O código de exemplo a seguir foi desenvolvido para PlatformIO, mas também é compatível com o nRF Connect SDK.
Baseado no VS Code, se você quiser usar o caso a seguir no nRF Connect SDK, consulte a conexão fornecida, adicione o arquivo app.overlay e modifique o conteúdo em prj.conf
XIAO nRF54L15 Adicionar arquivo overlay e modificar o arquivo conf.
Observador BLE
Uma aplicação simples que demonstra a funcionalidade do papel de Observador Bluetooth Low Energy. A aplicação irá periodicamente varrer dispositivos próximos. Se algum for encontrado, imprime o endereço do dispositivo, o valor RSSI, o tipo de Advertising e o comprimento dos dados de Advertising no console.
Se o controlador Bluetooth Low Energy utilizado suportar Varredura Estendida, você pode habilitar CONFIG_BT_EXT_ADV no arquivo de configuração do projeto prj.conf. Consulte o arquivo de configuração do projeto para mais detalhes.

Resultado da Varredura
Adicionar Placa XIAO nRF54L15
Para adicionar a placa XIAO nRF54L15(Sense) ao NCS (nRF Connect SDK), você pode consultar o guia "Primeiros Passos" na Wiki da Seeed Studio. Este guia fornecerá instruções detalhadas sobre o processo.
Código do Observador BLE
Main.c
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
int observer_start(void);
int main(void)
{
int err;
printk("Starting Observer Demo\n");
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return 0;
}
(void)observer_start();
printk("Exiting %s thread.\n", __func__);
return 0;
}
-
main.c:Inicializa o subsistema Bluetooth e inicia a demonstração do observador. -
bt_enable(NULL):Inicializa o Subsistema Bluetooth. -
observer_start():Chama a função que inicia o observador. -
printk("Exiting %s thread.\n", __func__):Imprime uma mensagem quando a função principal está encerrando.
observer.c
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#define NAME_LEN 30
static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
struct net_buf_simple *ad)
{
char addr_str[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
printk("Device found: %s (RSSI %d), type %u, AD data len %u\n",
addr_str, rssi, type, ad->len);
}
#if defined(CONFIG_BT_EXT_ADV)
static bool data_cb(struct bt_data *data, void *user_data)
{
char *name = user_data;
uint8_t len;
switch (data->type) {
case BT_DATA_NAME_SHORTENED:
case BT_DATA_NAME_COMPLETE:
len = MIN(data->data_len, NAME_LEN - 1);
(void)memcpy(name, data->data, len);
name[len] = '\0';
return false;
default:
return true;
}
}
static const char *phy2str(uint8_t phy)
{
switch (phy) {
case BT_GAP_LE_PHY_NONE: return "No packets";
case BT_GAP_LE_PHY_1M: return "LE 1M";
case BT_GAP_LE_PHY_2M: return "LE 2M";
case BT_GAP_LE_PHY_CODED: return "LE Coded";
default: return "Unknown";
}
}
static void scan_recv(const struct bt_le_scan_recv_info *info,
struct net_buf_simple *buf)
{
char le_addr[BT_ADDR_LE_STR_LEN];
char name[NAME_LEN];
uint8_t data_status;
uint16_t data_len;
(void)memset(name, 0, sizeof(name));
data_len = buf->len;
bt_data_parse(buf, data_cb, name);
data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(info->adv_props);
bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i "
"Data status: %u, AD data len: %u Name: %s "
"C:%u S:%u D:%u SR:%u E:%u Pri PHY: %s, Sec PHY: %s, "
"Interval: 0x%04x (%u ms), SID: %u\n",
le_addr, info->adv_type, info->tx_power, info->rssi,
data_status, data_len, name,
(info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
(info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
(info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
phy2str(info->primary_phy), phy2str(info->secondary_phy),
info->interval, info->interval * 5 / 4, info->sid);
}
static struct bt_le_scan_cb scan_callbacks = {
.recv = scan_recv,
};
#endif /* CONFIG_BT_EXT_ADV */
int observer_start(void)
{
struct bt_le_scan_param scan_param = {
.type = BT_LE_SCAN_TYPE_PASSIVE,
.options = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
.interval = BT_GAP_SCAN_FAST_INTERVAL,
.window = BT_GAP_SCAN_FAST_WINDOW,
};
int err;
#if defined(CONFIG_BT_EXT_ADV)
bt_le_scan_cb_register(&scan_callbacks);
printk("Registered scan callbacks\n");
#endif /* CONFIG_BT_EXT_ADV */
err = bt_le_scan_start(&scan_param, device_found);
if (err) {
printk("Start scanning failed (err %d)\n", err);
return err;
}
printk("Started scanning...\n");
return 0;
}
-
device_found:Função de callback chamada quando um dispositivo é encontrado durante uma varredura. Imprime o endereço do dispositivo, RSSI, tipo e comprimento dos dados AD. -
scan_recv:Função de callback para advertising estendido que imprime informações detalhadas sobre o pacote de advertisement recebido, incluindo o endereço do dispositivo, potência Tx, RSSI e dados de advertisement. -
data_cb:Função de callback usada por bt_data_parse para extrair o nome do dispositivo dos dados de advertisement. Trata tanto nomes abreviados quanto completos. -
phy2str:Função auxiliar que converte o valor PHY (Camada Física) em uma string legível por humanos (ex.: "LE 1M", "LE 2M", etc.). -
observer_start:A função principal para iniciar o observador. Define os parâmetros de varredura e inicia o processo de varredura. -
bt_le_scan_start:Função que inicia a varredura BLE com os parâmetros especificados e uma função de callback para quando dispositivos são encontrados.
Advertising BLE
Este tutorial de advertising Bluetooth é baseado no código de exemplo oficial modificado para rodar no Nordic Connect SDK. Com nossa placa de desenvolvimento combinada com a documentação oficial, você pode se aprofundar em mais aplicações Bluetooth.
Enquanto o telefone não estiver conectado ao XIAO nRF54L15, o indicador integrado permanecerá aceso permanentemente. Assim que o telefone for conectado com sucesso, o indicador começará a piscar para indicar que uma conexão foi estabelecida.

Conexão do Celular com o XIAO nRF54L15
Instalação de Software para Advertising BLE
Para este exemplo, você precisará baixar o aplicativo oficial de teste Bluetooth, nRF Connect, em seu celular.

Depois de gravar o programa na sua placa XIAO nRF54L15 Sense, você pode abrir a página principal do aplicativo nRF Connect para interagir com ela.
-
Passo 1 . No aplicativo nRF Connect, clique no botão de varredura no canto superior direito para iniciar a busca por dispositivos Bluetooth.
-
Passo 2 . Em seguida, insira o nome do seu dispositivo XIAO nRF54L15 Sense no campo "Name". Isso ajudará você a filtrar e localizar rapidamente o seu dispositivo.
-
Passo 3 . Na área de resultados da varredura, encontre o seu dispositivo XIAO nRF54L15 Sense e clique no botão "Connect" ao lado dele.
Após a conexão bem-sucedida, você será direcionado à página de detalhes do dispositivo. Nessa página, você pode observar a distribuição da intensidade do sinal Bluetooth (RSSI) ao longo de diferentes períodos de tempo, o que ajuda a entender a estabilidade da conexão do dispositivo.
![]() | ![]() |
Adicionar a Placa XIAO nRF54L15
Para adicionar a placa XIAO nRF54L15(Sense) ao NCS (nRF Connect SDK), você pode consultar o guia "Primeiros Passos" na Wiki da Seeed Studio. Este guia fornecerá instruções detalhadas sobre o processo.
Código de Advertising BLE
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
LOG_MODULE_REGISTER(BLE_LowPower, LOG_LEVEL_INF);
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static unsigned char url_data[] = {
0x17,
'/', '/', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.',
'n', 'o', 'r', 'd', 'i', 'c', 's', 'e', 'm', 'i', '.',
'c', 'o', 'm'
};
static const struct bt_data sd[] = {
BT_DATA(BT_DATA_URI, url_data, sizeof(url_data)),
};
static bool device_connected = false;
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err) {
LOG_ERR("Connection failed (err 0x%02x)\n", err);
} else {
LOG_INF("Device connected\n");
device_connected = true;
}
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
LOG_INF("Device disconnected (reason 0x%02x)\n", reason);
device_connected = false;
int err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
LOG_ERR("Failed to restart advertising (err %d)\n", err);
} else {
LOG_INF("Advertising successfully restarted (connectable)\n");
}
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
int main(void)
{
int err;
if (!gpio_is_ready_dt(&led0)) {
LOG_ERR("Error: LED device %s is not ready\n", led0.port->name);
return -1;
}
err = gpio_pin_configure_dt(&led0, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("Error: Failed to configure LED pin %d (err %d)\n", led0.pin, err);
return -1;
}
LOG_INF("LED configured, initially off.");
err = bt_enable(NULL);
if (err) {
LOG_ERR("Bluetooth initialization failed (err %d)\n", err);
return -1;
}
LOG_INF("Bluetooth initialized\n");
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
LOG_ERR("Advertising failed to start (err %d)\n", err);
return -1;
}
LOG_INF("Advertising successfully started (connectable)\n");
while (1) {
if (device_connected) {
gpio_pin_toggle_dt(&led0);
k_sleep(K_MSEC(500));
} else {
gpio_pin_set_dt(&led0, 0);
k_sleep(K_MSEC(1000));
}
}
return 0;
}
-
ad:Define os dados de advertising, incluindo os flags para modo geral detectável e sem suporte a BR/EDR, além do nome completo do dispositivo. -
sd:Define os dados de resposta de varredura, que contêm um URI (Identificador Uniforme de Recursos). -
connected:Esta função de callback é executada quando um dispositivo Bluetooth se conecta com sucesso. Ela define o flag device_connected como verdadeiro. -
disconnected:Esta função de callback é executada quando um dispositivo Bluetooth se desconecta. Ela define o flag device_connected como falso e reinicia o advertising para permitir novas conexões. -
conn_callbacks:Uma estrutura que define os callbacks de conexão, atribuindo as funções connected e disconnected aos seus respectivos eventos. -
main:A função principal do programa. -
gpio_is_ready_dt:Verifica se o dispositivo GPIO do LED está pronto. -
gpio_pin_configure_dt:Configura o pino do LED como saída, inicialmente definido como inativo. -
bt_enable(NULL):Inicializa o subsistema Bluetooth. -
bt_le_adv_start:Inicia o advertising Bluetooth. Este código inicia o advertising conectável usando os dados ad e sd. -
while (1):Um loop infinito que controla o comportamento do LED com base no status da conexão. -
gpio_pin_toggle_dt:Alterna o LED entre ligado e desligado. -
k_sleep:Coloca a thread em suspensão por um período de tempo especificado. -
device_connected:Um flag booleano que rastreia o status da conexão. O LED pisca em intervalos de 500ms quando um dispositivo está conectado. Quando nenhum dispositivo está conectado, o LED é apagado e o programa dorme por 1000ms. -
LOG_INF, LOG_ERR:Funções para registrar informações e erros.
BLE Central/GATT Write
Juntos, esses arquivos de código implementam um dispositivo Central de Bluetooth Low Energy (BLE). O Central varre continuamente periféricos Bluetooth próximos e estabelece automaticamente uma conexão ao encontrar um dispositivo específico (RSSI maior que -50). Uma vez estabelecida a conexão, ele realiza uma troca de MTU (Maximum Transmission Unit) via GATT (Generic Attribute Profile) para otimizar a eficiência da transferência de dados.
A função principal do programa é enviar continuamente comandos GATT Write Without Response ao periférico conectado. Isso é frequentemente usado para testes de desempenho, por exemplo, para medir a taxa de transferência de dados ou a taxa de escrita de uma conexão Bluetooth.

Resultado do gatt
Adicionar a Placa XIAO nRF54L15
Para adicionar a placa XIAO nRF54L15(Sense) ao NCS (nRF Connect SDK), você pode consultar o guia "Primeiros Passos" na Wiki da Seeed Studio. Este guia fornecerá instruções detalhadas sobre o processo.
Código BLE Central/GATT
Main.c
#include <stdint.h>
extern uint32_t central_gatt_write(uint32_t count);
int main(void)
{
(void)central_gatt_write(0U);
return 0;
}
main:O ponto de entrada do programa. Ele chama a funçãocentral_gatt_writecom uma contagem de0U, o que significa que os comandos de escrita serão enviados indefinidamente.
central_gatt_write.c
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
extern int mtu_exchange(struct bt_conn *conn);
extern int write_cmd(struct bt_conn *conn);
extern struct bt_conn *conn_connected;
extern uint32_t last_write_rate;
extern void (*start_scan_func)(void);
static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
struct net_buf_simple *ad)
{
char dev[BT_ADDR_LE_STR_LEN];
struct bt_conn *conn;
int err;
bt_addr_le_to_str(addr, dev, sizeof(dev));
printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
dev, type, ad->len, rssi);
/* We're only interested in connectable events */
if (type != BT_GAP_ADV_TYPE_ADV_IND &&
type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
return;
}
/* connect only to devices in close proximity */
if (rssi < -50) {
return;
}
err = bt_le_scan_stop();
if (err) {
printk("%s: Stop LE scan failed (err %d)\n", __func__, err);
return;
}
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
BT_LE_CONN_PARAM_DEFAULT, &conn);
if (err) {
printk("%s: Create conn failed (err %d)\n", __func__, err);
start_scan_func();
} else {
bt_conn_unref(conn);
}
}
static void start_scan(void)
{
int err;
err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
if (err) {
printk("%s: Scanning failed to start (err %d)\n", __func__,
err);
return;
}
printk("%s: Scanning successfully started\n", __func__);
}
void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
{
printk("Updated MTU: TX: %d RX: %d bytes\n", tx, rx);
}
static struct bt_gatt_cb gatt_callbacks = {
.att_mtu_updated = mtu_updated
};
uint32_t central_gatt_write(uint32_t count)
{
int err;
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return 0U;
}
printk("Bluetooth initialized\n");
bt_gatt_cb_register(&gatt_callbacks);
conn_connected = NULL;
last_write_rate = 0U;
start_scan_func = start_scan;
start_scan_func();
while (true) {
struct bt_conn *conn = NULL;
if (conn_connected) {
/* Get a connection reference to ensure that a
* reference is maintained in case disconnected
* callback is called while we perform GATT Write
* command.
*/
conn = bt_conn_ref(conn_connected);
}
if (conn) {
(void)write_cmd(conn);
bt_conn_unref(conn);
if (count) {
count--;
if (!count) {
break;
}
}
k_yield();
} else {
k_sleep(K_SECONDS(1));
}
}
return last_write_rate;
}
-
device_found:Função de callback acionada quando um novo dispositivo é encontrado durante uma varredura. Ela imprime informações sobre o dispositivo encontrado e tenta se conectar a dispositivos que sejam conectáveis e estejam próximos (RSSI maior que -50). Ela interrompe o processo de varredura antes de criar uma conexão. -
start_scan:Função que inicia uma varredura BLE ativa comdevice_foundcomo callback para dispositivos encontrados. -
mtu_updated:Função de callback para atualizações de MTU do GATT que imprime os novos tamanhos de MTU de TX e RX. -
gatt_callbacks:Uma estrutura que registra a funçãomtu_updatedcomo callback para eventos GATT. -
central_gatt_write:A função principal da aplicação do dispositivo central. Ela inicializa o subsistema Bluetooth, registra os callbacks GATT e inicia a varredura por dispositivos. Em seguida, entra em um loop, onde aguarda uma conexão e chama repetidamente write_cmd para realizar escritas GATT. O loop pode ser configurado para executar um número específico de vezes ou indefinidamente.
gatt_write_common.c
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
static struct bt_gatt_exchange_params mtu_exchange_params;
static uint32_t write_count;
static uint32_t write_len;
static uint32_t write_rate;
struct bt_conn *conn_connected;
uint32_t last_write_rate;
void (*start_scan_func)(void);
static void write_cmd_cb(struct bt_conn *conn, void *user_data)
{
static uint32_t cycle_stamp;
uint64_t delta;
delta = k_cycle_get_32() - cycle_stamp;
delta = k_cyc_to_ns_floor64(delta);
if (delta == 0) {
/* Skip division by zero */
return;
}
/* if last data rx-ed was greater than 1 second in the past,
* reset the metrics.
*/
if (delta > (1U * NSEC_PER_SEC)) {
printk("%s: count= %u, len= %u, rate= %u bps.\n", __func__,
write_count, write_len, write_rate);
last_write_rate = write_rate;
write_count = 0U;
write_len = 0U;
write_rate = 0U;
cycle_stamp = k_cycle_get_32();
} else {
uint16_t len;
write_count++;
/* Extract the 16-bit data length stored in user_data */
len = (uint32_t)user_data & 0xFFFF;
write_len += len;
write_rate = ((uint64_t)write_len << 3) * (1U * NSEC_PER_SEC) /
delta;
}
}
static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
struct bt_gatt_exchange_params *params)
{
printk("%s: MTU exchange %s (%u)\n", __func__,
err == 0U ? "successful" : "failed",
bt_gatt_get_mtu(conn));
}
static int mtu_exchange(struct bt_conn *conn)
{
int err;
printk("%s: Current MTU = %u\n", __func__, bt_gatt_get_mtu(conn));
mtu_exchange_params.func = mtu_exchange_cb;
printk("%s: Exchange MTU...\n", __func__);
err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params);
if (err) {
printk("%s: MTU exchange failed (err %d)", __func__, err);
}
return err;
}
static void connected(struct bt_conn *conn, uint8_t conn_err)
{
struct bt_conn_info conn_info;
char addr[BT_ADDR_LE_STR_LEN];
int err;
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (conn_err) {
printk("%s: Failed to connect to %s (%u)\n", __func__, addr,
conn_err);
return;
}
err = bt_conn_get_info(conn, &conn_info);
if (err) {
printk("Failed to get connection info (%d).\n", err);
return;
}
printk("%s: %s role %u\n", __func__, addr, conn_info.role);
conn_connected = bt_conn_ref(conn);
(void)mtu_exchange(conn);
#if defined(CONFIG_BT_SMP)
if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
err = bt_conn_set_security(conn, BT_SECURITY_L2);
if (err) {
printk("Failed to set security (%d).\n", err);
}
}
#endif
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
struct bt_conn_info conn_info;
char addr[BT_ADDR_LE_STR_LEN];
int err;
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
err = bt_conn_get_info(conn, &conn_info);
if (err) {
printk("Failed to get connection info (%d).\n", err);
return;
}
printk("%s: %s role %u, reason %u %s\n", __func__, addr, conn_info.role,
reason, bt_hci_err_to_str(reason));
conn_connected = NULL;
bt_conn_unref(conn);
if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
start_scan_func();
}
}
static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
{
printk("%s: int (0x%04x, 0x%04x) lat %u to %u\n", __func__,
param->interval_min, param->interval_max, param->latency,
param->timeout);
return true;
}
static void le_param_updated(struct bt_conn *conn, uint16_t interval,
uint16_t latency, uint16_t timeout)
{
printk("%s: int 0x%04x lat %u to %u\n", __func__, interval,
latency, timeout);
}
#if defined(CONFIG_BT_SMP)
static void security_changed(struct bt_conn *conn, bt_security_t level,
enum bt_security_err err)
{
printk("%s: to level %u, err %s(%u)\n", __func__, level, bt_security_err_to_str(err), err);
}
#endif
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
.le_param_req = le_param_req,
.le_param_updated = le_param_updated,
#if defined(CONFIG_BT_SMP)
.security_changed = security_changed,
#endif
};
int write_cmd(struct bt_conn *conn)
{
static uint8_t data[BT_ATT_MAX_ATTRIBUTE_LEN] = {0, };
static uint16_t data_len;
uint16_t data_len_max;
int err;
data_len_max = bt_gatt_get_mtu(conn) - 3;
if (data_len_max > BT_ATT_MAX_ATTRIBUTE_LEN) {
data_len_max = BT_ATT_MAX_ATTRIBUTE_LEN;
}
#if TEST_FRAGMENTATION_WITH_VARIABLE_LENGTH_DATA
/* Use incremental length data for every write command */
/* TODO: Include test case in BabbleSim tests */
static bool decrement;
if (decrement) {
data_len--;
if (data_len <= 1) {
data_len = 1;
decrement = false;
}
} else {
data_len++;
if (data_len >= data_len_max) {
data_len = data_len_max;
decrement = true;
}
}
#else
/* Use fixed length data for every write command */
data_len = data_len_max;
#endif
/* Pass the 16-bit data length value (instead of reference) in
* user_data so that unique value is pass for each write callback.
* Using handle 0x0001, we do not care if it is writable, we just want
* to transmit the data across.
*/
err = bt_gatt_write_without_response_cb(conn, 0x0001, data, data_len,
false, write_cmd_cb,
(void *)((uint32_t)data_len));
if (err) {
printk("%s: Write cmd failed (%d).\n", __func__, err);
}
return err;
}
-
write_cmd_cb:Uma função de callback para bt_gatt_write_without_response_cb. Ela calcula e imprime a contagem de escritas, o comprimento e a taxa de dados em bits por segundo (bps). Ela redefine essas métricas se o tempo desde o último dado recebido exceder um segundo. -
mtu_exchange_cb:Uma função de callback chamada após um procedimento de troca de MTU (Unidade Máxima de Transmissão). Ela imprime se a troca foi bem-sucedida ou falhou e exibe o novo tamanho do MTU. -
mtu_exchange:Inicia um procedimento de troca de MTU. Primeiro imprime o MTU atual e, em seguida, tenta trocá-lo, usando mtu_exchange_cb como callback. -
connected:Uma função de callback executada quando uma conexão é estabelecida. Imprime o endereço do dispositivo conectado e sua função. Em seguida, armazena uma referência à conexão e inicia uma troca de MTU. Se a segurança estiver habilitada, tenta definir o nível de segurança. -
disconnected:Uma função de callback executada quando uma conexão é encerrada. Imprime o endereço do dispositivo desconectado, sua função e o motivo da desconexão. Limpa a referência de conexão e, se o dispositivo era um central, reinicia a varredura. -
le_param_req:Uma função de callback para lidar com solicitações de atualização de parâmetros de conexão LE do periférico. Imprime os parâmetros solicitados (intervalo, latência e tempo limite). -
le_param_updated:Uma função de callback chamada quando os parâmetros de conexão são atualizados com sucesso. Imprime os novos valores de intervalo, latência e tempo limite. -
security_changed:Uma função de callback chamada quando o nível de segurança de uma conexão é alterado. -
write_cmd:Uma função que prepara e envia um comando de escrita GATT sem resposta. Determina o comprimento máximo dos dados com base no MTU atual e envia os dados para o handle 0x0001. Usa write_cmd_cb como callback.
Suporte Técnico e Discussão de Produtos
Obrigado por escolher nossos produtos! Estamos aqui para fornecer diferentes tipos de suporte para garantir que sua experiência com nossos produtos seja a mais tranquila possível. Oferecemos vários canais de comunicação para atender a diferentes preferências e necessidades.

