iOS开发之蓝牙4.0开发使用
<p>转载自https://www.jianshu.com/p/f0e4b0e98336</p><p>2015年的时候自己写过一个蓝牙4.0项目,当忘了写博客,最近看到这篇博客写的挺详细,所以转载一下</p>
<h2>一: 介绍</h2>
<p>蓝牙分为蓝牙2.0和蓝牙4.0。<br>蓝牙2.0为传统蓝牙,传统蓝牙也称为经典蓝牙。<br>蓝牙4.0因为低耗电,所以也叫做低功耗蓝(BLE),它将三种规格集一体,包括传统蓝牙技术、高速技术和低耗能技术。</p>
<p>这篇文章用来介绍BLE 4.0的使用以及相关问题的解决。</p>
<h2>二:BLE的两种模式</h2>
<p>BLE的两种模式分为CBCentralMannager 中心模式 和CBPeripheralManager 外设模式,在这里主要和大家分享CBCentralMannager 中心模式的开发和使用。</p>
<h4>CBCentralMannager 中心模式</h4>
<p>以手机(app)作为中心,连接其他外设的场景。详细流程如下:</p>
<ol>
<li>建立中心角色</li>
<li>扫描外设</li>
<li>发现外设</li>
<li>连接外设<br>4.1 连接失败<br>4.2 连接断开<br>4.3 连接成功</li>
<li>扫描外设中的服务<br>5.1 发现并获取外设中的服务</li>
<li>扫描外设对应服务的特征<br>6.1 发现并获取外设对应服务的特征<br>6.2 给对应特征写数据</li>
<li>订阅特征的通知<br>7.1 根据特征读取数据</li>
</ol>
<h4>CBPeripheralManager 外设模式</h4>
<p>使用手机作为外设连接其他中心设备操作的场景。<br>PS:因为苹果设备的安全性和封闭性,苹果设备不能通过与其他设备蓝牙链接进行文件传输等功能,所以在iOS与蓝牙开发的编程中是CBCentralMannager 中心模式编程居多.</p>
<ol>
<li>建立外设角色</li>
<li>设置本地外设的服务和特征</li>
<li>发布外设和特征</li>
<li>广播服务</li>
<li>响应中心的读写请求</li>
<li>发送更新的特征值,订阅中心</li>
</ol>
<h2>三:BLE开发步骤</h2>
<p>在介绍CBCentralMannager 中心模式开发步骤之前,首先需要对项目进行如下配置:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">#import</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ESPFBYBLEHelper.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">#import</span> <CoreBluetooth/CoreBluetooth.h>
<span style="color: rgba(0, 0, 255, 1)">@interface</span> ESPFBYBLEHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 中心管理者(管理设备的扫描和连接)</span>
@property (nonatomic, strong) CBCentralManager *<span style="color: rgba(0, 0, 0, 1)">centralManager;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 存储的设备</span>
@property (nonatomic, strong) NSMutableArray *<span style="color: rgba(0, 0, 0, 1)">peripherals;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 扫描到的设备</span>
@property (nonatomic, strong) CBPeripheral *<span style="color: rgba(0, 0, 0, 1)">cbPeripheral;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 外设状态</span>
<span style="color: rgba(0, 0, 0, 1)">@property (nonatomic, assign) CBManagerState peripheralState;
</span><span style="color: rgba(0, 0, 255, 1)">@end</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 蓝牙4.0设备名</span>
<span style="color: rgba(0, 0, 255, 1)">static</span> NSString * <span style="color: rgba(0, 0, 255, 1)">const</span> kBlePeripheralName = <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">lighte290</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通知服务</span>
<span style="color: rgba(0, 0, 255, 1)">static</span> NSString * <span style="color: rgba(0, 0, 255, 1)">const</span> kNotifyServerUUID = <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">FF03</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写服务</span>
<span style="color: rgba(0, 0, 255, 1)">static</span> NSString * <span style="color: rgba(0, 0, 255, 1)">const</span> kWriteServerUUID = <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">FFFF</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 通知特征值</span>
<span style="color: rgba(0, 0, 255, 1)">static</span> NSString * <span style="color: rgba(0, 0, 255, 1)">const</span> kNotifyCharacteristicUUID = <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">FF05</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写特征值</span>
<span style="color: rgba(0, 0, 255, 1)">static</span> NSString * <span style="color: rgba(0, 0, 255, 1)">const</span> kWriteCharacteristicUUID = <span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">FF08</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">@implementation</span> ESPFBYBLEHelper</pre>
</div>
<p>这其中需要导入CoreBluetooth框架</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">#import</span> <CoreBluetooth/CoreBluetooth.h></pre>
</div>
<p>遵守CBCentralManagerDelegate,CBPeripheralDelegate协议</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">@interface</span> ESPFBYBLEHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate></pre>
</div>
<p>然后需要检测蓝牙状态,代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 状态更新时调用</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)centralManagerDidUpdateState:(CBCentralManager *<span style="color: rgba(0, 0, 0, 1)">)central
{
</span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> (central.state) {
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CBManagerStateUnknown:{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">为知状态</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
self.peripheralState </span>=<span style="color: rgba(0, 0, 0, 1)"> central.state;
}
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CBManagerStateResetting:
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">重置状态</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
self.peripheralState </span>=<span style="color: rgba(0, 0, 0, 1)"> central.state;
}
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CBManagerStateUnsupported:
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">不支持的状态</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
self.peripheralState </span>=<span style="color: rgba(0, 0, 0, 1)"> central.state;
}
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CBManagerStateUnauthorized:
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">未授权的状态</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
self.peripheralState </span>=<span style="color: rgba(0, 0, 0, 1)"> central.state;
}
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CBManagerStatePoweredOff:
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">关闭状态</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
self.peripheralState </span>=<span style="color: rgba(0, 0, 0, 1)"> central.state;
}
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">case</span><span style="color: rgba(0, 0, 0, 1)"> CBManagerStatePoweredOn:
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">开启状态-可用状态</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
self.peripheralState </span>=<span style="color: rgba(0, 0, 0, 1)"> central.state;
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">%ld</span><span style="color: rgba(128, 0, 0, 1)">"</span>,(<span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)">)self.peripheralState);
}
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<p>添加属性和常量,常量需要根据自己的项目来进行配置。<br>下面只需要根据实现流程一步步实现即可,核心代码如下:</p>
<h5>1. 建立中心角色</h5>
<div class="cnblogs_code">
<pre>self.centralManager = [ initWithDelegate:self queue:nil];</pre>
</div>
<h5>2. 扫描外设</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span> (self.peripheralState ==<span style="color: rgba(0, 0, 0, 1)">CBManagerStatePoweredOn){
;
}</span></pre>
</div>
<h5>3. 发现外设</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
扫描到设备
@param central 中心管理者
@param peripheral 扫描到的设备
@param advertisementData 广告信息
@param RSSI 信号强度
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,<span style="color: rgba(0, 0, 255, 1)">id</span>> *)advertisementData RSSI:(NSNumber *<span style="color: rgba(0, 0, 0, 1)">)RSSI
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">%@</span><span style="color: rgba(128, 0, 0, 1)">"</span>,);
}</span></pre>
</div>
<p>4. 连接外设</p>
<div class="cnblogs_code">
<pre>;</pre>
</div>
<ul>
<li>4.1 连接失败 didFailToConnectPeripheral</li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
连接失败
@param central 中心管理者
@param peripheral 连接失败的设备
@param error 错误信息
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *<span style="color: rgba(0, 0, 0, 1)">)error
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">%@</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">连接失败</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<ul>
<li>4.2 连接断开</li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
连接断开
@param central 中心管理者
@param peripheral 连接断开的设备
@param error 错误信息
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *<span style="color: rgba(0, 0, 0, 1)">)error
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">%@</span><span style="color: rgba(128, 0, 0, 1)">"</span>,<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">断开连接</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<ul>
<li>4.3 连接成功</li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
连接成功
@param central 中心管理者
@param peripheral 连接成功的设备
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *<span style="color: rgba(0, 0, 0, 1)">)peripheral
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">连接设备:%@成功</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,peripheral.name);
;
}</span></pre>
</div>
<h5>5. 扫描外设中的服务</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置设备的代理</span>
peripheral.<span style="color: rgba(0, 0, 255, 1)">delegate</span> =<span style="color: rgba(0, 0, 0, 1)"> self;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> services:传入nil代表扫描所有服务</span>
;</pre>
</div>
<p>5.1 发现并获取外设中的服务</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
扫描到服务
@param peripheral 服务对应的设备
@param error 扫描错误信息
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *<span style="color: rgba(0, 0, 0, 1)">)error
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 遍历所有的服务</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (CBService *service <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> peripheral.services)
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">服务:%@</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,service.UUID.UUIDString);
}
}</span></pre>
</div>
<h5>6. 扫描外设对应服务的特征</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取对应的服务</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据服务去扫描特征</span>
;</pre>
</div>
<p>6.1 发现并获取外设对应服务的特征</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
扫描到对应的特征
@param peripheral 设备
@param service 特征对应的服务
@param error 错误信息
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *<span style="color: rgba(0, 0, 0, 1)">)error
{
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">%@</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,peripheral);
}</span></pre>
</div>
<p>6.2 给对应特征写数据</p>
<div class="cnblogs_code">
<pre>;</pre>
</div>
<h5>7. 订阅特征的通知</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (){
;
}</span></pre>
</div>
<p>7.1 根据特征读取数据 didUpdateValueForCharacteristic</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
根据特征读到数据
@param peripheral 读取到数据对应的设备
@param characteristic 特征
@param error 错误信息
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
- (<span style="color: rgba(0, 0, 255, 1)">void</span>)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *<span style="color: rgba(0, 0, 0, 1)">)error
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> ()
{
NSData </span>*data =<span style="color: rgba(0, 0, 0, 1)"> characteristic.value;
NSLog(</span><span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">%@</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,data);
}
}</span></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/hecanlin/p/11578097.html
頁:
[1]