Ali Atay
Ali Atay

Reputation: 1

CC2650 Module cannot Connect via Bluetooth with iOS app

I try to develop an iOS app using Swift. This app will be controlled Texas Instrument's CC2650 module via Bluetooth. I'm using iOS Core Bluetooth library. I took Bluetooth connection codes from

https://github.com/hoiberg/HM10-BluetoothSerial-iOS

import UIKit

import CoreBluetooth

var serial: BluetoothSerial!

final class BluetoothSerial: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {

var delegate: BluetoothSerialDelegate!

var centralManager: CBCentralManager!

}

var writeType: CBCharacteristicWriteType = .withResponse

init(delegate: BluetoothSerialDelegate) {
    super.init()
    self.delegate = delegate
    centralManager = CBCentralManager(delegate: self, queue: nil)
}

func startScan() {
    guard centralManager.state == .poweredOn else { return }

   let uuid = CBUUID(string: "0x180A")

    centralManager.scanForPeripherals(withServices: [uuid], options: nil)

    let peripherals = centralManager.retrieveConnectedPeripherals(withServices: [uuid])
    for peripheral in peripherals {


        let StrenghtOfRSSI = peripheral.readRSSI()
        delegate.serialDidDiscoverPeripheral(peripheral, RSSI: nil)

    }
}

func stopScan() {
    centralManager.stopScan()
}

func connectToPeripheral(_ peripheral: CBPeripheral) {
    pendingPeripheral = peripheral
    centralManager.connect(peripheral, options: nil)
}



func sendMessageToDevice(_ message: String) {
    guard isReady else { return }

    if let data = message.data(using: String.Encoding.init(rawValue: UInt(message)!)) {
        connectedPeripheral?.writeValue(data, for: writeCharacteristic!, type: .withResponse)
}





func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    delegate.serialDidDiscoverPeripheral(peripheral, RSSI: RSSI)
}

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

    peripheral.delegate = self
    pendingPeripheral = nil
    connectedPeripheral = peripheral
    delegate.serialDidConnect(peripheral)


    peripheral.discoverServices([CBUUID(string: "F0001110-0451-4000-B000-000000000000")])

}

func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
    connectedPeripheral = nil
    pendingPeripheral = nil

    delegate.serialDidDisconnect(peripheral, error: error as NSError?)
}

func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
    pendingPeripheral = nil

    delegate.serialDidFailToConnect(peripheral, error: error as NSError?)
}

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    connectedPeripheral = nil
    pendingPeripheral = nil

    delegate.serialDidChangeState()
}


func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

    for service in peripheral.services! {

        peripheral.discoverCharacteristics(nil, for: service)
    }
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

    for characteristic in service.characteristics! {


        if bluetoothCounter == false {

        if characteristic.uuid == CBUUID(string: "F0001112-0451-4000-B000-000000000000") {
            peripheral.setNotifyValue(true, for: characteristic)               
            writeCharacteristic = characteristic    
            delegate.serialIsReady(peripheral)
            }

        } else {

            if characteristic.uuid == CBUUID(string: "F0001113-0451-4000-B000-000000000000") {
                peripheral.setNotifyValue(true, for: characteristic
                writeCharacteristic = characteristic
                delegate.serialIsReady(peripheral)
            }

        }
    }


}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

    let data = characteristic.value
    guard data != nil else { return }


    delegate.serialDidReceiveData(data!)

    if let str = String(data: data!, encoding: String.Encoding.utf8) {
        delegate.serialDidReceiveString(str)
    } else {
        print("Received an invalid string!")
    }

}
}

But I have a problem with it. When my app scan for the peripheral, it can not find CC2650 module directly. However, there is something interesting situation happening. When I open BLE Scanner app (https://itunes.apple.com/us/app/ble-scanner-4-0/id1221763603?mt=8) I can discover my CC2650 module and send messages. After that, I open my app I can also discover my CC2650 and can send messages. My app cannot find CC2650 module directly.

I cannot solve this problem. I try everything which I found about Bluetooth connection.

I need some help with it.

Thank you guys.

Upvotes: 0

Views: 296

Answers (1)

Christian
Christian

Reputation: 1808

I would first check to see the status of the BLE adapter using something like:

func centralManagerDidUpdateState(_ central: CBCentralManager) {

    var consoleMsg = ""

    switch(central.state) {
    case .poweredOff:
        consoleMsg = "BLE is off"
    case .poweredOn:
        consoleMsg = "BLE is on"
        self.centralManager.scanForPeripherals(withServices: nil, options: nil)

    case .resetting:
        consoleMsg = "BLE is resetting"
    case .unauthorized:
        consoleMsg = "BLE is UA"
    case .unknown:
        consoleMsg = "BLE status unknown"
    case .unsupported:
        consoleMsg = "BLE is unsupported"

    }
    self.delegate?.statusUpdated(statusText: consoleMsg)
    print("\(consoleMsg) \n", terminator: "")

}

This code will replace your startScan method, if it prints "BLE is on" you are okay and it will start scanning for peripherals.

From your code it looks like you aren't actually connecting to a peripheral either.

For example, you call centralManager.connect(peripheral, options: nil) only within connectToPeripheral and I don't see a call to that from within the serialDidDiscoverPeripheral section.

You need to scan, then register for the didDiscoverPeripheral delegate method, check to see if that peripheral is the one you want (via a UUID or device name, you can get this from the BLE explorer app you are using), then connect to it, then scan for services then interact with them (read, write, notify etc).

You can add:

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    if let peripheralName = peripheral.name {
        print(peripheralName)
        if (peripheralName == "Your peripheral name"){
            self.peripheral = peripheral
            self.peripheral.delegate = self // This is to subscribe to delegate methods from the peripheral
            self.centralManager.stopScan() // Found your peripheral so stop scanning
            self.centralManager.connect(self.peripheral, options: nil)
        }
    }
}

That will connect (and print out to the console) to a peripheral. Then you need to scan for services (you can start this within the didConnect delegate method:

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    peripheral.delegate = self
    peripheral.discoverServices(nil)
}

Then you appear to have the code for discovering services and characteristics so that should all work ok.

Side note: You call let peripherals = centralManager.retrieveConnectedPeripherals(withServices: [uuid]) which will only retrieve already connected peripherals, so if you connect to it via another app (e.g. the BLE explorer) that is why it appears in your app.

Upvotes: 1

Related Questions