Swift iPhone 与 ESP32 之间的 BLE 通信

Swift BLE communication between iPhone and ESP32

我完全是 Swift 的新手,因此有一些非常基本的问题。 我计划构建一个简单的 iPhone 应用程序,它可以与连接到我的 eBike 控制器的 ESP32 对话(双向)。 ESP32 设置为通过 BLE 传输和接收数据。它发送 4 个信号:mode(1,2,3)、light(on/off)、bat(battery;值在 31,5 和 41,5 之间) 和 speed(float) 并接受命令:“um”改变模式和“li”在灯光之间切换 on/off

各自的UUID如下

#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"

在 Swift 一侧,我有 UI,但我无法让按钮(模式、指示灯、连接)和连接正常工作。

这是我的 swift 文件,包括。 BLE 功能:

//
//  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()
    }
}



这是 UI 文件:


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()
    }
}

我想运行扫描完周围后的connectBLE功能

因此我的问题如下,

1.) 扫描整个区域后如何连接到特定设备? 我在从“peripheral.name”返回到 CBPeripheral 格式时遇到问题,我可以使用它来放入我的 myCentral.connect 函数。 2.) 两台设备连接后如何收发数据? 来自 ESP32 的所有信号均使用单独的 UUID 通过 ESP32 的通知传输,但我不知道如何在 Swift 端 get/handle 它们。 使用“模式”和“灯光”按钮,我想向 ESP32 发送简单的 ASCII 代码。

如果有人能在我遇到困难时帮助我,我将不胜感激。

最佳大卫

重要的是您宣传要找到的服务,而不仅仅是 create/facilitate。像 nRF connect 这样的应用程序可以帮助您确定该服务是否被广告,否则扫描服务(该特定服务)将不成功。

第二个问题:看他的作品https://www.raywenderlich.com/231-core-bluetooth-tutorial-for-ios-heart-rate-monitor

你可以读出意在被读的特征,反之亦然。并不总是需要通知。