CoreBluetooth BLE4.0

Hi,

I am trying to develop a BLE application in SwiftUI to control an Arduino connected via serial to a HM-10 module, and are having some issues updating Published vars with data being sent from my Arduino via HM-10, and also perhaps timing issues setting my isConnected Boolean variable, and possibly timing when setting my characteristic notify subscription up, and this is a particular issue when setting up Bluetooth pairing when connecting to my module.

Im after some specialist help, and due to the application requiring my HM-10 module to be present locally to interact with, and also requiring the application to run live on my phone whilst debugging in Xcode, I was wondering if I could set up a Team viewer session / other screen sharing mechanism and perhaps a phone call same time to help me with my issues please?

My Arduino does send packets of Bluetooth Serial information periodically, however I’m having problems filling my Published variables with this received information before my view loads.

While routines are blocking when used in .onAppear, and Timers aren’t working particularly well, and I need the serial data to set up my view, so I need some help to write some code in my view that will wait for this information before creating my view.

The biggest issue is that code in .onAppear seems to run before my corebluetooth is actually set up, so trying to use this to capture my serial data into my PublishedVars results in errors due to there being no data available.

My view relies on my published vars having data available to display things like sliders, and as such my view appears without my sliders.

I need to find a way to run some code on my view so that when bleMabanager.decodedJSON.indices.contains(0) is true, it’ll then loop through and populate my publishedvars with data either before my view loads, or after (as an update).

Really struggling with this, so would really appreciate some help.

Thanks

Alan

Hi @alantrundle

I cannot provide direct help because of my limited understanding and experience with CoreBluetooth and hardware integrations, what I can share is a prospective on how to solve the problem, but please note that this is an idea only.

On a side note: please be reminded that our student support team may be unable to provide assistance with some topics or areas that fall outside of our scope, such as those not covered in any of our courses, consulting, and coaching, as part of our Student Support Policy. *

Firstly, let’s ensure that your Bluetooth connection is established before the view loads. To do this, we can create a BluetoothManager class that handles all Bluetooth-related tasks, such as connecting, subscribing to notifications, and receiving data. This class will be an ObservableObject so that we can use it with SwiftUI and observe its properties.

Here’s an example of how you can create a BluetoothManager :

import Foundation
import CoreBluetooth

class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    @Published var isConnected: Bool = false
    @Published var receivedData: Data?

    // Other Bluetooth related properties
    // ...

    override init() {
        super.init()
        // Initialize and set up CoreBluetooth objects
    }

    // Implement the required CBCentralManagerDelegate and CBPeripheralDelegate methods
    // ...
}

Next, we can create a View that displays a loading screen until the Bluetooth connection is established and the required data is received:

import SwiftUI

struct ContentView: View {
    @StateObject private var bluetoothManager = BluetoothManager()

    var body: some View {
        Group {
            if bluetoothManager.isConnected && bluetoothManager.receivedData != nil {
                MainView(bluetoothManager: bluetoothManager)
            } else {
                LoadingView()
            }
        }
        .onAppear {
            bluetoothManager.startScanning()
        }
    }
}

struct LoadingView: View {
    var body: some View {
        VStack {
            Text("Connecting...")
            ProgressView()
        }
    }
}

struct MainView: View {
    @ObservedObject var bluetoothManager: BluetoothManager

    var body: some View {
        // Your main view content with sliders and other components
    }
}

In this example, the ContentView will display a LoadingView until the isConnected property is true and the receivedData is not nil. After that, it will display the MainView with your sliders and other components. The BluetoothManager is responsible for setting the isConnected and receivedData properties when the connection is established and data is received, respectively.

To process the received data and update the Published variables, you can create a method in the BluetoothManager class that processes the data and updates the variables accordingly. Call this method when the data is received in the CBPeripheralDelegate 's didUpdateValueFor method.

I hope this helps you.