iOS Bluetooth 4.0 프로토콜 소개

12286 단어
iOS가 블루투스 4.0을 개발한 프레임워크는 코어블루투스입니다. 본고는 주로 코어블루투스의 사용을 소개합니다. 본고의 코드 부분은 대부분github의 데모에서 왔고 주소는 myz1104/블루투스입니다.
CoreBluetooth에는 두 가지 주요 부분, 즉 Central과 Peripheral이 있는데 하나는 클라이언트 서버와 유사하다.CBPeripheralManager는 주변 장치로서 서버입니다.CBCentral Manager는 중앙 장치로서 클라이언트입니다.사용 가능한 모든 iOS 장치는 주변(Peripheral) 또는 중앙(Central)이 될 수 있지만 주변과 중앙이 동시에 될 수는 없습니다.
일반적으로 휴대전화는 클라이언트이고 설비(예를 들어 팔찌)는 서버이다. 왜냐하면 휴대전화가 팔찌라는 서버를 연결하기 때문이다.주변(Peripheral)은 데이터를 생성하거나 저장하는 장치이고 중앙(Central)은 이 데이터를 사용하는 장치입니다.너는 주변이 방송 데이터의 설비라고 생각할 수 있다. 그는 외부 세계에 방송하여 그에게 데이터가 있다고 말할 뿐만 아니라 제공할 수 있는 서비스도 설명했다.다른 한편, 중앙은 부근에 서비스가 있는지 스캔하기 시작했다. 만약에 중앙이 원하는 서비스를 발견하면 중앙은 주변 연결을 요청하고 연결이 성공하면 두 장치 간에 전송 데이터를 교환하기 시작한다.중앙과 주변을 제외하고 우리는 그들 둘이 교환한 데이터 구조를 고려해야 한다.이러한 데이터는 서비스에서 구조화되고 각 서비스는 서로 다른 특징(Characteristics)으로 구성되며 특징은 하나의 단일 논리 값을 포함하는 속성 유형이다.

Peripheral 구현 단계


일단 굿즈를 만들도록 하겠습니다.
_peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];

다음은 에이전트의peripheral Manager Did UpdateState 방법에 응답하여peripheral의 상태 등 정보를 얻을 수 있습니다.
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {     switch (peripheral.state)     {         case CBPeripheralManagerStatePoweredOn:         {             [self setupService];         }             break;                      default:         {             NSLog(@"Peripheral Manager did change state");         }             break;     } }

주변 장치의 블루투스가 가능하다는 것을 발견했을 때, 다른 중앙 장치에 방송해야 할 서비스와 특징을 준비해야 한다. 여기서는 setup 서비스 방법을 호출해서 실현할 수 있다.모든 서비스와 특징은 하나의 UUID(unique identifier)로 표시해야 한다. UUID는 16bit 또는 128bit의 값이다.중앙-주변 앱을 만들려면 128bit의 UUID를 만들어야 합니다.당신은 자신의 UUID가 이미 존재하는 다른 서비스와 충돌할 수 없다는 것을 확인해야 합니다.만약 당신이 자신의 장치를 만들려면 표준위원회가 필요로 하는 UUID를 실현해야 한다.만약 당신이 단지 중앙 - 주변 앱을 만들 뿐이라면, 나는 당신이 맥 OS X의 Terminal을 열 것을 건의합니다.app, uidgen 명령으로 128bit의 UUID를 생성합니다.이 명령을 두 번 사용해서 두 개의 UUID를 생성해야 한다. 하나는 서비스에 쓰는 것이고, 하나는 특징에 쓰는 것이다.그리고 중앙과 주변 앱에 그들을 추가해야 합니다.이제view controller가 실행되기 전에 다음 코드를 추가합니다.
static NSString * const kServiceUUID = @"1C85D7B7-17FA-4362-82CF-85DD0B76A9A5"; static NSString * const kCharacteristicUUID = @"7E887E40-95DE-40D6-9AA0-36EDE2BAE253";

다음은 setup Service 방법입니다.
- (void)setupService {     CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];          self.customCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];          CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];          self.customService = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];     [self.customService setCharacteristics:@[self.customCharacteristic]];     [self.peripheralManager addService:self.customService];          }

CBPeripheral Manager의addService 방법이 호출되면 CBPeripheral Manager Delegate의 - (void)peripheral Manager: (CBPeripheral Manager *)peripheral didAdd Service: (CB Service *) service error: (NSError *) error 방법에 응답합니다.이럴 때 우리가 방금 만든 서비스를 방송할 수 있다.
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error {     if (error == nil)     {         [self.peripheralManager startAdvertising:@{ CBAdvertisementDataLocalNameKey : @"ICServer", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:kServiceUUID]] }];     } }

물론 여기까지는peripheral Manager의 일을 마쳤고 중앙 설비는 당신의 서비스를 받아들일 수 있습니다.하지만 이것은 정지된 데이터입니다. 당신은 - (BOOL) update Value: (NS Data *)value for Characteristic: (CB Mutable Characteristic *)characteristic on Subscribed Centrals: (NS Array *)centrals 방법으로 중앙에 동적 데이터를 생성할 수 있는 곳을 호출할 수 있습니다.
- (void)sendToSubscribers:(NSData *)data {   if (self.peripheral.state != CBPeripheralManagerStatePoweredOn) {     LXCBLog(@"sendToSubscribers: peripheral not ready for sending state: %d", self.peripheral.state);     return;   }   BOOL success = [self.peripheral updateValue:data                             forCharacteristic:self.characteristic                          onSubscribedCentrals:nil];   if (!success) {     LXCBLog(@"Failed to send data, buffering data for retry once ready.");     self.pendingData = data;     return;   } }

central은 characteristic의 값을 구독합니다. 값을 업데이트할 때peripheral은 updateValue: forCharacteristic: onSubscribedCentrals: (NSarray*) centrals를 호출하여 그룹 안의 centrals에 대응하는 characteristic의 값을 업데이트합니다. 업데이트된 후peripheral은 모든 central을 위해 다음 에이전트를 한 번 가십시오.
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic

peripheral이 읽거나 쓰는 요청을 받아들일 때 다음 두 가지 프록시 방법에 응답합니다
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request - (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests

그럼 이제peripheral이 만들어졌어요.

중앙 만들기


중앙을 만들고 주변을 연결합니다. 현재 우리는 주변을 하나 가지고 있습니다. 중앙을 만들 수 있습니다.중앙이 바로 주변에서 보낸 데이터를 처리하는 장치다.
self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];

Central Manager가 초기화되면 이 앱을 실행하는 장치가 BLE를 지원하는지 확인하기 위해 상태를 검사해야 합니다.CBCentralManagerDelegate를 구현하는 에이전트 방법:
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {     switch (central.state)     {         case CBCentralManagerStatePoweredOn:         {             [self.manager scanForPeripheralsWithServices:@[ [CBUUID UUIDWithString:kServiceUUID]]                                                  options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];         }             break;         default:         {             NSLog(@"Central Manager did change state");         }             break;     } }

앱의 장치가 블루투스를 지원할 때 CBCentral Manager의 실례적인 - (void) scan For Peripherals With Services: (NSArray *) 서비스 UIDs 옵션: (NS Dictionary *) 옵션 방법을 호출하여 지정한 서비스의peripheral을 찾는 데 사용합니다.일단 주변을 찾다가 발견되면 중앙의 대리는 다음과 같은 회답을 받을 것이다.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {          NSString *UUID = [peripheral.identifier UUIDString];     NSString *UUID1 = CFBridgingRelease(CFUUIDCreateString(NULL, peripheral.UUID));     NSLog(@"---- ----%@%@", UUID,UUID1);     [self.manager stopScan];          if (self.peripheral != peripheral)     {         self.peripheral = peripheral;         NSLog(@"Connecting to peripheral %@", peripheral);         [self.manager connectPeripheral:peripheral options:nil];     } }

이때 방송 데이터와 신호 질량(RSSI-Received Signal Strength Indicator)이 첨부된 주변이 발견되었다.이것은 매우 멋진 매개 변수로 신호의 질을 알게 되면 너는 그것으로 원근을 판단할 수 있다.모든 방송, 스캔된 응답 데이터는advertisementData에 저장되며, CBAdvertisementData를 통해 접근할 수 있습니다.이럴 때 이 주변 장치를 연결할 수 있는데,
[self.manager connectPeripheral:peripheral options:nil];

다음 에이전트 방법에 응답합니다.
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {     NSLog(@"---- ----");     [self.peripheral setDelegate:self];     [self.peripheral discoverServices:@[ [CBUUID UUIDWithString:kServiceUUID]]]; }

주변 서비스에 접근하는 CBCentral Manager Delegate 에이전트는 CBPeripheral의 실례를 되돌려줍니다. 그 - (void) discover 서비스: (NSArray *) 서비스 UIDs 방법은 주변 서비스에 접근하는 것입니다. 이 방법은 CBPeripheral Delegate 방법에 응답합니다.
- (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error {     NSLog(@"----didDiscoverServices----Error:%@",error);     if (error)     {         NSLog(@"Error discovering service: %@", [error localizedDescription]);         [self cleanup];         return;     }          for (CBService *service in aPeripheral.services)     {         NSLog(@"Service found with UUID: %@", service.UUID);         if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]])         {             [self.peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:kCharacteristicUUID],[CBUUID UUIDWithString:kWrriteCharacteristicUUID]] forService:service];         }     } }

위의 방법에 error가 없으면discoverCharacteristics 방법을 호출하여 주변에 서비스가 열거한 특징을 찾으라고 요청할 수 있습니다. 다음 방법에 응답합니다.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {     if (error)     {         NSLog(@"Error discovering characteristic: %@", [error localizedDescription]);         return;     }     if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]])     {         for (CBCharacteristic *characteristic in service.characteristics)         {             NSLog(@"----didDiscoverCharacteristicsForService---%@",characteristic);             if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]])             {                 [peripheral readValueForCharacteristic:characteristic];                 [peripheral setNotifyValue:YES forCharacteristic:characteristic];             }                          if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWrriteCharacteristicUUID]])             {                 writeCharacteristic = characteristic;             }                      }     } }

이 때peripheral은 두 가지 방법을 호출할 수 있습니다. [peripheral readValue ForCharacteristic:characteristic] 이것은 특징값을 읽고 응답합니다. - (void)peripheral: (CBPeripheral *)peripheral didUpdateValue ForCharacteristic: (CBCharacteristic *)characteristic error: (NSError *)error;
[peripheral setNotifyValue:YES forCharacteristic:characteristic];응답합니다 - (void)peripheral: (CBPeripheral*)peripheral didUpdateNotificationStateForCharacteristic: (CBCharacteristic*)characteristic error: (NSError*)error;
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {     if (error)     {         NSLog(@"Error changing notification state: %@", error.localizedDescription);     }          // Exits if it's not the transfer characteristic     if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]] )     {         // Notification has started         if (characteristic.isNotifying)         {             NSLog(@"Notification began on %@", characteristic);             [peripheral readValueForCharacteristic:characteristic];         }         else         { // Notification has stopped             // so disconnect from the peripheral             NSLog(@"Notification stopped on %@.  Disconnecting", characteristic);             [self.manager cancelPeripheralConnection:self.peripheral];         }     } } - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {     NSLog(@"----Value---%@",characteristic.value);     if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]])     {         if (writeCharacteristic)         {             Byte ACkValue[3] = {0};             ACkValue[0] = 0xe0; ACkValue[1] = 0x00; ACkValue[2] = ACkValue[0] + ACkValue[1];             NSData *data = [NSData dataWithBytes:&ACkValue length:sizeof(ACkValue)];             [self.peripheral writeValue:data                       forCharacteristic:writeCharacteristic                                    type:CBCharacteristicWriteWithoutResponse];         }     } }

위의 방법 중 - (void) writeValue: (NSData*) data forCharacteristic: (CBCharacteristic*) characteristic type: (CBCharacteristicWriteType) type은 주변 장치에 데이터를 쓰는 방법으로 다음 방법에 응답합니다
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {     NSLog(@"---didWriteValueForCharacteristic-----");     if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWrriteCharacteristicUUID]])     {         NSLog(@"----value ----");     } }

좋은 웹페이지 즐겨찾기