=========实例一
/**
蓝牙的简易使用
*/
import UIKit
import CoreBluetooth
@available(iOS 10.0, *)
class LYBBlueToothVC: UIViewController ,CBCentralManagerDelegate, CBPeripheralDelegate {
////中央管理器的状态改变时调用(也就是蓝牙开或者关的状态发生改变);这个方法必须实现
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch (central.state) {
case CBManagerState.poweredOn:
//蓝牙开启状态
//扫描外设
manager?.scanForPeripherals(withServices: [CBUUID.init(string: "ff15")], options: [CBCentralManagerScanOptionAllowDuplicatesKey :true])//是为了过滤掉其他设备,可以搜索特定标示的设备
break
case CBManagerState.poweredOff:
//蓝牙关闭状态
break
case CBManagerState.unauthorized:
//蓝牙未授权
break
default:
break
}
}
/**
1. 创建中央管理者
2. 扫描外围设备
3. 连接外围设备
4. 扫描服务和特性
5. 利用特性做数据的读写操作
6. 断开连接
*/
var manager:CBCentralManager?
//0. 初始化数组
var peripheralData = [CBPeripheral]()
override func viewDidLoad() {
super.viewDidLoad()
//1. 创建中央管理者
//Delegate: 代理
//queue : 队列 如果传nil, 就是主队列
manager=CBCentralManager.init(delegate: self, queue: nil)
//2. 扫描外围设备
//scan: 扫描
//Peripheral: 外设
//Services: 服务的UUID 如果传nil, 代表扫描所有的服务
manager?.scanForPeripherals(withServices: nil, options: nil)
}
/**
3. 当发现外围设备的时候会调用方法
peripheral: 外设
advertisementData: 数据
RSSI : 信号强度
*/
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
//当扫描到的时候, 我们需要数组保存, 然后创建tableView给用户显示, 让用户来选择连接哪一个设备
// 又可能扫描到重复的设备, 需要去重
if !peripheralData.contains(peripheral){
peripheralData.append(peripheral)
}
}
/**
4. 连接外设---将来需要选中tableViewCell的某一行, 来连接外设
用下面的方法connectPeripheral 模拟tableViewCell选中的方法
*/
func connect(peripheral:CBPeripheral){
manager?.connect(peripheral, options: nil)
}
/**
5. 当连接到外围设备时调用的代理方法
*/
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
//5.1 设置外设的代理
peripheral.delegate = self;
//5.2 用外设来扫描服务(传如UUID数组NSArray *)serviceUUIDs) 如果不传, 代表扫描所有服务
peripheral.discoverServices(nil)
}
/**
6. 当扫描到服务的时候, 此代理方法会调用
*/
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
//找到指定服务UUID, 然后去扫描此服务的特性
//services: 当扫描到服务时, 所有的服务会存在在外设的services属性中
for service:CBService in peripheral.services!{
//将来服务和特征的UUID, 都在蓝牙厂商提供的文档中
// 假设服务的UUID为 123456
if service.uuid.uuidString=="123456"{
//扫描此服务的特性
//Characteristics: 特征
//如果特征传nil, 代表扫描所有特征
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
/**
7. 扫描到某个服务的某个特征时, 会调用的代理方法
*/
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
//找到指定特征的UUID, 然后就可以做数据交互了
//characteristics: 当扫描到特征时, 所有的特征会存在在服务的characteristics属性中
for characteristic:CBCharacteristic in service.characteristics!{
// 假设特征的UUID为 654321
if characteristic.uuid.uuidString=="654321"{
let da = Data.init()
// 在这里进行写操作,写数据到特征中
peripheral.writeValue(da, for: characteristic, type: CBCharacteristicWriteType.withResponse)
//从特征中读取数据
peripheral.readValue(for: characteristic)
//处理蓝牙发过来的数据
//不过更好的办法是设置事件通知实时获取读取到的数据。设置了这个方法,会调用代理方法func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)
peripheral.setNotifyValue(true, for: characteristic)
}
}
}
///获取外设发来的数据,不论是read和notify,获取数据都是从这个方法中读取。
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
}
//向特征中写入数据后调用
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
}
//管理中心读取外设发来的实时数据(在前面设置了setNotifyValue:forCharacteristic:这个方法发送通知。会调用下面这个方法)
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
}
/**
8. 断开连接
*/
func stopScan(){
manager?.stopScan()
}
//蓝牙链接失败时调用
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
}
//蓝牙断开链接时调用
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
}
// 在和硬件之间的数据发送和接受,用的都是byte数组。
}
================================例子二
//需要在library link中加入coreblootooth.framework
/**
蓝牙的简易使用
*/
import UIKit
import CoreBluetooth
@available(iOS 10.0, *)
class LYBBlueToothVC: UIViewController ,CBCentralManagerDelegate, CBPeripheralDelegate {
/**
1. 创建中央管理者
2. 扫描外围设备
3. 连接外围设备
4. 扫描服务和特性
5. 利用特性做数据的读写操作
6. 断开连接
*/
//添加属性
var manager: CBCentralManager!
var peripheral: CBPeripheral!
var writeCharacteristic: CBCharacteristic!
//保存收到的蓝牙设备
var deviceList:NSMutableArray = NSMutableArray()
//服务和特征的UUID
let kServiceUUID = [CBUUID(string:"FFE0")]
let kCharacteristicUUID = [CBUUID(string:"FFE1")]
override func viewDidLoad() {
//1.创建一个中央对象
self.manager = CBCentralManager(delegate: self, queue: nil)
}
//2.检查运行这个App的设备是不是支持BLE。代理方法
func centralManagerDidUpdateState(_ central: CBCentralManager){
switch central.state {
case CBManagerState.poweredOn:
//扫描周边蓝牙外设.
//写nil表示扫描所有蓝牙外设,如果传上面的kServiceUUID,那么只能扫描出FFEO这个服务的外设。
//CBCentralManagerScanOptionAllowDuplicatesKey为true表示允许扫到重名,false表示不扫描重名的。
self.manager.scanForPeripherals(withServices: kServiceUUID, options:[CBCentralManagerScanOptionAllowDuplicatesKey: false])
print("蓝牙已打开,请扫描外设")
case CBManagerState.unauthorized:
print("这个应用程序是无权使用蓝牙低功耗")
case CBManagerState.poweredOff:
print("蓝牙目前已关闭")
default:
print("中央管理器没有改变状态")
}
}
//3.查到外设后,停止扫描,连接设备
//广播、扫描的响应数据保存在advertisementData 中,可以通过CBAdvertisementData 来访问它。
private func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI : NSNumber!){
}
//4.连接外设成功,开始发现服务
func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!){
//停止扫描外设
self.manager.stopScan()
self.peripheral = peripheral
self.peripheral.delegate = self
self.peripheral.discoverServices(nil)
}
//连接外设失败
private func centralManager(central: CBCentralManager!, didFailToConnectPeripheral peripheral: CBPeripheral!, error: NSError!){
print("连接外设失败===\(String(describing: error))")
}
//5.请求周边去寻找它的服务所列出的特征
func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: Error?){
if error != nil {
print("错误的服务特征:\(error!.localizedDescription)")
return
}
for service in peripheral!.services as! [CBService] {
print("服务的UUID:\(service.uuid)")
//发现给定格式的服务的特性
// if (service.UUID == CBUUID(string:"FFE0")) {
// peripheral.discoverCharacteristics(kCharacteristicUUID, forService: service as CBService)
// }
peripheral.discoverCharacteristics(nil, for: service )
}
}
//6.已搜索到Characteristics
private func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!){
//println("发现特征的服务:\(service.UUID.data) == 服务UUID:\(service.UUID)")
if (error != nil){
print("发现错误的特征:\(error.localizedDescription)")
}
for characteristic in service!.characteristics as! [CBCharacteristic]{
//罗列出所有特性,看哪些是notify方式的,哪些是read方式的,哪些是可写入的。
print("服务UUID:\(service.uuid) ---- 特征UUID:\(characteristic.uuid)")
//特征的值被更新,用setNotifyValue:forCharacteristic
switch characteristic.uuid.description {
case "FFE1":
//如果以通知的形式读取数据,则直接发到didUpdateValueForCharacteristic方法处理数据。
self.peripheral.setNotifyValue(true, for: characteristic )
case "2A37":
//通知关闭,read方式接受数据。则先发送到didUpdateNotificationStateForCharacteristic方法,再通过readValueForCharacteristic发到didUpdateValueForCharacteristic方法处理数据。
self.peripheral.readValue(for: characteristic )
case "2A38":
self.peripheral.readValue(for: characteristic )
case "Battery Level":
self.peripheral.setNotifyValue(true, for: characteristic )
case "Manufacturer Name String":
self.peripheral.readValue(for: characteristic )
case "6E400003-B5A3-F393-E0A9-E50E24DCCA9E":
self.peripheral.setNotifyValue(true, for: characteristic )
case "6E400002-B5A3-F393-E0A9-E50E24DCCA9E":
self.peripheral.readValue(for: characteristic )
self.writeCharacteristic = characteristic
let heartRate: NSString = "ZhuHai XY"
let dataValue: Data = heartRate.data(using: String.Encoding.utf8.rawValue, allowLossyConversion: true)! as Data
// let dat:String = String(data: dataValue as Data, encoding: String.Encoding.utf8)!
//写入数据
self.writeValue(serviceUUID: service.uuid.description, characteristicUUID: characteristic.uuid.description, peripheral: self.peripheral, data: dataValue as NSData )
default:
break
}
}
}
//8.获取外设发来的数据,不论是read和notify,获取数据都是从这个方法中读取。
func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: Error?){
if(error != nil){
print("发送数据错误的特性是:\(characteristic.uuid) 错误信息:\(error!.localizedDescription) 错误数据:\(String(describing: characteristic.value))")
return
}
switch characteristic.uuid.description {
// case "FFE1":
// print("=\(characteristic.uuid)特征发来的数据是:\(String(describing: characteristic.value))=")
case "2A37":
print("=\(characteristic.uuid.description):\(String(describing: characteristic.value))=")
case "2A38": break
// var dataValue: Int = 0
// characteristic.valuecopyBytes.getBytes(&dataValue, range:NSRange(location: 0, length: 1))
// print("2A38的值为:\(dataValue)")
case "Battery Level": break
////如果发过来的是Byte值,在Objective-C中直接.getBytes就是Byte数组了,在swift目前就用这个方法处理吧!
// var batteryLevel: Int = 0
// characteristic.valuecopyBytes.getBytes(&batteryLevel, range:NSRange(location: 0, length: 1))
// print("当前为你检测了\(batteryLevel)秒!")
case "Manufacturer Name String":
//如果发过来的是字符串,则用NSData和NSString转换函数
let manufacturerName: NSString = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue)!
print("制造商名称为:\(manufacturerName)")
break
case "6E400003-B5A3-F393-E0A9-E50E24DCCA9E": break
// print("=\(characteristic.uuid)特征发来的数据是:\(String(describing: characteristic.value))=")
// case "6E400002-B5A3-F393-E0A9-E50E24DCCA9E":
// print("返回的数据是:\(characteristic.value)")
default:
break
}
}
//7.这个是接收蓝牙通知,很少用。读取外设数据主要用上面那个方法didUpdateValueForCharacteristic。
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?){
if error != nil {
print("更改通知状态错误:\(error!.localizedDescription)")
}
print("收到的特性数据:\(String(describing: characteristic.value))")
//如果它不是传输特性,退出.
// if characteristic.UUID.isEqual(kCharacteristicUUID) {
// return
// }
//开始通知
if characteristic.isNotifying {
print("开始的通知\(String(describing: characteristic))")
peripheral.readValue(for: characteristic)
}else{
//通知已停止
//所有外设断开
print("通知\(String(describing: characteristic))已停止设备断开连接")
self.manager.cancelPeripheralConnection(self.peripheral)
}
}
//写入数据
func writeValue(serviceUUID: String, characteristicUUID: String, peripheral: CBPeripheral!, data: NSData!){
peripheral.writeValue(data as Data, for: self.writeCharacteristic, type: CBCharacteristicWriteType.withResponse)
print("手机向蓝牙发送的数据为:\(String(describing: data))")
}
//用于检测中心向外设写数据是否成功
func peripheral(peripheral: CBPeripheral!, didWriteValueForCharacteristic characteristic: CBCharacteristic!, error: Error?) {
if(error != nil){
print("发送数据失败!error信息:\(String(describing: error))")
}else{
print("发送数据成功\(String(describing: characteristic))")
}
}
}