目标
我正在开发一个运行Linux的简单设备。它具有BLE功能,我目前正在使用bluez 5.8。
我想使用iPhone在此设备上触发操作。
已有效的方法:
我在linux上设置了这样的蓝牙设备(感谢this question):
# activate bluetooth
hciconfig hci0 up
# set advertise data: "hello world"
hcitool -i hci0 cmd 0x08 0x0008 48 45 4c 4c 4f 57 4f 52 4c 44
# start advertising as connectable
hciconfig hci0 leadv 0
iOS代码很简单:
- (int) scanForPeripherals
{
if (self->centralManager.state != CBCentralManagerStatePoweredOn) {
return -1;
}
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[self.centralManager scanForPeripheralsWithServices:nil options:options];
return 0;
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (central.state == CBCentralManagerStatePoweredOn) {
NSLog(@"Starting scan");
[self scanForPeripherals];
}
}
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"didDiscoverPeripheral");
/*
* Retain the peripheral to avoid the error:
* CoreBluetooth[WARNING]: state = connecting> is being dealloc'ed while connecting
*/
self.activePeripheral = peripheral;
[centralManager connectPeripheral:peripheral options:nil];
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"Connected to peripheral");
/* discover all services */
[peripheral discoverServices:nil];
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(@"Discovered services");
for (CBService *service in peripheral.services) {
NSLog(@"Discovered service %@", service);
}
}
在iPhone上运行此代码时,我会收到此日志:
2013-12-19 12:53:22.609 Test2[18518:60b] Starting scan
2013-12-19 12:53:29.945 Test2[18518:60b] didDiscoverPeripheral
2013-12-19 12:53:31.230 Test2[18518:60b] Connected to peripheral
所以似乎iPhone连接正常,但没有看到任何服务。
我缺少什么
我应该提一下,我看到了这个问题:Creating a gatt server,但答案提出了太多问题(例如,GATT api for bluez在哪里?如何设置GATT数据库?如何注册读取/写事件?)
编辑: 我使用的命令仅设置BLE设备以通告某些数据,但iOS报告连接已接受。 bluez的哪一部分正在接受传入连接?
答案 0 :(得分:17)
最终,我发现了所有问题的答案。
我将首先回答最后一个问题:
我使用的命令仅设置BLE设备来宣传某些数据,但iOS报告连接已被接受。 bluez的哪一部分正在接受传入连接?
这个是answered on the bluez mailing-list,是对我的回应。
摘要:内核在HCI级别接受BLE连接。如果要在用户空间中使用该连接,则需要使用带有ATT通道ID(即4)的l2cap套接字。
Bleno has a good example of using an L2CAP socket
L2CAP套接字如何工作基本上是这样的:
/* create L2CAP socket, and bind it to the local adapter */
l2cap_socket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
hci_device_id = hci_get_route(NULL);
hci_socket = hci_open_dev(hci_device_id);
memset(&l2cap_address, sizeof(l2cap_address));
l2cap_address.l2_family = AF_BLUETOOTH;
l2cap_address.l2_bdaddr = hci_device_address;
l2cap_address.l2_cid = htobs(ATT_CID);
bind(l2cap_socket, (struct sockaddr*)&l2cap_address, sizeof(l2cap_address));
listen(l2cap_socket, 1);
while (1) {
/* now select and accept() client connections. */
select(l2cap_socket + 1, &afds, NULL, NULL, &tv);
client_socket = accept(l2cap_socket, (struct sockaddr *)&l2cap_address, &len);
/* you can now read() what the client sends you */
int ret = read(client_socket, buffer, sizeof(buffer));
printf("data len: %d\n", ret);
for (i = 0; i < ret; i++) {
printf("%02x", ((int)buffer[i]) & 0xff);
}
printf("\n");
close(client_socket);
}
如何宣传服务?
我意识到我需要回答上一个问题才能回答这个问题。
一旦你可以通过L2CAP套接字读取数据,一切都更有意义,例如,如果你的Android手机有gatt.discoverServices()
,那么上面的小程序将会读取(即接收):
10 0100 ffff 0028
这基本上意味着:
10: READ_BY_GROUP
0100: from handle 0001
ffff: to handle ffff
0028: with UUID 2800
此请求是任何BLE外围设备请求服务列表的方式。
然后,您可以使用您的设备提供的服务列表来回答此请求,并根据GATT协议进行格式化。
答案 1 :(得分:4)
你真的很亲密。
要使用iOS代码查看设备上的服务,请尝试添加
peripheral.delegate = self;
在didConnectPeripheral
来电之前,到discoverServices
。我从Apple documentation得到了它并且它为我修复了一些东西(只是不要忘记将CBPeripheralDelegate
添加到头文件中的接口声明中)。没有它,didDiscoverServices
永远不会被调用。
通过使用gatt-example
从源代码编译BlueZ,我能够运行./configure --enable-maintainer-mode
服务插件。然后,如果您启动bluetoothd -nd
,您会看到类似
src/plugin.c:add_plugin() Loading gatt_example plugin
靠近输出的顶部,然后
attrib/gatt-service.c:gatt_service_add() New service: handle 0x0009, UUID a002, 4 attributes
src/attrib-server.c:attrib_db_add_new() handle=0x0009
attrib/gatt-service.c:gatt_service_add() New characteristic: handle 0x000a
src/attrib-server.c:attrib_db_add_new() handle=0x000a
此时,我的iOS应用程序能够看到BlueZ peripheral
,连接并发现其服务(在hciconfig hci0 leadv
之后)。