• Swift语言iOS8的蓝牙Bluetooth解析


    开发中央步骤:

      1.添加CoreBluetooth.framework框架到你的工程

      2.继承两个协议:CBCentralManagerDelegate和CBPeripheralDelegate

      个人写的demo,有详细注释。看不懂的在提出来,这里就不做过多的解释了。

      

      1 //
      2 //  ViewController.swift
      3 //  CoreBluetooth
      4 //
      5 //  Created by fanviwa on 15/4/23.
      6 //  Copyright (c) 2015年 fanviwa. All rights reserved.
      7 //
      8 
      9 import UIKit
     10 
     11 class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
     12 
     13     @IBOutlet weak var tableView: UITableView!
     14     
     15     //添加属性
     16     var manager: CBCentralManager!
     17     var peripheral: CBPeripheral!
     18     var writeCharacteristic: CBCharacteristic!
     19     //保存收到的蓝牙设备
     20     var deviceList:NSMutableArray = NSMutableArray()
     21     //服务和特征的UUID
     22     let kServiceUUID = [CBUUID(string:"FFE0")]
     23     let kCharacteristicUUID = [CBUUID(string:"FFE1")]
     24     
     25     override func viewDidLoad() {
     26         super.viewDidLoad()
     27         //1.创建一个中央对象
     28         self.manager = CBCentralManager(delegate: self, queue: nil)
     29     }
     30     
     31     //2.检查运行这个App的设备是不是支持BLE。代理方法
     32     func centralManagerDidUpdateState(central: CBCentralManager){
     33         switch central.state {
     34         case CBCentralManagerState.PoweredOn:
     35             //扫描周边蓝牙外设.
     36             //写nil表示扫描所有蓝牙外设,如果传上面的kServiceUUID,那么只能扫描出FFEO这个服务的外设。
     37             //CBCentralManagerScanOptionAllowDuplicatesKey为true表示允许扫到重名,false表示不扫描重名的。
     38             self.manager.scanForPeripheralsWithServices(kServiceUUID, options:[CBCentralManagerScanOptionAllowDuplicatesKey: false])
     39             println("蓝牙已打开,请扫描外设")
     40         case CBCentralManagerState.Unauthorized:
     41             println("这个应用程序是无权使用蓝牙低功耗")
     42         case CBCentralManagerState.PoweredOff:
     43             println("蓝牙目前已关闭")
     44         default:
     45             println("中央管理器没有改变状态")
     46         }
     47     }
     48     
     49     //3.查到外设后,停止扫描,连接设备
     50     //广播、扫描的响应数据保存在advertisementData 中,可以通过CBAdvertisementData 来访问它。
     51     func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI : NSNumber!){
     52         if(!self.deviceList.containsObject(peripheral)){
     53             self.deviceList.addObject(peripheral)
     54         }
     55         self.tableView.reloadData()
     56     }
     57     
     58     //4.连接外设成功,开始发现服务
     59     func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!){
     60         //停止扫描外设
     61         self.manager.stopScan()
     62         self.peripheral = peripheral
     63         self.peripheral.delegate = self
     64         self.peripheral.discoverServices(nil)
     65         
     66     }
     67     
     68     //连接外设失败
     69     func centralManager(central: CBCentralManager!, didFailToConnectPeripheral peripheral: CBPeripheral!, error: NSError!){
     70         println("连接外设失败===(error)")
     71     }
     72     
     73     //5.请求周边去寻找它的服务所列出的特征
     74     func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!){
     75         if error != nil {
     76             println("错误的服务特征:(error.localizedDescription)")
     77             return
     78         }
     79         var i: Int = 0
     80         for service in peripheral.services {
     81             println("服务的UUID:(service.UUID)")
     82             i++
     83             //发现给定格式的服务的特性
     84 //            if (service.UUID == CBUUID(string:"FFE0")) {
     85 //                peripheral.discoverCharacteristics(kCharacteristicUUID, forService: service as CBService)
     86 //            }
     87             peripheral.discoverCharacteristics(nil, forService: service as! CBService)
     88         }
     89     }
     90     
     91     //6.已搜索到Characteristics
     92     func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!){
     93         //println("发现特征的服务:(service.UUID.data)   ==  服务UUID:(service.UUID)")
     94         if (error != nil){
     95             println("发现错误的特征:(error.localizedDescription)")
     96             return
     97         }
     98         
     99         for  characteristic in service.characteristics  {
    100             //罗列出所有特性,看哪些是notify方式的,哪些是read方式的,哪些是可写入的。
    101             println("服务UUID:(service.UUID)         特征UUID:(characteristic.UUID)")
    102             //特征的值被更新,用setNotifyValue:forCharacteristic
    103             switch characteristic.UUID.description {
    104             case "FFE1":
    105                 //如果以通知的形式读取数据,则直接发到didUpdateValueForCharacteristic方法处理数据。
    106                 self.peripheral.setNotifyValue(true, forCharacteristic: characteristic as! CBCharacteristic)
    107                 
    108             case "2A37":
    109                 //通知关闭,read方式接受数据。则先发送到didUpdateNotificationStateForCharacteristic方法,再通过readValueForCharacteristic发到didUpdateValueForCharacteristic方法处理数据。
    110                 self.peripheral.readValueForCharacteristic(characteristic as! CBCharacteristic)
    111                 
    112             case "2A38":
    113                 self.peripheral.readValueForCharacteristic(characteristic as! CBCharacteristic)
    114                 
    115             case "Battery Level":
    116                 self.peripheral.setNotifyValue(true, forCharacteristic: characteristic as! CBCharacteristic)
    117                 
    118             case "Manufacturer Name String":
    119                 self.peripheral.readValueForCharacteristic(characteristic as! CBCharacteristic)
    120                 
    121             case "6E400003-B5A3-F393-E0A9-E50E24DCCA9E":
    122                 self.peripheral.setNotifyValue(true, forCharacteristic: characteristic as! CBCharacteristic)
    123                 
    124             case "6E400002-B5A3-F393-E0A9-E50E24DCCA9E":
    125                 self.peripheral.readValueForCharacteristic(characteristic as! CBCharacteristic)
    126                 self.writeCharacteristic = characteristic as! CBCharacteristic
    127                 let heartRate: NSString = "ZhuHai XY"
    128                 let dataValue: NSData = heartRate.dataUsingEncoding(NSUTF8StringEncoding)!
    129                 //写入数据
    130                 self.writeValue(service.UUID.description, characteristicUUID: characteristic.UUID.description, peripheral: self.peripheral, data: dataValue)
    131                 
    132             default:
    133                 break
    134             }
    135         }
    136     }
    137     
    138     //8.获取外设发来的数据,不论是read和notify,获取数据都是从这个方法中读取。
    139     func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!){
    140         if(error != nil){
    141             println("发送数据错误的特性是:(characteristic.UUID)     错误信息:(error.localizedDescription)       错误数据:(characteristic.value)")
    142             return
    143         }
    144         
    145         
    146 
    147         switch characteristic.UUID.description {
    148         case "FFE1":
    149             println("=(characteristic.UUID)特征发来的数据是:(characteristic.value)=")
    150             
    151         case "2A37":
    152             println("=(characteristic.UUID.description):(characteristic.value)=")
    153             
    154         case "2A38":
    155             var dataValue: Int = 0
    156             characteristic.value.getBytes(&dataValue, range:NSRange(location: 0, length: 1))
    157             println("2A38的值为:(dataValue)")
    158             
    159         case "Battery Level":          //如果发过来的是Byte值,在Objective-C中直接.getBytes就是Byte数组了,在swift目前就用这个方法处理吧!
    160             var batteryLevel: Int = 0
    161             characteristic.value.getBytes(&batteryLevel, range:NSRange(location: 0, length: 1))
    162             println("当前为你检测了(batteryLevel)秒!")
    163             
    164         case "Manufacturer Name String":          //如果发过来的是字符串,则用NSData和NSString转换函数
    165             let manufacturerName: NSString = NSString(data: characteristic.value, encoding: NSUTF8StringEncoding)!
    166             println("制造商名称为:(manufacturerName)")
    167             
    168         case "6E400003-B5A3-F393-E0A9-E50E24DCCA9E":
    169             println("=(characteristic.UUID)特征发来的数据是:(characteristic.value)=")
    170             
    171         case "6E400002-B5A3-F393-E0A9-E50E24DCCA9E":
    172             println("返回的数据是:(characteristic.value)")
    173             
    174         default:
    175             break
    176         }
    177     }
    178     
    179     //7.这个是接收蓝牙通知,很少用。读取外设数据主要用上面那个方法didUpdateValueForCharacteristic。
    180     func peripheral(peripheral: CBPeripheral!, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic!, error: NSError!){
    181         if error != nil {
    182             println("更改通知状态错误:(error.localizedDescription)")
    183         }
    184         
    185         println("收到的特性数据:(characteristic.value)")
    186         //如果它不是传输特性,退出.
    187 //        if characteristic.UUID.isEqual(kCharacteristicUUID) {
    188 //            return
    189 //        }
    190         //开始通知
    191         if characteristic.isNotifying {
    192             println("开始的通知(characteristic)")
    193             peripheral.readValueForCharacteristic(characteristic)
    194         }else{
    195             //通知已停止
    196             //所有外设断开
    197             println("通知(characteristic)已停止设备断开连接")
    198             self.manager.cancelPeripheralConnection(self.peripheral)
    199         }
    200     }
    201     
    202     //写入数据
    203     func writeValue(serviceUUID: String, characteristicUUID: String, peripheral: CBPeripheral!, data: NSData!){
    204         peripheral.writeValue(data, forCharacteristic: self.writeCharacteristic, type: CBCharacteristicWriteType.WithResponse)
    205         println("手机向蓝牙发送的数据为:(data)")
    206     }
    207     //用于检测中心向外设写数据是否成功
    208     func peripheral(peripheral: CBPeripheral!, didWriteValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
    209         if(error != nil){
    210             println("发送数据失败!error信息:(error)")
    211         }else{
    212             println("发送数据成功(characteristic)")
    213         }
    214     }
    215     
    216     func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    217         // #warning Potentially incomplete method implementation.
    218         // Return the number of sections.
    219         return 1
    220     }
    221     
    222     func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    223         // #warning Incomplete method implementation.
    224         // Return the number of rows in the section.
    225         return self.deviceList.count
    226     }
    227     
    228     
    229     func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    230         //PCell,确定单元格的样式
    231         let cell = tableView.dequeueReusableCellWithIdentifier("FhrCell", forIndexPath: indexPath) as! UITableViewCell
    232         var device:CBPeripheral=self.deviceList.objectAtIndex(indexPath.row) as! CBPeripheral
    233         //主标题
    234         cell.textLabel?.text = device.name
    235         //副标题
    236         cell.detailTextLabel?.text = device.identifier.UUIDString
    237         return cell
    238     }
    239     
    240     //通过选择来连接和断开外设
    241     func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    242         if(self.peripheralList.containsObject(self.deviceList.objectAtIndex(indexPath.row))){
    243             self.manager.cancelPeripheralConnection(self.deviceList.objectAtIndex(indexPath.row) as! CBPeripheral)
    244             self.peripheralList.removeObject(self.deviceList.objectAtIndex(indexPath.row))
    245             println("蓝牙已断开!")
    246         }else{
    247             self.manager.connectPeripheral(self.deviceList.objectAtIndex(indexPath.row) as! CBPeripheral, options: nil)
    248             self.peripheralList.addObject(self.deviceList.objectAtIndex(indexPath.row))
    249             println("蓝牙已连接! (self.peripheralList.count)")
    250         }
    251     }
    252 
    253 }

      注意:

    查看特性以什么方式读取,就看每个Characteristic的notifying属性值,NO说明read方式,YES说明notifying通知方式

    <CBCharacteristic: 0x17008a0f0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = (null), notifying = YES>

    下面是properties的具体解释:

    SWIFT
    struct CBCharacteristicProperties : RawOptionSetType {
        init(_ value: UInt)
        var value: UInt
        static var Broadcast: CBCharacteristicProperties { get }
        static var Read: CBCharacteristicProperties { get }
        static var WriteWithoutResponse: CBCharacteristicProperties { get }
        static var Write: CBCharacteristicProperties { get }
        static var Notify: CBCharacteristicProperties { get }
        static var Indicate: CBCharacteristicProperties { get }
        static var AuthenticatedSignedWrites: CBCharacteristicProperties { get }
        static var ExtendedProperties: CBCharacteristicProperties { get }
        static var NotifyEncryptionRequired: CBCharacteristicProperties { get }
        static var IndicateEncryptionRequired: CBCharacteristicProperties { get }
    }
    OBJECTIVE-C
    typedef enum {
       CBCharacteristicPropertyBroadcast = 0x01,
       CBCharacteristicPropertyRead = 0x02,
       CBCharacteristicPropertyWriteWithoutResponse = 0x04,
       CBCharacteristicPropertyWrite = 0x08,
       CBCharacteristicPropertyNotify = 0x10,
       CBCharacteristicPropertyIndicate = 0x20,
       CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
       CBCharacteristicPropertyExtendedProperties = 0x80,
       CBCharacteristicPropertyNotifyEncryptionRequired = 0x100,
       CBCharacteristicPropertyIndicateEncryptionRequired = 0x200,
    } CBCharacteristicProperties;
  • 相关阅读:
    python之路3-元组、列表、字典、集合
    python之路2-字符串操作
    Python之路1-变量、数据类型、循环语法
    config模块
    os模块
    logging模块
    控制台报错定位问题所在
    time模块
    random模块
    列表生成
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4995178.html
Copyright © 2020-2023  润新知