demo下载 http://download.csdn.NET/detail/swibyn/9717588
直接看代码 http://blog.csdn.Net/swibyn/article/details/53785249
首先推荐去看官方文档哦
现将创建蓝牙工程的要点总结一下,由于工程主要涉及中心模式,所以只总结中心模式的用法
1,引入CoreBluetooth.framework
2,实现蓝牙协议,如:
.h文件如下
@protocolCBCentralManagerDelegate;
@protocolCBPeripheralDelegate;
@interface ViewController :UIViewController<CBCentralManagerDelegate,CBPeripheralDelegate>
.m文件如下
#import "CoreBluetooth/CoreBluetooth.h"
另外还有代理部分请自行添加
3,下面是使蓝牙动起来的过程
3.1创建CBCentralManager实例
self.cbCentralMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
设置代理,比如:
self.cbCentralMgr.delegate =self;
创建数组管理外设
self.peripheralArray = [NSMutableArrayarray];
3.2扫描周围的蓝牙
实际上周围的蓝牙如果可被发现,则会一直往外发送广告消息,中心设备就是通过接收这些消息来发现周围的蓝牙的
[self.cbCentralMgr scanForPeripheralsWithServices:nil options:nil];
3.3发现一个蓝牙设备
也就是收到了一个周围的蓝牙发来的广告信息,这是CBCentralManager会通知代理来处理
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
}
如果周围的蓝牙有多个,则这个方法会被调用多次,你可以通过tableView或其他的控件把这些周围的蓝牙的信息打印出来
3.4连接一个蓝牙
[self.cbCentralMgrconnectPeripheral:peripheral options:nil];
一个中心设备可以同时连接多个周围的蓝牙设备
当连接上某个蓝牙之后,CBCentralManager会通知代理处理
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
}
因为在后面我们要从外设蓝牙那边再获取一些信息,并与之通讯,这些过程会有一些事件可能要处理,所以要给这个外设设置代理,比如:
peripheral.delegate =self;
3.5查询蓝牙服务
[peripheral discoverServices:nil];
返回的蓝牙服务通知通过代理实现
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
for (CBService* service in peripheral.services){
}
}
3.6查询服务所带的特征值
[peripheral discoverCharacteristics:nil forService:service];
返回的蓝牙特征值通知通过代理实现
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
for (CBCharacteristic * characteristic in service.characteristics) {
}
}
3.7给蓝牙发数据
[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
这时还会触发一个代理事件
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
}
3.8处理蓝牙发过来的数据
一种方法是主动读取数据,不过更好的办法是设置事件通知。
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
这样当有数据时会自动触发代理事件
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
}
3.9 retrievePeripheralsWithIdentifiers使用例子
-(IBAction) Retrieve:(id)Sender
{
[self.tvLogsetText:@""];
NSMutableArray * Identifiers = [NSMutableArrayarray];
for (CBPeripheral * peripheralinself.peripheralArray) {
[IdentifiersaddObject:peripheral.identifier];
}
[selfaddLog:@"[self.cbCentralMgr retrievePeripheralsWithIdentifiers:self.PeripheralIdentifiers]"];
self.retrievePeripherals = [self.cbCentralMgrretrievePeripheralsWithIdentifiers:Identifiers];
for (CBPeripheral* peripheralinself.retrievePeripherals) {
[selfaddLog:[NSStringstringWithFormat:@"%@ name:%@",peripheral,peripheral.name]];
}
[self.tableViewPeripheralreloadData];
}
3.10 retrieveConnectedPeripheralsWithServices使用例子
-(IBAction) Retrieve:(id)Sender
{
[self.tvLogsetText:@""];
NSMutableArray * services = [NSMutableArrayarray];
for (CBPeripheral * peripheralinself.peripheralArray) {
if (peripheral.isConnected) {
for (CBService *servicein peripheral.services) {
[servicesaddObject:service.UUID];
}
}
}
[selfaddLog:@"[self.cbCentralMgr retrieveConnectedPeripheralsWithServices:peripheral.services]"];
self.retrievePeripherals = [self.cbCentralMgrretrieveConnectedPeripheralsWithServices:services];
for (CBPeripheral* peripheralinself.retrievePeripherals) {
[selfaddLog:[NSStringstringWithFormat:@"%@ name:%@",peripheral,peripheral.name]];
}
[self.tableViewPeripheralreloadData];
}
大概就这个个流程,例子中的参数设置,及其其他的一些代理请自己研究。
import UIKit
import CoreBluetooth
/**
中心管理模式
1.引入CoreBluetooth,初始化中心管理者
2.监听cMgr的状态,当是On的时候,才可以进行搜索外设
3.当状态为On的时候,开始搜索我们的外设
4.发现外设后,过滤出我们要的外设,并且对其进行标记或者存储到外设数组中(每个中心管理者都可以连接1-7个外设,但是每个外设都只能连接一个cMgr)
*/
class ViewController: UIViewController {
var cMgr :CBCentralManager!
var per: CBPeripheral?
//var start :Bool?
@IBAction func startBLE() {
//self.start = true
// 1.初始化中心管理者
self.cMgr = CBCentralManager(delegate: self, queue: dispatch_get_main_queue(), options: nil)
}
@IBAction func stopConnect() {
//self.start = false
self.yf_cMgr(self.cMgr, stopConnectWithPeripheral: self.per!)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
extension ViewController: CBCentralManagerDelegate
{
// 2.监听cMgr的状态(模拟器永远不会是On)
func centralManagerDidUpdateState(central: CBCentralManager) {
//
switch central.state {
case .PoweredOff:
print("PoweredOff")
case .PoweredOn:
print("PoweredOn")
// 3.搜索外设.会触发 centralManager:didDiscoverPeripheral:advertisementData:RSSI:
central.scanForPeripheralsWithServices(nil, options: nil)
case .Resetting:
print("Resetting")
case .Unsupported:
// 使用模拟器会打印此处
print("Unsupported")
default:
print("others")
}
}
// 4.发现外设
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
print("central: \(central), peripheral: \(peripheral), adv: \(advertisementData), RSSI: \(RSSI)")
// 一般会根据advertisementData来过滤出我们想要连接的外设(当然,信号强度RSSI也可以作为过滤凭据)
/**
["kCBAdvDataManufacturerData": <570100ae fcda4d72 8ea10132 3c4dafc4 22aec402 880f1060 8b1d>, "kCBAdvDataIsConnectable": 1, "kCBAdvDataServiceUUIDs": <__NSArrayM 0x1545560e0>(
FEE0,
FEE7
)
, "kCBAdvDataServiceData": {
FEE0 = <54080000>;
}, "kCBAdvDataLocalName": MI]
*/
let advRecName = advertisementData[CBAdvertisementDataLocalNameKey] as? String
if (advRecName!.containsString("MI"))
{
print("advRecName: \(advRecName) success")
// 5.连接想要的外设
// 5.1.停止扫描
central.stopScan()
//self.start = false
// 5.2.将外设标记/存入外设数组(1-7)(1-1)
self.per = peripheral
// 5.3.连接这个外设
central.connectPeripheral(self.per!, options: nil)
}else
{
print(advRecName)
}
}
// 6.连接外设的结果
// 6.1 连接成功
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
//
print("didConnectPeripheral")
peripheral.delegate = self
// 7. 与外设信息进行分析交互
peripheral.discoverServices(nil)
}
// 6.2 连接失败
func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) {
print("didFailToConnectPeripheral")
}
// 6.3 丢失连接(手动取消调用/ 每信号了也调用)
func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {
//
print("didDisconnectPeripheral")
}
// 自定义的取消连接方法
func yf_cMgr(central: CBCentralManager,stopConnectWithPeripheral peripheral: CBPeripheral) -> ()
{
central.stopScan()
central.cancelPeripheralConnection(peripheral)
}
}
extension ViewController: CBPeripheralDelegate
{
// 7.1 外设发现服务
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
guard error == nil else
{
print("didDiscoverServices : \(error)")
return
}
for service in peripheral.services! {
// 7.2 外设检索服务中的每一个特征 peripheral:didDiscoverCharacteristicsForService
peripheral.discoverCharacteristics(nil, forService: service)
}
}
// 7.3 外设发现服务中的特征
func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
guard error == nil else
{
print("didDiscoverCharacteristicsForService : \(error)")
return
}
print(service.characteristics!.count)
for character in service.characteristics! {
// 7.4 外设检索特征的描述 peripheral:didDiscoverDescriptorsForCharacteristic:error:
peripheral.discoverDescriptorsForCharacteristic(character)
// 判断如果特征的UUID是 2B4A,那就对其进行订阅
if character.UUID.isEqual(CBUUID(string: "2B4A"))
{
self.yf_Per(peripheral, setNotifyValueForCharacteristic: character)
}
// 7.5 外设读取特征的值
guard character.properties.contains(.Read) else
{
print("character.properties must contains read")
// 如果是只读的特征,那就跳过本条进行下一个遍历
continue
}
print("note guard")
// peripheral:didUpdateValueForCharacteristic:error:
peripheral.readValueForCharacteristic(character)
}
}
// 7.6 外设发现了特征中的描述
func peripheral(peripheral: CBPeripheral, didDiscoverDescriptorsForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
//
guard error == nil else
{
print("didDiscoverDescriptorsForCharacteristic : \(error)")
return
}
for des in characteristic.descriptors! {
print("characteristic: \(characteristic) .des :\(des)")
// peripheral:didUpdateValueForDescriptor:error: method
peripheral.readValueForDescriptor(des)
}
}
// 7.7 更新特征value
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
guard error == nil else
{
print("didUpdateValueForCharacteristic : \(error)")
return
}
print("\(characteristic.description) didUpdateValueForCharacteristic")
}
func yfPer(peripheral: CBPeripheral, writeData data: NSData, forCharacteristic characteristic: CBCharacteristic) -> () {
//外设写输入进特征
guard characteristic.properties.contains(.Write) else
{
print("characteristic.properties must contains Write")
return
}
// 会触发peripheral:didWriteValueForCharacteristic:error:
peripheral.writeValue(data, forCharacteristic: characteristic, type: CBCharacteristicWriteType.WithResponse)
}
// 订阅与取消订阅
func yf_Per(peripheral: CBPeripheral, setNotifyValueForCharacteristic characteristic: CBCharacteristic) -> () {
guard characteristic.properties.contains(.Notify) else
{
print("characteristic.properties must contains notify")
return
}
// peripheral:didUpdateNotificationStateForCharacteristic:error:
peripheral.setNotifyValue(true, forCharacteristic: characteristic)
}
func yf_Per(peripheral: CBPeripheral, canleNotifyValueForCharacteristic characteristic: CBCharacteristic) -> () {
guard characteristic.properties.contains(.Notify) else
{
print("characteristic.properties must contains notify")
return
}
peripheral.setNotifyValue(false, forCharacteristic: characteristic)
}
}