树莓派4B作为蓝牙BLE设备被苹果和安卓手机识别并连接
废话不多说,直接上步骤:
使蓝牙工作
sudo adduser pi bluetooth
sudo reboot
蓝牙开启很重要的一项:
1.下载bluez-5.65.tar.gz(备注:第一次因为版本没找对,废了较大功夫,发现很多功能没有,比如btgatt-server)
2.解压并执行($./conifgure)
3.生成Makefile并编译($make)
4.修改btgatt-server.c,添加自己的UUID服务
#define UUID_PLYTEST 0xFFE0
#define UUID_PLYTEST_CTRL 0xFFE1
static void ply_control_point_read_cb(struct gatt_db_attribute* attrib,
unsigned int id, uint16_t offset,
uint8_t opcode, struct bt_att* att,
void* user_data)
{
struct server* server = user_data;
uint8_t value[2];
value[0] = server->ply_msrmt_enabled ? 0x01 : 0x00;
value[1] = 0x00;
gatt_db_attribute_read_result(attrib, id, 0, value, 2);
}
static void ply_control_point_write_cb(struct gatt_db_attribute* attrib,
unsigned int id, uint16_t offset,
const uint8_t* value, size_t len,
uint8_t opcode, struct bt_att* att,
void* user_data)
{
struct server* server = user_data;
uint8_t ecode = 0;
char* p_value = (char*)malloc(len * 2 + 1);
if (p_value != 0)
{
memset(p_value, 0, len * 2 + 1);
for (size_t i = 0; i < len; i++)
{
sprintf(&p_value[i*2], "%02X", value[i]);
}
PRLOG("recv data: [%s]\n", p_value);
free(p_value);
p_value = 0;
}
done:
gatt_db_attribute_write_result(attrib, id, ecode);
}
static void populate_plytest_service(struct server* server)
{
bt_uuid_t uuid;
struct gatt_db_attribute* service, * ply_msrmt, * body;
uint8_t body_loc = 1; /* "Chest" */
/* Add the BATTERYLEVEL service */
bt_uuid16_create(&uuid, UUID_PLYTEST);
service = gatt_db_add_service(server->db, &uuid, true, 2);
/* Ply Test Control Point Characteristic */
bt_uuid16_create(&uuid, UUID_PLYTEST_CTRL);
ply_msrmt = gatt_db_service_add_characteristic(service, &uuid,
BT_ATT_PERM_NONE | BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP | BT_GATT_CHRC_PROP_WRITE | BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_NOTIFY,
ply_control_point_read_cb, ply_control_point_write_cb,
server);
bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
gatt_db_service_add_descriptor(service, &uuid, BT_ATT_PERM_READ,
gap_device_name_ext_prop_read_cb,
NULL, server);
server->ply_msrmt_handle = gatt_db_attribute_get_handle(ply_msrmt);
if (server->ply_visible)
gatt_db_service_set_active(service, true);
}
static void populate_db(struct server *server)
{
populate_plytest_service(server);
populate_gap_service(server);
populate_gatt_service(server);
populate_hr_service(server);
}
5.btmgmt添加服务UUID和厂商名字到广播数据(Advertise)
6.自定义Advertise需关闭advertise(advertise off)
附带一个测试脚本:
#!/bin/bash
sudo rfkill
sudo rfkill unblock bluetooth
sudo systemctl disable bluetooth.service
sudo systemctl stop bluetooth.service
sudo pkill bluetoothd
sudo ./bluetoothd -E -C & #若与串口共用则取消/etc/systemd/system/dbus-org.bluez.service的修改(保持默认即可)
sudo ./btmgmt -i hci0 power off
sudo ./btmgmt -i hci0 le off
sudo ./btmgmt -i hci0 bondable off
sudo ./btmgmt -i hci0 connectable off
sudo ./btmgmt -i hci0 discov off
sudo ./btmgmt -i hci0 bredr off # Disables BR/EDR !
sudo ./btmgmt -i hci0 advertising off
sudo ./btmgmt -i hci0 clr-adv
#sudo ./btmgmt -i hci0 add-adv -u 0x1802 -u 0x180D -d 1 1 1
sudo ./btmgmt -i hci0 advinfo
sudo ./btmgmt -i hci0 le on
sudo ./btmgmt -i hci0 bondable on
sudo ./btmgmt -i hci0 connectable on
#sudo ./btmgmt -i hci0 discov on
#sudo ./btmgmt -i hci0 advertising on
sudo ./btmgmt -i hci0 add-adv -u 0x1802 -u 0xFFE0 -d 02010606095241535000 -s 05061805051206000a00020a00 1
sudo ./btmgmt -i hci0 name raspi001
sudo ./btmgmt -i hci0 power on
sudo ./btgatt-server -i hci0 -s low -t public -r -v
如遇到蓝牙无控制台运行,无法正常连接及接收命令,则可尝试一下方法:
屏蔽代码
/*if (mainloop_add_fd(fileno(stdout),
EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR,
prompt_read_cb, pBtGattUserData->server, NULL) < 0) {
fprintf(stderr, "Failed to initialize console\n");
if (pBtGattUserData->server != NULL)
{
server_destroy(pBtGattUserData->server);
pBtGattUserData->server = NULL;
}
if (pBtGattUserData->cfd >= 0)
{
close(pBtGattUserData->cfd);
pBtGattUserData->cfd = (-1);
}
return EXIT_FAILURE;
}*/