目标
我正在开发一个运行Linux的简单设备。它具有BLE功能,而我目前正在使用bluez 5.8。
我想使用iPhone在此设备上触发操作。
已经工作的内容:
我在linux上设置了这样的蓝牙设备:
# 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可以正常连接,但看不到任何服务。
我所缺少的
我可能应该提到,我看到了一个问题:创建一个gatt服务器,但是答案提出了很多问题(例如,用于bluez的GATT api在哪里?如何设置GATT数据库?如何注册读/写事件? )
编辑:我仅使用命令设置BLE设备来播发一些数据,但iOS报告该连接被 接受 。bluez的哪一部分接受传入连接?
最终,我找到了所有问题的答案。
我将从回答最后一个问题开始:
我仅使用命令设置BLE设备来通告一些数据,但iOS报告已接受连接。 bluez的哪一部分接受传入连接?
这一次是回答的bluez邮件列表上,以响应我。
简介: 内核在HCI级别接受BLE连接。如果要从用户空间使用该连接,则需要使用具有ATT通道ID(为4)的l2cap套接字。
Bleno有一个使用L2CAP套接字的很好的例子。
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(),则上面的小程序将读取(即接收):
gatt.discoverServices()
10 0100 ffff 0028
这基本上意味着:
10: READ_BY_GROUP 0100: from handle 0001 ffff: to handle ffff 0028: with UUID 2800
此请求是任何BLE外围设备将请求服务列表的方式。
然后,您可以使用设备提供的服务列表(根据GATT协议格式化)来回答此请求。
再次,请参见Bleno中的实现。