I am trying to communicate through Bluetooth Low-Energy, our CBCentralManager implementation is already done in Objective-C, but I am trying to implement CBPeripheral through Swift.
I am not able to make the connection. This is how I am advertising in CBPeripheral implementation:
public func initialize()
{
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
perpheralManager = CBPeripheralManager(delegate: self, queue: queue)
startConnecting()
}
public func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager)
{
switch peripheral.state
{
case CBPeripheralManagerState.PoweredOn:
setUpServices()
break
default:break
}
}
private func setUpServices()
{
self.slideIndexCharacterestics = CBMutableCharacteristic(type: CBUUID(string: UUID.transferSlideIndex), properties: [CBCharacteristicProperties.Read,CBCharacteristicProperties.NotifyEncryptionRequired],
value: nil, permissions: CBAttributePermissions.ReadEncryptionRequired)
let services = CBMutableService(type: CBUUID(string: UUID.transferService), primary: true)
services.characteristics = [self.slideIndexCharacterestics!]
self.perpheralManager!.addService(services)
}
public func peripheralManager(peripheral: CBPeripheralManager, didAddService service: CBService, error: NSError?)
{
startConnecting()
}
func startConnecting()
{
let adData = [CBAdvertisementDataServiceUUIDsKey:CBUUID(string:"D6087B90-F460-4BE1-A9C8-E1CD8E7858E9")]
self.perpheralManager!.stopAdvertising()
self.perpheralManager!.startAdvertising(adData)
}
Note: I am able to communicate successfully if I implement in Objective-C both ends.
Related
I'm currently trying to make 2 iOS devices connect with each other so I can send gps locations between the two. Right now I'm using corebluetooth to achieve this.
What I did so far is I created 2 separate projects, one being the receiver one being the sender. I followed some instructions from apple itself to broadcast the iPad. However it doesn't seem to be found by the project that is trying to search for Bluetooth devices. I ran both apps on separate physical devices with bluetooth turned on. Below the code that I've used (keep in mind this is some quick code I wrote to try and see if I can actually find the device.) This is also the first time I work with bluetooth so it's a learning curve for sure.
FYI: I'm planning on using the GATT protocol. I'm also wondering if it can be done without a pairing handshake in the way that I get a popup to accept the connection. I would like the receiver to automatically receive and broadcasted signal and start obtaining the data that is being sent without additional steps needed. Or would I need something like Multipeer Connectivity Framework for this?
Receiver
import UIKit
import CoreBluetooth
import CoreLocation
class ViewController: UIViewController {
private let uuidBeacon = "A26962FC-F9DD-4251-B339-A25B3E808213"
var peripheral: CBPeripheralManager!
var peripheralData: NSMutableDictionary!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
peripheral = CBPeripheralManager(delegate: self, queue: nil)
}
override func viewDidAppear(_ animated: Bool) {
guard let region = createBeaconRegion() else { return }
advertiseDevice(region: region)
}
private func createBeaconRegion() -> CLBeaconRegion? {
let proximityUUID = UUID(uuidString: uuidBeacon)
let major : CLBeaconMajorValue = 100
let minor : CLBeaconMinorValue = 1
let beaconID = "com.example.myDeviceRegion"
return CLBeaconRegion(proximityUUID: proximityUUID!,
major: major, minor: minor, identifier: beaconID)
}
func advertiseDevice(region : CLBeaconRegion) {
peripheralData = region.peripheralData(withMeasuredPower: nil)
}
}
extension ViewController: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
switch peripheral.state {
case .poweredOn:
peripheral.startAdvertising(((peripheralData as NSDictionary) as! [String : Any]))
case .poweredOff:
break
// peripheral.stopAdvertising()
default:
break
}
}
}
Broadcaster
import UIKit
import CoreBluetooth
import CoreLocation
class ViewController: UIViewController {
var centralManager: CBCentralManager!
var sensorTag: CBPeripheral?
var keepScanning: Bool = false
private var timerScanInterval: TimeInterval = 5
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
}
extension ViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
keepScanning = true
_ = Timer(timeInterval: timerScanInterval, target: self, selector: #selector(pauseScan), userInfo: nil, repeats: false)
centralManager.scanForPeripherals(withServices: nil, options: nil)
break
case .poweredOff:
break
case .unsupported:
break
case .unauthorized:
break
case .resetting:
break
case .unknown:
break
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
peripheral.discoverServices(nil)
if let peripheralName = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
print(peripheralName)
}
}
#objc private func pauseScan() {
centralManager.stopScan()
_ = Timer(timeInterval: 2, target: self, selector: #selector(resumeScan), userInfo: nil, repeats: false)
}
#objc private func resumeScan() {
if keepScanning {
centralManager.scanForPeripherals(withServices: nil, options: nil)
_ = Timer(timeInterval: timerScanInterval, target: self, selector: #selector(pauseScan), userInfo: nil, repeats: false)
}
}
}
extension ViewController: CBPeripheralDelegate {
}
So I currently got a bluetooth connection setup between a iPad and iPhone. I've created my testcode in the ViewController and everything works fine. Now I moved it to 2 manager classes one for the CBCentralManager and one for the CBPeripheralManager above those to classes I made a BluetoothManager which is a singleton class and holds some information regarding currently connected devices.
However when doing this I'm facing a problem it seems like the centralManager.connect() call doesn't actually work. I debugged my entire code and after that line nothing seems to happen and I can't seem to figure out why this is or where I'm actually going wrong.
The CentralManager class
import Foundation
import CoreBluetooth
class CentralManager: NSObject {
private var centralManager: CBCentralManager!
var peripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
}
// MARK: - CBCentralManager Delegate Methods
extension CentralManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: [BLEConstants.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
default:
break
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if !peripherals.contains(peripheral) {
peripheral.delegate = self
peripherals.append(peripheral)
centralManager.connect(peripheral, options: nil)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.discoverServices([BLEConstants.serviceUUID])
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
guard let peripheralIndex = peripherals.index(of: peripheral), BluetoothManager.shared.deviceCharacteristic[peripheral] != nil else { return }
peripherals.remove(at: peripheralIndex)
BluetoothManager.shared.deviceCharacteristic.removeValue(forKey: peripheral)
}
}
// MARK: - CBPeripheral Delegate Methods
extension CentralManager: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service in peripheral.services! {
if service.uuid == BLEConstants.serviceUUID {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
let characteristic = characteristic as CBCharacteristic
if BluetoothManager.shared.deviceCharacteristic[peripheral] == nil {
BluetoothManager.shared.deviceCharacteristic[peripheral] = characteristic
}
}
}
func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
}
}
The PeripheralManager class
class PeripheralManager: NSObject {
private var peripheralManager: CBPeripheralManager!
override init() {
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
}
}
// MARK: - Manage Methods
extension PeripheralManager {
func updateAdvertising() {
guard !peripheralManager.isAdvertising else { peripheralManager.stopAdvertising(); return }
let advertisingData: [String: Any] = [CBAdvertisementDataServiceUUIDsKey: BLEConstants.serviceUUID,
CBAdvertisementDataLocalNameKey: BLEConstants.bleAdvertisementKey]
peripheralManager.startAdvertising(advertisingData)
}
func initializeService() {
let service = CBMutableService(type: BLEConstants.serviceUUID, primary: true)
let characteristic = CBMutableCharacteristic(type: BLEConstants.charUUID, properties: BLEConstants.charProperties, value: nil, permissions: BLEConstants.charPermissions)
service.characteristics = [characteristic]
peripheralManager.add(service)
}
}
// MARK: - CBPeripheralManager Delegate Methods
extension PeripheralManager: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
initializeService()
updateAdvertising()
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
for request in requests {
if let value = request.value {
let messageText = String(data: value, encoding: String.Encoding.utf8)
print(messageText ?? "")
}
self.peripheralManager.respond(to: request, withResult: .success)
}
}
}
The BluetoothManager class
class BluetoothManager {
static let shared = BluetoothManager()
private var centralManager: CentralManager!
private var peripheralManager: PeripheralManager!
var deviceCharacteristic: [CBPeripheral: CBCharacteristic] = [:]
var connectedPeripherals: [CBPeripheral] { return centralManager.peripherals }
func setup() {
centralManager = CentralManager()
peripheralManager = PeripheralManager()
}
}
and then in my ViewController didLoad I'm calling BluetoothManager.shared.setup()
Does anyone know why the devices don't seem to connect with eachother or maybe the delegate functions after that just don't get called?
The process starts when the static shared variable is initialized with BluetoothManager(). I am not sure when this happens in Swift, it is either at the very start of the program, or when you use BluetoothManager.setup for the first time.
Initialization of the variable calls the init() method of the BluetoothManager. This will instantiate a CentralManager, and its init() method will be called. This will instantiate a CBCentralManager, which will start the Bluetooth process.
Then you call setup(), which will instantiate a new CentralManager, with its own CBCentralManager. I can imagine something goes wrong with two CBCentralManager.
To solve it, don't use setup(), but initialize the variables in init() instead.
To debug this kind of situation, put breakpoints in all init() methods. Create destructors, and put breakpoints in those as well. Technically, you need destructors anyways, because you need to remove yourself as delegate from the CBCentralManager object.
Note also that you only call scanForPeripherals from centralManagerDidUpdateState. The CBCentralManager can already be in poweredOn state when it starts, this can happen when another app is using Bluetooth at the same time - or when your first CBCentralManager object has already started it. In that case, centralManagerDidUpdateState will never be called.
Are you sure your Singleton is correctly initialized?
Try this:
import Foundation
private let singleton = Singleton()
class Singleton {
static let sharedInstance : Singleton = {
return singleton
}()
let cnetralManager = = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
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.
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
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: ¶meter, 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.