1

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.

Maihan Nijat
  • 9,054
  • 11
  • 62
  • 110
  • 2
    The standard battery level characteristic is described here: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml - It is a percentage, so 0x12 indicates 18% battery – Paulw11 Nov 23 '17 at 01:11
  • @Paulw11 Thanks. it means I am not getting the right value as I recently changed the battery and I should get above 90%. – Maihan Nijat Nov 23 '17 at 01:15
  • I did find some code that referred to `TI_KEYFOB_LEVEL_SERVICE_UUID` which was defined as 0xFFF1, but I couldn't find any mention of this in the TI sensortag document. I would try with the standard battery service of 0x180F and the standard battery characteristic 0x2A19 and see what you get – Paulw11 Nov 23 '17 at 01:23
  • @Paulw11 I printed the value of it `print(characteristic.value!)` and it returns `1 byte` which is Data. I am trying to use `var batlevel = 0 characteristic.value.getBytes(batlevel, length: TI_KEYFOB_LEVEL_SERVICE_READ_LEN) batteryLevel = Float(batlevel) ` but looks like it dosn't work for Swift 4. – Maihan Nijat Nov 23 '17 at 01:27
  • "The Battery Service exposes the Battery Level of the coin cell in V.BTTN. Battery level are reported as a percentage, e.g. 5C is 92%." – Maihan Nijat Nov 23 '17 at 01:28
  • It is a single byte Int8; so 0x12 is 18 decimal, which is 18%. Either you aren't reading the correct battery service/characterstic, the battery level hardware isn't reading correctly or your new battery is low. What is the definition of `TI_KEYFOB_BATT_SERVICE_UUID` ? – Paulw11 Nov 23 '17 at 01:35
  • It is `0x180F`. And I am getting `Battery Life` when I print it. – Maihan Nijat Nov 23 '17 at 01:43
  • I changed the battery. It is 18 for another one as well. – Maihan Nijat Nov 23 '17 at 01:44

2 Answers2

4

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.

tooberand
  • 78
  • 6
0
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)
        }
    }
}
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Rudresh
  • 1
  • 1
  • You can get the battery percentage – Rudresh Apr 22 '22 at 13:01
  • 1
    Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Apr 22 '22 at 13:45
  • 2A19 is for the battery characteristics peripheral.setNotifyValue(true, for: newChar) this is for notifying the values that means we can get the battery values – Rudresh May 20 '22 at 13:42