SWIFT – Comunicaciones BLE

¡Tengo una aplicación SWIFT que debe enviar un valor a mi Arduino con el module Bluetooth LowEnergy!

He hecho correctamente las partes de búsqueda y connection, pero no puedo enviar ni recibir ningún dato.

¡Aquí está mi código para get una list de dispositivos BLE disponibles y poner todo esto en una vista de tabla luego de hacer clic en una celda que la aplicación proporciona para conectar el dispositivo con ellos!

Todo esto funciona perfectamente, pero no sé enviar por ejemplo un carácter "a" de la aplicación a BLE y recuperar la respuesta de arduino a la aplicación.

import UIKit import CoreBluetooth class BluetoothList: UITableViewController,CBCentralManagerDelegate, CBPeripheralDelegate { var listValue = [Lista]() var Blue: CBCentralManager! var conn: CBPeripheral! var a: String! var char: CBCharacteristic! func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { if (peripheral.name == a){ self.conn = peripheral self.conn.delegate = self Blue.stopScan() Blue.connectPeripheral(self.conn, options: nil) self.performSegueWithIdentifier("ConnectionSegue", sender: nil) } else{ listValue = [ Lista(Name: peripheral.name!, RSS: RSSI.stringValue) ] self.tableView.reloadData() } } func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) { peripheral.delegate = self peripheral.discoverServices(nil) } func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) { if let servicePeripheral = peripheral.services! as [CBService]!{ for service in servicePeripheral{ peripheral.discoverCharacteristics(nil, forService: service) } } } func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) { if let characterArray = service.characteristics! as [CBCharacteristic]!{ for cc in characterArray { if(cc.UUID.UUIDString == "FF05"){ print("OKOK") peripheral.readValueForCharacteristic(cc) } } } } func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { if (characteristic.UUID.UUIDString == "FF05"){ let value = UnsafePointer<Int>((characteristic.value?.bytes.memory)!) print("\(value)") } } func centralManagerDidUpdateState(central: CBCentralManager){ switch(central.state){ case .PowenetworkingOn: Blue.scanForPeripheralsWithServices(nil, options:nil) print("Bluetooth is powenetworking ON") case .PowenetworkingOff: print("Bluetooth is powenetworking OFF") case .Resetting: print("Bluetooth is resetting") case .Unauthorized: print("Bluetooth is unauthorized") case .Unknown: print("Bluetooth is unknown") case .Unsupported: print("Bluetooth is not supported") } } override func viewDidLoad() { super.viewDidLoad() Blue = CBCentralManager(delegate: self, queue: nil) } override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let currentCell = tableView.cellForRowAtIndexPath(tableView.indexPathForSelectedRow!)! as UITableViewCell a = currentCell.textLabel?.text Blue = CBCentralManager(delegate: self, queue: nil) } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } @IBAction func Reload_BTN(sender: AnyObject) { self.tableView.reloadData() } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.listValue.count } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cella = self.tableView.dequeueReusableCellWithIdentifier("Cella", forIndexPath: indexPath) let Lista = self.listValue[indexPath.row] cella.textLabel?.text = Lista.Name cella.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator return cella } 

El siguiente código es para Swift 3 (XCode 8 Beta 6). Es un ejemplo con los UUID estándar para puertos serie como los que se encuentran en algunos modules comerciales. Entonces, las declaraciones para el service y las características deberían verse así:

 private let UuidSerialService = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" private let UuidTx = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" private let UuidRx = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" 

Y entonces el método de su delegado para didDiscoverCharacteristic puede ser algo como esto:

 public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let characteristics = service.characteristics { for characteristic in characteristics { // Tx: if characteristic.uuid == CBUUID(string: UuidTx) { print("Tx char found: \(characteristic.uuid)") txCharacteristic = characteristic } // Rx: if characteristic.uuid == CBUUID(string: UuidRx) { rxCharacteristic = characteristic if let rxCharacteristic = rxCharacteristic { print("Rx char found: \(characteristic.uuid)") serialPortPeripheral?.setNotifyValue(true, for: rxCharacteristic) } } } } } 

Para escribir en el Tx, algo así como las siguientes obras, donde el valor es un [UInt8]:

 let data = NSData(bytes: value, length: value.count) serialPortPeripheral?.writeValue(data as Data, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse) 

¿Leyendo?

 public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { let rxData = characteristic.value if let rxData = rxData { let numberOfBytes = rxData.count var rxByteArray = [UInt8](repeating: 0, count: numberOfBytes) (rxData as NSData).getBytes(&rxByteArray, length: numberOfBytes) print(rxByteArray) } } 

Finalmente, si no sabe o no está seguro acerca de los services y características de su dispositivo BLE, puede search una aplicación de iOS gratuita llamada "LightBlue". Descubrirá un dispositivo y, si se conecta a él, enumerará todos los services y características. Solo tenga en count que, obviamente, su aplicación no podrá acceder al hardware BLE mientras LightBlue esté conectado a su dispositivo.