Can't discover any services, but can connect to device - ios

I'm able to connect to a BLE device, but .discoverServices() doesn't work. My logs show an unhelpfully generic error: [CoreBluetooth] XPC connection invalid
Connecting to it does work:
func connectToPeripheral(id: Int) -> Bool {
guard id >= 0 && id <= peripherals.count else {
return false
}
let arrayItem = peripherals[id]
connectedPeripheral = arrayItem.peripheral
connectedPeripheral!.delegate = self
myCentral.connect(connectedPeripheral!, options: nil)
print("connected to \(arrayItem.name)")
myCentral.stopScan()
return true
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected to \(String(describing: peripheral.name)) \(peripheral.description)!")
print(peripheral.services as Any)
peripheral.discoverServices(nil)
}
But this function never gets called. Why????
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
print("Services:")
print(peripheral.services as Any)
}
Not sure what I'm doing wrong, help?
Here's the full code:
import Foundation
import CoreBluetooth
class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
var myCentral: CBCentralManager!
#Published var isSwitchedOn = false
#Published var peripherals = [Peripheral]()
#Published var connectedPeripheral: CBPeripheral?
override init() {
super.init()
myCentral = CBCentralManager(delegate: self, queue: nil)
myCentral.delegate = self
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
var peripheralName: String!
if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
peripheralName = name
} else {
peripheralName = "Unknown"
}
if peripherals.contains(where: { p in p.name == peripheralName }) {
return
}
let newPeripheral = Peripheral(id: peripherals.count, name: peripheralName, rssi: RSSI.intValue, peripheral: peripheral)
peripherals.append(newPeripheral)
}
func startScanning() {
print("startScanning")
peripherals.removeAll()
myCentral.scanForPeripherals(withServices: nil, options: nil)
}
func stopScanning() {
print("stopScanning")
myCentral.stopScan()
}
func connectToPeripheral(id: Int) -> Bool {
guard id >= 0 && id <= peripherals.count else {
return false
}
let arrayItem = peripherals[id]
connectedPeripheral = arrayItem.peripheral
connectedPeripheral!.delegate = self
myCentral.connect(connectedPeripheral!, options: nil)
print("connected to \(arrayItem.name)")
myCentral.stopScan()
return true
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected to \(String(describing: peripheral.name)) \(peripheral.description)!")
print(peripheral.services as Any)
peripheral.discoverServices(nil)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
print("Services:")
print(peripheral.services as Any)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
print("got Characteristics...")
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
print("centralManagerDidUpdateState: poweredOn=\(central.state == .poweredOn)")
if central.state == .poweredOn {
//if it wasn't previously on, start scanning
if !isSwitchedOn {
isSwitchedOn = true
startScanning()
}
} else {
isSwitchedOn = false
}
}
}
struct Peripheral: Identifiable {
let id: Int
let name: String
let rssi: Int
let peripheral: CBPeripheral
}

I figured out two bugs in my code.
I was calling startScanning() when centralManagerDidUpdateState() was called with central.state == .poweredOn. This causing scanning to start again right after calling myCentral.connect(connectedPeripheral!, options: nil)
Calling myCentral.stopScan() after myCentral.connect(connectedPeripheral!, options: nil) was causing disconnections
I don't understand why either of those were happening, but fixing them allowed me to now connect and get services and characteristics!

Related

Convert from Nsnumber to data to send rssi to bluetooth module IOS swift 4

I found the received signal strength of iPhone to the bluetooth 4.0 module that I am using, but it is in the format of NSNumber and the writeValue() method only takes values of type Data.
How would I go about converting from NSNumber to type Data? Or is there another, better way to send this data from my iPhone to the bluetooth module?
The bluetooth module I am using is the HM-10 and it is connected to an arduino.
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBPeripheralDelegate, CBCentralManagerDelegate {
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!
var readRSSITimer: Timer!
func centralManagerDidUpdateState(_ central: CBCentralManager) {
print("Central state update")
if central.state != .poweredOn {
print("Central is not powered on")
} else {
print("Central scanning for", ParticlePeripheral.particleLEDServiceUUID);
centralManager.scanForPeripherals(withServices: [ParticlePeripheral.particleLEDServiceUUID],
options: [CBCentralManagerScanOptionAllowDuplicatesKey : true])
}
}
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
// We've found it so stop scan
self.centralManager.stopScan()
// Copy the peripheral instance
self.peripheral = peripheral
self.peripheral.delegate = self
// Connect!
self.centralManager.connect(self.peripheral, options: nil)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
if peripheral == self.peripheral {
print("Connected to your Particle Board")
peripheral.discoverServices([ParticlePeripheral.particleLEDServiceUUID])
print(self.peripheral.readRSSI())
self.startReadRSSI()
peripheral.delegate = self
}
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
self.stopReadRSSI()
if self.peripheral != nil {
self.peripheral.delegate = nil
self.peripheral = nil
}
}
func stopScan() {
self.centralManager.stopScan()
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let services = peripheral.services {
for service in services {
if service.uuid == ParticlePeripheral.particleLEDServiceUUID {
print("LED service found")
//Now kick off discovery of characteristics
peripheral.discoverCharacteristics([ParticlePeripheral.redLEDCharacteristicUUID,
], for: service) //edited this
return
}
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let characteristics = service.characteristics {
for characteristic in characteristics {
if characteristic.uuid == ParticlePeripheral.redLEDCharacteristicUUID {
print("Red LED characteristic found")
} else if characteristic.uuid == ParticlePeripheral.greenLEDCharacteristicUUID {
print("Green LED characteristic found")
} else if characteristic.uuid == ParticlePeripheral.blueLEDCharacteristicUUID {
print("Blue LED characteristic found");
}
}
}
}
func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
print("RSSI = \(RSSI)")
}
#objc func readRSSI() {
if (self.peripheral != nil) {
self.peripheral.delegate = self
print("RSSI Request - \(peripheral.name!)")
print(self.peripheral.readRSSI())
} else {
print("peripheral = nil")
}
}
func startReadRSSI() {
if self.readRSSITimer == nil {
self.readRSSITimer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(ViewController.readRSSI), userInfo: nil, repeats: true)
}
}
func stopReadRSSI() {
if (self.readRSSITimer != nil) {
self.readRSSITimer.invalidate()
self.readRSSITimer = nil
}
}
}
You can use Data bytes initialiser and pass your received number to it to convert it to Data:
init(bytes: UnsafeRawPointer, count: Int)
extension NSNumber {
var data: Data {
var source = self
return Data(bytes: &source, count: MemoryLayout<NSNumber>.size)
}
}
To convert it from Data back to NSNumber you can use Data's method
func withUnsafeBytes<ResultType>(_ body: (UnsafeRawBufferPointer) throws -> ResultType) rethrows -> ResultType
extension Data {
func object<T>() -> T { withUnsafeBytes { $0.load(as: T.self) } }
var nsNumber: NSNumber { object() }
}
Playground testing:
let integerNumber = NSNumber.init(value: 2)
let integerNumberData = integerNumber.data
let loadedintegerNumber: NSNumber = integerNumberData.nsNumber
loadedintegerNumber // 2
let floatNumber = NSNumber.init(value: 2.7)
let floatNumberData = floatNumber.data
let loadedFloatNumber: NSNumber = floatNumberData.nsNumber
loadedFloatNumber // 2.7
let boolNumber = NSNumber.init(value: true)
let boolNumberData = boolNumber.data
let loadedBoolNumber: NSNumber = boolNumberData.nsNumber
loadedBoolNumber // 1

Receive string data via Bluetooth

I'm creating a simple BLE app that communicates with a single peripheral. The phone acts as the central. I have an iPad which I'm using as the peripheral for testing. It has the app LightBlue installed to simulate a peripheral. The peripheral is supposed to send a string of data in this format.
TEM:25.11 | HUM:70 | PM10:43 | PM25:32
So I created a blank virtual peripheral in LightBlue with one service.
Below is my code for Bluetooth connectivity handling.
import UIKit
import CoreBluetooth
class ViewController: UIViewController {
fileprivate let serviceUUID = CBUUID(string: "19B10010-E8F2-537E-4F6C-D104768A1214")
fileprivate let characteristicUUID = CBUUID(string: "19B10011-E8F2-537E-4F6C-D104768A1214")
fileprivate var manager: CBCentralManager!
fileprivate var peripheral: CBPeripheral!
fileprivate var characteristic: CBCharacteristic!
override func viewDidLoad() {
super.viewDidLoad()
manager = CBCentralManager(delegate: self, queue: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
stopScan()
}
fileprivate func startScan() {
manager.scanForPeripherals(withServices: [serviceUUID], options: nil)
}
fileprivate func stopScan() {
manager.stopScan()
}
fileprivate func disconnectFromDevice() {
guard let peripheral = peripheral else { return }
manager.cancelPeripheralConnection(peripheral)
}
fileprivate func restoreCentralManager() {
manager.delegate = self
}
}
// MARK: - CBCentralManagerDelegate
extension ViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unsupported:
print("Unsupported")
case .unauthorized:
print("Unauthorized")
case .poweredOn:
print("Powered On")
startScan()
case .resetting:
print("Resetting")
case .poweredOff:
print("Powered Off")
case .unknown:
print("Unknown")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Discovered \(String(describing: peripheral.name)) at \(RSSI)")
if peripheral.name == nil || peripheral.name == "" {
return
}
if self.peripheral == nil || self.peripheral.state == .disconnected {
stopScan()
self.peripheral = peripheral
central.connect(peripheral, options: nil)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices([serviceUUID])
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
self.peripheral = nil
central.scanForPeripherals(withServices: nil, options: nil)
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
self.peripheral = nil
}
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
}
}
// MARK: - CBPeripheralDelegate
extension ViewController: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
print("No. of services: \(services.count)")
for service in services {
print(service.uuid)
if service.uuid == serviceUUID {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
guard let characteristics = service.characteristics else { return }
for characteristic in characteristics {
print("characteristic: \(characteristic.uuid)")
if characteristic.uuid == characteristicUUID {
self.characteristic = characteristic
peripheral.setNotifyValue(true, for: characteristic)
peripheral.readValue(for: characteristic)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
print(error)
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic.uuid == characteristicUUID {
print("Got reply from: \(characteristic.uuid)")
print(characteristic.value)
if let data = characteristic.value, let string = String(data: data, encoding: String.Encoding.utf8) {
print(string)
} else {
print("No response!")
}
}
}
}
The discovering and connecting part works just fine. The problem is I don't receive that data string from the peripheral.
The method peripheral(_:didUpdateValueFor:error:) does get fired. I get the Got reply from: 19B10011-E8F2-537E-4F6C-D104768A1214 output in the console. However when I tried to see if there's any data by printing out the characteristic.value, it returns nil.
Not sure if it's something wrong with my code. Or I've configured the peripheral on LightBlue wrong. Does LightBlue send out data automatically? I don't see any Send button or anything anywhere either.
I uploaded a demo project here as well.
Your LightBlue configuration showing that you can only write value on that particular characteristic You have to make this read also

Swift 3 Core Bluetooth not discovering services

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)
}
}

iOS Bluetooth caching error?

I am extremely confused on this matter and wonder if anyone has any ideas as I am not sure what the problem is and my best guess is caching. When I run this application about 95% of the time it will connect correctly and access the alert characteristic but will not trigger didUpdateValueFor. Sometimes though when I change, or re-install the app it works correctly and does trigger. I know the peripheral value is updating correctly as I tested in on other apps. I'm working with a iPhone 6 and I've restarted multiple times. I am unsure what does cause it to work sometimes and thus have not been able to debug. Any idea's or ways I can find the problem?
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
var manager: CBCentralManager!
var peripheral: CBPeripheral!
var devices: [CBPeripheral] = []
var closestRSSI = 0
var alertCharacteristic: CBCharacteristic? = nil
let SERVICE_UUID = CBUUID(string: "06758213-258D-44B2-A577-8AE43E9DF674")
let ALERT_UUID = CBUUID(string: "B9FBC271-666B-4CA7-8F9C-F8E9C0223D20")
let BATTERY_UUID = CBUUID(string: "4D757E85-6A28-48CB-9CF5-299CB72D5AB2")
let FIRMWARE_UUID = CBUUID(string: "64CD5AF5-B6EE-4D46-A164-246BB197F5DA")
let CLIENT_CONFIG_UUID = CBUUID(string: "00002902-0000-1000-8000-00805F9B34FB")
var characteristicUUIDArray: [CBUUID] = []
#IBOutlet weak var connectButton: UIButton!
#IBOutlet weak var infoLabel: UILabel!
#IBOutlet weak var headLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
manager = CBCentralManager(delegate: self, queue: nil)
infoLabel.text = "0"
characteristicUUIDArray = [ALERT_UUID, BATTERY_UUID, FIRMWARE_UUID]
}
#IBAction func connectButtonPressed(_ sender: Any) {
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state{
case .unauthorized:
print("Unauthorized to use BLE")
break
case .poweredOff:
print("Bluetooth is currently powered off")
break
case .poweredOn:
print("Bluetooth is ready to use")
manager.scanForPeripherals(withServices: [SERVICE_UUID], options: nil)
break
case .resetting:
print("Blueooth is resetting")
break
case .unknown:
print("Bluetooth is unknown")
break
case .unsupported:
print("Bluetooth is unsupported")
break
}
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
print(error!)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(peripheral.name ?? "Null")
if peripheral.name != nil{
if peripheral.name! == "Watch" {
self.manager.stopScan()
self.peripheral = peripheral
self.peripheral.delegate = self
manager.connect(peripheral, options: nil)
}
}
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
print("Disconnected")
manager.cancelPeripheralConnection(peripheral)
manager.scanForPeripherals(withServices: [SERVICE_UUID], options: nil)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("\nDid Connect To \(peripheral.name!)")
peripheral.discoverServices([SERVICE_UUID])
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
print("Did Discover Services")
for service in peripheral.services!{
let thisService = service
if thisService.uuid == SERVICE_UUID{
peripheral.discoverCharacteristics(characteristicUUIDArray, for: thisService)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
print("Did Discover Characteristics")
for charateristic in service.characteristics! {
let thisCharacter = charateristic
if thisCharacter.uuid == ALERT_UUID{
print("Alert")
peripheral.setNotifyValue(true, for: thisCharacter)
}
// if thisCharacter.uuid == BATTERY_UUID{
// print("Battery")
// self.peripheral.setNotifyValue(true, for: thisCharacter)
// }
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("Did update")
if(characteristic.uuid == ALERT_UUID){
print("Did Update Value For Alert")
let content = String(data: characteristic.value!, encoding: String.Encoding.utf8)
let value = content?.components(separatedBy: ",")
let warning = Int(value![0])
infoLabel.text = String(warning!)
}
if(characteristic.uuid == BATTERY_UUID){
print("Did Update Value For Battery")
}
}
}
So I believe it was a race condition error. By Wrapping each characteristic in a delay the problem was fixed. Here is what I changed. So I believe it was a race condition error. By Wrapping each characteristic in a delay the problem was fixed. Here is what I changed. I am unsure why this fixes it but if anyone has any ideas I'd enjoy hearing why this is
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
print("Did Discover Characteristics")
for charateristic in service.characteristics! {
let thisCharacter = charateristic
if thisCharacter.uuid == ALERT_UUID{
print("Alert")
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute: {
peripheral.setNotifyValue(true, for: thisCharacter)
})
}
if thisCharacter.uuid == BATTERY_UUID{
print("Battery")
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute: {
peripheral.setNotifyValue(true, for: thisCharacter)
})
}
}
}

Swift CoreBluetooth: why I do not find the same characteristic as my bluetooth peripheral?

I'm starting with the bluetooth as a project car Arduino controlled by an iPhone.
The problem is that I try to send a single data from my iphone but looking more closely at the scan function is not good caracteristic and I think the problem comes from here.
Have you an idea to find the same in their characteristic UUID?
import UIKit
import CoreBluetooth
#IBOutlet weak var peripheralLabel: UILabel!
//713D0000503E4C75BA943148F18D941E
let BEAN_NAME = "Carduino"
let CBUUIDUuidTx = CBUUID(string: "713D0000-503E-4C75-BA94-3148F18D941E")
let CBUUIDUuIdRx = CBUUID(string: "713D0000-503E-4C75-BA94-3148F18D941E")
let UuidTx = "713D0000-503E-4C75-BA94-3148F18D941E"
let UuIdRx = "713D0000-503E-4C75-BA94-3148F18D941E"
var peripheralBLE: CBPeripheral?
var manager:CBCentralManager!
var myPeripheral:CBPeripheral!
var sendDataCharacteristic:CBCharacteristic!
var txCharacteristic: CBCharacteristic!
var rxCharacteristic: CBCharacteristic!
override func viewDidLoad() {
super.viewDidLoad()
manager = CBCentralManager(delegate: self, queue: nil)
}
//Scan For devices
func centralManagerDidUpdateState(_ central: CBCentralManager) {
manager.scanForPeripherals(withServices: [CBUUIDUuidTx], options: nil)
}
//Connect to a Device
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
let device = (advertisementData as NSDictionary)
.object(forKey: CBAdvertisementDataLocalNameKey)
as? NSString
if device?.contains(BEAN_NAME) == true {
self.manager.stopScan()
self.myPeripheral = peripheral
self.myPeripheral.delegate = self
manager.connect(peripheral, options: nil)
peripheralLabel.text = "Connect to \(peripheral.name!)"
}
}
//Get Services
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
peripheral.discoverServices(nil)
}
//Get Characteristics
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service in peripheral.services! {
let thisService = service as CBService
if service.uuid == CBUUIDUuidTx {
peripheral.discoverCharacteristics(
nil,
for: thisService
)
}
print("This Service : \(thisService)")
}
}
func peripheral( _ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
let thisCharacteristic = characteristic as CBCharacteristic
if thisCharacteristic.uuid == CBUUIDUuidTx {
self.myPeripheral.setNotifyValue(
true,
for: thisCharacteristic
)
}
print("This Characteristic : \(thisCharacteristic)")
}
}
//Disconnect and Try Again
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?) {
central.scanForPeripherals(withServices: nil, options: nil)
}
#IBAction func ledAction(_ sender: AnyObject) {
writeValue(data: "0x01")
}
func writeValue(data: String) {
if(myPeripheral != nil)
{
print(myPeripheral)
//happens for sure
var bytesData = [UInt8](data.utf8)
let writeData = NSData (bytes: &bytesData, length: bytesData.count)
myPeripheral.writeValue(writeData as Data, for: txCharacteristic, type: CBCharacteristicWriteType.withResponse)
print(txCharacteristic)
}
}

Resources