2016-08-14 5 views
0

У меня есть программа, работающая на ПК с ОС Windows, которая отправляет/принимает данные через COM-порт. Данные передаются по Bluetooth через модуль Bluetooth HM10.Запись данных на периферийные устройства bluetooth не выполняется

Я могу обнаружить периферийное устройство, подключиться к нему, успешно изучить его услуги и характеристики. Однако моя проблема связана с отправкой данных. Центральным является мой iPhone. ПК действует как периферийное устройство.

Первый мой код.

import CoreBluetooth 
import UIKit 

class ViewController: UIViewController { 

    @IBOutlet weak var peripheralNameLabel: UILabel! 
    @IBOutlet weak var noOfServicesLabel: UILabel! 
    @IBOutlet weak var sendBytesButton: UIButton! 
    @IBOutlet weak var sendStringButton: UIButton! 
    @IBOutlet weak var responseTextView: UITextView! 

    private let serviceUUID = CBUUID(string: "FFE0") 
    private var characteristicUUID = CBUUID(string: "FFE1") 

    private var manager: CBCentralManager! 
    private var peripheral: CBPeripheral! 
    private var characteristic: CBCharacteristic! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     manager = CBCentralManager(delegate: self, queue: nil) 
    } 

    @IBAction func didTapSendBytesButton(sender: UIButton) { 
     let bytes: [UInt8] = [0x35, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] 
     let data = NSData(bytes: bytes, length: bytes.count) 
     peripheral.writeValue(data, forCharacteristic: characteristic, type: .WithResponse) 
    } 

    @IBAction func didTapSendStringButton(sender: UIButton) { 
     let string = "5100000000" 
     if let data = string.dataUsingEncoding(NSUTF8StringEncoding) { 
      peripheral.writeValue(data, forCharacteristic: characteristic, type: .WithResponse) 
     } else { 
      sendStringButton.enabled = false 
      sendStringButton.setTitle("", forState: .Normal) 
     } 
    } 

} 

extension ViewController: CBCentralManagerDelegate { 

    func centralManagerDidUpdateState(central: CBCentralManager) { 
     print(#function) 

     switch central.state { 
     case .Unsupported: 
      print("Unsupported") 
     case .Unauthorized: 
      print("Unauthorized") 
     case .PoweredOn: 
      print("Powered On") 
      navigationItem.title = "Connecting..." 
      central.scanForPeripheralsWithServices([serviceUUID], options: nil) 
     case .Resetting: 
      print("Resetting") 
     case .PoweredOff: 
      print("Powered Off") 
     case .Unknown: 
      print("Unknown") 
     } 
    } 

    func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { 
     print(#function) 

     print("Discovered \(peripheral.name) at \(RSSI)") 
     peripheralNameLabel.text = peripheral.name 

     if peripheral.name == nil || peripheral.name == "" { 
      return 
     } 

     if self.peripheral == nil || self.peripheral.state == .Disconnected { 
      self.peripheral = peripheral 
      central.connectPeripheral(peripheral, options: nil) 

      central.stopScan() 
     } 
    } 

    func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) { 
     print(#function) 
     navigationItem.title = "Connected!" 
     sendBytesButton.enabled = true 
     sendStringButton.enabled = true 

     peripheral.delegate = self 
     peripheral.discoverServices([serviceUUID]) 
    } 

    func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) { 
     self.peripheral = nil 
     central.scanForPeripheralsWithServices(nil, options: nil) 
    } 

    func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) { 
     print(#function) 
     self.peripheral = nil 
    } 

} 

extension ViewController: CBPeripheralDelegate { 

    func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) { 
     print(#function) 

     guard let services = peripheral.services else { 
      return 
     } 

     noOfServicesLabel.text = "\(services.count)" 

     for service in services { 
      print(service.UUID) 
      if service.UUID == serviceUUID { 
       peripheral.discoverCharacteristics(nil, forService: service) 
      } 
     } 
    } 

    func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) { 
     print(#function) 

     guard let characteristics = service.characteristics else { 
      return 
     } 

     for characteristic in characteristics { 
      print("characteristic: \(characteristic.UUID)") 
      if characteristic.UUID == characteristicUUID { 
       self.characteristic = characteristic 
       peripheral.setNotifyValue(true, forCharacteristic: characteristic) 
      } 
     } 
    } 

    func peripheral(peripheral: CBPeripheral, didWriteValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { 
     print(#function) 
     print(error) 
    } 

    func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { 
     print(#function) 

     if characteristic.UUID == characteristicUUID { 
      print("Got reply from: \(characteristic.UUID)") 
      if let data = characteristic.value, let string = String(data: data, encoding: NSUTF8StringEncoding) { 
       responseTextView.text = string 
      } else { 
       print("No response!") 
      } 
     } 
    } 

} 

Я должен послать массив байт, как это,

0x35 0x31 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

периферийных и если периферийные успешно принимает его, я получаю это как ответ,

0x43 0x41 0x4E 0x20 0x31 0x31 0x2F 0x35 0x30 0x30 0x0D 0x0A.

Как это должно выглядеть.

enter image description here

Это то, что происходит на самом деле.

enter image description here

enter image description here

enter image description here

Пакеты данных разбиваются на куски при передаче. Поэтому я не получаю ответа на успех.

Странная часть иногда, очень редко она на самом деле работает! Данные отправляются правильно (как показано на самом первом изображении), и я получаю ответ успеха. Но неудачи происходят чаще, чем нет. Как в 99% случаев.

Я пробовал оба способа, отправляя данные в виде байтового массива (didTapSendBytesButton()) и отправляя его как преобразованную строку (didTapSendStringButton()). Оба привели к тому же.

Также протестировали его с помощью приложения под названием Bluetooth Serial. Тот же результат.

Я не могу понять, почему это происходит.

+0

Вы ссылаетесь на iOS и Windows здесь, которые вы используете для отправки данных? С какой периферией вы пытаетесь поговорить? – Carter

+0

Извините, если я не понял этого. Я обновлю ответ. Устройство iOS действует как центральное. ПК действует как периферийное устройство. – Isuru

+0

Вы протестировали с помощью приложения Bluetooth Serial и имели такое же поведение, разве это не означает, что проблема возникает на стороне приемника? Каков ваш код для получения данных? – Carter

ответ

1

Вы отправляете менее 20 байт, поэтому данные Bluetooth будут отправляться в одной передаче.

Проблема на вашей стороне приема или на самом деле, как вы структурировали свои сообщения.

Последовательный порт может отправлять или принимать только один байт за один раз, поэтому, несмотря на то, что iOS отправляет все байты сразу (это побочный эффект, как последовательные порты эмулируются через GATT), Windows должна представить их в виртуальный драйвер COM-порта по одному за раз. Windows имеет буферизацию на COM-портах, так что байты не теряются, если ваша программа не читает достаточно быстро, поэтому вы видите более одного байта на «RX», но нет понятия «пакет» в драйвере COM , поэтому он не знает, сколько байтов было отправлено или что он должен ждать, пока все не будут получены, и доставьте их как одну группу.

Окончательный ответ заключается в том, что вам необходимо изменить свое сообщение, чтобы он имел какой-то разделитель (даже простой \ n), который позволяет получающей программе знать, что конец сообщения получен. Затем он может подтвердить сообщение и ответить соответствующим образом.

Или, если вы не можете управлять принимающей программой, и эта программа работает с другим кодом отправки, то я подозреваю, что у вас есть проблема с данными, которые вы отправляете, потому что тот факт, что последовательные байты разделены аксоном несколько RX-вызовы являются нормальными, и приемная программа должна быть записана для обработки этого

+0

Спасибо за подробный ответ, Пол. Мне сказали, что программа, работающая в Windows, ищет 10 байт в течение примерно 100 мс, а затем получает тайм-аут. Может ли это повлиять на это? – Isuru

+0

Возможно, опять же проблема будет связана с драйвером виртуального com на ПК, а не с iOS-кодом или устройством BLE. 100 мс должно быть достаточным временем для доставки 10 байтов при 9600 бит/с – Paulw11