7
votes

I am new to Core Bluetooth Framework. I am developing an application that act as peripheral. I need the app to notify characteristic value to subscribed centrals and also write the value of characteristic by the connected central. I am setting the value of characteristic while creating it. The issue is when i am setting the property of characteristic to notify or write it is showing error "Characteristics with cached values must be read-only". Can anybody help me ?

 var charValue = characteristicDetail["value"] as String
 var charProperties:CBCharacteristicProperties = getProperty(characteristicDetail["properties"] as String )
 let data = charValue.dataUsingEncoding(NSUTF8StringEncoding)
 var characteristic = CBMutableCharacteristic(type: charId, properties: charProperties, value: data, permissions: CBAttributePermissions.Readable)



func getProperty(string:String) -> CBCharacteristicProperties
    {
    var propertyString:CBCharacteristicProperties?
    switch string{
    case "r","R":
        propertyString = CBCharacteristicProperties.Read
    case "w","W":
        propertyString = CBCharacteristicProperties.Write
    case "n","N":
        propertyString = CBCharacteristicProperties.Notify
    case "i","I":
        propertyString = CBCharacteristicProperties.Indicate
    case "rw","wr","WR","RW":
        propertyString = CBCharacteristicProperties.Read|CBCharacteristicProperties.Write
    case "rn","nr","NR","RN":
        propertyString = CBCharacteristicProperties.Read|CBCharacteristicProperties.Notify
    case "wn","nw","NW","WN":
        propertyString = CBCharacteristicProperties.Write|CBCharacteristicProperties.Notify
    default:
        propertyString = CBCharacteristicProperties.Read
    }
    return propertyString!

}
2

2 Answers

13
votes

If you specify a non-nil value when you create the CBMutableCharacteristic then it is a 'cached characteristic' and as the error message says, you cannot change the value later.

From the documentation of the CBMutableCharacteristic init method -

value - The characteristic value to be cached. If nil, the value is dynamic and will be requested on demand.

Specify nil when you create the CBMutableCharacteristic- You supply the value when requested in the didReceiveReadRequest CBPeripheralManagerDelegate method.

If you have centrals that have subscribed to the characteristic then you should also call updateValue on your CBPeripheralManager whenever the value changes.

Be sure to read the section Performing Common Peripheral Role Tasks in the Core Bluetooth Programming Guide

-1
votes

I found a solid post Medium that contains tons of great snippets for different tasks when it comes to BLE:

Create a service:

let serviceUUID = CBUUID(string: kServiceUUID)
let service = CBMutableService(type: serviceUUID, primary: true)

Create characteristics:

let characteristicUUID = CBUUID(string: kCharacteristicUUID)
let properties: CBCharacteristicProperties = [.Notify, .Read, .Write]
let permissions: CBAttributePermissions = [.Readable, .Writeable]
let characteristic = CBMutableCharacteristic(
    type: characteristicUUID,
    properties: properties,
    value: nil,
    permissions: permissions)

Add characteristics to a service:

service.characteristics = [characteristic1, characteristic2]

Add a service to the peripheral manager:

peripheralManager.addService(service)

Source