以下是使用 BlueZ(Linux Bluetooth 协议栈)作为被连接端(Server/Peripheral)的示例代码,基于 C 语言和 DBus API 实现。
1. 前置条件
- 确保系统已安装
bluez
和dbus
开发库:sudo apt-get install libbluetooth-dev libdbus-1-dev
- BlueZ 服务需正常运行:
sudo systemctl start bluetooth
2. DBus GATT Server 示例代码
以下是一个简单的 GATT Server,提供一个可读写的特征(Characteristic):
代码 (gatt_server.c
)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <glib.h>
#include <gio/gio.h>
// DBus BlueZ接口路径
#define ADAPTER_PATH "/org/bluez/hci0"
#define SERVICE_PATH "/org/bluez/example/service"
#define CHARACTERISTIC_PATH "/org/bluez/example/service/char1"
static GMainLoop *loop;
static GDBusConnection *conn;
// Characteristic的值(模拟数据)
static char char_value[20] = "Hello BLE";
// DBus方法调用处理:读取特征值
static gboolean handle_read_value(
GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data) {
printf("Read request received\n");
// 返回当前特征值(格式:"ay"表示字节数组)
GVariant *value = g_variant_new_fixed_array(
G_VARIANT_TYPE_BYTE,
char_value,
strlen(char_value),
sizeof(char));
g_dbus_method_invocation_return_value(invocation, g_variant_new("(ay)", value));
return TRUE;
}
// DBus方法调用处理:写入特征值
static gboolean handle_write_value(
GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant* parameters,
GDBusMethodInvocation* invocation,
gpointer user_data) {
printf("Write request received\n");
//解析写入的数据(格式:"ay"表示字节数组)
GVariantIter* iter;
g_variant_get(parameters,"(@ay)", &iter);
gsize len=0;
const guint8* data=g_variant_get_fixed_array(iter,&len,sizeof(guint8));
memcpy(char_value,data,len);
printf("New value: %s\n", char_value);
g_dbus_method_invocation_return_value(invocation,NULL);
return TRUE;
}
int main() {
GError* error=NULL;
//初始化主循环
loop=g_main_loop_new(NULL,FALSE);
//连接到系统总线(System Bus)
conn=g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL,&error);
if(error){fprintf(stderr,"Failed to connect to DBus:%s\n",error->message);exit(1);}
//注册Service和Characteristic到BlueZ (通过DBus)
{
/* Service */
GVariantBuilder service_builder;
g_variant_builder_init(&service_builder,G_VARIANT_TYPE_ARRAY);
g_variant_builder_add(&service_builder,"{sv}","UUID",g_variant_new_string("0000180a-0000-1000-8000-00805f9b34fb")); //自定义UUID
g_variant_builder_add(&service_builder,"{sv}","Primary",g_variant_new_boolean(TRUE));
/* Characteristic */
GVariantBuilder char_builder;
g_variant_builder_init(&char_builder,G_VARIANT_TYPE_ARRAY);
g_variant_builder_add(&char_builder,"{sv}","UUID",g_variant_new_string("00002a57-0000-1000-8000-00805f9b34fb")); //自定义UUID
g_variant_builder_add(&char_builder,"{sv}","Flags",g_variant_new_strv((const char*[]){"read","write"},2));
//发布Service和Characteristic到BlueZ (简化版,实际需更多步骤)
if(!g_dbus_connection_register_object(conn,SERVICE_PATH,g_dbus_node_info_lookup_interface(),NULL,NULL,&error)){fprintf(stderr,"Failed to register service:%s\n",error->message);exit(1);}
if(!g_dbus_connection_register_object(conn,CHARACTERISTIC_PATH,g_dbus_node_info_lookup_interface(),handle_read_value,handle_write_value,&error)){fprintf(stderr,"Failed to register characteristic:%s\n",error->message);exit(1);} }
printf("BLE GATT Server running...\n");
//运行主循环 (等待连接)
signal(SIGINT,signal_handler);//捕获Ctrl+C退出信号
main_loop_run();
cleanup(); return0;}
void signal_handler(int sig){ if(sig==SIGINT){ printf("\nStopping server...\n"); if(main_loop_is_running())main_quit();}}
void cleanup(){ if(main_loop_is_running())main_quit(); if(object_registered)g_dbus_unregister_all(); if(dbus_con)g_object_unref(dbus_con);}
3.关键说明
UUID定义:
- Service UUID和Characteristic UUID需符合蓝牙标准或自定义格式。
- 示例中使用了通用UUID (
180A
为设备信息服务)。
权限控制:
Flags
字段指定特征的属性(如read
、write
、notify
)。
运行方式: “`bash #编译并运行 ./ble_gatt_server
客户端连接测试: -使用工具如
bluetoothctl
,gatttool
,或手机APP (例如 nRF Connect)。
###4.Python简化版 (基于PyBluez) 若需快速验证,可用Python实现简单服务端:
from bluetooth import *
server_sock=BluetoothSocket(RFCOMM)
server_sock.bind(("00:11:22:33:44:55",PORT_ANY))
server_sock.listen()
client_sock.addr=server_sock.accept()
print(f"Connected to {addr}")
data=client_sock.recv(1024)
print(f"Received:{data}")
client.close()
###5.BlueZ官方推荐方式* 生产环境建议使用官方推荐的 bluetoothd + D-Bus API ,而非直接操作Socket。
需要更详细的特性实现吗?比如通知(Notify)、多服务等?
内容由零声教学AI助手提供,问题来源于学员提问