以下是一个使用BlueZ开源库实现一个Gatt Server的样例工程,支持蓝牙5.0和可读写的Characteristics:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/gatt.h>
#define ATT_CID 4
struct bt_att *att;
struct bt_gatt_manager *gatt_manager;
int characteristic_handle;
static void on_write_cb(struct bt_conn *conn, uint8_t err,
struct bt_gatt_write_params *params)
{
if (err) {
printf("Failed to write data (err %d)\n", err);
return;
}
printf("Data written successfully\n");
}
static ssize_t read_value_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
static const char value[] = "Hello GATT Client!";
size_t value_len = sizeof(value);
return bt_gatt_attr_read(conn, attr, buf, len, offset, value, value_len);
}
static ssize_t write_value_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *buf, uint16_t len, uint16_t offset,
uint8_t flags)
{
// Handle the incoming data here
printf("Received data: %.*s\n", len, buf);
return len;
}
static struct bt_gatt_attr attrs[] = {
BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(BT_UUID_HEART_RATE)),
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(BT_UUID_HEART_RATE_MEASUREMENT),
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY),
BT_GATT_DESCRIPTOR(BT_UUID_DECLARE_128(BT_UUID_CHAR_DESCRIPTION),
BT_GATT_PERM_READ, read_value_cb, NULL, NULL),
BT_GATT_DESCRIPTOR(BT_UUID_DECLARE_128(BT_UUID_CLIENT_CHAR_CONFIG),
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
bt_gatt_attr_read_ccc_cfg, bt_gatt_attr_write_ccc_cfg,
(void *)BT_GATT_CCC_NOTIFY),
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(BT_UUID_TEMPERATURE_MEASUREMENT),
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE),
BT_GATT_DESCRIPTOR(BT_UUID_DECLARE_128(BT_UUID_CHAR_DESCRIPTION),
BT_GATT_PERM_READ, read_value_cb, NULL, NULL),
BT_GATT_DESCRIPTOR(BT_UUID_DECLARE_128(BT_UUID_VALID_RANGE),
BT_GATT_PERM_READ,
bt_gatt_attr_read_valid_range16, NULL, NULL),
BT_GATT_DESCRIPTOR(BT_UUID_DECLARE_128(0x2902),
0x02 /* FIXME: not always notify */,
read_value_cb, write_value_cb, NULL),
/* Battery Service Declaration */
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_16(0x2a19),
(BT_ATT_PERM_READ | 0), // battery level
((BT_ATT_NO_TIMEOUT) << 12)),
};
static void gatt_manager_connected(struct bt_conn *conn)
{
printf("GATT client connected\n");
// Enable notifications on the first characteristic
uint16_t value = BT_GATT_CCC_NOTIFY;
struct bt_gatt_write_params write_params;
write_params.data = &value;
write_params.length = sizeof(value);
write_params.handle = characteristic_handle + 2; // CCCD handle
write_params.offset = 0;
write_params.func = on_write_cb;
bt_gatt_write(conn, &write_params);
}
static void gatt_manager_disconnected(struct bt_conn *conn)
{
printf("GATT client disconnected\n");
}
static struct bt_gatt_manager_cb gatt_manager_callbacks = {
.connected = gatt_manager_connected,
.disconnected = gatt_manager_disconnected,
};
int main(int argc, char *argv[])
{
// Initialize Bluetooth
if (bt_init() < 0) {
fprintf(stderr, "Failed to initialize Bluetooth\n");
return -1;
}
// Register GATT attributes
if (bt_gatt_register(attrs, ARRAY_SIZE(attrs)) < 0) {
fprintf(stderr, "Failed to register GATT attributes\n");
return -1;
}
// Start GATT manager
gatt_manager = bt_gatt_manager_new();
if (!gatt_manager) {
fprintf(stderr, "Failed to create GATT manager\n");
return -1;
}
bt_gatt_manager_set_coding_format(gatt_manager, BT_GATT_CODING_FORMAT_16);
// Create ATT layer
att = bt_att_new(ATT_CID);
if (!att) {
fprintf(stderr, "Failed to create ATT layer\n");
return -1;
}
// Attach ATT layer with GATT manager
bt_att_attach(att, g_io_channel_unix_get_fd(bt_g_io_channel_get_io_channel(g_io_channel_default())));
// Set up callbacks for GATT manager events
bt_gio_set_watch(GIOChannelEventFlag_Readable | GIOChannelEventFlag_Hup | GIOChannelEventFlag_Error,
g_io_channel_unix_get_fd(bt_g_io_channel_get_io_channel(g_io_channel_default())));
bt_gio_set_callbacks(g_io_channel_unix_get_fd(bt_g_io_channel_get_io_channel(g_io_channel_default())),
&gatt_manager_callbacks);
// Run the main loop
while (1) {
g_main_context_iteration(NULL, TRUE);
}
// Clean up resources
bt_att_unref(att);
bt_gatt_manager_unref(gatt_manager);
return 0;
}
请注意,此示例代码仅供参考,并可能需要根据具体的需求和硬件配置进行适当的修改。同时,确保你已经正确安装了BlueZ开源库并设置好相关依赖。
希望这可以帮助你开始使用BlueZ开发一个支持蓝牙5.0和可读写Characteristics的Gatt Server。
内容由零声教学AI助手提供,问题来源于学员提问




