前言
目前APP同硬件模块通信的方式主要有几种模式:蓝牙连接模式、WiFi 连接模式(Socket 或 HTTP server)、DLNA 音视频共享 (iOS端还可使用AirPlay)。最近小编项目中测试了APP与外设通过蓝牙方式实现硬件连接的功能,对相关的开发实现和测试方法进行一些整理,在此分享给大家。
蓝牙基础知识
iOS平台下蓝牙开发可以使用 MFI(ExternalAccessory 框架) 或 BLE (CoreBluetooth 框架) 进行,但实际开发中基本都使用 CoreBluetooth 框架,因为它功能更强大,支持蓝牙4.0标准。
蓝牙4.0 BLE (Bluetooth low energy) :它的优点在于传输快,耗电低,但传输数据有限,虽然这个传输字节大小硬件工程师可调,但也不会太大。
CoreBluetooth框架的核心是peripheral和 central, 可以理解成外设和中心,发起连接的是central,被连接的设备为 peripheral,它们是一组相对概念。比如,当手机去连接控制蓝牙耳机时,你的手机就是central,当手机蓝牙被另一个手机连接并为其提供服务时就是peripheral。
Service和Characteristic:蓝牙设备通过GATT协议定义的数据通讯方式。一个 peripheral可以提供多种 服务Service,一种Service 又可以包含多个不同的 特征Characteristic。特征就是具体键值对,提供数据的地方。每个特征属性分为读、写、通知等几种方式。
central通过peripheral 的 Characteristic 来读写外设的数据,和获取通知。Peripheral广播自己的Service和characteristic,Central订阅某一个具体的characteristic,Peripheral就和Central之间通过characteristic建立了一个双向的数据通道
外设peripheral、服务Service、特征characteristic之间的关系:
- UUID:蓝牙上的唯一标示符,为了区分不同服务和特征,就用UUID来表示。
蓝牙的两种工作模式
1. 中心模式
1. 建立中心
2. 扫描外设(discover)
3. 连接外设(connect) 连接失败、连接断开、连接成功
4. 扫描外设中的服务和特征(discover)
-
4.1 获取外设的 services
-
4.2 获取外设的 Characteristics,获取Characteristics的值,获 Characteristics的 Descriptor 和Descriptor 的值
5. 与外设做数据交互(explore and interact)
6. 订阅 Characteristic 的通知
7. 断开连接(disconnect)
2. 外设模式
-
启动一个 Peripheral 管理对象
-
本地 Peripheral 设置服务,特性,描述,权限等等
-
Peripheral 发送广播
-
设置处理订阅、取消订阅、读 characteristic、写 characteristic 的委托方法
3. 蓝牙设备的工作状态
-
准备(standby)
-
广播(advertising)
-
监听扫描(Scanning
-
发起连接(Initiating)
-
已连接(Connected)
蓝牙连接的开发实现
这里以手机端作为central,以蓝牙设备作为peripheral,蓝牙设备连接的开发实现主要包括以下步骤:
1. 导入苹果系统蓝牙框架
#import
2. 遵循两个蓝牙框架相关的协议
<cbcentralmanagerdelegate,cbperipheraldelegate></cbcentralmanagerdelegate,cbperipheraldelegate>
3. 新建两个实例属性,一个特征属性
@property (nonatomic, strong) CBCentralManager*centralManager; //中心管理者
@property (nonatomic, strong) CBPeripheral *peripheral; //连接到的外设
@property (nonatomic, strong) CBCharacteristic*characteristic; //特征
4. 初始化 CBCentralManager ,进行蓝牙管理
- (void)viewDidLoad {
[superviewDidLoad];
self.centralManager= [[CBCentralManager alloc] initWithDelegate:selfqueue:dispatch_get_main_queue()]; //创建实例进行蓝牙管理
}
//若中心管理者初始化之后就会触发下面这个代理方法。该代理方法是用来判断手机蓝牙的状态的
-(void)centralManagerDidUpdateState:(CBCentralManager *)central {
//蓝牙可用,开始扫描外设
if(central.state == CBManagerStatePoweredOn) {
NSLog(@"蓝牙可用");
//在中心管理者成功开启之后再进行一些操作
//搜索扫描外设
//根据SERVICE_UUID来扫描外设,如果不设置SERVICE_UUID,则扫描所有蓝牙设备
//[self.centralManagerstartAdvertising:@{CBAdvertisementDataServiceUUIDsKey:@[[CBUUIDUUIDWithString:SERVICE_UUID]]}];
[centralscanForPeripheralsWithServices:nil options:nil];
}
if(central.state== CBManagerStateUnsupported) {
NSLog(@"该设备不支持蓝牙");
}
if(central.state == CBManagerStatePoweredOff) {
NSLog(@"蓝牙已关闭");
}
if(central.state == CBManagerStateUnknown) {
NSLog(@"蓝牙当前状态不明确");
}
if(central.state == CBManagerStateUnauthorized) {
NSLog(@"蓝牙未被授权");
}
} 5. 搜索外围设备
//执行扫描动作之后,如果扫描到外设了,就会自动回调下面的协议方法
// 发现符合要求的外设,回调
- (void)centralManager:(CBCentralManager*)central didDiscoverPeripheral:(CBPeripheral >)peripheraladvertisementData:(NSDictionary)advertisementDataRSSI:(NSNumber *)RSSI {
NSLog(@"%@====",peripheral.name);
//根据外设名字有选择性的筛选连接蓝牙设备
if([peripheral.name hasPrefix:@"TEAMOSA"]) {
//在这里对外设携带的广播数据进行进一步的处理
if([self.peripheraNames containsObject:peripheral.name]) {
//如果数组中包含了就不再添加
return;
}
//添加到外设名字数组中
[self.peripheraNamesaddObject:peripheral.name];
//标记外设,让它的生命周期与控制器的一致
self.peripheral= peripheral;
//可以根据外设名字来过滤外设
//[central connectPeripheral:peripheral options:nil];
}
//连接外设
//[central connectPeripheral:peripheral options:nil];
}
6. 连接外围设备
//连接外围设备,中心管理者连接外设成功,如果连接成功就会回调这个协议方法
/** 连接成功 */
- (void)centralManager:(CBCentralManager*)central didConnectPeripheral:(CBPeripheral >*)peripheral{
//连接成功之后,可以进行服务和特性的发现。停止中心管理设备的扫描动作,要不然在你和已经连接好的外>设进行数据沟通时,如果又有一个外设进行广播且符合你的连接条件,那么你的iOS设备也会去连接这个设备(因为>iOS BLE4.0是支持一对多连接的),导致数据的混乱。
//停止扫描动作
[self.centralManagerstopScan];
//设置外设的代理
peripheral.delegate= self;
//根据UUID来寻找服务
//[peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
//外设发现服务,传nil代表不过滤,一次性读出外设的所有服务
[peripheraldiscoverServices:nil];
NSLog(@"%s,line = %d, %@=连接成功", FUNCTION, LINE,peripheral.name);
}
//外设连接失败
/** 连接失败的回调 */
- (void)centralManager:(CBCentralManager*)central didFailToConnectPeripheral:(CBPeripheral >)peripheral error:(NSError)error {
. NSLog(@"%s,line = %d, %@=连接失败", FUNCTION, LINE,peripheral.name);
}
//丢失连接 掉线
/** 断开连接 */
- (void)centralManager:(CBCentralManager*)central didDisconnectPeripheral:(CBPeripheral >*)peripheral error:(nullableNSError *)error {
NSLog(@"%s,line = %d, %@=断开连接", FUNCTION, LINE,peripheral.name);
//断开连接可以设置重新连接
[centralconnectPeripheral:peripheral options:nil];
}
以上,已经实现了APP端连接蓝牙设备的功能,蓝牙设备连接完成后,还可以对设备进行数据读写,包括:获取外围设备服务和特征;从外围设备读取数据;向外围设备发送(写入)数据等操作。这里暂不具体展开。
APP链接蓝牙设备的测试关注点
一.功能测试
介绍了蓝牙的基础知识、APP连接蓝牙设备的开发实现,接下来将介绍APP连接蓝牙设备这一过程测试中需要关注的测试点(由于每种蓝牙设备连接需求不同,开发实现上也会有细小差别,实际测试中可视具体开发逻辑进行调整):
1. APP扫描设备
①手机端蓝牙不同设置下是否能正常扫描:蓝牙打开、蓝牙关闭;
②蓝牙设备被扫描到并出现在可连接设备列表的条件:蓝牙设备名称与可连接的设备列表中的名称匹配、设备处于广播状态;
蓝牙设备与可连接的设备列表中名称是否匹配:匹配、不匹配;
蓝牙设备状态(视具体硬件而定):待机状态、广播状态、已连接状态、蓝牙设备操作中、数据传输中、关机状态;
测试以上各种组合场景下,蓝牙设备是否能正常扫描且出现在可连接设备列表;
③不同场景下,是否正常扫描:
一个手机同时扫描多个设备;
多个手机同时扫描同一个设备;
多个手机同时扫描多个设备;
④扫描过程中取消;
⑤扫描结果:扫描超时;未扫描到可连接设备,是否支持重试;扫描失败;扫描成功;\
2. 连接设备(APP端点击可连接设备列表,连接蓝牙设备)
①测试蓝牙设备状态变化后,不同状态下是否可正常连接:待机状态、广播状态、已连接状态、蓝牙设备操作中、数据传输中、关机状态;
②连接结果的处理:连接成功、连接失败、连接超时等;
③连接成功后的操作:APP其他操作、连接中断、退到后台、杀掉APP等;
④其他场景:扫描到多个设备;
3. 断开连接
①设备端断开:设备关机、设备电量耗尽;
②APP端断开:手动断开、其他操作断开连接;
4. 其他交互操作
①切换其他蓝牙设备,是否正常连接;
②蓝牙断开后重新打开,支持自动连接;
③距离超出蓝牙可检测范围,是否会断开连接,再恢复到可检测范围,能否自动连接;
④手机端连接多个不同蓝牙设备,各个设备功能是否都正常使用;
5. 连接成功后的数据传输
①功能上,APP端和蓝牙设备端是否符合正常使用需求;
②性能上,APP与蓝牙设备的交互是否满足需求;
(本文只讨论了蓝牙设备连接部分,具体数据传输部分的用例,大家可自行扩展)
二.兼容性测试
1 车载蓝牙
1)配对连接:
- 手机搜索车载配对;
- 车载搜索手机配对;
- 错误密码配对;
- 电话本、通话记录、短信同步:
- 车载手动、自动匹配SIM卡、手机联系人;
- 车载匹配群组联系人;
- 手机/车载操作:联系人删除、添加同步;
- 手机/车载操作:通话记录同步-呼入、呼出、错过、删除同步;
- 手机/车载操作:短信消息同步-接收、发送、删除、未读/已读状态;
- 权限控制-拒绝时不允许同步;
2)通话:
- 手机端发起/接收通话检查-手机操作车载同步,音质、音量、通道;
- 车载端发起/接收通话检查-车载操作手机同步,音质、音量、通道;
- 拨打运营商号码提示按键操作;
- 多路通话;
- 通话车载重连压力;
3)音乐播放:
- 手机端播放音乐-手机端操作车载同步,音量、进度条、暂停、播放;
- 手机端播放音乐-车载段操作手机同步,音量、进度条、暂停、播放;
- 手机/车载交叉控制;
- 音乐播放时车载重连压力;
4)交互测试:
- 音乐播放时来电-手机/车载接听、挂断;
- 音乐播放时拨号-手机车载拨号、挂断;
- 音乐播放时手机接收/发送微信语音消息;
- 车载导航语音播报时来电接听后挂断;
2
蓝牙耳机、音箱
1)搜索配对连接。
2)通话:
- 通话效果-主观;
- 通话中手机控制;
- 通话中耳机控制-接听、拒接、回拨、挂断、静音/恢复、音量调节;
- 拨打运营商号码提示按键操作 ;
- 多路通话;
- 通话中蓝牙耳机重连;
3)音乐:
- 音乐效果-主观;
- 播放音乐手机端控制;
- 播放音乐耳机端控制-暂停/播放、上/下一首、音量调节;
- 播放音乐时手机/蓝牙交互-暂停、播放;
- 音乐播放时耳机重连;
4)交互:
- 音乐时来电-手机/耳机接听、挂断;
- 音乐时拨号-手机/耳机拨号;
- 音乐时接收/发送微信语音消息;
5)三方应用:
- 抖音短视频;
- 爱奇艺播放视频;
- 王者荣耀游戏;
- 微信语音、视频通话;
3 蓝牙鼠标和键盘
- 鼠标、键盘搜索配对连接;
- 鼠标左键单击-图片、音乐控制、视频控制;
- 鼠标左键双击-打开应用、网页缩放、窗口缩放;
- 鼠标长按-execl表选中;
- 鼠标右键-网页操作;
- 鼠标滑轮-联系人滚动、网页浏览、ppt翻页,滑轮按压;
- 键盘所有字符输入;
- 键盘上的功能键-如tab换行、空格键等;
- 键盘上的组合键操作;
- 三方应用上鼠标、键盘操作;
4 蓝牙手环
搜索配对连接;
手环手机同步;
手环解锁;
多profile交互-如蓝牙耳机播放音乐过程中手环解锁和数据同步;
5 蓝牙自拍杆
- 搜索配对连接;
- 前摄、后摄拍照、连拍;
6 蓝牙打印机
- 搜索配对连接;
- 单张、多张连续打印;
- 打印过程中交互-来电、消息、蓝牙配对等请求和文件传入等;
7 蓝牙文件传输
- 系统覆盖:Android、ios各系统版本。
- 手机品牌覆盖:小米对三星、华为、oppo、vivo、iphone、小米等。
- 系统、品牌测试文件格式覆盖:视频、图片、txt、vcf、apk、压缩包等。
三.稳定性测试
1 开关和连接稳定性
- 状态栏开关压力断开/连接;
- 设置开关压力断开/连接;
- 重启蓝牙耳机自动连接;
- 重启/开关手机自动连接 -需要支持的耳机;
- 传输文件大小-大文件;
- 传输文件个数限制;
- 蓝牙共享网络;
2 配对稳定性
- 测试机与辅助机主动配对;
- 测试机与辅助机被动配对;
- 测试机与车载配对;
- 测试机与自拍杆配对;
- 测试机与耳机配对;
3 蓝牙搜索
测试机搜索蓝牙的个数与对比机对比
4 长时间播放音乐、通话
四.性能测试
- 配对连接耗时;
- 重连耗时;
- 1米、10米无障碍发送、接收10M文件;
- 1米、10米有人体障碍发送、接收10M文件;
- 隔墙发送、接收10M文件;
- 5米距离不开WiFi传输10M文件性能-室外;
- 5米距离开WiFi传输10M文件性能-室外;
- 蓝牙耳机播放音乐卡顿距离;
- 蓝牙耳机播放音乐断开距离;
- 蓝牙耳机通话时卡顿距离;
- 50米(-80-90dbm)弱信号传输10M文件;
- 1米抗干扰;
- 10米抗干扰。