# IOS BLE **Repository Path**: gitee_gu/ios_ble ## Basic Information - **Project Name**: IOS BLE - **Description**: ios平台上连接ble(蓝牙低功耗设备)的demo,包含打开、扫描蓝牙、连接、通信、断开连接各种功能。使用objective-c,可以同时支持4个蓝牙设备进行操作。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-03-31 - **Last Updated**: 2023-03-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一、了解BLE - 蓝牙是一个标准的无线通讯协议,具有设备成本低、传输距离近和功耗低等特点,被广泛的应用在多种场合。蓝牙一般分为传统蓝牙和BLE两种模式:传统蓝牙可以传输音频等较大数据量,距离近、功耗相对大;而BLE则用来传输节点数据,传输数据量十分小,多数情况处于休眠状态,因而功耗十分低,被广泛的应用于智能穿戴设备 - CoreBluetooth.framework 功能强大的蓝牙开发框架,要求设备必须支持蓝牙4.0,可与其他第三方设备进行通信 - CBPeripheralManager:外围设备通常用于发布服务、生成数据、保存数据。外围设备发布并广播服务,告诉周围的中央设备它的可用服务和特征。 - CBCentralManager:中央设备使用外围设备的数据。中央设备扫描到外围设备后会就会试图建立连接,一旦连接成功就可以使用这些服务和特征。 - 外围设备和中央设备之间交互的桥梁是服务(CBService)和特征(CBCharacteristic),二者都有一个唯一的标识UUID(CBUUID类型)来唯一确定一个服务或者特征,每个服务可以拥有多个特征。 - 参考网址1:https://blog.csdn.net/vnanyesheshou/article/details/50572860。iOS蓝牙Ble开发 - 参考网址2:https://www.jianshu.com/p/67374e06fb38。iOS蓝牙BLE开发 # 二、BLE开发 - 新建xcode工程。 用XCode11新建一个工程支持的最小iOS版本小于iOS13,运行的iphone ios版本小于13,XCode控制台会爆出[Application] The app delegate must implement the window property if it wants to use a main storyboard file.的提示。遇到了这个问题,在打开APP内容的时候一片黑,Apple对APP的生命周期略做了更改,把iOS13之前的那些管理整个App生命周期等的任务都委托给了SceneDelegate,而这个SceneDelegate又被我们标注了只能iOS13可以用,也就是说iOS13以下版本的iPhone是不会执行整个SceneDelegate的代码的,所以在低版本中系统就找不到window属性。打开AppDelegate.m,添加下面代码 ``` //添加到“@implementation AppDelegate”后面 @synthesize window = _window; ``` - 获取CBCenteralManager对象,CBCenteralManager提供扫描、连接和断开外设等功能。 ``` //创建CBCentralManager对象 dispatch_queue_t queue = dispatch_queue_create("bluetooth", DISPATCH_QUEUE_SERIAL); CBCentralManager *mgr = [[CBCentralManager alloc] initWithDelegate:self queue:queue]; ``` - 扫描蓝牙设备,serviceUUIDs: 指定扫描包含特点服务的外设,传nil表明是所有服务,options: 扫描时的设置,是一个字典 ``` //CBCentralManagerScanOptionAllowDuplicatesKey值为 No,表示不重复扫描已发现的设备 NSDictionary *optionDic = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey]; [_mgr scanForPeripheralsWithServices:nil options:optionDic]; ``` - 停止扫描蓝牙设备,这里是延迟3秒后停止扫描,可以根据自己需求停止扫描 ``` dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self->_mgr stopScan]; }) ``` - 实现CBCentralManagerDelegate的centralManagerDidUpdateState方法,更新手机蓝牙状态时会调用这个方法 ``` - (void)centralManagerDidUpdateState:(CBCentralManager *)central{ switch (central.state) { case CBManagerStatePoweredOn: { NSLog(@"开启蓝牙, 开始扫描"); } break; case CBManagerStateUnsupported: NSLog(@"不支持蓝牙"); break; case CBManagerStatePoweredOff: NSLog(@"蓝牙未打开"); break; default: NSLog(@"蓝牙打开失败"); break; } } ``` - 实现CBCentralManagerDelegate的centralManager:didDiscoverPeripheral:advertisementData:RSSI:方法,扫描到蓝牙设备时会调用该方法。可以对发现蓝牙设备进行判断并进行处理,这里是先存储起来备用。 ``` - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{ if (peripheral.name != nil) { [peripherals addObject:peripheral]; } } ``` - 连接蓝牙设备。前面扫描可以得到蓝牙设备列表,进过判断,连接需要的蓝牙设备。 ``` [_mgr connectPeripheral:peripheral options:nil]; ``` - 实现CBCentralManagerDelegate的centralManager:didConnectPeripheral:方法,连接蓝牙设备成功后会调用该方法。 ``` - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{ peripheral.delegate = self; } ``` - 实现CBCentralManagerDelegate的centralManager:didDisconnectPeripheral:error:方法,蓝牙设备断开连后会调用该方法。 ``` - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{ } ``` - 连接蓝牙设备成功后,要搜索服务。设置好CBPeripheralDelegate ``` peripheral.delegate = self; [peripheral discoverServices:nil]; ``` - 实现CBPeripheralDelegate的peripheral:didDiscoverServices:方法,搜索到蓝牙设备的服务会调用这个方法。扫描到服务后,需要扫描服务的特征,蓝牙通信主要是对特征Characteristic进行读写。 ``` - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{ if(error){ NSLog(@"didDiscoverServices error"); return; } for (CBService *service in peripheral.services) { //扫描每个service的characteristics [peripheral discoverCharacteristics:nil forService:service]; } } ``` - 实现CBPeripheralDelegate的peripheral:didDiscoverCharacteristicsForService:error:方法,搜索到服务的特征会调用这个方法。蓝牙通信主要是对特征Characteristic进行读写,把可以写的特征存到数组备用,用于写特征值。可以通知的特征设置通知后,蓝牙设备修改特征值后会进行通知。当然,也可以把可以读的特征存到数组,然后手动读取特征值。 ``` - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{ if(error){ NSLog(@"didDiscoverCharacteristicsForService error"); return; } for (CBCharacteristic *characteristic in service.characteristics) { if (characteristic.properties & CBCharacteristicPropertyWrite) { [writeCharacteristicArray addObject:characteristic]; } if (characteristic.properties & CBCharacteristicPropertyNotify) { [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } } } ``` - 实现CBPeripheralDelegate的peripheral:didUpdateValueForCharacteristic:error:方法,蓝色设备更新特征值会调用这个方法 ``` //获取到characteristics的数据 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{ NSData *data = characteristic.value; Byte *resultByte = (Byte *)[data bytes]; } ``` - 发送数据给蓝牙设备,使用writeValue:forCharacteristic:type:方法。在didConnectPeripheral方法保存连接设备connectedPeripheral,然后在didDiscoverCharacteristicsForService有保存特征数组writeCharacteristicArray。 ``` - (void)sendData:(NSData *)data{ for (CBCharacteristic *characteristic in writeCharacteristicArray) { [connectedPeripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; } } ``` - 如果需要断开连接,调用cancelPeripheralConnection方法 ``` [_mgr cancelPeripheralConnection:connectedPeripheral]; ``` - 添加蓝牙权限NSBluetoothAlwaysUsageDescription和NSBluetoothPeripheralUsageDescription ``` //代码模式 NSBluetoothAlwaysUsageDescription App needs to use Bluetooth to communicate with development board NSBluetoothPeripheralUsageDescription App needs to use Bluetooth to communicate with development board //列表模式 Privacy - Bluetooth Always Usage Description,String,App needs to use Bluetooth to communicate with development board Privacy - Bluetooth Peripheral Usage Description,String,App needs to use Bluetooth to communicate with development board ``` - 接收的数据十六进制显示 ``` //获取到characteristics的数据 - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{ NSData *data = characteristic.value; NSString *resultStr = [self hexStringFromNSdata:data]; } -(NSString *)hexStringFromNSdata:(NSData *)data{ Byte *byteData = (Byte *)[data bytes]; NSString *hexString = @""; for (int i=0; i