我正在尝试将android用作BLE外围设备(gatt服务器)。我能够获得它的广告,并且当某些特征发生更改时,我可以收到iOS应用程序的重新通知,但是我在执行简单的writeValue时遇到了麻烦。
在iOS上,我有:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
if (!error) {
for(int i = 0; i < service.characteristics.count; i++) { //Show every one
CBCharacteristic *c = [service.characteristics objectAtIndex:i];
if ([[c.UUID UUIDString] rangeOfString:@"43FF0001"].location!=NSNotFound){
self.shot_detected_characteristic = c;
[peripheral setNotifyValue:YES forCharacteristic:self.shot_detected_characteristic];
}else if ([[c.UUID UUIDString] rangeOfString:@"43FF0002"].location!=NSNotFound){
self.display_characteristic = c;
[self writeValue:@"ABC" forCharacteristic:c onPeripheral:peripheral];
}
NSLog(@"characteristic uuid: %@", [c.UUID UUIDString]);
}
} else {
NSLog(@"Characteristic discovery unsuccessful");
}
}
-(IBAction*) sendData {
CBPeripheral *p = [peripherals lastObject];
[self writeValue:@"ABC" forCharacteristic:self.display_characteristic onPeripheral:p];
}
-(void) writeValue:(NSString*)value forCharacteristic:(CBCharacteristic*)c onPeripheral:(CBPeripheral *)p {
NSData *d = [value dataUsingEncoding:NSUTF8StringEncoding];
if (c.properties & CBCharacteristicPropertyWrite) {
NSLog(@"Write with response"); //I am getting this message
[p writeValue:d forCharacteristic:c type:CBCharacteristicWriteWithResponse];
}else{
NSLog(@"Unable to write");
}
}
在Android方面,我有:
private BluetoothManager bluetoothManager;
private BluetoothGattServer gattServer;
private BluetoothGattCharacteristic displayCharacteristic;
private BluetoothDevice connected_device;
private BluetoothLeAdvertiser advertiser;
private void setupBLEService() {
bluetoothManager = (android.bluetooth.BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
if( ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
gattServer = bluetoothManager.openGattServer(this, gattServerCallback);
String uuid_string = "92D9D153-9BE6-43FF-9672-3E2904628B9D";
BluetoothGattService service = new BluetoothGattService(UUID.fromString(uuid_string), BluetoothGattService.SERVICE_TYPE_PRIMARY);
shotDetectedCharacteristic = new BluetoothGattCharacteristic(
UUID.fromString("43FF0001-9BE6-43FF-9672-3E2904628B9D"),
BluetoothGattCharacteristic.PROPERTY_BROADCAST | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
BluetoothGattDescriptor gD = new BluetoothGattDescriptor(UUID.fromString(NOTIFICATION_DESCRIPTOR), BluetoothGattDescriptor.PERMISSION_WRITE | BluetoothGattDescriptor.PERMISSION_READ);
shotDetectedCharacteristic.addDescriptor(gD);
service.addCharacteristic(shotDetectedCharacteristic);
displayCharacteristic = new BluetoothGattCharacteristic(
UUID.fromString("43FF0002-2BE5-46FE-9162-1D2905728B9B"),
BluetoothGattCharacteristic.PROPERTY_BROADCAST | BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
service.addCharacteristic(displayCharacteristic);
gattServer.addService(service);
}
private BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
if (newState == 2){
connected_device = device;
advertiser.stopAdvertising(new AdvertiseCallback() {});
}
Log.i("chase", "Connection state changed: "+newState);
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
long millis = System.currentTimeMillis();
characteristic.setValue( ""+millis );
Log.i("chase", "reading: "+millis);
gattServer.sendResponse(device, requestId, 2, offset, characteristic.getValue());
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
Log.i("chase", "characteristic write request");
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
characteristic.setValue(value);
gattServer.sendResponse(device, requestId, 2, offset, characteristic.getValue());
if (characteristic == displayCharacteristic){
//TODO: UPDATE DISPLAY
Log.i("chase", "display write request: "+value.toString());
}else
Log.i("chase", "char write request: "+value.toString());
}
...
}
我认为问题出在iOS方面的原因是我下载了nrf Connect应用程序,并且能够使用nrf connect成功写入android特性。或者至少进入BluetoothGattServerCallback#onCharacteristicWriteRequest
中的日志语句。
但是,我还编写了与BLE芯片接口的应用程序,而用[p writeValue:d forCharacteristic:c type:CBCharacteristicWriteWithResponse];
编写NSData从未遇到任何麻烦。在此先感谢您提供任何有关如何解决此问题的帮助或想法。
更新:
当我说那行不通的时候。我根本没有收到任何错误消息。 [p writeValue:d forCharacteristic:c type:CBCharacteristicWriteWithResponse];
被调用,并且android端没有对BluetoothGattServerCallback#onCharacteristicWriteRequest
的任何调用,而ios端没有了对-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
的任何回调。
但是,我确实得到了一些有趣的东西。如果我注释掉ios行:
//[peripheral setNotifyValue:YES forCharacteristic:self.shot_detected_characteristic];
然后,我执行呼叫Android的onCharacteristicWriteRequest
,并确实回调了didWriteValueForCharacteristic
(我收到一条错误消息,该消息无法编写,但我认为我可以解决(至少我得到了一些东西)。
我订阅的是有关其他特征的通知,但是订阅的是同一服务,并且由于某种原因,这使我无法针对其他特征写数据。