最近公司做了两个项目都用到了蓝牙,一个是在车轮上的安装蓝牙设备,传图片给蓝牙,当轮子旋转,在车轮上呈现画面,挺酷一东西。还有一个还没上线,就不说了。有机会研究新东西,还是不错的。记录下蓝牙开发:
先明确5个概念:
CBCentral 中心设备(蓝牙主机)
CBPeripheral 外设(蓝牙从机)
CBService 服务
CBCharacteristic 特征
CBUUID UUID
蓝牙连接的步骤就是建立中心设备,扫描外设,按硬件话说就是主机找从机。在外设中找到服务,在服务里找到它所有的特征。
写了个BluetoothHelper,注释已经写的很清楚了。
[self.cbPeripheral writeValue:bluetoothData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse]; [self.manger scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }]; BluetoothHelper.h #import #import @interface BluetoothHelper : NSObject + (BluetoothHelper *)sharedInstance; - (void)connect; - (void)disConnect; - (void)sendData:(NSString *)command; @end BluetoothHelper.m #import "BluetoothHelper.h" #import "ToolHelper.h" static NSString * const kName = @"BLE_Serial"; static NSString * const kSUUID= @"0003CDD0-XXXX-XXXX-XXXX-00805f9bXXXX"; static NSString * const KNotifyUUID = @"0003CDD1-XXXX-XXXX-XXXX-00805f9bXXXX"; static NSString * const kWriteUUID= @"0003CDD2-XXXX-XXXX-XXXX-00805f9bXXXX"; @interface BluetoothHelper () @property (nonatomic, strong) CBCentralManager * manger; @property (nonatomic, strong) CBPeripheral * cbPeripheral; @property (nonatomic, assign) BOOL blueIsOn; @end @implementation BluetoothHelper #pragma mark - life cycle + (BluetoothHelper *)sharedInstance{ static BluetoothHelper *instance = nil; static dispatch_once_t predicate; dispatch_once(&predicate, ^{ instance = [[self alloc] init]; }); return instance; } - (instancetype)init{ self = [super init]; if (self) { self.manger = [[CBCentralManager alloc]initWithDelegate:self queue:nil]; } return self; } #pragma mark - CBCentralManagerDelegate Methods //检测蓝牙状态 - (void)centralManagerDidUpdateState:(CBCentralManager *)central{ switch (central.state) { case CBCentralManagerStatePoweredOn:{ self.blueIsOn = YES; } break; case CBCentralManagerStateResetting: case CBCentralManagerStateUnauthorized: case CBCentralManagerStateUnknown: case CBCentralManagerStateUnsupported: case CBCentralManagerStatePoweredOff:{ self.blueIsOn = NO; } break; default: NSLog(@"Central Manager did change state"); break; } } //发现蓝牙设备 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{ //设置监听,以保证始终寻找外设 [self startScanningTimeoutMonitor]; if ([peripheral.name isEqualToString:kName]) { [self.manger stopScan]; [self.manger connectPeripheral:peripheral options:nil]; self.cbPeripheral = peripheral; } NSLog(@"发现蓝牙%@",peripheral); } //连接外设成功 -(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{ self.cbPeripheral = peripheral; self.cbPeripheral.delegate = self; [self.cbPeripheral discoverServices:@[]]; [self cancelScanningTimeoutMonitor]; [self cancelSendTimeOut]; NSLog(@"连接成功%@",self.cbPeripheral); } //连接外设失败 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ if (error) { NSLog(@"连接失败ERROR:%@ peripheral:%@",error,peripheral); } } //断开外设连接 -(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ NSLog(@"断开连接%@",peripheral); self.cbPeripheral = nil; [ToolHelper showErrorMessage:@"连接失败,重新连接"]; [self connect]; } #pragma mark - CBPeripheralDelegate Methods //已搜索到services 根据周边找特征 -(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{ for (CBService *s in peripheral.services) { if ([s.UUID isEqual:[CBUUID UUIDWithString:kSUUID]]) { [peripheral discoverCharacteristics:nil forService:s]; NSLog(@"找到周边peripheral:%@ Service:%@",peripheral,s); return; } } } //已搜索到Characteristics 设置订阅 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{ for (CBCharacteristic *c in service.characteristics) { if ([c.UUID isEqual:[CBUUID UUIDWithString:KNotifyUUID]]) { //设置监听然后会走didUpdateNotificationStateForCharacteristic [peripheral setNotifyValue:YES forCharacteristic:c]; NSLog(@"设置订阅 peripheral%@ Characteristic%@",peripheral,c); } } } //注册订阅后的中间通知步骤 判断是否正确 - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ if (error == nil) { [peripheral readValueForCharacteristic:characteristic]; } NSLog(@"设置读取返回数据 peripheral%@ characteristic%@",peripheral,characteristic); //给外设发送指定字符验证是否联通 [self sendData:@"yue?"]; } //蓝牙回传的数据都会从这个方法中得到 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{ if (error) { NSLog(@"返回数据ERROR:%@",error); } NSString * updateString = [[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding]; NSLog(@"updateString - %@",updateString); if ([updateString isEqualToString:@"yue!"]){ [ToolHelper showSuccessMessage:@"成功连接设备"]; } else { } } #pragma mark - private methods //把要发送的数据用ASCII编码 - (void)sendData:(NSString *)command { NSData * data = [command dataUsingEncoding:NSASCIIStringEncoding]; [self writeData:data]; } //将数据传送给蓝牙 - (void)writeData:(NSData *)bluetoothData{ for (CBService *service in self.cbPeripheral.services ) { if ([service.UUID isEqual:[CBUUID UUIDWithString:kSUUID]]) { for ( CBCharacteristic *characteristic in service.characteristics ) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWriteUUID]]) { /* EVERYTHING IS FOUND, WRITE characteristic ! */ [self.cbPeripheral writeValue:bluetoothData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse]; } } } } } #pragma mark - public methods //寻找外设 - (void)connect{ if (self.blueIsOn) { NSLog(@"scan...."); if(self.cbPeripheral){ [self.manger connectPeripheral:self.cbPeripheral options:nil]; }else { [self.manger scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }]; } } [self startSendTimeOut]; } //断开蓝牙连接 - (void)disConnect{ if (self.cbPeripheral) { [self.manger cancelPeripheralConnection:self.cbPeripheral]; [self.manger stopScan]; } [ToolHelper showErrorMessage:@"发送失败,请重新发送"]; } #pragma mark - Connection Timeout - (void)startScanningTimeoutMonitor { [self cancelScanningTimeoutMonitor]; [self performSelector:@selector(connect) withObject:nil afterDelay:2.0f]; } - (void)cancelScanningTimeoutMonitor { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(connect) object:nil]; } - (void)startSendTimeOut { [self performSelector:@selector(disConnect) withObject:nil afterDelay:60.0f]; } - (void)cancelSendTimeOut { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disConnect) object:nil]; } @end
网友评论