苹果手机可以作为蓝牙外设端,被蓝牙中央端来扫描连接交互数据,实现模拟蓝牙外设硬件。通过阅读CoreBluetooth库,可以找到一个CBPeripheralManager的类,该类主要的作用就是允许你来管理发布services,把这些services广告给其他的设备。如果想详细了解该类的属性和方法,建议去看看CoreBluetooth/CBPeripheralManager.h。 下面来模拟一个简单的蓝牙外设端。 准备工作 CBUUID *serviceUUID; CBUUID *characteristicUUID; NSData *characteristicValue; NSString *localName; NSArray *serviceUUIDs; 上面中,serviceUUID为给外设配置的服务的UUID,可以有多个,characteristicUUID为给service添加的特征的UUID,也可以有多个,可自定义可读可写等等属性.characteristicValue为characteristic的值,localName和serviceUUIDs分别为键CBAdvertisementDataLocalNameKey和CBAdvertisementDataServiceUUIDsKey对应的value。由于作为外设端时发送广播包,广播包中提供包含着两个键值对,如果有另外的键值对想要发送,例如CBAdvertisementDataServiceDataKey,会出现错误。 开始 首先要导入蓝牙库 #import <CoreBluetooth/CoreBluetooth.h> 遵守协议 @interface viewController()<CBPeripheralManagerDelegate> 创建peripheralManager对象 self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];//nil表示在主线程中执行。 创建了peripheralManager对象后会自动调用回调方法didUpdateState - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { if (peripheral.state != CBPeripheralManagerStatePowerOn) { return; } } 给外设配置服务和特征 - (void)configServiceAndCharacteristicForPeripheral { CBMutableCharacteristic *writeReadCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID properties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadEncryptionRequired | CBAttributePermissionsWriteEncryptionRequired]; CBMutableService *service = [[CBMutableService alloc] initWithType:serviceUUID primary:YES]; [service setCharacteristics:@[writeReadCharacteristic]]; [self.peripheralManager addService:service]; } 调用上面的方法时,会监听didAddService: - (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error { } 开始广播 [self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:serviceUUIDs,CBAdvertisementDataNameKey:localName}]; 调用上 面方法时,会监听DidStartAdvertising: - (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error { } 当中央端连接上了此设备并订阅了特征时会回调 didSubscribeToCharacteristic: - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic { [self.peripheralManager updateValue:characteristicValue forCharacteristic:characteristic onSubscribedCentrals:nil]; } 当中央端取消订阅时会调用didUnsubscribeFromCharacteristic: - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic { } 当接收到中央端读的请求时会调用didReceiveReadRequest: - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request { if (request.characteristic.properties & CBCharacteristicPropertyRead) { NSData *data = request.characteristic.value; [request setValue:data]; [self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess]; } else { [self.peripheralManager respondToRequest:request withResult:CBATTErrorReadNotPermitted]; } } 当接收到中央端写的请求时会调用didReceiveWriteRequest: - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests { CBATTRequest *request = requests[0]; if (request.characteristic.properties & CBCharacteristicPropertyWrite) { CBMutableCharacteristic *c = (CBMutableCharacteristic *)request.characteristic; c.value = request.value; [self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess]; } else { [self.peripheralManager respondToRequest:request withResult:CBATTErrorWriteNotPermitted]; } } 手机app可以作为一个蓝牙外设端来模拟外设硬件,但广播包里的数据只能包含localName和serviceUUID,相对于外设硬件来说还是有一些不足之处。