2. Learn core bluetooth

Original link:current page

Now, I will learn and make the ble work in the application.

Apple Developer have introduced all the function and usage of Bluetooth, you can get anything you want if you take time to read it, although it's not a efficient way.
I may not have so much time to do this, so, I should find out anther way.

I search large data and finally a project is come out:https://github.com/adafruit/Basic-Chat, it's about a basic chat application with a ble device, and important, it's based in swift, this may be the best tempate.

I check out from the github and compile it as soon as possible

  $ cd [yourworkspace]
  $ git clone https://github.com/adafruit/Basic-Chat.git
  Cloning into 'Basic-Chat'...
  remote: Enumerating objects: 101, done.
  remote: Total 101 (delta 0), reused 0 (delta 0), pack-reused 101
  Receiving objects: 100% (101/101), 27.87 KiB | 110.00 KiB/s, done.
  Resolving deltas: 100% (51/51), done.

then enter the source directory

  $ cd Basic-Chat
  $ ls
  Basic Chat		Basic Chat.xcodeproj	LICENSE			README.md

now, open the xcode project

  $ open Basic Chat.xcodeproj


The porject is now in front of your eyes, you can see the project files in the left of xcode workspace.


what you should change is the Bundle Identifier, the Organization and the Team, if you haven't work in xcode before, you may need to configure your xcode.


OK, let's compile it, in xcode, press CMD + R, or click the button at the left-top side of xcode


Succeed…
Now the project is ready, and let's analyze the source code.

The Basic Code project has 3 part in Main.storyboard.

The ble related file is BLECentralViewController.swift, it contains the ble methods, such as connect, disconnect, peripheral related, and so on.

First, we need to change is ble's UUID.
First, you should found out the UUID of your ble devices, include the service UUID, transmit characteristic UUID and receive characteristic UUID.

Get UUID

Normally it is define in the ble init part.
If your device's ble mcu is a Nordic chip, such as NRF51822 or NRF52832, the UUID is always be call in the code like this:

    ble_uuid_t    ble_uuid;
    ...
    ble_uuid.type = p_oximeter->uuid_type;
    ble_uuid.uuid = BLE_UUID_OXIMETER_SERVICE;
    ...
    // Add the service.
    sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                &ble_uuid,
                                &p_oximeter->service_handle);

the BLE_UUID_OXIMETER_SERVICE is the service UUID,
and the transmit characteristic UUID as well as the receive is like this:

    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    ...
    ble_uuid.type = p_oximeter->uuid_type;
    ble_uuid.uuid = BLE_UUID_TX_CHARACTERISTIC;
    ...
    attr_char_value.p_uuid    = &ble_uuid;
    ...
    sd_ble_gatts_characteristic_add(p_oximeter->service_handle,
                                       &char_md,
                                       &attr_char_value,
                                       &p_oximeter->tx_handles);

the BLE_UUID_TX_CHARACTERISTIC is the transmit characteristic UUID.
For the receive characteristic is the same like this.
After finding these micro definitions, you can find out what the UUIDs they are.

If you can't get the UUID, another way is to debug this project, print the service and the characteristic's attributes, following the steps:

1. locate the startScan function in BLECentralViewController.swift, replace the

centralManager?.scanForPeripherals(withServices: [BLEService_UUID] , options: [CBCentralManagerScanOptionAllowDuplicatesKey:false])

with

centralManager?.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey:false])

2. add the print code in the front of the func peripheral-didDiscoverServices:

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    print("*******************************************************")
    print(peripheral.services) // print the services information

Now debug this project on your iOS device, if your ble peripheral device is advertising, the xcode debug area will print your device's ble service and characteristic's information, of course, all the ble device arround.
You need to check out which one is that you need, and replace it back in the UUIDKey.swift.

let kBLEService_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
let kBLE_Characteristic_uuid_Tx = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
let kBLE_Characteristic_uuid_Rx = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"

Receive data by ble

The callback function when iOS device receives data from ble peripheral is peripheral-didUpdateValueFor.
We can edit this function to do anything we want when receiving data.
For this example, the data is wave data for heartrate, the data is just be convert to a type UInt32 and save in a buffer.

Add a new graphview

We have the data already, next we will show all these value on iOS device.
Click the Main.storyboard, select the Uart Module View Controller Scene, Change the Base Text View height:

select the Base Text View, then click the Scroll View, change the Top Space to value to 350


add a new graphView by the steps of tutorial, if you had finished it before, just copy the swift file to this project. if everything is ok, you will get the storyboard view.

All right, the data and the graphView are already, what we need to do is to let the data be shown in the graphView.

Show data in GraphView

There is an array graphPoints in GraphView.swift, where the data should be put into.

First, edit the GraphView.swft, to define an array to store the data and the handle function.

  • add a member to the struct Constants:
static let maxBufferSize = 200
  • change the graphPoints definition and add a variable, switch
var graphPoints = [4, 2, 6, 4, 5, 8, 3]

with

var graphPoints:[Int32] = Array(repeating: 1, count: Constants.maxBufferSize)

add

var pos:Int = 0 // to record position of current data

behind the definition of graphPoints

  • add a function to handle the data addition.
func addHeartRatePoint(point: Int32) {
        if pos < graphPoints.count - 1 {
            pos += 1
        }
        else {
            pos = 0
        }
        graphPoints[pos] = point
}


Second, edit UartModuleViewController.swift, add a notification observer.

  • add function behind the function updateIncomingData
    func updateHeartrateData() {
        NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "Heartrate"), object: nil , queue: nil){
            notification in
 
            if self.refreshParse {
                return
            }
 
            self.HRLine.addHeartRatePoint(point: hrValue)
            self.HRLine.setNeedsDisplay()
        }
    }
  • add a caller of notification observer at the end of function viewDidLoad
updateHeartrateData()

Third, edit the BLECentralViewController.swift

  • add a global variable at the top of this file, to store the value converted from the source data.
var hrValue:Int32 = 0
  • edit the function peripheral-didUpdateValueFor, add the code to convert data to a [Int32] heartrate value, according to the format of the transmitted data from the peripheral device.
    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)
 
            }
 
            convertDataToInt32(data, hrValue) //this function must be defined by your self, according to the format of data from peripheral device
            NotificationCenter.default.post(name:NSNotification.Name(rawValue: "Heartrate"), object: nil)
        }
    }

By now, we had finished all the needed job. Now you can see what the application looks like.

The application on my Iphone 7 plus is like this:

It might be different with yours, because I commented the gradient code in GraphView.swift, made it simple.

the end

  • Last modified: 2019/08/23 12:18