swift 之蓝牙的应用

  • Post author:
  • Post category:其他


=========实例一

/**
 蓝牙的简易使用
 
 */
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<CBUUID *> *)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.请求周边去寻找它的服务所列出的特征
    private func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: Error?){
   if error != nil {
    print("错误的服务特征:\(error!.localizedDescription)")
      return
       }
    
        for service in peripheral!.services! {
        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!{
  //罗列出所有特性,看哪些是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 = "LAMBO"
                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, didUpdateValueFor 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))")
    }
 //用于检测中心向外设写数据是否成功
    private func peripheral(peripheral: CBPeripheral!, didWriteValueForCharacteristic characteristic: CBCharacteristic!, error: Error?) {
   if(error != nil){
    print("发送数据失败!error信息:\(String(describing: error))")
      }else{
    print("发送数据成功\(String(describing: characteristic))")
    }
    }
    
}



版权声明:本文为u011146511原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。