I have bluetooth hearing aid. They have different device name and same service UUID.
I want to my app can connect them at the same time. How should I do?
My code just can connect one peripheral.
My code:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Find deviceļ¼ \(String(describing: peripheral.name))")
guard peripheral.name != nil else {
return
}
guard peripheral.name?.range(of: "HD100-5201000") != nil else {
return
}
guard peripheral.name?.range(of: "HD100-5200526") != nil else {
return
}
central.stopScan()
if peripheral.name?.range(of: "HD100-5201000") != nil {
connectPeripheral = peripheral
connectPeripheral.delegate = self
centralManager.connect(connectPeripheral, options: nil)
}
if peripheral.name?.range(of: "HD100-5200526") != nil {
connectPeripheral = peripheral
connectPeripheral.delegate = self
centralManager.connect(connectPeripheral, options: nil)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
charDictionary = [:]
peripheral.discoverServices(nil)
}
Related
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.
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.
I tried but i didn't get any device list near by me.
below code i tried.I apperciate your answer and please help me.Thank you in advance.
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
let option:[String:Any] = [CBCentralManagerScanOptionAllowDuplicatesKey:true]
self.manager.scanForPeripherals(withServices: nil, options: option)
}
else {
print("Bluetooth is not available")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("peripheral:=\(peripheral.name)")
if let device = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
print("peripheral_ UUID:=\(peripheral.services)")
if let service = peripheral.services {
BEAN_SERVICE_UUID = service[0].uuid
let idstr = service[0].characteristics![0].uuid
BEAN_SCRATCH_UUID = idstr
print("BEAN_SERVICE_UUID:=\(BEAN_SERVICE_UUID)")
}
manager.stopScan()
self.peripheral = peripheral
self.peripheral.delegate = self
manager.connect(self.peripheral, options: nil)
}
else {
print("device not Found")
}
}
I'm trying to discover services from a BLE device I've connected to from my iOS app, but when my didDiscoverServices function gets called, the peripheral services array is empty.
The app connects to the device, runs peripheral.discoverServices(nil) and then the didDiscoverServices function gets called, but there are no services returned.
I've read a number of bluetooth related answers and other examples online and as best I can tell, my code is no different to what it should be, except it is not working. I feel like I must've missed something somewhere but I'm not sure what.
I've added my console log below for what I get when running the code, and the bluetooth code at the bottom for reference.
Bluetooth initialised
BLE is powered on
Optional("Nordic_Blinky") found at -72
Scanning stopped
Connect request sent
Connected to <CBPeripheral: 0x1c0301a70, identifier = 0887CF7F-98C8-3FCF-2D10-873FFFFB2B65, name = Nordic_Blinky, state = connected>
Discovering services
Services -- Optional([]) and Error -- nil
My BluetoothHandler class code is below
class BluetoothHandler : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
// MARK: Properties
var manager: CBCentralManager!
var targetPeripheral: CBPeripheral!
// MARK: Shared Instance
static let sharedInstance = BluetoothHandler()
private override init() {
super.init()
self.startManager()
print("Bluetooth initialised")
}
// MARK: Functions
func startManager() {
manager = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
var consoleMessage = ""
switch (central.state) {
case.poweredOn:
consoleMessage = "BLE is powered on"
manager.scanForPeripherals(withServices: nil, options: nil)
case.poweredOff:
consoleMessage = "BLE is powered off"
case.resetting:
consoleMessage = "BLE Resetting"
case.unknown:
consoleMessage = "BLE state unknown"
case.unsupported:
consoleMessage = "Device not supported by BLE"
case.unauthorized:
consoleMessage = "BLE not authorised"
}
print("\(consoleMessage)")
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if (peripheral.name == "Nordic_Blinky") {
print("\(String(describing: peripheral.name)) found at \(RSSI)")
self.stopScan()
if targetPeripheral != peripheral {
targetPeripheral = peripheral
targetPeripheral!.delegate = self
manager.connect(targetPeripheral, options: nil)
print("Connect request sent")
}
}
else if (peripheral.name != nil) {
print("\(String(describing: peripheral.name))")
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected to \(peripheral)")
peripheral.delegate = self
peripheral.discoverServices(nil)
print("Discovering services")
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Any) {
print("Connection failed", error)
}
func centralManager(_ central: CBCentralManager, didDisconnect peripheral: CBPeripheral) {
if self.targetPeripheral != nil {
self.targetPeripheral!.delegate = nil
self.targetPeripheral = nil
}
print("Connection disconnected")
self.startManager()
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
print("Services -- \(peripheral.services) and Error -- \(error)")
if let services = peripheral.services {
for service in services {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
Try this: swift 3
If your peripheral(BLE device) have services then print in log.
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let services = peripheral.services as [CBService]!{
for service in services{
peripheral.discoverCharacteristics(nil, for: service)
}
}
print("==>",peripheral.services!)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for newChar: CBCharacteristic in service.characteristics!{
print(newChar)
}
}
I'm new in swift. How to show the connect status if I connect another iPad with bluetooth. I want the label to show connect status.
func centralManagerDidUpdateState(_ central: CBCentralManager) {
guard central.state == .poweredOn else {
return
}
centralManager.scanForPeripherals(withServices: nil, options: nil)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Find the device: \(peripheral.name)")
guard peripheral.name == "My Bluetooth Device" || peripheral.name == "iPhone" else {
return
}
central.stopScan()
uuid = peripheral.identifier
connectPeripheral = peripheral
connectPeripheral.delegate = self
central.connect(peripheral, options: nil)
}
I need to use bluetooth for my app. I only want to use the bluetooth connected by my iPhone. I found code blow for bluetooth:
///bluetooth scan for devices
func centralManagerDidUpdateState(central: CBCentralManager) {
if central.state == .PoweredOn {
central.scanForPeripheralsWithServices(nil, options: nil)
} else {
print("Bluetooth not available.")
}
}
///bluetooth connect to a device
func centralManager(
central: CBCentralManager,
didDiscoverPeripheral peripheral: CBPeripheral,
advertisementData: [String : AnyObject],
RSSI: NSNumber) {
print("--didDiscoverPeripheral-")
print(peripheral.name)
//central.scanForPeripheralsWithServices(nil, options: nil)
/*let device = (advertisementData as NSDictionary)
.objectForKey(CBAdvertisementDataLocalNameKey)
as? NSString
if device?.containsString(self.BEAN_NAME!) == true {
self.manager.stopScan()
self.peripheral = peripheral
self.peripheral.delegate = self
manager.connectPeripheral(peripheral, options: nil)
}*/
}
///bluetooth get services
func centralManager(
central: CBCentralManager,
didConnectPeripheral peripheral: CBPeripheral) {
peripheral.discoverServices(nil)
}
///bluetooth get characteristics
func peripheral(
peripheral: CBPeripheral,
didDiscoverServices error: NSError?) {
for service in peripheral.services! {
let thisService = service as CBService
if service.UUID == BEAN_SERVICE_UUID {
peripheral.discoverCharacteristics(
nil,
forService: thisService
)
}
}
}
///bluetooth setup notifications
func peripheral(
peripheral: CBPeripheral,
didDiscoverCharacteristicsForService service: CBService,
error: NSError?) {
for characteristic in service.characteristics! {
let thisCharacteristic = characteristic as CBCharacteristic
if thisCharacteristic.UUID == BEAN_SCRATCH_UUID {
self.peripheral.setNotifyValue(
true,
forCharacteristic: thisCharacteristic
)
}
}
}
///bluetooth changes are coming
func peripheral(
peripheral: CBPeripheral,
didUpdateValueForCharacteristic characteristic: CBCharacteristic,
error: NSError?) {
var count:UInt32 = 0;
if characteristic.UUID == BEAN_SCRATCH_UUID {
characteristic.value!.getBytes(&count, length: sizeof(UInt32))
}
}
///bluetooth disconnect and try again
func centralManager(
central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: NSError?) {
central.scanForPeripheralsWithServices(nil, options: nil)
}
This code scan bluetooth, but I think I don't need to scan bluetooth. How to use the bluetooth which is already connected by iPhone ?
Thank you very much.