Thursday, September 29, 2022
HomeiOS Developmentios - Swift BLE communication between iPhone and ESP32

ios – Swift BLE communication between iPhone and ESP32

[ad_1]

I am a complete noobie in Swift and have therefore some very basic questions.
I planned to build a simple iPhone app, which can talk (bidirectional) with my ESP32 which is connected to my eBike controller. The ESP32 is set up to transmit and receive data over BLE. It sends 4 signals: mode(1,2,3), light(on/off), bat(battery; values between 31,5 and 41,5) and speed(float) and accepts to commands: “um” to change the mode and “li” to switch between light on/off

The respective UUIDs are as followed

#define SERVICE_UUID           "19074fb4-161b-47c7-964e-9d087266d6a7" 
#define CHARACTERISTIC_UUID_RX "101880eb-a78e-4cee-b252-56e06093f4da"
#define CHARACTERISTIC_UUID_TX_MODE "5d64d30b-3e03-4e65-82a2-a85e9d568f84"
#define CHARACTERISTIC_UUID_TX_LIGHT "dfbec318-8292-4b34-87b5-f13e4efb1560"
#define CHARACTERISTIC_UUID_TX_BAT "a5b79c5d-977a-4ef0-b3f3-b8f26e166378"
#define CHARACTERISTIC_UUID_TX_SPEED "b0bfad34-c571-41a5-8bc3-7726ced1ebbe"

on the Swift side, I have the UI, but I can’t the get the buttons (mode, light, connect) and the connection to work properly.

Here is my swift file incl. the BLE-functions:

//
//  BLEController.swift
//  Bike Controller
//
//  Created by David Melinc on 19.05.22.
//

import Foundation
import CoreBluetooth

struct Peripheral: Identifiable {
    let id: Int
    let name: String
    let rssi: Int
}

class BLEController: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
   
    var myCentral: CBCentralManager!
    var myPeripheral: CBPeripheral!
   
    @Published var isSwitchedOn = false
    @Published var peripherals = [Peripheral]()
    @Published var mode: UInt16 = 0
    @Published var light: String = " "
    @Published var bat: UInt16 = 0
    @Published var speed: UInt16 = 0
    
    let SERVICE_UUID  = CBUUID(string: "19074fb4-161b-47c7-964e-9d087266d6a7")
    let CHARACTERISTIC_UUID_RX  = CBUUID(string: "101880eb-a78e-4cee-b252-56e06093f4da")
    let CHARACTERISTIC_UUID_TX_MODE  = CBUUID(string: "5d64d30b-3e03-4e65-82a2-a85e9d568f84")
    let CHARACTERISTIC_UUID_TX_LIGHT  = CBUUID(string: "dfbec318-8292-4b34-87b5-f13e4efb1560")
    let CHARACTERISTIC_UUID_TX_BAT = CBUUID(string:  "a5b79c5d-977a-4ef0-b3f3-b8f26e166378")
    let CHARACTERISTIC_UUID_TX_SPEED  = CBUUID(string: "b0bfad34-c571-41a5-8bc3-7726ced1ebbe")

    override init() {
        super.init()
        myCentral = CBCentralManager(delegate: self, queue: nil)
    }
   
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            isSwitchedOn = true
        }
        else {
            isSwitchedOn = false
        }
    }    
    
       func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        var peripheralName: String!
           
        if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
            peripheralName = name
        }
        else {
            peripheralName = "Unknown"
        }
           
        let newPeripheral = Peripheral(id: peripherals.count, name: peripheralName, rssi: RSSI.intValue)
        print(newPeripheral)
        peripherals.append(newPeripheral)
        
    }

     
    func connectBLE(peripheral1) {
        print("trying to connect to \(peripheral1)")
                        self.myCentral.connect(peripheral1, options: nil)
                        print(2)
                        }
            }
        }
         
    }

    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        self.myPeripheral.discoverServices(nil)
        print("Connected to "+peripheral.name!)
    }
    
    func startScanning() {
        print("startScanning")
        myCentral.scanForPeripherals(withServices: nil, options: nil)
        self.perform(#selector(stopScanning), with: self, afterDelay: 5)
    }
    @objc func stopScanning() {
        print("stopScanning")
        myCentral.stopScan()
    }
}



Here is the UI file:


import SwiftUI

struct BLEdevices: View {
    
    //@StateObject var bleController = BLEController()
    @EnvironmentObject var bleController: BLEController
    
    var body: some View {
        ZStack {
            Color("Themecolor")
            .edgesIgnoringSafeArea(.all)
                VStack (spacing: 10) {
                    Text("Bluetooth Devices")
                        .font(.largeTitle)
                        .frame(maxWidth: .infinity, alignment: .center)
                    List(bleController.peripherals) { peripheral in
                        HStack {
                            Text(peripheral.name)
                            Spacer()
                            Text(String(peripheral.rssi))
                            Spacer()
                            Button(action: {
                                //bleController.connectBLE(peripheral.name)
                                    }) {
                                Text("CONNECT")
                                    .font(.system(size: 10))
                                    .fontWeight(.bold)
                                    .padding()
                                    .foregroundColor(.black)
                                    .frame(alignment: .center)
                                    .background(
                                      RoundedRectangle(cornerRadius: 10)
                                          .stroke(Color.white, lineWidth: 2)
                                          .background(Color.white.cornerRadius(10)))
                                    }
                            
                        }
                    }
                    .frame(height: 600)
                    HStack (spacing: 10) {
                        Button(action: {
                            bleController.startScanning()
                                }) {
                            Text("SCAN")
                                .font(.title)
                                .fontWeight(.bold)
                                .padding()
                                .foregroundColor(.black)
                                .frame(width: 150, alignment: .center)
                                .background(
                                  RoundedRectangle(cornerRadius: 25)
                                      .stroke(Color.white, lineWidth: 2)
                                      .background(Color.white.cornerRadius(25)))
                                }
                        Button(action: {
                            bleController.stopScanning()
                                }) {
                            Text("STOP")
                                .font(.title)
                                .fontWeight(.bold)
                                .padding()
                                .foregroundColor(.black)
                                .frame(width: 150, alignment: .center)
                                .background(
                                  RoundedRectangle(cornerRadius: 25)
                                      .stroke(Color.white, lineWidth: 2)
                                      .background(Color.white.cornerRadius(25)))
                                }
                        }
                    }
        }
    }
}

struct BLEdevices_Previews: PreviewProvider {
    static var previews: some View {
        BLEdevices()
    }
}

I would like to run the connectBLE function after I scanned the surrounding.

my questions are therefore as follows,

1.) how can I connect to a specific device after I scanned the whole area?
I have problems to get from the “peripheral.name” back to the CBPeripheral format, which I could use to put in my myCentral.connect function.
2.) how can I receive and transmit data between the two devices after they are connected?
All signals from ESP32 are transmitted via notify from the ESP32 using separate UUIDs, but I don’t know how I get/handle them on the Swift side.
With the buttons “mode” and “light” I want to send simple ASCII code to the ESP32.

I would highly appreciate, if someone can help me here as I am stuck.

Best David

UI of main page

[ad_2]

Source link

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments