- import CoreBluetooth
- import SwiftUI
- struct ContentView: View {
- @State private var fileURL: URL? = nil
- @State private var status: String = "Not Connected"
- @StateObject private var bluetoothManager = BluetoothManager()
- var transferRateText: String {
- let transferRateKB = bluetoothManager.transferRate / 1024
- if transferRateKB < 1024 {
- return String(format: "%.2f KB/s", transferRateKB)
- } else {
- let transferRateMB = transferRateKB / 1024
- return String(format: "%.2f MB/s", transferRateMB)
- }
- }
- var body: some View {
- VStack {
- Button("Select File") {
- // TODO: Select file
- selectFile()
- }
- .padding()
- Text("Status: \(bluetoothManager.status)")
- .padding()
- Text("Transfer Rate: \(transferRateText)")
- .padding()
- Text("Total Time: \(bluetoothManager.totalTime, specifier: "%.2f") seconds")
- .padding()
- List(bluetoothManager.discoveredDevices, id: \.identifier) { device in
- HStack {
- Text(device.name ?? "Unknown")
- Spacer()
- Button("Connect") {
- bluetoothManager.connectToDevice(device)
- }
- }
- }
- }
- }
- private func selectFile() {
- bluetoothManager.presentFilePicker()
- }
- }
- #Preview {
- ContentView()
- }
- class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
- private var centralManager: CBCentralManager!
- private var peripheral: CBPeripheral?
- public var fileTransferCharacteristic: CBCharacteristic?
- @Published var status: String = "Not Connected"
- @Published var discoveredDevices: [CBPeripheral] = []
- private var startTime: Date?
- private var endTime: Date?
- var fileData: Data!
- @Published var transferRate: Double = 0.0
- @Published var totalTime: Double = 0.0
- private var connectionParameters: [String: Any]?
- override init() {
- super.init()
- centralManager = CBCentralManager(delegate: self, queue: nil)
- }
- func centralManagerDidUpdateState(_ central: CBCentralManager) {
- if central.state == .poweredOn {
- centralManager.scanForPeripherals(withServices: nil, options: nil)
- }
- }
- // TODO: Implement other delegate methods
- func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
- if !discoveredDevices.contains(where: { $0.identifier == peripheral.identifier }) {
- discoveredDevices.append(peripheral)
- }
- }
- func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
- print("Connected to peripheral: \(peripheral.name ?? "Unknown")")
- status = "Connected to \(peripheral.name ?? "Unknown")"
- peripheral.delegate = self
- peripheral.discoverServices(nil)
- }
- func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
- if let error = error {
- print("Error discovering services: \(error)")
- return
- }
- for service in peripheral.services ?? [] {
- print("Discovered service: \(service.uuid)")
- peripheral.discoverCharacteristics(nil, for: service)
- }
- }
- func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
- if let error = error {
- print("Error discovering characteristics: \(error)")
- return
- }
- for characteristic in service.characteristics ?? [] {
- print("Discovered characteristic: \(characteristic.uuid)")
- if characteristic.uuid == CBUUID(string: "0000ff01-0000-1000-8000-00805f9b34fb") { // Replace with your characteristic UUID
- fileTransferCharacteristic = characteristic
- // Check MTU size
- let mtu = peripheral.maximumWriteValueLength(for: .withResponse)
- print("MTU size: \(mtu) bytes")
- }
- }
- }
- public func sendFileData(_ data: Data, to characteristic: CBCharacteristic?) {
- guard let characteristic = characteristic else { return }
- let mtu = peripheral!.maximumWriteValueLength(for: .withResponse)
- var offset = 0
- DispatchQueue.global(qos: .default).async { // Move to a background thread
- self.startTime = Date() // Record the start time
- let writeType: CBCharacteristicWriteType = characteristic.properties.contains(.writeWithoutResponse) ? .withoutResponse : .withResponse
- while offset < data.count {
- let chunkSize = min(mtu - 3, data.count - offset) // Subtract 3 bytes for BLE header
- let chunk = data.subdata(in: offset ..< offset + chunkSize)
- self.peripheral?.writeValue(chunk, for: characteristic, type: writeType)
- offset += chunkSize
- usleep(10000) // 20 millisecond delay
- }
- }
- }
- func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
- if let error = error {
- print("Error writing value: \(error)")
- status = "Error: \(error)"
- return
- }
- print("Successfully wrote value for characteristic: \(characteristic.uuid)")
- endTime = Date() // Record the end time
- if let startTime = startTime, let endTime = endTime {
- let elapsedTime = endTime.timeIntervalSince(startTime)
- let fileSize = Double(fileData.count)
- let transferRateValue = fileSize / elapsedTime // bytes per second
- print("File transferred successfully")
- print("Transfer Rate: \(transferRateValue) B/s")
- print("Total Time: \(elapsedTime) seconds")
- // Update the published variables
- transferRate = transferRateValue
- totalTime = elapsedTime
- }
- }
- func presentFilePicker() {
- let filePicker = UIDocumentPickerViewController(documentTypes: ["public.data"], in: .import)
- filePicker.delegate = self
- UIApplication.shared.windows.first?.rootViewController?.present(filePicker, animated: true, completion: nil)
- }
- func connectToDevice(_ device: CBPeripheral) {
- peripheral = device
- peripheral?.delegate = self
- let options = [
- CBConnectPeripheralOptionNotifyOnConnectionKey: true,
- CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
- // Add other options if needed
- ]
- centralManager.connect(peripheral!, options: options)
- }
- }
- extension BluetoothManager: UIDocumentPickerDelegate {
- func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
- guard let url = urls.first else { return }
- // Create a temporary directory for the file
- let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(url.lastPathComponent)
- do {
- // Check if file exists at temporary directory
- if FileManager.default.fileExists(atPath: tempURL.path) {
- // Remove the file if it exists
- try FileManager.default.removeItem(at: tempURL)
- }
- // Copy the file to the temporary directory
- try FileManager.default.copyItem(at: url, to: tempURL)
- // Read the file data
- // let fileData = try Data(contentsOf: tempURL)
- fileData = try Data(contentsOf: tempURL)
- // Send the file data
- sendFileData(fileData, to: fileTransferCharacteristic)
- } catch {
- print("Error reading file data: \(error)")
- status = "Error: \(error.localizedDescription)"
- }
- }
- }
iOS开发蓝牙传输文件实时速率只有7kb/s, 型号是ESP32-S3。iOS端传输的文件只有300kb,耗时40秒才完成传输,找不到导致传输文件慢的问题原因,求助大佬们帮忙.这是我的完整代码
iOS开发蓝牙传输文件实时速率只有7kb/s, 型号是ESP32-S3。iOS端传输的文件只有300kb,耗时40秒才完成传输,找不到导致传输文件慢的问题原因,求助大佬们帮忙.这是我的完整代码
Who is online
Users browsing this forum: No registered users and 81 guests