iOS开发蓝牙传输文件实时速率只有7kb/s, 型号是ESP32-S3。iOS端传输的文件只有300kb,耗时40秒才完成传输,找不到导致传输文件慢的问题原因,求助大佬们帮忙.这是我的完整代码

nengqi
Posts: 2
Joined: Fri Aug 18, 2023 8:15 am

iOS开发蓝牙传输文件实时速率只有7kb/s, 型号是ESP32-S3。iOS端传输的文件只有300kb,耗时40秒才完成传输,找不到导致传输文件慢的问题原因,求助大佬们帮忙.这是我的完整代码

Postby nengqi » Fri Aug 18, 2023 8:21 am

  1. import CoreBluetooth
  2. import SwiftUI
  3.  
  4. struct ContentView: View {
  5.   @State private var fileURL: URL? = nil
  6.   @State private var status: String = "Not Connected"
  7.   @StateObject private var bluetoothManager = BluetoothManager()
  8.  
  9.   var transferRateText: String {
  10.     let transferRateKB = bluetoothManager.transferRate / 1024
  11.     if transferRateKB < 1024 {
  12.       return String(format: "%.2f KB/s", transferRateKB)
  13.     } else {
  14.       let transferRateMB = transferRateKB / 1024
  15.       return String(format: "%.2f MB/s", transferRateMB)
  16.     }
  17.   }
  18.  
  19.   var body: some View {
  20.     VStack {
  21.       Button("Select File") {
  22.         // TODO: Select file
  23.         selectFile()
  24.       }
  25.       .padding()
  26.  
  27.       Text("Status: \(bluetoothManager.status)")
  28.         .padding()
  29.       Text("Transfer Rate: \(transferRateText)")
  30.         .padding()
  31.  
  32.       Text("Total Time: \(bluetoothManager.totalTime, specifier: "%.2f") seconds")
  33.         .padding()
  34.       List(bluetoothManager.discoveredDevices, id: \.identifier) { device in
  35.         HStack {
  36.           Text(device.name ?? "Unknown")
  37.           Spacer()
  38.           Button("Connect") {
  39.             bluetoothManager.connectToDevice(device)
  40.           }
  41.         }
  42.       }
  43.     }
  44.   }
  45.  
  46.   private func selectFile() {
  47.     bluetoothManager.presentFilePicker()
  48.   }
  49. }
  50.  
  51. #Preview {
  52.   ContentView()
  53. }
  54.  
  55. class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
  56.   private var centralManager: CBCentralManager!
  57.   private var peripheral: CBPeripheral?
  58.   public var fileTransferCharacteristic: CBCharacteristic?
  59.   @Published var status: String = "Not Connected"
  60.   @Published var discoveredDevices: [CBPeripheral] = []
  61.   private var startTime: Date?
  62.   private var endTime: Date?
  63.   var fileData: Data!
  64.   @Published var transferRate: Double = 0.0
  65.   @Published var totalTime: Double = 0.0
  66.   private var connectionParameters: [String: Any]?
  67.  
  68.   override init() {
  69.     super.init()
  70.     centralManager = CBCentralManager(delegate: self, queue: nil)
  71.   }
  72.  
  73.   func centralManagerDidUpdateState(_ central: CBCentralManager) {
  74.     if central.state == .poweredOn {
  75.       centralManager.scanForPeripherals(withServices: nil, options: nil)
  76.     }
  77.   }
  78.  
  79.   // TODO: Implement other delegate methods
  80.  
  81.   func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
  82.     if !discoveredDevices.contains(where: { $0.identifier == peripheral.identifier }) {
  83.       discoveredDevices.append(peripheral)
  84.     }
  85.   }
  86.  
  87.   func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
  88.     print("Connected to peripheral: \(peripheral.name ?? "Unknown")")
  89.     status = "Connected to \(peripheral.name ?? "Unknown")"
  90.     peripheral.delegate = self
  91.     peripheral.discoverServices(nil)
  92.   }
  93.  
  94.   func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
  95.     if let error = error {
  96.       print("Error discovering services: \(error)")
  97.       return
  98.     }
  99.  
  100.     for service in peripheral.services ?? [] {
  101.       print("Discovered service: \(service.uuid)")
  102.       peripheral.discoverCharacteristics(nil, for: service)
  103.     }
  104.   }
  105.  
  106.   func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
  107.     if let error = error {
  108.       print("Error discovering characteristics: \(error)")
  109.       return
  110.     }
  111.  
  112.     for characteristic in service.characteristics ?? [] {
  113.       print("Discovered characteristic: \(characteristic.uuid)")
  114.       if characteristic.uuid == CBUUID(string: "0000ff01-0000-1000-8000-00805f9b34fb") { // Replace with your characteristic UUID
  115.         fileTransferCharacteristic = characteristic
  116.         // Check MTU size
  117.         let mtu = peripheral.maximumWriteValueLength(for: .withResponse)
  118.         print("MTU size: \(mtu) bytes")
  119.       }
  120.     }
  121.   }
  122.  
  123.   public func sendFileData(_ data: Data, to characteristic: CBCharacteristic?) {
  124.     guard let characteristic = characteristic else { return }
  125.     let mtu = peripheral!.maximumWriteValueLength(for: .withResponse)
  126.     var offset = 0
  127.  
  128.     DispatchQueue.global(qos: .default).async { // Move to a background thread
  129.       self.startTime = Date() // Record the start time
  130.  
  131.       let writeType: CBCharacteristicWriteType = characteristic.properties.contains(.writeWithoutResponse) ? .withoutResponse : .withResponse
  132.  
  133.       while offset < data.count {
  134.         let chunkSize = min(mtu - 3, data.count - offset) // Subtract 3 bytes for BLE header
  135.         let chunk = data.subdata(in: offset ..< offset + chunkSize)
  136.         self.peripheral?.writeValue(chunk, for: characteristic, type: writeType)
  137.         offset += chunkSize
  138.         usleep(10000) // 20 millisecond delay
  139.       }
  140.     }
  141.   }
  142.  
  143.   func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
  144.     if let error = error {
  145.       print("Error writing value: \(error)")
  146.       status = "Error: \(error)"
  147.       return
  148.     }
  149.  
  150.     print("Successfully wrote value for characteristic: \(characteristic.uuid)")
  151.  
  152.     endTime = Date() // Record the end time
  153.  
  154.     if let startTime = startTime, let endTime = endTime {
  155.       let elapsedTime = endTime.timeIntervalSince(startTime)
  156.       let fileSize = Double(fileData.count)
  157.       let transferRateValue = fileSize / elapsedTime // bytes per second
  158.  
  159.       print("File transferred successfully")
  160.       print("Transfer Rate: \(transferRateValue) B/s")
  161.       print("Total Time: \(elapsedTime) seconds")
  162.  
  163.       // Update the published variables
  164.       transferRate = transferRateValue
  165.       totalTime = elapsedTime
  166.     }
  167.   }
  168.  
  169.   func presentFilePicker() {
  170.     let filePicker = UIDocumentPickerViewController(documentTypes: ["public.data"], in: .import)
  171.     filePicker.delegate = self
  172.     UIApplication.shared.windows.first?.rootViewController?.present(filePicker, animated: true, completion: nil)
  173.   }
  174.  
  175.   func connectToDevice(_ device: CBPeripheral) {
  176.     peripheral = device
  177.     peripheral?.delegate = self
  178.    
  179.     let options = [
  180.         CBConnectPeripheralOptionNotifyOnConnectionKey: true,
  181.         CBConnectPeripheralOptionNotifyOnDisconnectionKey: true,
  182.         // Add other options if needed
  183.     ]
  184.     centralManager.connect(peripheral!, options: options)
  185.   }
  186. }
  187.  
  188. extension BluetoothManager: UIDocumentPickerDelegate {
  189.   func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
  190.     guard let url = urls.first else { return }
  191.  
  192.     // Create a temporary directory for the file
  193.     let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(url.lastPathComponent)
  194.  
  195.     do {
  196.       // Check if file exists at temporary directory
  197.       if FileManager.default.fileExists(atPath: tempURL.path) {
  198.         // Remove the file if it exists
  199.         try FileManager.default.removeItem(at: tempURL)
  200.       }
  201.  
  202.       // Copy the file to the temporary directory
  203.       try FileManager.default.copyItem(at: url, to: tempURL)
  204.  
  205.       // Read the file data
  206. //      let fileData = try Data(contentsOf: tempURL)
  207.       fileData = try Data(contentsOf: tempURL)
  208.  
  209.       // Send the file data
  210.       sendFileData(fileData, to: fileTransferCharacteristic)
  211.     } catch {
  212.       print("Error reading file data: \(error)")
  213.       status = "Error: \(error.localizedDescription)"
  214.     }
  215.   }
  216. }
  217.  


Who is online

Users browsing this forum: No registered users and 80 guests