http://www.itnose.net/detail/6253738.html
开发中央步骤:
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,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;