This guide will show y'all the basics of developing your own Bluetooth Low Free energy (BLE) app using the Core Bluetooth Framework in Xcode.

Y'all'll demand a basic understanding of Swift, but no prior experience with Bluetooth Low Energy is required. The example lawmaking provided in this guide can be applied to both iPhone and iPad users running the current version of iOS.

For this guide I'll be using the Adafruit Plume 32u4 Bluefruit LE to send and receive data.

Before you begin, know that the Simulator in Xcode isn't capable of using Bluetooth LE services. You'll need to follow along using an iPhone or iPad running the well-nigh electric current version of iOS (Version fourteen+).

Since you'll need to test your app using an iOS device, y'all'll also need an Apple Developer membership (please annotation that gratuitous membership enrollment is fine for following along with this guide).If you lot need help getting started as an iOS programmer, check out the Adafruit guide covering how to enroll to the Apple Developer plan and gain membership:

  • Introduction to iOS Development

Before starting...

  • Install Xcode. Click here to download Xcode from the Apple App Store.
  • Make sure your version of Xcode is up to date. I'thousand using Xcode Version 12.4 at the time of making this guide.
  • While in Xcode make certain the Evolution Target is 14.0 or higher.
  • Download the Arduino IDE from the main website here if you haven't already.

Parts

You don't demand much to start this project, only you'll demand these:

Plume is the new development board from Adafruit, and like its namesake it is thin, lite, and lets you fly! Nosotros designed Plumage to be a new standard for portable microcontroller...

Or

Feather is the new development board from Adafruit, and like its namesake, it is thin, light, and lets you wing! Nosotros designed Feather to exist a new standard for portable microcontroller...

And

This hither is your standard A to micro-B USB cable, for USB 1.ane or ii.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or...

Download project from Github

To all-time visualize how things work, I recommend that you should follow forth with the app provided in this guide. The Bones Conversation app sends and receives information using the Feather Bluefruit'southward UART connection. Y'all tin learn more about UARTs here.

Get to the download page for the project. One time on the folio, click on the "Clone or download" button.

breakout_boards_Screen_Shot_2021-02-18_at_9.44.24_PM.png

Once the file is downloaded, click on the Basic Conversation MVC.xcodeproj app and information technology will open up up the project in Xcode.

breakout_boards_Screen_Shot_2021-02-18_at_9.47.37_PM.png

Once we have the project open, select your iOS device'southward scheme in Xcode.

breakout_boards_Screen_Shot_2021-02-18_at_9.48.42_PM.png

Now only printing the Run button to test the app on your iOS device.

feather_www.png

If all goes well, theBasic Chat MVC app will run on your iOS device and y'all'll exist able to use the app as a reference while you explore the guide.

Make sure your Bluetooth is enabled while using Basic Chat

Understanding Core Bluetooth

The Core Bluetooth framework provides the classes needed for your apps to communicate with Bluetooth-equipped low energy (LE) and Basic Charge per unit / Enhanced Data Rate (BR/EDR) wireless technology.

Nosotros demand the CBCentralManager object that scans for, discovers, connects to, and manages peripherals. Nosotros'll besides need the CBPeripheral object that represents remote peripheral devices that your app discovers with a central manager.

A CBPeripheral is used to discover, explore, and collaborate with the services bachelor on a remote peripheral that supports Bluetooth low energy.

A service encapsulates the way function of the device behaves. For example, ane service of a eye rate monitor may be to expose heart rate data from a sensor.

Services themselves contain of characteristics or included services (references to other services).

Characteristics provide further details about a peripheral'south service. For case, the centre rate service may contain multiple characteristics.

The post-obit diagram shows the hierarchy of the CBPeripheral:

feather_CB-diagram.jpg

Getting Started

Earlier starting to code, you need to create a prompt that asks for permission to use the device's Bluetooth.

In your file hierarchy on the left, locate Info.plist.

breakout_boards_Screen_Shot_2021-02-18_at_10.33.13_PM.png

Add together these to your info.plist:

• Privacy - Bluetooth Peripheral Usage Description

• Privacy - Bluetooth Always Usage Description

Add a clarification you see fit.

breakout_boards_Screen_Shot_2021-02-18_at_10.21.15_PM.png

In this example, a bulletin tells the user why the app is requesting the ability to connect to Bluetooth peripherals.

Now, to look at some code.

In your project'south file bureaucracy, locate "ViewController.swift". This file handles the majority of the tasks which need to be performed to connect to a Bluetooth device.

breakout_boards_Screen_Shot_2021-02-18_at_10.08.42_PM.png

At the top of the file, import CoreBluetooth:

import CoreBluetooth
import CoreBluetooth

This line adds Core Bluetooth framework to the project andgives the ability to communicate with Bluetooth devices.

Now create variable to store your cardinal manager. The primal director manages discovered or connected remote peripheral devices (represented past CBPeripheral objects), including scanning for, discovering, and connecting to advertising peripherals.

var centralManager: CBCentralManager!
var centralManager: CBCentralManager!

Then in your viewDidLoad, initialize the central manager by setting the delegate to self, otherwise the central state never changes on startup.

override func viewDidLoad() {    super.viewDidLoad()    centralManager = CBCentralManager(delegate: cocky, queue: nil)  }
override func viewDidLoad() {    super.viewDidLoad()    centralManager = CBCentralManager(delegate: self, queue: nil)  }

At present add a CBCentralManagerDelegate protocol to the ViewController in order to scan, find and connect a peripheral.

The CBCentralManagerDelegate protocol defines the methods that a delegate of a CBCentralManager object must prefer.

extension ViewController: CBCentralManagerDelegate {    func centralManagerDidUpdateState(_ central: CBCentralManager) {           switch central.land {           instance .poweredOff:               print("Is Powered Off.")           case .poweredOn:               print("Is Powered On.")               startScanning()           case .unsupported:               print("Is Unsupported.")           instance .unauthorized:           print("Is Unauthorized.")           case .unknown:               print("Unknown")           case .resetting:               print("Resetting")           @unknown default:             print("Error")           }   }  }
extension ViewController: CBCentralManagerDelegate {    func centralManagerDidUpdateState(_ cardinal: CBCentralManager) {           switch cardinal.land {           case .poweredOff:               impress("Is Powered Off.")           case .poweredOn:               print("Is Powered On.")               startScanning()           case .unsupported:               impress("Is Unsupported.")           case .unauthorized:           impress("Is Unauthorized.")           case .unknown:               impress("Unknown")           case .resetting:               print("Resetting")           @unknown default:             print("Mistake")           }   }  }

The only method required forCBCentralManagerDelegate would becentralManagerDidUpdateState(_:); the central manager calls this when its state updates, thereby indicating the availability of the central manager.

This required method is added to ensure that the central device (your iPhone or iPad) supports Bluetooth low free energy and that it's available to apply.

Also add a CBPeripheralDelegate protocol. The CBPeripheralDelegate provides updates on the use of a peripheral'due south services. This volition exist needed later.

extension ViewController: CBPeripheralDelegate { }
extension ViewController: CBPeripheralDelegate { }

Earlier going any further, you need to shop a list of unique identifiers to assistance look for specific Bluetooth devices. Create a new file chosen CBUUIDs that stores the unique identifiers.

import Foundation import CoreBluetooth  struct CBUUIDs{      static let kBLEService_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"     static permit kBLE_Characteristic_uuid_Tx = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"     static allow kBLE_Characteristic_uuid_Rx = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"      static let BLEService_UUID = CBUUID(cord: kBLEService_UUID)     static let BLE_Characteristic_uuid_Tx = CBUUID(string: kBLE_Characteristic_uuid_Tx)//(Property = Write without response)     static allow BLE_Characteristic_uuid_Rx = CBUUID(string: kBLE_Characteristic_uuid_Rx)// (Holding = Read/Notify)  }
import Foundation import CoreBluetooth  struct CBUUIDs{      static let kBLEService_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"     static let kBLE_Characteristic_uuid_Tx = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"     static let kBLE_Characteristic_uuid_Rx = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"      static allow BLEService_UUID = CBUUID(cord: kBLEService_UUID)     static let BLE_Characteristic_uuid_Tx = CBUUID(cord: kBLE_Characteristic_uuid_Tx)//(Property = Write without response)     static let BLE_Characteristic_uuid_Rx = CBUUID(string: kBLE_Characteristic_uuid_Rx)// (Property = Read/Notify)  }

CBUUID class represents universally unique identifiers (UUIDs) of attributes used in Bluetooth low energy advice, such as a peripheral's services, characteristics, and descriptors.

Past specifying what service to looking for, y'all tell the CBCentralManager to ignore all peripherals which don't advertise that specific service, and return a list of only the peripherals that offer this service.

Now to head back into the ViewController to start scanning for peripherals.

Scanning for Peripherals

Once the CBCentralManager is up and powered on, y'all tin create a function that scan for peripherals around u.s..

Create a function called startScanning. Call the method scanForPeripherals(withServices:).

This method scans for peripherals that are advert services. Now since the unique identifier is set up, add that reference to the method.

func startScanning() -> Void {   // Start Scanning   centralManager?.scanForPeripherals(withServices: [CBUUIDs.BLEService_UUID]) }
func startScanning() -> Void {   // Start Scanning   centralManager?.scanForPeripherals(withServices: [CBUUIDs.BLEService_UUID]) }

Now add together the startScanning() function to the centralManagerDidUpdateState to scan as before long as the app opens.

extension ViewController: CBCentralManagerDelegate {    func centralManagerDidUpdateState(_ primal: CBCentralManager) {           switch central.state {           instance .poweredOff:               print("Is Powered Off.")           case .poweredOn:               print("Is Powered On.")               startScanning()           case .unsupported:               print("Is Unsupported.")           example .unauthorized:           print("Is Unauthorized.")           example .unknown:               print("Unknown")           case .resetting:               print("Resetting")           @unknown default:             impress("Error")           }   }  }
extension ViewController: CBCentralManagerDelegate {    func centralManagerDidUpdateState(_ central: CBCentralManager) {           switch fundamental.state {           instance .poweredOff:               print("Is Powered Off.")           instance .poweredOn:               print("Is Powered On.")               startScanning()           case .unsupported:               print("Is Unsupported.")           instance .unauthorized:           print("Is Unauthorized.")           case .unknown:               print("Unknown")           instance .resetting:               impress("Resetting")           @unknown default:             print("Error")           }   }  }

When you run your app, your device will start scanning for peripherals.

Discovering Peripherals

Now that scanning is started, what happens when a peripheral is discovered?

Every time a peripheral is discovered, theCBCentralManager will notify you by calling the centralManager(_:didDiscover:advertisementData:rssi:) function on its delegate.

This function provides the following information about the newly discovered peripheral:

  • The discovered peripheral is recognized and tin can be stored as a CBPeripheral.
  • The discovered peripheral has stored advertisement data.
  • The current received signal strength indicator (RSSI) of the peripheral, in decibels.

Since you lot are interested in connecting to one peripheral, create an instance of a peripheral.

private var bluefruitPeripheral: CBPeripheral!
private var bluefruitPeripheral: CBPeripheral!

Call the didDiscover office. This tells the delegate the cardinal director discovered a peripheral while scanning for devices.

func centralManager(_ key: CBCentralManager, didDiscover peripheral: CBPeripheral,advertisementData: [String : Whatever], rssi RSSI: NSNumber) {      bluefruitPeripheral = peripheral      bluefruitPeripheral.delegate = self      print("Peripheral Discovered: \(peripheral)")   	impress("Peripheral proper name: \(peripheral.name)")     print ("Advertizement Data : \(advertisementData)")              centralManager?.stopScan()    }
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,advertisementData: [String : Whatsoever], rssi RSSI: NSNumber) {      bluefruitPeripheral = peripheral      bluefruitPeripheral.delegate = self      print("Peripheral Discovered: \(peripheral)")   	print("Peripheral proper noun: \(peripheral.proper name)")     print ("Advertisement Data : \(advertisementData)")              centralManager?.stopScan()    }

The implementation of this role performs the following deportment:

  • Gear up the bluefruitPeripheral variable to the new peripheral found.
  • Set the peripheral's consul to self (ViewController)
  • Printed the newly discovered peripheral'due south information in the console.
  • Stopped scanning for peripherals.

Adjacent up - really connect to that peripheral.

To connect to a peripheral, employ this method to establish a local connection to the desired peripheral.

centralManager?.connect(blePeripheral!, options: cipher)
centralManager?.connect(blePeripheral!, options: aught)

Add this to the didDiscover function.

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,advertisementData: [String : Any], rssi RSSI: NSNumber) {      bluefruitPeripheral = peripheral     bluefruitPeripheral.delegate = cocky      print("Peripheral Discovered: \(peripheral)")   	print("Peripheral name: \(peripheral.proper name)")     impress ("Ad Data : \(advertisementData)")          centralManager?.connect(bluefruitPeripheral!, options: nil)     }
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,advertisementData: [String : Any], rssi RSSI: NSNumber) {      bluefruitPeripheral = peripheral     bluefruitPeripheral.delegate = self      impress("Peripheral Discovered: \(peripheral)")   	impress("Peripheral name: \(peripheral.name)")     print ("Advertisement Information : \(advertisementData)")          centralManager?.connect(bluefruitPeripheral!, options: nil)     }

One time the connectedness is fabricated, the central managing director calls thecentralManager(_:didConnect) delegate role to provide incoming data about the newly continued peripheral.

Once this function is chosen, you'll discover a service that the peripheral is property.

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {    bluefruitPeripheral.discoverServices([CBUUIDs.BLEService_UUID]) }
func centralManager(_ key: CBCentralManager, didConnect peripheral: CBPeripheral) {    bluefruitPeripheral.discoverServices([CBUUIDs.BLEService_UUID]) }

Finishing the discovering services, you'll become a didDiscoverServices upshot. Iterate through all the "available" services.

Discovering Services

Now that the peripheral'due south services are successfully discovered, the central director volition telephone call thedidDiscoverServices() consul part.didDiscoverService() handles and filters services, and so that yous can apply whichever service y'all are interested in correct away.

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices mistake: Error?) {         print("*******************************************************")          if ((fault) != zero) {             print("Error discovering services: \(error!.localizedDescription)")             return         }         guard let services = peripheral.services else {             return         }         //We need to discover the all characteristic         for service in services { 			peripheral.discoverCharacteristics(nil, for: service)         }         print("Discovered Services: \(services)")     }
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices mistake: Fault?) {         print("*******************************************************")          if ((fault) != nil) {             impress("Mistake discovering services: \(fault!.localizedDescription)")             return         }         guard let services = peripheral.services else {             return         }         //Nosotros need to discover the all characteristic         for service in services { 			peripheral.discoverCharacteristics(nil, for: service)         }         print("Discovered Services: \(services)")     }

First, handle any possible errors returned by the central manager, then request characteristics for each service returned past calling discoverCharacteristics(_:)

Discovering Characteristics

Create two feature variables to reference.

private var txCharacteristic: CBCharacteristic! private var rxCharacteristic: CBCharacteristic!
private var txCharacteristic: CBCharacteristic! private var rxCharacteristic: CBCharacteristic!

Now call the discoverCharacteristics(_:) office, the central manager will call thedidDiscoverCharacteristicsFor() delegate function and provide the discovered characteristics of the specified service.

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {                    baby-sit let characteristics = service.characteristics else {           return       }        print("Institute \(characteristics.count) characteristics.")        for feature in characteristics {          if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Rx)  {            rxCharacteristic = characteristic            peripheral.setNotifyValue(truthful, for: rxCharacteristic!)           peripheral.readValue(for: characteristic)            print("RX Characteristic: \(rxCharacteristic.uuid)")         }          if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Tx){                      txCharacteristic = feature                      print("TX Characteristic: \(txCharacteristic.uuid)")         }       } }
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, fault: Mistake?) {                    baby-sit let characteristics = service.characteristics else {           return       }        print("Establish \(characteristics.count) characteristics.")        for characteristic in characteristics {          if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Rx)  {            rxCharacteristic = characteristic            peripheral.setNotifyValue(true, for: rxCharacteristic!)           peripheral.readValue(for: characteristic)            print("RX Feature: \(rxCharacteristic.uuid)")         }          if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Tx){                      txCharacteristic = characteristic                      print("TX Characteristic: \(txCharacteristic.uuid)")         }       } }

A couple of things are happening in this office:

  1. Handle errors and print characteristic info to the debug panel
  2. Look through the assortment of characteristics for a lucifer to desired UUIDs.
  3. Perform whatsoever necessary actions for the matching characteristics
  4. Detect descriptors for each characteristic

In this instance, the specific UUIDs we're looking for are stored in theBLE_Characteristic_uuid_Rx and BLE_Characteristic_uuid_Tx variables.

When it finds the RX characteristic, information technology subscribe to updates to its value by calling setNotifyValue() - this is how to receive information from the peripheral. Additionally, read the current value from the characteristic and print its information to the console.

When it finds the TX feature, it saves a reference to information technology to write values to it after - this is how to ship data to the peripheral.

Disconnecting from Peripheral

To disconnect or cancels an active or awaiting local connexion to a peripheral, use the .cancelPeripheralConnection method.

func disconnectFromDevice () { 	if blePeripheral != nil { 	centralManager?.cancelPeripheralConnection(blePeripheral!)     }  }
func disconnectFromDevice () { 	if blePeripheral != zippo { 	centralManager?.cancelPeripheralConnection(blePeripheral!)     }  }

This method is nonblocking, and whatsoever CBPeripheral class commands that are still pending to peripheral may not complete.

Because other apps may still accept a connection to the peripheral, canceling a local connectedness doesn't guarantee that the underlying physical link is immediately disconnected.

Now, that you've connected to our Bluetooth device, it'due south time to communicate send and receive data.

Setting up communication

To start communicating with the Bluetooth device, you'll need to setup a protocol that provides updates for local peripheral state and interactions with remote central devices.

That protocol would be CBPeripheralManagerDelegate, so add an extension to the ViewController and add CBPeripheralManagerDelegate.

extension ViewController: CBPeripheralManagerDelegate {    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {     switch peripheral.state {     instance .poweredOn:         print("Peripheral Is Powered On.")     case .unsupported:         print("Peripheral Is Unsupported.")     case .unauthorized:     print("Peripheral Is Unauthorized.")     case .unknown:         print("Peripheral Unknown")     instance .resetting:         print("Peripheral Resetting")     example .poweredOff:       impress("Peripheral Is Powered Off.")     @unknown default:       impress("Error")     }   } }
extension ViewController: CBPeripheralManagerDelegate {    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {     switch peripheral.land {     instance .poweredOn:         print("Peripheral Is Powered On.")     case .unsupported:         impress("Peripheral Is Unsupported.")     case .unauthorized:     print("Peripheral Is Unauthorized.")     example .unknown:         impress("Peripheral Unknown")     instance .resetting:         impress("Peripheral Resetting")     case .poweredOff:       print("Peripheral Is Powered Off.")     @unknown default:       impress("Mistake")     }   } }

The protocol's requires ane method, peripheralManagerDidUpdateState(_:) , which Core Bluetooth calls whenever the peripheral manager'south state updates to indicate whether the peripheral managing director is available.

Reading the Value of a Characteristic

Since peripheral.setNotifyValue has been chosen previously in the didDiscoverCharacteristicsFor method, y'all are able to set notifications or indications for incoming values registered to the rxcharacteristic.

Once receiving incoming values from a Bluetooth device, Core Bluetooth invokesdidUpdateValueFor to handle that incoming data.

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, fault: Error?) {        var characteristicASCIIValue = NSString()        baby-sit characteristic == rxCharacteristic,        let characteristicValue = characteristic.value,       let ASCIIstring = NSString(data: characteristicValue, encoding: String.Encoding.utf8.rawValue) else { return }        characteristicASCIIValue = ASCIIstring        print("Value Recieved: \((characteristicASCIIValue as String))") }
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {        var characteristicASCIIValue = NSString()        guard feature == rxCharacteristic,        allow characteristicValue = characteristic.value,       let ASCIIstring = NSString(data: characteristicValue, encoding: String.Encoding.utf8.rawValue) else { render }        characteristicASCIIValue = ASCIIstring        print("Value Recieved: \((characteristicASCIIValue as String))") }

IndidUpdateValueFor(), first create an example of NSString , that will be  the characteristicASCIIValue variable to hold an incoming value, then convert it to an ASCII string, then print the converted ASCII value to the console.

Writing to a Feature

Before writing information to an external peripheral, yous need to know how nosotros want to write that information.

At that place are two types of CBCharacteristic write types. 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 transport any response back from the peripheral.

To write to a characteristic you'll need to write a value with an instance of NSData and practise that past calling writeValue(for: , type: CBCharacteristicWriteType.withResponse) method:

bluefruitPeripheral.writeValue(data!, for: txCharacteristic, blazon: CBCharacteristicWriteType.withResponse)
bluefruitPeripheral.writeValue(data!, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse)

Create a new function that will communicate with the Bluetooth device. I've chosen this function writeOutgoingValue(), simply call it whatever you'd like.

First, format the outgoing string equally NSData. Then, make sure bluefruitPeripheral and txCharacteristic variables are non prepare to naught.

So add the writeValue method into your function.

func writeOutgoingValue(data: String){            allow valueString = (data as NSString).data(using: String.Encoding.utf8.rawValue)          if let bluefruitPeripheral = bluefruitPeripheral {                  if let txCharacteristic = txCharacteristic {                        bluefruitPeripheral.writeValue(valueString!, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse)           }       }   }
func writeOutgoingValue(data: String){            permit valueString = (data as NSString).data(using: String.Encoding.utf8.rawValue)          if let bluefruitPeripheral = bluefruitPeripheral {                  if allow txCharacteristic = txCharacteristic {                        bluefruitPeripheral.writeValue(valueString!, for: txCharacteristic, blazon: CBCharacteristicWriteType.withResponse)           }       }   }

Crawly. Now that yous've given the app the ability to communicate with a Bluetooth device, claw up the device to the Arduino IDE.

Ok, now to hook up some quick UI to test out the app.

In your file hierarchy located on the left, locate and go to Main.storyboard. Hither, create a button that volition trigger the part to transmit the data to the Bluetooth device.

breakout_boards_Screen_Shot_2021-02-22_at_12.28.07_AM.png

Above your navigation pane, select the "+" push to display a library of UI elements.

breakout_boards_Screen_Shot_2021-02-22_at_12.28.30_AM.png

Now that you lot've opened up the UI library, press and slide "Button" onto you View Controller.

breakout_boards_Screen_Shot_2021-02-22_at_12.28.53_AM.png

Ok, I gave my changed my push button label to "Send How-do-you-do World", you can modify it to your liking.

breakout_boards_Screen_Shot_2021-02-22_at_1.19.08_AM.png

Now connect the UI to the lawmaking. Press this icon on the upper correct corner of your Navigation Pane, and locate your ViewController.swift file.

breakout_boards_Screen_Shot_2021-02-22_at_1.23.57_AM.png

Once you lot've washed that, Control elevate and drib the push to the ViewController.swift file. Instead if calculation an Outlet, create an action and name it "buttonPress".

breakout_boards_Screen_Shot_2021-02-22_at_1.25.32_AM.png

Now caput back into the ourViewController.swift file. Inside the buttonPress method, add together the writeOutgoingValue()  method and add together a cord into the parameter. I've chosen to send "Howdy Give-and-take".

@IBAction func buttonPress(_ sender: Whatever) {     writeOutgoingValue(data: "Hullo World")   }
@IBAction func buttonPress(_ sender: Whatever) {     writeOutgoingValue(data: "Hi Globe")   }

Neat! Now to set upwardly communications on the Bluetooth device.

Sending Information

To demonstrate the functionality of the app using an Adafruit Feather Bluefruit 32u4 board, connect it to a figurer running the Arduino IDE. If you don't already have your Arduino IDE setup or if it's not recognizing your board, take a look at this learn guide on how to exercise and then:

  • Adafruit Feather 32u4 Bluefruit LE Acquire Guide

You lot tin can use the serial monitor to read and write letters back and forth with the Basic Chat app.

Inside the Arduino IDE, go to File->Examples->Adafruit BluefruitLEnRF51then select bleart_cmdmode.  Once the sketch is opened, upload it to your Feather and click on the Serial Monitor button in the upper right of the Arduino IDE window.  A new serial monitor window will open up.

feather_new-450.jpg

feather_serialcomm-450.jpg

This new serial monitor window is where you'll be able to communicate between your Bluetooth device and yourapp.

Open up the app you've made and and so hit your button.

breakout_boards_blinka.png

When y'all tap the button, your message should pop upwardly in the Arduino Serial monitor view.

breakout_boards_Screen_Shot_2021-02-22_at_2.26.07_AM.png

Now you've successfully sent the cord "Hello Earth!" to the Plume and it displayed in the Series monitor view.

Now to send "Hullo Back" to your app. Type "Hello World!" in the text field of the Arduino IDE's series monitor window and and so hit Send.

breakout_boards_Screen_Shot_2021-02-22_at_2.30.31_AM.png

You should receive a "Hello Back" in the console.

Congrats!

You've successfully demonstrated the Bluetooth app's functionality and learned the basics of BLE communication using CoreBluetooth.  With this knowledge and the Basic Conversation MVC app as a reference, you can start building fifty-fifty more complex Bluetooth apps!

This guide was offset published on Jul 27, 2022. It was last updated on 2022-02-23 12:51:57 -0500.