BLE Swift write characterisitc - ios

I am trying hard to get my TI sensortag temperature sensor to notify. According to http://processors.wiki.ti.com/images/a/a8/BLE_SensorTag_GATT_Server.pdf I need to set the value of the characteristic with UUID F000AA02-0451-4000-B000-000000000000 to "01:00". Here is what I do:
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate{
var centralManager:CBCentralManager!
var blueToothReady = false
var connectingPeripheral: CBPeripheral!
#IBOutlet weak var textField: UITextView!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidLoad() {
super.viewDidLoad()
startUpCentralManager()
}
func startUpCentralManager() {
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func discoverDevices() {
centralManager.scanForPeripheralsWithServices(nil, options: nil)
}
func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: (NSDictionary), RSSI: NSNumber!) {
output("Discovered", data: peripheral.name)
self.connectingPeripheral = peripheral
centralManager.stopScan()
self.centralManager.connectPeripheral(peripheral, options: nil)
}
func centralManagerDidUpdateState(central: CBCentralManager!) { //BLE status
var msg = ""
switch (central.state) {
case .PoweredOff:
msg = "CoreBluetooth BLE hardware is powered off"
println("\(msg)")
case .PoweredOn:
msg = "CoreBluetooth BLE hardware is powered on and ready"
blueToothReady = true;
case .Resetting:
var msg = "CoreBluetooth BLE hardware is resetting"
case .Unauthorized:
var msg = "CoreBluetooth BLE state is unauthorized"
case .Unknown:
var msg = "CoreBluetooth BLE state is unknown"
case .Unsupported:
var msg = "CoreBluetooth BLE hardware is unsupported on this platform"
}
output("State", data: msg)
if blueToothReady {
discoverDevices()
}
}
func centralManager(central: CBCentralManager!,didConnectPeripheral peripheral: CBPeripheral!)
{
peripheral.delegate = self
peripheral.discoverServices([CBUUID.UUIDWithString("F000AA00-0451-4000-B000-000000000000")])
output("Connected", data: peripheral.name)
}
func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!)
{
if let servicePeripherals = peripheral.services as? [CBService]
{
for servicePeripheral in servicePeripherals
{
output("Service", data: servicePeripheral.UUID)
peripheral.discoverCharacteristics(nil, forService: servicePeripheral)
}
}
}
#IBAction func refreshBLE(sender: UIButton) {
centralManager.scanForPeripheralsWithServices(nil, options: nil)
}
func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) {
if let charactericsArr = service.characteristics as? [CBCharacteristic]
{
for charactericsx in charactericsArr
{
peripheral.setNotifyValue(true, forCharacteristic: charactericsx)
// *************************
if charactericsx.UUID.UUIDString == "F000AA02-0451-4000-B000-000000000000"{
output("Characteristic", data: charactericsx)
let data: NSData = "01:00".dataUsingEncoding(NSUTF8StringEncoding)!
peripheral.writeValue(data, forCharacteristic: charactericsx, type: CBCharacteristicWriteType.WithResponse)
output("Characteristic", data: charactericsx)
}
// *************************
peripheral.readValueForCharacteristic(charactericsx)
}
}
}
func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
if var data :NSData = characteristic.value {
output("Data", data: characteristic.value)
}
}
func output(description: String, data: AnyObject){
println("\(description): \(data)")
textField.text = textField.text + "\(description): \(data)\n"
}
}
Problem is that peripheral.writeValue... doesn't seem to change anything. I looked at the objective c example found here http://www.ti.com/tool/sensortag-sw and think the corresponding lines to
let data: NSData = "01:00".dataUsingEncoding(NSUTF8StringEncoding)!
peripheral.writeValue(data, forCharacteristic: characteric, type: CBCharacteristicWriteType.WithResponse)
are these:
uint8_t data = 0x01;
[BLEUtility writeCharacteristic:self.d.p sCBUUID:sUUID cCBUUID:cUUID data:[NSData dataWithBytes:&data length:1]];
What am I missing?

The Swift code written by you is not equivalent to the Objective-C example. The data parameter should be initialized with binary "1" instead of a string "01:00":
var parameter = NSInteger(1)
let data = NSData(bytes: &parameter, length: 1)
peripheral.writeValue(data, for: characteristic, type: .withResponse)
I think that whenever TI docs specify a value in quotes like "01:00" they really mean a hexadecimal value like 0x0100, which is a bit confusing.

Related

Updating code to Swift 3

I am a beginner to programming with swift and programming in general. I am currently working on an app which allows one phone to send a message (peripheral) to another which will receive the message (central). I have taken most of the code from an app built using swift 2 and have tweaked it slightly to remove any errors. As a result, my code is a jumble of swift 2/3 (or so I have been told). I am not sure how to update this code fully to swift 3 which I need someones help to do. I believe it is the IBActions and delegates that are outdated but I am completely clueless on how to amend it.
I have tried running the app and it runs successfully but when I press any of the buttons nothing happens as far as I can tell. I have a basic understanding of what my code does and what each function is there for but I find myself stuck on what to do for it to work. If anyone has experience working with Bluetooth via swift and can see what I am doing wrong or perhaps if I haven't included something important. I am led to believe the issue is that all the code has not been updated to swift 3 but I can't be sure. I have read the Apple documentation for Core bluetooth.
PS: I know this question is very vague as I am unsure on what part of my code I need to fix so it is very difficult to make it specific to a single issue. Sorry!
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBPeripheralManagerDelegate, CBCentralManagerDelegate, CBPeripheralDelegate {
let messageUUID = CBUUID(string: "053D6600-821E-46A7-AC25-43A81D948E8B")
let inputUUID = CBUUID(string: "49A79D26-5323-4374-81EA-29B099AF85C8")
let otherUUID = CBUUID(string: "053D6600-821E-46A7-AC25-43A81D948E87")
var peripheralManager: CBPeripheralManager!
var characteritic: CBMutableCharacteristic!
var getDataPeripheralCharacteristic: CBMutableCharacteristic!
var service: CBMutableService!
var outputData:String = ""
var centralManager: CBCentralManager!
var connectingPeripheral: CBPeripheral?
var centralWriteCharacteristic: CBCharacteristic!
#IBOutlet var inputLabel: UITextField!
#IBOutlet weak var outputLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func centralMode(_ sender: UIButton) {
centralManager = CBCentralManager(delegate: self, queue: nil)
peripheralManager = nil
}
#IBAction func peripheralMode(_ sender: UIButton) {
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
centralManager = nil
}
#IBAction func sendData(_ sender: UIButton) {
if (peripheralManager != nil) {
let passed = peripheralManager.updateValue(inputLabel.text!.data(using: String.Encoding.utf8)!, for: characteritic!, onSubscribedCentrals: nil)
if passed == false {
print("error couldn't send data")
}
}
if (centralManager != nil) {
if (connectingPeripheral != nil) {
connectingPeripheral?.writeValue(inputLabel.text!.data(using: String.Encoding.utf8)!, for: centralWriteCharacteristic, type: CBCharacteristicWriteType.withResponse)
}
}
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if (peripheral.state == .poweredOn) {
characteritic = CBMutableCharacteristic(type: messageUUID, properties: CBCharacteristicProperties.notify, value: nil, permissions: CBAttributePermissions.readable)
getDataPeripheralCharacteristic = CBMutableCharacteristic(type: inputUUID, properties:
CBCharacteristicProperties.write, value: nil, permissions: CBAttributePermissions.writeable)
service = CBMutableService(type: otherUUID, primary: true)
service.characteristics = [characteritic!, getDataPeripheralCharacteristic!]
peripheralManager!.add(service)
}
}
func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?) {
peripheral.stopAdvertising()
let identifier = Bundle.main.bundleIdentifier!
let manufacturerData = identifier.data(using: String.Encoding.utf8, allowLossyConversion: false)
let dataToBeAdvertised:[String: Any] = [
CBAdvertisementDataLocalNameKey : "Sample peripheral",
CBAdvertisementDataManufacturerDataKey : manufacturerData as Any,
CBAdvertisementDataServiceUUIDsKey : [messageUUID, inputUUID],
]
peripheralManager.startAdvertising(dataToBeAdvertised)
}
func peripheralManager(peripheral: CBPeripheralManager, didReceiveWriteRequests requests: [CBATTRequest]) {
for request in requests {
if (request.characteristic.uuid.uuidString == inputUUID.uuidString) {
outputData = String(data: request.value!, encoding: String.Encoding.utf8)!
outputLabel.text = outputData
}
}
}
func peripheralManager(peripheral: CBPeripheralManager, didReceiveReadRequest request: CBATTRequest) {
}
func peripheralManager(peripheral: CBPeripheralManager, central: CBCentral, didSubscribeToCharacteristic characteristic: CBCharacteristic) {
outputLabel.text = "Press send message"
print("Now connected")
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
centralManager.scanForPeripherals(withServices: nil, options: nil)
//search for peripheral device
}
}
//when peripheral is discovered, this method is called
private func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
self.centralManager.stopScan();
self.connectingPeripheral = peripheral;
peripheral.delegate = self;
centralManager.connect(peripheral, options: nil)
}
//if connection request from central is succesfull, this method is called
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
peripheral.delegate = self;
peripheral.discoverServices(nil)
}
//if central discovers services, this method is called
private func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
for service: CBService in peripheral.services! {
peripheral.discoverCharacteristics(nil, for: service)
}
}
private func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
if (service.uuid.uuidString == otherUUID.uuidString) {
guard let characteristics = service.characteristics else {
return
}
for characteristic in characteristics {
if characteristic.uuid.uuidString == messageUUID.uuidString {
peripheral.setNotifyValue(true, for: characteristic)
} else if characteristic.uuid.uuidString == inputUUID.uuidString {
centralWriteCharacteristic = characteristic
}
}
}
}
private func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
if error != nil {
print("Error reading characteristics");
}
if (characteristic.uuid == messageUUID) {
outputData = String(data: characteristic.value!, encoding: String.Encoding.utf8)!
print(outputData)
outputLabel.text = outputData
}
}
}
If the issue is because of swift 2/3 mismatch. Try upgrading your code to swift3.
Go to Xcode-edit-convert- to current swift syntax.
This will lead to few build errors, identify them and fix them.
Make your sure if you have any pod or cart file , do not forget to upgrade them as well.
Hopefully this should resolve your issue.

Thread 1 : signal SIGABRT unrecognized selector

I am currently creating a Bluetooth chat application with Xcode 8 that allows two devices to connect to each other via Bluetooth and send and receive messages to one another. Below is the code for this.
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBPeripheralManagerDelegate, CBCentralManagerDelegate, CBPeripheralDelegate {
let messageUUID = CBUUID(string: "053D6600-821E-46A7-AC25-43A81D948E8B")
let inputUUID = CBUUID(string: "49A79D26-5323-4374-81EA-29B099AF85C8")
let otherUUID = CBUUID(string: "053D6600-821E-46A7-AC25-43A81D948E87")
var peripheralManager: CBPeripheralManager!
var characteritic: CBMutableCharacteristic!
var getDataPeripheralCharacteristic: CBMutableCharacteristic!
var service: CBMutableService!
var outputData:String = ""
var centralManager: CBCentralManager!
var connectingPeripheral: CBPeripheral?
var centralWriteCharacteristic: CBCharacteristic!
#IBOutlet weak var inputLabel: UITextField!
#IBOutlet weak var outputLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func centralMode(sender: AnyObject) {
centralManager = CBCentralManager(delegate: self, queue: nil)
peripheralManager = nil
}
#IBAction func peripheralMode(sender: AnyObject) {
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
centralManager = nil
}
func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?) {
peripheral.stopAdvertising()
let identifier = Bundle.main.bundleIdentifier!
let manufacturerData = identifier.data(using: String.Encoding.utf8, allowLossyConversion: false)
let dataToBeAdvertised:[String: Any] = [
CBAdvertisementDataLocalNameKey : "Sample peripheral",
CBAdvertisementDataManufacturerDataKey : manufacturerData as Any,
CBAdvertisementDataServiceUUIDsKey : [messageUUID, inputUUID],
]
peripheralManager.startAdvertising(dataToBeAdvertised)
}
#IBAction func sendData(_ sender: UIButton) {
if (peripheralManager != nil) {
let passed = peripheralManager.updateValue(inputLabel.text!.data(using: String.Encoding.utf8)!, for: characteritic!, onSubscribedCentrals: nil)
if passed == false {
print("error couldn't send data")
}
}
if (centralManager != nil) {
if (connectingPeripheral != nil) {
connectingPeripheral?.writeValue(inputLabel.text!.data(using: String.Encoding.utf8)!, for: centralWriteCharacteristic, type: CBCharacteristicWriteType.withResponse)
}
}
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if (peripheral.state == .poweredOn) {
characteritic = CBMutableCharacteristic(type: messageUUID, properties: CBCharacteristicProperties.notify, value: nil, permissions: CBAttributePermissions.readable)
getDataPeripheralCharacteristic = CBMutableCharacteristic(type: inputUUID, properties:
CBCharacteristicProperties.write, value: nil, permissions: CBAttributePermissions.writeable)
service = CBMutableService(type: otherUUID, primary: true)
service.characteristics = [characteritic!, getDataPeripheralCharacteristic!]
peripheralManager!.add(service)
}
}
func peripheralManager(peripheral: CBPeripheralManager, didReceiveWriteRequests requests: [CBATTRequest]) {
for request in requests {
if (request.characteristic.uuid.uuidString == inputUUID.uuidString) {
outputData = String(data: request.value!, encoding: String.Encoding.utf8)!
outputLabel.text = outputData
}
}
}
func peripheralManager(peripheral: CBPeripheralManager, didReceiveReadRequest request: CBATTRequest) {
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
centralManager.scanForPeripherals(withServices: nil, options: nil)
//search for peripheral device
}
}
//when peripheral is discovered, this method is called
private func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
self.centralManager.stopScan();
self.connectingPeripheral = peripheral;
peripheral.delegate = self;
centralManager.connect(peripheral, options: nil)
}
//if connection request from central is succesfull, this method is called
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
peripheral.delegate = self;
peripheral.discoverServices(nil)
}
//if central discovers services, this method is called
private func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
for service: CBService in peripheral.services! {
peripheral.discoverCharacteristics(nil, for: service)
}
}
private func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
if (service.uuid.uuidString == otherUUID.uuidString) {
guard let characteristics = service.characteristics else {
return
}
for characteristic in characteristics {
if characteristic.uuid.uuidString == messageUUID.uuidString {
peripheral.setNotifyValue(true, for: characteristic)
} else if characteristic.uuid.uuidString == inputUUID.uuidString {
centralWriteCharacteristic = characteristic
}
}
}
}
private func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
if error != nil {
print("Error reading characteristics");
}
if (characteristic.uuid == messageUUID) {
outputData = String(data: characteristic.value!, encoding: String.Encoding.utf8)!
print(outputData)
outputLabel.text = outputData
}
}
}
The Thread 1 signal SIGABRT error is produced when I click either central mode or peripheral mode but not when I click send data. I have done some research online and the general solution to this error is to check the connections for the buttons and make sure there is only one connection and it is the correct one. I have done this but it still has not fixed the error. Below are images of the connections for these buttons.
central mode button
peripheral mode button

iOS BLE app - I can get notifications from a characteristic, but can't read it

I've been working on an iOS app that interfaces with a BLE device. The device has 1 service with 5 characteristics. Three of them are read/notify, while the other two are read/write/notify.
When I first launch the app, I need to read the 5 characteristics, then listen for future notifications. For some reason, the read is not working (no response to readValueForCharacteristic), but the notifications do work (changes on the device show up in the app).
Also unusual - I never receive calls to didUpdateNotificationStateForCharacteristic, despite the fact that the notifications do indeed work.
I also am unable to write to the 2 writable characteristics, though that isn't my primary concern right now. I've verified none of these problems are on the device end, because I can perform them using the LightBlue.app
Here's my code:
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
// GUI elements
#IBOutlet var statusLabel: UILabel!
#IBOutlet var char1Field: UITextField!
#IBOutlet var char2Field: UITextField!
#IBOutlet var char3Field: UITextField!
#IBOutlet var char4Selector: UISegmentedControl!
#IBOutlet var char5Field: UITextField!
// BLE
var centralManager : CBCentralManager!
var myPeriph : CBPeripheral!
var char3 : CBCharacteristic!
var char4 : CBCharacteristic!
var value1 : UInt32 = 0
var value2 : UInt32 = 0
var value3 : Float32 = 0
var value4 : UInt8 = 0
var value5 : UInt8 = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Initialize central manager on load
centralManager = CBCentralManager(delegate: self, queue: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func char3FieldChanged(sender: AnyObject) {
if char3Field.text == "" {
value3 = 0
} else {
value3 = Float32(char3Field.text!)!
}
let wtBytes = NSData(bytes: &value3, length: sizeof(UInt8))
char3Field.text = String(format: "%0.1f", arguments: [value3])
if char3 != nil {
self.myPeriph.writeValue(wtBytes, forCharacteristic: char3, type: CBCharacteristicWriteType.WithoutResponse)
}
}
#IBAction func char4SelectorChanged(sender: AnyObject) {
value4 = UInt8(char4Selector.selectedSegmentIndex)
let char4Bytes = NSData(bytes: &value4, length: sizeof(UInt8))
if char4 != nil {
self.myPeriph.writeValue(char4Bytes, forCharacteristic: char4, type: CBCharacteristicWriteType.WithoutResponse)
}
}
/******* CBCentralManagerDelegate *******/
// Check status of BLE hardware
func centralManagerDidUpdateState(central: CBCentralManager) {
if central.state == CBCentralManagerState.PoweredOn {
// Scan for peripherals if BLE is turned on
central.scanForPeripheralsWithServices(nil, options: nil)
self.statusLabel.text = "Searching for BLE Devices"
}
else {
// Can have different conditions for all states if needed - show generic alert for now
showAlertWithText("Error", message: "Bluetooth switched off or not initialized")
}
}
// Check out the discovered peripherals to find Sensor Tag
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
if MyPeriph.NameFound(advertisementData) == true {
// Update Status Label
self.statusLabel.text = "Device Found"
// Stop scanning, set as the peripheral to use and establish connection
self.centralManager.stopScan()
self.myPeriph = peripheral
self.myPeriph.delegate = self
self.centralManager.connectPeripheral(peripheral, options: nil)
}
else {
self.statusLabel.text = "Device NOT Found"
}
}
// Discover services of the peripheral
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
self.statusLabel.text = "Discovering peripheral services"
peripheral.discoverServices(nil)
print("Searching for peripheral")
}
// If disconnected, start searching again
func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {
self.statusLabel.text = "Disconnected"
central.scanForPeripheralsWithServices(nil, options: nil)
print("Disconnected")
}
/******* CBCentralPeripheralDelegate *******/
// Check if the service discovered is valid
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
self.statusLabel.text = "Looking at peripheral services"
for service in peripheral.services! {
let thisService = service as CBService
if MyPeriph.validService(thisService) {
// Discover characteristics of all valid services
peripheral.discoverCharacteristics(nil, forService: thisService)
print("Peripheral service found, searching for characteristics")
}
}
}
func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
print("Did update notify status for \(characteristic.description)")
}
func peripheral(peripheral: CBPeripheral, didUpdateValueForDescriptor descriptor: CBDescriptor, error: NSError?) {
print("Did update value for descriptor")
}
// Enable notification and sensor for each characteristic of valid service
func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
self.statusLabel.text = "Configuring..."
print("Found \(service.characteristics?.count) characteristics")
for characteristic in service.characteristics! {
let thisCharacteristic = characteristic as CBCharacteristic
self.myPeriph.readValueForCharacteristic(thisCharacteristic)
self.myPeriph.discoverDescriptorsForCharacteristic(thisCharacteristic)
switch characteristic.UUID {
case Char1Uuid:
self.myPeriph.setNotifyValue(true, forCharacteristic: thisCharacteristic)
case Char2Uuid:
self.myPeriph.setNotifyValue(true, forCharacteristic: thisCharacteristic)
case Char3Uuid:
self.myPeriph.setNotifyValue(true, forCharacteristic: thisCharacteristic)
char3 = characteristic
case Char4Uuid:
self.myPeriph.setNotifyValue(true, forCharacteristic: thisCharacteristic)
char4 = characteristic
case Char5Uuid:
self.myPeriph.setNotifyValue(true, forCharacteristic: thisCharacteristic)
default: break
}
}
}
// Get data values when they are updated
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
self.statusLabel.text = "Connected"
switch characteristic.UUID {
case Char1Uuid:
value1 = MyPeriph.getvalue1(characteristic.value!)
char1Field.text = String(value1)
case Char2Uuid:
value2 = MyPeriph.getvalue2(characteristic.value!)
char2Field.text = String(value2)
case Char3Uuid:
value3 = MyPeriph.getvalue3(characteristic.value!)
char3Field.text = String(value3)
char3 = characteristic
case Char4Uuid:
value4 = MyPeriph.getvalue4(characteristic.value!)
if value4 == 0 {
char4Selector.selectedSegmentIndex = 0
} else {
char4Selector.selectedSegmentIndex = 1
}
char4 = characteristic
case Char5Uuid:
value5 = MyPeriph.getvalue5(characteristic.value!)
char5Field.text = String(value5)
default: break
}
}
/******* Helper *******/
// Show alert
func showAlertWithText (header : String = "Warning", message : String) {
let alert = UIAlertController(title: header, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
alert.view.tintColor = UIColor.redColor()
self.presentViewController(alert, animated: true, completion: nil)
}
}

SWIFT - BLE communications

I've got a SWIFT application that have to send a value to my Arduino with Bluetooth LowEnergy module!
I've done correctly the search and connection parts but I'm not able to send and receive any data.
Here is my code to get a list of BLE devices available and put all this in a table view then after click in a cell the app provide to connect the device with them!
All this works perfectly but I don't know to send for example a "a" character from app to BLE and get back the answer from arduino to app!
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 .PoweredOn:
Blue.scanForPeripheralsWithServices(nil, options:nil)
print("Bluetooth is powered ON")
case .PoweredOff:
print("Bluetooth is powered 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
}
The following code is for Swift 3 (XCode 8 Beta 6). It's an example using the standard UUIDs for serial ports like the ones on some commercial modules. So the declarations for the service and characteristics should look like this:
private let UuidSerialService = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
private let UuidTx = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
private let UuidRx = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
And then your delegate's method for the didDiscoverCharacteristic can be something like this:
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)
}
}
}
}
}
For writing to the Tx, something like the following works, where value is an [UInt8]:
let data = NSData(bytes: value, length: value.count)
serialPortPeripheral?.writeValue(data as Data, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse)
Reading?
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)
}
}
Finally, if you don't know or you are not sure about the services and characteristics of your BLE device, you can look for a free iOS app called "LightBlue". It will discover a device and if you connect to it, it will list all services and characteristics. Just be aware that obvoiusly your app will not be able to access the BLE hardware while LightBlue is connected to your device.

Swift/BLE Notifications not working

I am using the Ti sensortag to play around with bluetooth and sensors. My goal is to get the barometer and the buttons working. The buttons notify when pressed but the barometer never notifies or changes its value at all. Here is the code:
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate{
var centralManager:CBCentralManager!
var blueToothReady = false
var connectingPeripheral: CBPeripheral!
let data = "01".dataUsingEncoding(NSUTF8StringEncoding)
#IBOutlet weak var textField: UITextView!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidLoad() {
super.viewDidLoad()
startUpCentralManager()
}
func startUpCentralManager() {
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func discoverDevices() {
centralManager.scanForPeripheralsWithServices(nil, options: nil)
}
func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: (NSDictionary), RSSI: NSNumber!) {
println("Discovered: \(peripheral.name)")
textField.text = textField.text + "Discovered: \(peripheral.name)\n"
self.connectingPeripheral = peripheral
centralManager.stopScan()
self.centralManager.connectPeripheral(peripheral, options: nil)
}
func centralManagerDidUpdateState(central: CBCentralManager!) { //BLE status
var msg = ""
switch (central.state) {
case .PoweredOff:
msg = "CoreBluetooth BLE hardware is powered off"
println("\(msg)")
case .PoweredOn:
msg = "CoreBluetooth BLE hardware is powered on and ready"
blueToothReady = true;
case .Resetting:
var msg = "CoreBluetooth BLE hardware is resetting"
case .Unauthorized:
var msg = "CoreBluetooth BLE state is unauthorized"
case .Unknown:
var msg = "CoreBluetooth BLE state is unknown"
case .Unsupported:
var msg = "CoreBluetooth BLE hardware is unsupported on this platform"
}
textField.text = textField.text + "\(msg)\n"
println(msg)
if blueToothReady {
discoverDevices()
}
}
func centralManager(central: CBCentralManager!,didConnectPeripheral peripheral: CBPeripheral!)
{
peripheral.delegate = self
peripheral.discoverServices([CBUUID.UUIDWithString("F000AA40-0451-4000-B000-000000000000"),CBUUID.UUIDWithString("FFE0")])
println("Connected")
textField.text = textField.text + "Connected\n"
}
func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!)
{
if let servicePeripherals = peripheral.services as? [CBService]
{
for servicePeripheral in servicePeripherals
{
println("Service: \(servicePeripheral.UUID)")
textField.text = textField.text + "Service: \(servicePeripheral.UUID)\n"
peripheral.discoverCharacteristics(nil, forService: servicePeripheral)
}
}
}
#IBAction func refreshBLE(sender: UIButton) {
centralManager.scanForPeripheralsWithServices(nil, options: nil)
}
func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) {
if let charactericsArr = service.characteristics as? [CBCharacteristic]
{
for charactericsx in charactericsArr
{
peripheral.setNotifyValue(true, forCharacteristic: charactericsx)
println("Characteristic: \(charactericsx)")
textField.text = textField.text + "Characteristic: \(charactericsx)\n"
peripheral.readValueForCharacteristic(charactericsx)
}
}
}
func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
if var data :NSData = characteristic.value {
textField.text = textField.text + "Data: \(characteristic.value)\n Notifying: \(characteristic.isNotifying)\n"
println("Data: \(characteristic.value)\n Notifying: \(characteristic.isNotifying)")
}
}
}
And here is the attribute table: http://processors.wiki.ti.com/images/a/a8/BLE_SensorTag_GATT_Server.pdf
Why do I only get the initial value of the barometer and no notifications?

Resources