Hi folks,
I want to connect a bluetooth device on macos 10.15 for development reasons. But any read/write operstion to the characteristics fails with this message:
The console app of macos show the following corresponding error:
In the Bluetooth settings the Countour device is paired, but on the iMac without exchange the pairing code like in iOS.
What can I do? I mean it should be possible to handle BLE development in macOS with any BLE capable device, isn't it?
To be complete, here' the code:
I want to connect a bluetooth device on macos 10.15 for development reasons. But any read/write operstion to the characteristics fails with this message:
Bluetooth powered on.
------------------------------------------------
Device Contour7802H6798544 found, try to connect...
Connected to Contour7802H6798544
*******************************************************
Service: <CBService: 0x10047a550, isPrimary = NO, UUID = Glucose>
<CBCharacteristic: 0x1005069c0, UUID = 2A18, properties = 0x10, value = (null), notifying = NO>
... has notify
<CBCharacteristic: 0x10047be80, UUID = 2A34, properties = 0x10, value = (null), notifying = NO>
... has notify
<CBCharacteristic: 0x10047a1e0, UUID = 2A51, properties = 0x2, value = (null), notifying = NO>
... has read
<CBCharacteristic: 0x10047c220, UUID = 2A52, properties = 0x28, value = (null), notifying = NO>
... has write
2020-12-12 23:35:05.701945+0100 bluetooth.test[1255:37185] [CoreBluetooth] WARNING: Unknown error: -536870212
Optional(Error Domain=CBErrorDomain Code=0 "Unknown error." UserInfo={NSLocalizedDescription=Unknown error.})
2020-12-12 23:35:05.758360+0100 bluetooth.test[1255:37186] [CoreBluetooth] WARNING: Unknown error: -536870212
*******************************************************
Error changing notification state:Optional("Unknown error.")
CBCharacteristicProperties(rawValue: 16)
The console app of macos show the following corresponding error:
standard 12:18:36.349729+0100 bluetoothd Read Device Name: c7532430
standard 12:18:36.393712+0100 bluetoothd ***** [handleATTErrorResponse].
fehler 12:18:36.393780+0100 bluetoothd ***** [handleATTErrorResponse] - Insufficient Encryption.
standard 12:18:36.393820+0100 bluetoothd ***** [handleATTErrorResponse] - Link is not encrypted, perform pairing with MITM disbled.
standard 12:18:36.393858+0100 bluetoothd ***** [startLESecurityManagerPairingSecureConnection] Start secure pairing with mitm: 0, bonding: 1, sc: 1, keypress: 0, ct2: 0
standard 12:18:36.394505+0100 bluetoothd ***** [startLESecurityManagerPairingSecureConnection] - Master: _localAuthReq: 0x9, localInitiatorKeyDistribution: 0x3, localResponderKeyDistribution: 0x3
standard 12:18:36.394572+0100 bluetoothd ***** [pairingRequest] Send Pairing Request: auth 0x9
standard 12:18:36.417047+0100 bluetoothd ***** [l2capChannelData] - Received Pairing Failed.
fehler 12:18:36.417088+0100 bluetoothd *****[handlePairingFailed] reason = 5.
fehler 12:18:36.418854+0100 bluetooth.test WARNING: Unknown error: -536870212
In the Bluetooth settings the Countour device is paired, but on the iMac without exchange the pairing code like in iOS.
What can I do? I mean it should be possible to handle BLE development in macOS with any BLE capable device, isn't it?
To be complete, here' the code:
//
// main.swift
// bluetooth.test
//
// Created by Christoph Bilz on 07.12.20.
//
import Foundation
import CoreBluetooth
let serviceGlucose = CBUUID(string: "1808");
let glucoseMeasurementCharacteristicCBUUID = CBUUID(string: "2A18");
let glucoseMeasurementContextCharacteristicCBUUID = CBUUID(string: "2A34");
let glucoseFeatureCharacteristicCBUUID = CBUUID(string: "2A51");
let readAccessControlPointCharacteristicCBUUID = CBUUID(string: "2A52");
// MARK: - BLE Class
class BLE : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
var centralManager : CBCentralManager!
var characteristics: [CBUUID : CBCharacteristic] = [:]
var device: CBPeripheral?
override init() {
super.init();
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.global());
}
func hex(from string: String) -> Data? {
.init(stride(from: 0, to: string.count, by: 2).map {
string[string.index(string.startIndex, offsetBy: $0) ... string.index(string.startIndex, offsetBy: $0 + 1)]
}.map {
UInt8($0, radix: 16)!
})
}
// MARK: - didUpdateState
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if(central.state == CBManagerState.poweredOn) {
print("Bluetooth powered on.");
central.scanForPeripherals(withServices: nil, options: nil);
} else {
print("Error: Bluetooth not powerd on.");
}
}
// func startScan() {
// print("Now Scanning...")
// self.timer.invalidate()
// cm?.scanForPeripherals(withServices: nil , options: [CBCentralManagerScanOptionAllowDuplicatesKey:false])
// Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.cancelScan), userInfo: nil, repeats: false)
// }
//
// @objc func cancelScan() {
// self.cm?.stopScan()
// print("Scan Stopped")
// print("Number of Peripherals Found: \(peripherals.count)")
// }
// MARK: - didDiscover
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,advertisementData: [String : Any], rssi RSSI: NSNumber) {
guard let pname = peripheral.name else {
return;
}
if(pname.hasPrefix("Contour") || pname.hasPrefix("Christoph")) {
print("Device " + pname + " found, try to connect...");
device = peripheral as CBPeripheral
device?.delegate = self;
central.connect(device!, options: nil);
central.stopScan();
} else {
print("Unknown device \(pname)");
print(peripheral);
print("------------------------------------------------")
}
}
// MARK: - didConnect
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected to " + (peripheral.name ?? "unknown"));
peripheral.discoverServices(nil);
}
// MARK: - didDiscoverServices
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
print("*******************************************************")
if ((error) != nil) {
print("Error discovering services: \(error!.localizedDescription)")
return
}
guard let services = peripheral.services else {
return
}
for service in services {
if(service.uuid == serviceGlucose) {
print("Service: " + service.description)
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
// MARK: - didDiscoverCharacteristics
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if ((error) != nil) {
print("Error discovering services: \(error!.localizedDescription)")
return
}
guard let _characteristics = service.characteristics else {
return
}
var cpMember = Dictionary<String,CBCharacteristicProperties>();
cpMember = ["read":.read,"write":.write,"notify":.notify];
for _characteristic in _characteristics {
characteristics[_characteristic.uuid] = _characteristic;
print(_characteristic);
for (md,m) in cpMember {
if(_characteristic.properties.contains(m)) {
print("... has \(md)");
}
}
switch(_characteristic.uuid) {
case CBUUID(string: "2A18"):
peripheral.setNotifyValue(true, for: _characteristic);
case CBUUID(string: "2A52"):
// guard let data = hex(from: "0101") else {
// print("error operator set");
// return;
// }
let data = Data([0x01,0x01,0x00]);
peripheral.writeValue(data , for: _characteristic, type: .withResponse);
default:
();
}
//peripheral.discoverDescriptors(for: characteristic)
}
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
print(error);
}
// MARK: - didUpdateValueFor
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("------------------------------------------");
print(characteristic.uuid);
print(characteristic.value ?? "no value")
}
// MARK: - didDiscoverDescriptors
// func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
// print("*******************************************************")
//
// if error != nil {
// print("\(error.debugDescription)")
// return
// }
// guard let descriptors = characteristic.descriptors else { return }
//
// descriptors.forEach { descript in
// print("function name: DidDiscoverDescriptorForChar \(String(describing: descript.description))")
// print("Rx Value \(String(describing: rxCharacteristic?.value))")
// print("Tx Value \(String(describing: txCharacteristic?.value))")
//
// }
// }
//
// MARK: - didUpdateNotificationStateFor
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
print("*******************************************************")
if (error != nil) {
print("Error changing notification state:\(String(describing: error?.localizedDescription))")
print(characteristic.properties)
} else {
print("Characteristic's value subscribed")
}
if (characteristic.isNotifying) {
print ("Subscribed. Notification has begun for: \(characteristic.uuid)")
}
}
}
// MARK: - Main Loop
BLE();
RunLoop.current.run();