'How to get battery life of Bluetooth Low Energy in Swift 4?

I am able to get a value for BLE battery life with the help of following questions:

Read data from BLE device

Reading a BLE Peripheral Characteristic and checking its value?

But I am not sure if It returns the right value? It returns 18, and I am also not sure about the maximum number to determine the battery life based on percentage. Does it mean 18 hours?

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

    print("-CBService is: \(service.uuid.description)")

    if compare(service.uuid, uuid2: CBUUID(string:BluetoothConstants.TI_KEYFOB_BATT_SERVICE_UUID)) {
        print("Battyer Life determination")

        for characteristic: CBCharacteristic in service.characteristics! {
            if characteristic.uuid == CBUUID(string: BluetoothConstants.TI_KEYFOB_LEVEL_SERVICE_UUID) {
                print(characteristic.properties.rawValue)
            }
        }
    }
}

The following line is print for characterstic:

CBCharacteristic: 0x1c00be8a0, UUID = Battery Level, properties =
0x12, value = (null), notifying = NO>

I tried most of the answers here but they are not working for Swift 4.



Solution 1:[1]

I'm not sure about Swift 4, but here's how I figured it out using Swift 5. The value in the characteristic.properties is not the battery level. You need to request a read from the device on the Battery Level characteristic (0x2A19):

if characteristic.uuid == CBUUID(string: "0x2A19") {
   peripheral.readValue(for: characteristic)
}

Then you'll need to add the didUpdateValueFor as part of your CBPeripheralDelegate as well:

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
   print("Battery level: \(characteristic.value![0])")
}

I tested this with an old 3V that was at 2.76V (which is pretty much considered dead) and it gave me a value of 3. Then I put in a new battery and it gave me a value of 100.

Solution 2:[2]

func peripheral(
    _ peripheral: CBPeripheral,
    didUpdateValueFor characteristic: CBCharacteristic,
    error: Error?
) {
    if characteristic.uuid.uuidString == "2A19" {
        print("Battery level: \(characteristic.value![0])")
    }
}
    
func peripheral(
    _ peripheral: CBPeripheral,
    didDiscoverCharacteristicsFor service: CBService,
    error: Error?
) {
    if let error = error {
        print("Error discovering service characteristics: \(error.localizedDescription)")
    }
    for newChar: CBCharacteristic in service.characteristics! {
        peripheral.readValue(for: newChar)
        if newChar.properties.rawValue == 0x12 {
            peripheral.setNotifyValue(true, for: newChar)
            print("characteristicValues",newChar)
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tooberand
Solution 2 Tyler2P