Swift语言iOS8的蓝牙Bluetooth解析(转帖)

开发中央步骤:

  1.添加CoreBluetooth.framework框架到你的工程  (目前swift只需要import CoreBluetooth就行了)

  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 import CoreBluetooth //注:直接引入
 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)  //我在此处后面加入调用self.manager.connectPeripheral()方法 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;
时间: 2024-08-24 23:49:32

Swift语言iOS8的蓝牙Bluetooth解析(转帖)的相关文章

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年

基于swift语言iOS8的蓝牙连接(初步)

看过一些蓝牙App的事例,大体上对蓝牙的连接过程进行了了解.但是开始真正自己写一个小的BLE程序的时候就举步维艰了.那些模棱两可的概念在头脑中瞬间就蒸发了,所以还是决定从最基本的蓝牙连接过程进行.这里所说的蓝牙是针对 bluetooth 4.0的. 第一步就是去看官方的关于蓝牙框架的文档,即Core Bluetooth Programming Guide,在苹果的官方网站上可以轻松找到,不管你对蓝牙的基本概念是否有了解,这个文件可以使你更好的对蓝牙的连接过程有个了解.这个文档的前面几张介绍了关于

swift语言IOS8开发战记24 解析Json

在IOS中使用NSURLConnection实现http通信,NSURLConnection提供了异步和同步两种通信方式,同步请求会造成进程阻塞,通常我们使用异步的方式,不管同步还是异步,建立通信的基本步骤都是一样的: 1,创建NSURL 2,创建Request对象 3,创建NSURLConnection连接 第3步结束后就建立了一个http连接. 这里我们用一个开放的api做例子: http://www.weather.com.cn/adat/sk/101010100.html 这是北京市的当

swift语言IOS8开发战记23 Core Data4

这后面的部分痘子的视频已经不讲了,我自己看着英文书试着给大家讲的,书名叫<Beginning IOS8 Programming with Swift>,感兴趣的同学自己搜一下哈.上一话中我们讲解了coredadta的用法,那么如何把coredata用到我们的工程中么,可以把上一话中的代码粘贴到我们工程的AppDelegate中,基本这套代码是通用的,注意有两句要修改一下,一句是: let modelURL = NSBundle.mainBundle().URLForResource("

swift语言IOS8开发战记20 Core Data1

Core Data字面意思就是核心数据,但它其实并不是一个数据库,它是一个框架,就像我们之前经常用到的Foundation一样,我们做持久化的时候,使用Core Data非常方便.下面展示的是Core Data框架的结构图: 我们来新建一个项目进行添加core data的学习. 新建一个项目,在项目中添加new file的时候可以看到专门有一个Core Data的选项 我们选择Data Model,创建,使用默认名字,现在看到工程里多出了一个Model.xcdatamodeld,点击已下按钮添加

swift语言IOS8开发战记21 Core Data2

新年到了,祝大家大家羊年快乐,喜气洋洋.上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用.这一话中建立的几个变量对照上一话中讲到的coredata中重要的变量,在AppDelegate中,添加如下代码: lazy var applicationDocumentsDirectory:NSURL = { let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDire

swift语言IOS8开发战记22 Core Data3

上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功.首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc(Info),不然后面会报错,我也不知道为什么. 然后在viewController中添加代码如下代码来实现: import UIKit import CoreData class ViewController: UIViewController { var tempInfo: Info! override func viewD

Swift语言IOS8开发战记27 Sketch初探

在之前我们新建了一个计算器项目,现在我想要给这个计算器项目制作一个桌面图标,可以使用Sketch,这是一款非常棒的软件.要想详细地学习这个软件请访问"Sketch中国",里面有很多专业的Demo和教材. 相对于PS这样的软件,Sketch简直就是为移动平台量身定做的. 打开Sketch,然后在右侧选择新建一个DeskTop HD,主页面有点像我们的Xcode,中间是画布,右侧是检查器. 可以使用快捷键A建立画板,你可以把画板当做图层的顶层,在上面自由发挥.然后我们使用U新建一个圆角矩形

Swift语言IOS8开发战记25 网络通信Get和Post方式

Get是从服务器上获取数据,Post是向服务器传送数据.对于Get方式,服务器端用Requset.QueryString获取变量的值,对于Post方式,服务器端用Request.Form获取提交的数据.Get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内个个字段一一对应,在URL中可以看到.Post是通过HTTP Post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址.用户看不到这个过程. Get安全性非常低,Po