Reading the Value of a Characteristic

Because we called peripheral.setNotify() in the previous step, whenever new data is available on the RX characteristic, two functions will be called on the peripheral's delegate –peripheral(_:didUpdateNotificationStateFor:error:)peripheral(_:didUpdateValueFor:error:).

In our implementation, peripheral(_:didUpdateNotificationStateFor:error:) simply prints info to the console.  peripheral(_:didUpdateValueFor:error:) is where we read and handle the new incoming data from the peripheral.

Download: file
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

   if characteristic == rxCharacteristic {
     if let ASCIIstring = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue) {
        characteristicASCIIValue = ASCIIstring
        print("Value Recieved: \((characteristicASCIIValue as String))")
        NotificationCenter.default.post(name:NSNotification.Name(rawValue: "Notify"), object: nil)
	}
  }
}

In didUpdateValueFor(), we check to make sure the characteristic is the RX characteristic.  If it is, we read the value and convert it to an ASCII string.  We print the converted ASCII value to the console and we post a notification which can be used to update UI elements with the newly received data.

Writing to a Characteristic

Before we can write data to our external peripheral, we need to know how we want to write that data.  There are two types of CBCharacteristic write types that we need to be aware of. The CBCharacteristic write type can be either .withResponse or .withoutResponse.

The .withResponse property type gets a response from the peripheral to indicate whether the write was successful. The .withoutResponse doesn't send any response back from the peripheral.

To write to a characteristic we’ll need to write a value with an instance NSData and we’ll do that by calling  writeValue(for: , type: CBCharacteristicWriteType.withResponse) method:

Download: file
blePeripheral.writeValue(data!, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse)

Now you’ll be able to write to a characteristic with a writeable attribute. You can find this example code in the UartModuleViewController.

Download: file
// Write functions
    func writeValue(data: String){
      let valueString = (data as NSString).data(using: String.Encoding.utf8.rawValue)
        if let blePeripheral = blePeripheral{
           if let txCharacteristic = txCharacteristic {
              blePeripheral.writeValue(valueString!, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse)
            }
        }
    }

In the writeValue(data) function above, we format the outgoing string as NSData and then check to see if the bleperipheral and txCharacteristic varaiables are set.  If they are, we then call the the writeValue() function as explained previously.

Because we wrote the value with a type of CBCharacteristicWriteType.withResponse, we can be notified of the response by implementing the following function in the delegate:

Download: file
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    guard error == nil else {
        print("Error discovering services: error")
      return
    }
     print("Message sent")
}

In this case, we simply use the write response to print relevant info to the debug console.

This guide was first published on Jul 27, 2017. It was last updated on Jul 27, 2017.

This page (Communication ) was last updated on Nov 24, 2020.