admin管理员组文章数量:1641931
初次在简书写文章,如文章有哪里不妥,望提出,海涵!
复制代码
最近刚刚忙完一个有关蓝牙4.0的开发,似乎此前蓝牙在手机里还不怎么起眼!不过随着智能家居物联网的潮流兴起,低功耗蓝牙,无线 WiFi 等技术必大有作为(纯属个人见解)。以下简单推出一个需求(需求驱动开发,希望能吸引到你):
1、手机作为中心设备,连接外设,向外设发送指令;
2、智能硬件作为从设备,广播信息,接收中心的指令,做出相应动作。
复制代码
一、开发模式
蓝牙开发有两种开发模式,一种是中心模式,一种是从设备模式,此时的需求正是采用中心开发模式,此处引入一个开发所需的重要框架#import <CoreBluetooth/CoreBluetooth.h>
二、中心模式的开发步骤
- 建立中心管理者
- 扫描外设(scan -> discover)
- 连接外设(connect)
- 扫描外设中的服务与特征(discover,我们需要找到“可写入的”属性的特征)
- 获得外设的服务(services)
- 获得外设的Characteristics,获得Characteristics的值(再往下就是获得Characteristics的Descriptor和Descriptor的值)
- 与外设进行数据交互、订阅或通知
- 断开与外设的连接(disconnect)
三、demo 实现
此时我们需要关注两个委托<CBCentralManagerDelegate,CBPeripheralDelegate>
CBCentralManagerDelegate
#pragma mark- CBCentralManagerDelegate
// 蓝牙更新状态
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (central.state != CBCentralManagerStatePoweredOn) {
_isConnected = NO;
} else if (central.state == CBCentralManagerStatePoweredOn) {
[self scanForPeripherals];
/*
一号坑在此处解决:(手机蓝牙已打开)
打开 APP 第一次出现了搜索不到设备的 bug,几经推测发现手机的蓝牙状态为
CBCentralManagerStateUnknown,手机蓝牙并未达到我们所期望的开启状态,
因此会搜索不到设备,我们需要在此委托方法中监听蓝牙状态的状态改变,
一旦为 ON 马上扫描外设(配合自己的需求)
*/
}
}
复制代码
// 发现外设
- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary<NSString *,id> *)advertisementData
RSSI:(NSNumber *)RSSI
{
/*
二号坑在此处解决:(外设蓝牙名字修改后搜索不到的问题)
一般在日常使用中蓝牙的名称并不需要经常改动,往往需求是造化弄人的。外设较多时我们一般会根据外设的名称进行过滤,
在此委托方法中,我么可以直接通过 peripheral.name 的属性来过滤,此时好像并没有什么问题,直到蓝牙的名称被修改后
部分蓝牙怎么就搜索不到了,此时我发现蓝牙修改前的名字却能搜索到,与硬件开发的同事几经交涉后,蓝牙的名字确确实实已经被
修改。
解决办法:
在蓝牙的广播数据中 根据@"kCBAdvDataLocalName"这个 key 便可获得准确的蓝牙名称(在 github上一个优秀的蓝牙开源项目中发现的)
至于为什么从 peripheral.name 这个属性拿到的名称不准确仍是不解,知道的书友麻烦告知一下!
*/
NSString *locolName = [[advertisementData objectForKey:@"kCBAdvDataLocalName"] lowercaseString];
NSString *peripheralName = [peripheral.name lowercaseString];
NSString *myInBleName = [myDelegate.selectedLock.inBleName lowercaseString];
NSString *myOutBleName = [myDelegate.selectedLock.outBleName lowercaseString];
YKLog(@"----------广播:%@--设备:%@--进:%@--出:%@",locolName, peripheralName,myInBleName,myOutBleName);
if ([locolName isEqualToString:myInBleName] ||
[peripheralName isEqualToString:myInBleName] ||
[locolName isEqualToString:myOutBleName] ||
[peripheralName isEqualToString:myOutBleName]) {
[self.peripherals addObject:peripheral];
// 注意:必须持有需要进行数据交互的外设
[self connect:peripheral];
[SVProgressHUD showInfoWithStatus:@"正在开门"];
}
}
复制代码
//Peripherals断开连接
- (void) centralManager: (CBCentralManager *)central
didDisconnectPeripheral: (CBPeripheral *)peripheral
error: (NSError *)error{
if (error == NULL) {
[SVProgressHUD showSuccessWithStatus:@"开门成功.."];
_myDisType = kDisconnectRight;
}
YKLog(@">>>外设连接断开连接 %@: %@\n", [peripheral name], [error localizedDescription]);
_isConnected = NO;
self.connectedPeripheral = nil;
self.peripherals = nil;
}
//连接到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
_isConnected = YES;
self.connectedPeripheral = peripheral;
[peripheral setDelegate:self];
CBUUID *uuid = [CBUUID UUIDWithString:@"0003CDD0-0000-1000-8000-00805F9B0131"];
[peripheral discoverServices:@[uuid]];
}
复制代码
CBPeripheralDelegate
#pragma mark- CBPeripheralDelegate
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
//YKLog(@"--------发现服务,扫描服务-----------");
if (error) {
YKLog(@"Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);
return;
}
[peripheral.services enumerateObjectsUsingBlock:^(CBService * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[peripheral discoverCharacteristics:nil forService:obj];
YKLog(@"%@",obj);
}];
}
/**
* 获取外设的Characteristics,获取Characteristics的值,获取Characteristics的Descriptor和Descriptor的值
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
YKLog(@"---------发现特征----------");
if (error)
{
YKLog(@"error Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
return;
}
[service.characteristics enumerateObjectsUsingBlock:^(CBCharacteristic * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self notifyCharacteristic:self.connectedPeripheral characteristic:obj];
if (obj.properties == CBCharacteristicPropertyWriteWithoutResponse ||
obj.properties == CBCharacteristicWriteWithResponse) {
self.WCharacteristi = obj;
[peripheral setNotifyValue:NO forCharacteristic:obj];
[self writeCharacteristic:peripheral characteristic:self.WCharacteristi value:self.valueW];
YKLog(@"%@",self.valueW);
}
}];
}
//获取的charateristic的值
-(void)peripheral: (CBPeripheral *)peripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
//打印出characteristic的UUID和值
//!注意,value的类型是NSData,具体开发时,会根据外设协议制定的方式去解析数据
YKLog(@"特征的值更新---characteristic uuid:%@ value:%lu",characteristic.UUID,(unsigned long)characteristic.properties);
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
[self disconnect];
}
复制代码
数据交互
#pragma mark- 读写数据
//写数据
-(void)writeCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic
value:(NSData *)value
{
YKLog(@"%@--%lu",value, (unsigned long)characteristic.properties);
//只有 characteristic.properties 有write的权限才可以写
if((characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) != 0){
[peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}else{
[peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
}
//设置通知
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
//设置通知,数据通知会进入:didUpdateValueForCharacteristic方法
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
复制代码
四、结尾
三号坑在此处提出:调用断开蓝牙的接口,手机蓝牙并没有马上与外设断开连接,而是等待5秒左右的时间后才真正断开。
断开连接的接口:
[self.manager cancelPeripheralConnection:self.connectedPeripheral];
复制代码
查阅了苹果的官方文档,指出调用此接口后有可能会断开与外设的连接,是“有可能”也就是说也有可能是不会断开。由于是物理层的特性,我们无法在手机端做到马上断开连接。
- 解决方法:与硬件开发的同事沟通,从设备收到数据后主动断开连接即可。
- Swift demo 文章就写到此处,感谢您的阅读,欢迎沟通学习!
转载于:https://juejin.im/post/5a324fe1f265da432718411f
版权声明:本文标题:iOS 蓝牙开发总结,专治莫名其妙的坑! 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1729329508a1196205.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论