如题所述
第1个回答 2022-06-24
1. iOS中开发蓝牙常用的系统库是<CoreBluetooth/CoreBluetooth.h>。
2.蓝牙外设必需为4.0及以上(2.0需要MFI认证),否则无法进行开发,蓝牙4.0设施由于低耗电,所以也叫做BLE。
3. CoreBluetooth框架的核心其实是俩东西
3.1 Peripheral
3.2 Central
4. 服务和特征(service characteristic):简而言之,外部蓝牙中它有若干个服务service(服务你能了解为蓝牙所拥有的可以力),而每个服务service下拥有若干个特征characteristic(特征你能了解为解释这个服务的属性)。
5. Descriptor(形容)使用来形容characteristic变量的属性。例如,一个descriptor能规定一个可读的形容,或者者一个characteristic变量可接受的范围,或者者一个characteristic变量特定的单位。
3.1 创建一个CBCentralManager实例来进行蓝牙管理;
3.2 搜索扫描外围设备;
3.3 连接外围设备;
3.4 获得外围设备的服务;
3.5 获得服务的特征;
3.6 从外围设备读取数据;
3.7 给外围设备发送(写入)数据。
4.1 初始化
dispatch_queue_t centralQueue = dispatch_queue_create(“centralQueue",DISPATCH_QUEUE_SERIAL);
NSDictionary *dic = @{CBCentralManagerOptionRestoreIdentifierKey : restoreIdentifier};
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:dic];
CBCentralManagerOptionRestoreIdentifierKey对应的是一个唯一标识的字符串,用于蓝牙进程被杀掉恢复连接时使用
4.2 扫描
/*
*扫描设备
*/
- ( void )scanForDevices:(NSError**)error
{
if (CBCentralManagerStatePoweredOn == self .centralManager.state) {
//取回已连接的service设备
NSArray* retrievedPeripherals = [ self .centralManagerretrieveConnectedPeripheralsWithServices:@[ self .serviceUUID]];
for (CBPeripheral* peripheral in retrievedPeripherals){
//NSLog(@"retrieved peripheral:%@", peripheral);
[ self .delegateclient: self didDiscoverDevice:peripheral.identifier];
}
//启动扫描
if ( self .advertisementUUID) {
[ self .centralManager scanForPeripheralsWithServices:@[ self .advertisementUUID ] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];
} else {
[ self .centralManager scanForPeripheralsWithServices: nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];
// [self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
} else {
if (error != NULL ) {
*error = [NSErrorerrorWithDomain:HCErrorDomaincode:(SRVClientErrorUnknown+ self .centralManager.state)userInfo: nil ];
NSLog(@"[NSError errorWithDomain:HCErrorDomain code:(SRVClientErrorUnknown + self.centralManager.state) userInfo:nil];");
}
}
}
4.3 发现外围设备
- ( void )centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(CBPeripheral*)peripheraladvertisementData:(NSDictionary*)advertisementDataRSSI:(NSNumber*)RSSI {
NSString*peripheralName = peripheral.name;
if (peripheralName == nil || peripheralName.length==0) {
return ;
}
if ([peripheralNameisEqualToString:SRV_CLIENT_DEV_NAME] || [peripheralNameisEqualToString:SRV_CLIENT_DFU_NAME]) {
}
}
4.4 连接外围设备
//蓝牙连接成功回调
- ( void )centralManager:(CBCentralManager*)centraldidConnectPeripheral:(CBPeripheral*)peripheral {
[ self .centralManager stopScan];
peripheral.delegate= self ;
self .commandNo=0;
NSLog(@"[D] CentralManager Discover services.");
NSLog(@"%@", self .peripheral);
self .peripheral.delegate= self ;
[ self .peripheral discoverServices:@[ self .serviceUUID]];
NSLog(@"%@", self .serviceUUID);
//定时获取RSSI
if ( self .needReadRSSI) {
[ self readPeripheralRSSI];
if (! self .rssiTimer) {
self .rssiTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target: self
selector: @selector (readPeripheralRSSI)
userInfo: nil
repeats: YES ];
}
}
}
#pragma mark 连接外设——失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@", error);
}
#pragma mark 取消与外设的连接回调
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@", peripheral);
}
4.5 获得外围设备的服务
//发现服务的回调
- ( void )peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error
{
NSLog(@"%@---didDiscoverServices",peripheral);
if (error){
NSLog(@"[E] peripheral didDiscoverServices error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
for (CBService* service in peripheral.services){
NSLog(@"[D] Discover characteristics. For service = %@", service);
[peripheraldiscoverCharacteristics: nil forService:service];
}
}
//发现特征的回调
- ( void )peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if (error){
NSLog(@"[E] peripheral didDiscoverCharacteristicsForService error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
NSLog(@"[D] peripheral DiscoverCharacteristics = %@", service.characteristics);
//订阅特征
for (CBCharacteristic*characteristic in service.characteristics){
if (characteristic.properties & (CBCharacteristicPropertyNotify|CBCharacteristicPropertyIndicate)){
if (!characteristic.isNotifying) {
if ([ self .ignoreCharacteristicUUIDscontainsObject:characteristic.UUID]) {
continue ;
}
NSLog(@"[D] Enable notify value. For characteristic = %@", characteristic);
//d订阅特性当数据频繁改变时用 setNotifyValue 不频繁时用readValueForCharacteristic
[peripheralsetNotifyValue: YES forCharacteristic:characteristic];
}
}
}
}
// 订阅后的callback
- ( void )peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error){
NSLog(@"[E] peripheral didUpdateNotificationStateForCharacteristic error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
if ([ self isAllCharacteristicNotificationEnabled]){
NSLog(@"订阅成功");
//authorizeRequest 授权认证
[ self .delegate clientDidPrepareForOperation: self ];
}
// [self.delegate clientDidPrepareForOperation:self];
}
4.6 从外围设备读取数据
// peripheral主动发数据,包括写命令后主动返回的状态 读数据的回调
- ( void )peripheral:(CBPeripheral*)peripheraldidUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if (error) {
NSLog(@"[E] peripheral didUpdateValueForCharacteristic error: %@ %@", error.localizedDescription,characteristic);
[ self cancelConnection];
[ self cleanupOperationUnexpectedly];
return ;
}
NSLog(@"%@",peripheral);
NSLog(@"%@",characteristic);
[ self .delegate client: self didUpdateValueForCharacteristic:characteristic.UUID value:characteristic.value];
if ([characteristic.UUIDisEqual: self .ctrlptUUID]) {
if (CTRLPTProgressWaitResp == self .ctrlptProgress) {
}
}
}
4.7 给外围设备发送(写入)数据
- ( BOOL )performOperationSegment:(CBCharacteristic*)characteristic
{
BOOL isLastSegment;
uint8_tsegment[20];
uint16_tindex =0;
uint16_tsegLength;
NSIntegerforwardLength = self .forwardFlow.length;
if ((forwardLength - self .forwardOffset) > (20- index)) {
isLastSegment = NO ;
segLength = (20- index);
} else {
isLastSegment = YES ;
segLength = (forwardLength - self .forwardOffset);
}
memcpy(&segment[index], & self .forwardFlow.bytes[ self .forwardOffset], segLength);
self .forwardOffset+= segLength;
index += segLength;
NSData*writeData = [NSDatadataWithBytes:segmentlength:index];
NSLog(@"[D] Write value = %@. For characteristic = %@", writeData, characteristic);
[ self .peripheral writeValue:writeData forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];//对于操控类蓝牙,数据写入要求非常快,其中writeWithSponce写入消耗的时间是writeWithoutSponce的2.3倍,因此尽量改写成writeWithoutSponce来提升写入速率
return isLastSegment;
}
//是否写入成功的回调
- ( void )peripheral:(CBPeripheral*)peripheraldidWriteValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if (error) {
NSLog(@"[E] peripheral didWriteValueForCharacteristic error: %@", error);
[ self cancelConnection];
[ self cleanupOperationUnexpectedly];
return ;
}
NSLog(@"写入成功----%@",characteristic);
if ([characteristic.UUIDisEqual: self .ctrlptUUID]) {
if (CTRLPTProgressWritting == self .ctrlptProgress) {
if ([ self performOperationSegment:characteristic]) {
self .ctrlptProgress = CTRLPTProgressWaitResp;
self .backwardFlow.length=0;
self .backwardOffset=0;
}
}
}
}
4.8 如何解析蓝牙数据
//判断是否第一个包,若是,取出包长度
if (0== self .backwardOffset&& length >=2) {
uint16_tcommandLength;
[characteristicDatagetBytes:&commandLengthlength: sizeof (commandLength)];
offset += sizeof (commandLength);
self .backwardLength= commandLength;
[ self .backwardFlowappendData:[characteristicDatasubdataWithRange:NSMakeRange(offset, length - offset)]];
} else {
[ self .backwardFlowappendData:characteristicData];
}
2.蓝牙外设必需为4.0及以上(2.0需要MFI认证),否则无法进行开发,蓝牙4.0设施由于低耗电,所以也叫做BLE。
3. CoreBluetooth框架的核心其实是俩东西
3.1 Peripheral
3.2 Central
4. 服务和特征(service characteristic):简而言之,外部蓝牙中它有若干个服务service(服务你能了解为蓝牙所拥有的可以力),而每个服务service下拥有若干个特征characteristic(特征你能了解为解释这个服务的属性)。
5. Descriptor(形容)使用来形容characteristic变量的属性。例如,一个descriptor能规定一个可读的形容,或者者一个characteristic变量可接受的范围,或者者一个characteristic变量特定的单位。
3.1 创建一个CBCentralManager实例来进行蓝牙管理;
3.2 搜索扫描外围设备;
3.3 连接外围设备;
3.4 获得外围设备的服务;
3.5 获得服务的特征;
3.6 从外围设备读取数据;
3.7 给外围设备发送(写入)数据。
4.1 初始化
dispatch_queue_t centralQueue = dispatch_queue_create(“centralQueue",DISPATCH_QUEUE_SERIAL);
NSDictionary *dic = @{CBCentralManagerOptionRestoreIdentifierKey : restoreIdentifier};
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:dic];
CBCentralManagerOptionRestoreIdentifierKey对应的是一个唯一标识的字符串,用于蓝牙进程被杀掉恢复连接时使用
4.2 扫描
/*
*扫描设备
*/
- ( void )scanForDevices:(NSError**)error
{
if (CBCentralManagerStatePoweredOn == self .centralManager.state) {
//取回已连接的service设备
NSArray* retrievedPeripherals = [ self .centralManagerretrieveConnectedPeripheralsWithServices:@[ self .serviceUUID]];
for (CBPeripheral* peripheral in retrievedPeripherals){
//NSLog(@"retrieved peripheral:%@", peripheral);
[ self .delegateclient: self didDiscoverDevice:peripheral.identifier];
}
//启动扫描
if ( self .advertisementUUID) {
[ self .centralManager scanForPeripheralsWithServices:@[ self .advertisementUUID ] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];
} else {
[ self .centralManager scanForPeripheralsWithServices: nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];
// [self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
} else {
if (error != NULL ) {
*error = [NSErrorerrorWithDomain:HCErrorDomaincode:(SRVClientErrorUnknown+ self .centralManager.state)userInfo: nil ];
NSLog(@"[NSError errorWithDomain:HCErrorDomain code:(SRVClientErrorUnknown + self.centralManager.state) userInfo:nil];");
}
}
}
4.3 发现外围设备
- ( void )centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(CBPeripheral*)peripheraladvertisementData:(NSDictionary*)advertisementDataRSSI:(NSNumber*)RSSI {
NSString*peripheralName = peripheral.name;
if (peripheralName == nil || peripheralName.length==0) {
return ;
}
if ([peripheralNameisEqualToString:SRV_CLIENT_DEV_NAME] || [peripheralNameisEqualToString:SRV_CLIENT_DFU_NAME]) {
}
}
4.4 连接外围设备
//蓝牙连接成功回调
- ( void )centralManager:(CBCentralManager*)centraldidConnectPeripheral:(CBPeripheral*)peripheral {
[ self .centralManager stopScan];
peripheral.delegate= self ;
self .commandNo=0;
NSLog(@"[D] CentralManager Discover services.");
NSLog(@"%@", self .peripheral);
self .peripheral.delegate= self ;
[ self .peripheral discoverServices:@[ self .serviceUUID]];
NSLog(@"%@", self .serviceUUID);
//定时获取RSSI
if ( self .needReadRSSI) {
[ self readPeripheralRSSI];
if (! self .rssiTimer) {
self .rssiTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target: self
selector: @selector (readPeripheralRSSI)
userInfo: nil
repeats: YES ];
}
}
}
#pragma mark 连接外设——失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@", error);
}
#pragma mark 取消与外设的连接回调
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"%@", peripheral);
}
4.5 获得外围设备的服务
//发现服务的回调
- ( void )peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error
{
NSLog(@"%@---didDiscoverServices",peripheral);
if (error){
NSLog(@"[E] peripheral didDiscoverServices error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
for (CBService* service in peripheral.services){
NSLog(@"[D] Discover characteristics. For service = %@", service);
[peripheraldiscoverCharacteristics: nil forService:service];
}
}
//发现特征的回调
- ( void )peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if (error){
NSLog(@"[E] peripheral didDiscoverCharacteristicsForService error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
NSLog(@"[D] peripheral DiscoverCharacteristics = %@", service.characteristics);
//订阅特征
for (CBCharacteristic*characteristic in service.characteristics){
if (characteristic.properties & (CBCharacteristicPropertyNotify|CBCharacteristicPropertyIndicate)){
if (!characteristic.isNotifying) {
if ([ self .ignoreCharacteristicUUIDscontainsObject:characteristic.UUID]) {
continue ;
}
NSLog(@"[D] Enable notify value. For characteristic = %@", characteristic);
//d订阅特性当数据频繁改变时用 setNotifyValue 不频繁时用readValueForCharacteristic
[peripheralsetNotifyValue: YES forCharacteristic:characteristic];
}
}
}
}
// 订阅后的callback
- ( void )peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error){
NSLog(@"[E] peripheral didUpdateNotificationStateForCharacteristic error: %@", error.localizedDescription);
[ self cancelConnection];
return ;
}
if ([ self isAllCharacteristicNotificationEnabled]){
NSLog(@"订阅成功");
//authorizeRequest 授权认证
[ self .delegate clientDidPrepareForOperation: self ];
}
// [self.delegate clientDidPrepareForOperation:self];
}
4.6 从外围设备读取数据
// peripheral主动发数据,包括写命令后主动返回的状态 读数据的回调
- ( void )peripheral:(CBPeripheral*)peripheraldidUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if (error) {
NSLog(@"[E] peripheral didUpdateValueForCharacteristic error: %@ %@", error.localizedDescription,characteristic);
[ self cancelConnection];
[ self cleanupOperationUnexpectedly];
return ;
}
NSLog(@"%@",peripheral);
NSLog(@"%@",characteristic);
[ self .delegate client: self didUpdateValueForCharacteristic:characteristic.UUID value:characteristic.value];
if ([characteristic.UUIDisEqual: self .ctrlptUUID]) {
if (CTRLPTProgressWaitResp == self .ctrlptProgress) {
}
}
}
4.7 给外围设备发送(写入)数据
- ( BOOL )performOperationSegment:(CBCharacteristic*)characteristic
{
BOOL isLastSegment;
uint8_tsegment[20];
uint16_tindex =0;
uint16_tsegLength;
NSIntegerforwardLength = self .forwardFlow.length;
if ((forwardLength - self .forwardOffset) > (20- index)) {
isLastSegment = NO ;
segLength = (20- index);
} else {
isLastSegment = YES ;
segLength = (forwardLength - self .forwardOffset);
}
memcpy(&segment[index], & self .forwardFlow.bytes[ self .forwardOffset], segLength);
self .forwardOffset+= segLength;
index += segLength;
NSData*writeData = [NSDatadataWithBytes:segmentlength:index];
NSLog(@"[D] Write value = %@. For characteristic = %@", writeData, characteristic);
[ self .peripheral writeValue:writeData forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];//对于操控类蓝牙,数据写入要求非常快,其中writeWithSponce写入消耗的时间是writeWithoutSponce的2.3倍,因此尽量改写成writeWithoutSponce来提升写入速率
return isLastSegment;
}
//是否写入成功的回调
- ( void )peripheral:(CBPeripheral*)peripheraldidWriteValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error
{
if (error) {
NSLog(@"[E] peripheral didWriteValueForCharacteristic error: %@", error);
[ self cancelConnection];
[ self cleanupOperationUnexpectedly];
return ;
}
NSLog(@"写入成功----%@",characteristic);
if ([characteristic.UUIDisEqual: self .ctrlptUUID]) {
if (CTRLPTProgressWritting == self .ctrlptProgress) {
if ([ self performOperationSegment:characteristic]) {
self .ctrlptProgress = CTRLPTProgressWaitResp;
self .backwardFlow.length=0;
self .backwardOffset=0;
}
}
}
}
4.8 如何解析蓝牙数据
//判断是否第一个包,若是,取出包长度
if (0== self .backwardOffset&& length >=2) {
uint16_tcommandLength;
[characteristicDatagetBytes:&commandLengthlength: sizeof (commandLength)];
offset += sizeof (commandLength);
self .backwardLength= commandLength;
[ self .backwardFlowappendData:[characteristicDatasubdataWithRange:NSMakeRange(offset, length - offset)]];
} else {
[ self .backwardFlowappendData:characteristicData];
}