diff options
author | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-11-23 18:02:09 +0100 |
---|---|---|
committer | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-11-26 13:00:34 +0100 |
commit | be750788c7f5276b0a8686e1f11bf4ca12ee9231 (patch) | |
tree | 17d95e86ba063fad3193f5291fe0fd9db0bfb9f3 /src/bluetooth/osx/osxbtcentralmanager.mm | |
parent | 9966c69e301a041ad224ef08bc3da45ca249041d (diff) |
QLowEnergyService::writeCharacteristic - implementation for OS X and iOS
writeCharacteristic - implemented with Core Bluetooth for OS X and iOS.
Change-Id: Ia228ff451e1e6d7b6fb7de6cad29198aa9257602
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src/bluetooth/osx/osxbtcentralmanager.mm')
-rw-r--r-- | src/bluetooth/osx/osxbtcentralmanager.mm | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm index 71622b1c..025313d0 100644 --- a/src/bluetooth/osx/osxbtcentralmanager.mm +++ b/src/bluetooth/osx/osxbtcentralmanager.mm @@ -78,6 +78,8 @@ using namespace QT_NAMESPACE; - (CBCharacteristic *)nextCharacteristicForService:(CBService*)service startingFrom:(CBCharacteristic *)from withProperties:(CBCharacteristicProperties)properties; +- (CBCharacteristic *)characteristicForService:(CBService *)service + withIndex:(NSUInteger)index; - (CBDescriptor *)nextDescriptorForCharacteristic:(CBCharacteristic *)characteristic startingFrom:(CBDescriptor *)descriptor; @@ -437,6 +439,60 @@ using namespace QT_NAMESPACE; delegate->serviceDetailsDiscoveryFinished(ObjCStrongReference<CBService>(service, true)); } +- (bool)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value + characteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + serviceUuid:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid + serviceHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))serviceHandle + withResponse:(bool)withResponse +{ + using namespace OSXBluetooth; + + Q_ASSERT_X(!serviceUuid.isNull(), "-write:characteristic:serviceUuid:serviceHandle:withResponse:", + "invalid service uuid"); + Q_ASSERT_X(serviceHandle, "-write:characteristic:serviceUuid:serviceHandle:withResponse:", + "invalid service handle (0)"); + Q_ASSERT_X(serviceHandle < charHandle, "-write:characteristic:serviceUuid:serviceHandle:withResponse:", + "invalid characteristic handle (<= serviceHandle)"); + + + QT_BT_MAC_AUTORELEASEPOOL; + + CBService *const service = [self serviceForUUID:serviceUuid]; + if (!service) { + qCWarning(QT_BT_OSX) << "-write:characteristic:serviceUuid:serviceHandle:withResponse:, " + "service with uuid: " << serviceUuid << " not found"; + return false; + } + + // 'Convert' charHandle into the 'index' and find a characteristic. + CBCharacteristic *const ch = [self characteristicForService:service + withIndex:charHandle - serviceHandle - 1]; + + if (!ch) { + qCWarning(QT_BT_OSX) << "-write:characteristic:serviceUuid:serviceHandle:withResponse:, " + "characteristic with handle: " << charHandle << " not " + "found on service: " << serviceUuid; + return false; + } + + Q_ASSERT_X(peripheral, "-write:characteristic:serviceUuid:serviceHandle:withResponse:", + "invalid peripheral (nil)"); + + ObjCStrongReference<NSData> data(data_from_bytearray(value)); + if (!data) { + // Even if qtData.size() == 0, we still need NSData object. + qCWarning(QT_BT_OSX) << "-write:characteristic:serviceUuid:serviceHandle:withResponse:, " + "failed to allocate NSData object"; + return false; + } + + // TODO: check what happens if I'm using NSData with length 0. + [peripheral writeValue:data.data() forCharacteristic:ch + type: withResponse? CBCharacteristicWriteWithResponse : CBCharacteristicWriteWithoutResponse]; + + return true; +} + // Aux. methods: - (CBService *)serviceForUUID:(const QBluetoothUuid &)qtUuid @@ -560,6 +616,30 @@ using namespace QT_NAMESPACE; return nil; } +- (CBCharacteristic *)characteristicForService:(CBService *)service + withIndex:(NSUInteger)index +{ + Q_ASSERT_X(service, "-characteristicForService:withIndex:", + "invalid service (nil)"); + + QT_BT_MAC_AUTORELEASEPOOL; + + NSArray *const chars = service.characteristics; + + if (!chars || !chars.count) + return nil; + + for (NSUInteger i = 0, j = 0, e = chars.count; i < e; ++i) { + CBCharacteristic *const ch = [chars objectAtIndex:i]; + if (j == index) + return ch; + if (ch.descriptors) + j += ch.descriptors.count + 1; // + 1 for characteristic itself. + } + + return nil; +} + - (CBDescriptor *)nextDescriptorForCharacteristic:(CBCharacteristic *)characteristic startingFrom:(CBDescriptor *)descriptor { @@ -1003,4 +1083,38 @@ using namespace QT_NAMESPACE; } } +- (void)peripheral:(CBPeripheral *)aPeripheral + didWriteValueForCharacteristic:(CBCharacteristic *)characteristic + error:(NSError *)error +{ + // From docs: + // + // "This method is invoked only when your app calls the writeValue:forCharacteristic:type: + // method with the CBCharacteristicWriteWithResponse constant specified as the write type. + // If successful, the error parameter is nil. If unsuccessful, + // the error parameter returns the cause of the failure." + + using namespace OSXBluetooth; + + Q_UNUSED(aPeripheral) + Q_UNUSED(characteristic) + Q_UNUSED(error) + + Q_ASSERT_X(delegate, "-peripheral:didWriteValueForCharacteristic:error", + "invalid delegate (null)"); + + if (error) { + // Use NSLog to log the actual error: + NSLog(@"-peripheral:didWriteValueForCharacteristic:error:, failed with error: %@", + error); + // TODO: no char handle at the moment, have to change to char index instead + // and calculate the right handle in the LE controller. + delegate->error(qt_uuid(characteristic.service.UUID), 0, + QLowEnergyService::CharacteristicWriteError); + } else { + ObjCStrongReference<CBCharacteristic> ch(characteristic, true); + delegate->characteristicWriteNotification(ch); + } +} + @end |