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];
}