Read data from BLE device
To read a value from a BLE peripheral device, follow these steps
Scan for avilable devices
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];[self.myCentralManager scanForPeripheralsWithServices:nil options:options];`
On detecting a device, will get a call back to "didDiscoverPeripheral" delegate method. Then establish a connection with detected BLE device
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { //Connect detected device.... if (!peripheral.isConnected) { peripheral.delegate = self; [bluetoothManager_ connectPeripheral:peripheral options:nil]; }}
On successful connection, request for all the services available in the BLE device
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{NSLog(@"Peripheral Connected"); // Make sure we get the discovery callbacks peripheral.delegate = self; // Search only for services that match our UUID [peripheral discoverServices:nil];}
Request all the characteristics available in each services
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { NSLog(@"Error discovering services: %@", [error localizedDescription]); return; } // Loop through the newly filled peripheral.services array, just in case there's more than one. for (CBService *service in peripheral.services) { [peripheral discoverCharacteristics:nil forService:service]; }}
Once we get the required characteristics detail, we need to subscribe to it, which lets the peripheral know we want the data it contains
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{ // Deal with errors (if any) if (error) { NSLog(@"Error discovering characteristics: %@", [error localizedDescription]); return; } // Again, we loop through the array, just in case. for (CBCharacteristic *characteristic in service.characteristics) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:REQUIRED_CHARA_ID]]) { // If it is, subscribe to it [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } }}
Completing all these steps, BLE device will let you know the notification status change through delegate method
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ if (error) { NSLog(@"Error changing notification state: %@", error.localizedDescription); } // Notification has started if (characteristic.isNotifying) { NSLog(@"Notification began on %@", characteristic); }}
You will recieve any notification from BLE device in the following method
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"Error reading characteristics: %@", [error localizedDescription]); return; } if (characteristic.value != nil) { //value here. }}
Swift version of itZme's answer with a little modification due to didConnectToPeripheral
not being called (you also need to keep a strong reference to the peripherals in order to connect, as follows):
Scan for available devices:
centralManager.scanForPeripheralsWithServices(nil, options: nil)
On detecting a device, will get a call back to "didDiscoverPeripheral" delegate method. Then establish a connection with detected BLE device. But also keep a strong reference of the peripherals first:
private var peripherals: [CBPeripheral] = []func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { if peripheral.state != .connected { self.peripherals.append(peripheral) peripheral.delegate = self centralManager.connectPeripheral(peripheral , options: nil) }}
And the rest should be like this:
extension ViewController: CBPeripheralDelegate {func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) { if error != nil { print("Error connecting to peripheral: \(error?.localizedDescription)") return }}func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {print("Peripheral connected.") peripheral.delegate = self peripheral.discoverServices(nil)}func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) { if error != nil { print("Error discovering services \(error?.localizedDescription)") return } for service: CBService in peripheral.services! { peripheral.discoverCharacteristics(nil, forService: service) }}func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) { if error != nil { print("Error discovering characteristics \(error?.localizedDescription)") return } for characteristic: CBCharacteristic in service.characteristics! { if characteristic.UUID == CBUUID(string: YOUR_CHARACTERISTIC_UUID) { peripheral.readValueForCharacteristic(characteristic) // for some devices, you can skip readValue() and print the value here } }}func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { if characteristic.UUID == CBUUID(string: YOUR_CHARACTERISTIC_UUID) { print(characteristic.value) } }}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { for newChar: CBCharacteristic in service.characteristics!{ peripheral.readValue(for: newChar) if newChar.properties.rawValue == 0x10 || newChar.properties.rawValue == 0x8C{ peripheral.setNotifyValue(true, for: newChar) } else if newChar.properties.rawValue == 0x12{ peripheral.setNotifyValue(true, for: newChar) } } func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { print(characteristic) }