본문 바로가기
ios 뽀개기/objective-c

objective c 블루투스 corebluetooth

by 인생여희 2019. 10. 18.
반응형

objective c 블루투스 corebluetooth

#import "SosRequestViewController.h"
#import <UIKit/UIKit.h>
//코어 블루투스 라이브러리 추가한것 임포트 한다.
#import <CoreBluetooth/CoreBluetooth.h>


//센트럴의 이벤트를 수행할 수 있도록, 델리게이트 구현
@interface ViewController : UIViewController <CBCentralManagerDelegate,CBPeripheralDelegate>

@property (strong, nonatomic) CBCentralManager *centralManager; //센트럴 역할을 수행해줄 객체
@property (strong, nonatomic) CBPeripheral *safetyPeripheral;   //주변기기 객체
@property (strong, nonatomic) CBCharacteristic *characteristic;   //특성정보


//좌측 상단, ble 연결 체크 이미지
@property (weak, nonatomic) IBOutlet UIImageView *bleOnOffImage;

//중앙 상단, ble 상태 메시지
@property (weak, nonatomic) IBOutlet UILabel *bleModeStateText;

//정중앙, ble 파란색 연속 이미지
@property (weak, nonatomic) IBOutlet UIImageView *bleCenterImage;

//정중앙, 이미지 변경을 위한 타이머
@property (weak, nonatomic) NSTimer *imageTimer;

//정중앙, 이미지 변경을 위한 배열
@property (nonatomic, strong) NSArray *imagesList;


//블루투스 모드 on off 모드 버튼
@property (weak, nonatomic) IBOutlet UIButton *bleOnOffButton;

//경고 문구 1
@property (weak, nonatomic) IBOutlet UILabel *warningLabel;


//블루투스 연결 모드 of off 체크 (실제연결체크 아님)
@property (nonatomic, assign) BOOL BleOnOffCheck;

@end

 


//블루투스 관련 기기 정보 상수
#define DEVICE_NAME @"이름"                                                   //블루투스 이름
#define SAFETY_BLE_SERVICE @"서비스아이디"              //서비스 uuid
#define SAFETY_BLE_CHARACTERISTIC @"특성아이디"      //특성 uuid

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

//센트럴 매니저 초기화
-(void) initCentralManager{
      //센트럴 매니저 초기화 + 대리자 설정
      //이제 블루투스 기능을 사용할 수 있고, 관리할 수 있다
      _centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
}

//화면이 로드되었을때
- (void)viewDidLoad {
    [super viewDidLoad];
   
    //센트럴 매니저 초기화
    [self initCentralManager];

    //블루투스 스캔 초기 값 : NO 셋팅
    _BleOnOffCheck = NO;
    
    [self colorWord];
}


//블루투스 상태 확인 - centralManager가 생성될 때 한번 호출되고,
//나중에 상태가 변경될 때마다 호출되기 때문에 필요한 로직을 추가 할 수 있다.
- (void) centralManagerDidUpdateState:(CBCentralManager *)central{
    
    //휴대폰의 블루투스가 켜져있을 경우.
    if(central.state == CBManagerStatePoweredOn){
        //주변 장치를 찾을 수 있는 유일한 상태!
        NSLog(@"CBManagerStatePoweredOn");
        //앱에서 블루투스 스캔 ON 일경우
        if(_BleOnOffCheck == YES){
            NSLog(@"블루투스 스캔 ON 상태. 주변 기기 스캔 중...");
            //주변 기기 스캔 작동 중...
            [_centralManager scanForPeripheralsWithServices:nil options:nil];
        }else{
        //OFF 일경우
            NSLog(@"블루투스 스캔 OFF 상태");
        }
    }
    
}


//블루투스가 on 상태, 연결가능 기기 목록 검색
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    NSLog(@"bluetooth 연결 가능 기기");
    NSLog(@" name : %@", peripheral.name);
    NSLog(@" service : %@", peripheral.services);
    NSLog(@" state : %ld", (long)peripheral.state);
    NSLog(@"=======================================");
    
    
    //특정 기기 찾기
    //블루투스 기기 이름이 Safety 라면
    if([peripheral.name isEqualToString:DEVICE_NAME]){
        
        
    //######## 휴대폰에서 특정 0x01 값을 던지면 연결 하기!####
        if(YES){
            
            //로직 작성
        }
        
        
        //원하는 블루투스 기기를 찾았기 때문에, central은 스캔 중지 시켜준다.
        [_centralManager stopScan];
        
        //찾은 주변기기 맴버변수에 할당
        _safetyPeripheral = peripheral;
        
        //대리자를 할당해주어야 프로토콜의 메소드를 사용할 수 있다!
        _safetyPeripheral.delegate = self;
        
        
        //cantral 에 찾은 peripheral(주변기기 safety) 연결 시켜준다.
        //기기에 연결이 되었는지 확인은 바로 아래 델리게이트 메소드(didConnectPeripheral) 호출 결과를 통해 알 수 있다.
        [_centralManager connectPeripheral:_safetyPeripheral options:nil];
        
    }
    
    
}

//central에 특정 블루투스 기기가 연결이 되었는지 확인하는 델리게이트 함수.
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    
    NSLog(@"Safety 기기 연결 성공 ! - 연결된 기기");
    
    //왼쪽 상단 이미지 변경 -> on 이미지
    [_bleOnOffImage setImage:[UIImage imageNamed:@"bt_on.png"]];
    
    //중앙 상단 텍스트 변경.
    [_bleModeStateText setText:@"블루투스(BLE) 연결 완료"];
    
    //주변 장치의 서비스 검색 - 결과를 확인하려면 델리게이트 메소드(peripheral : didDiscoverServices) 작성필요.(CBPeripheralDelegate 프로토콜 구현)
    [_safetyPeripheral discoverServices:@[ [CBUUID UUIDWithString:SAFETY_BLE_SERVICE]]];    //특정 serivce uuid 입력!

}


//주변기기가 제공하는 서비스 확인
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    
    //오류가 있다면
    if (error != NULL) {
        NSLog(@"discoverServices 에러 발생! : peripheral: %@, error: %@",peripheral.name,error.debugDescription);
    }else{
        
        //서비스를 제공하는 주변기기 맴버 변수에 할당
        _safetyPeripheral = peripheral;
        
        for (int i=0; i < peripheral.services.count; i++) {
            CBService *service = [peripheral.services objectAtIndex:i];
            NSLog(@"찾은 서비스 아이디 : %@" , service.UUID.UUIDString);
            NSLog(@"찾은 서비스 설명 : %@" , service.debugDescription);
            
            //찾은 서비스의 id가 특정 service 아이디와 같으면
            if([service.UUID.UUIDString isEqualToString:SAFETY_BLE_SERVICE]){
                //서비스 id로 특성을 찾는다
                [peripheral discoverCharacteristics:@[ [CBUUID UUIDWithString:SAFETY_BLE_CHARACTERISTIC]] forService:service];
            }
        }
    }
}

//주변기기 특성 발견 델리게이트 메소드 + 구독
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    
    for (int i = 0; i < service.characteristics.count; i++) {
        
        //특성 가져오기
       CBCharacteristic *character = service.characteristics[i];
        
        NSLog(@"제공 가능 특성 UUID : %@" ,character.UUID.UUIDString);
        NSLog(@"제공 가능 특성 properties : %lu" ,(unsigned long)character.properties);
        NSLog(@"제공 가능 특성 character : %@" ,character);
        NSLog(@"\n");
        
        _safetyPeripheral = peripheral;
        _safetyPeripheral.delegate = self;
        
        //아래 메소드를 통해서 특성을 구독할 수 있다.
        //기기가 가진 특성의 noti값을 YES로 변경을 요청하면, 값이 변경된다면 데이터가 될때 자동으로 Central 쪽으로 데이터를 전송한다.
        //데이터를 보내는 용도로만 사용하는 특성은 구독을 해도 상태값이 변경되지 않도록 막혀 있다.
        [_safetyPeripheral setNotifyValue:YES forCharacteristic:character];
       
    }
}

//noti를 변경하려고 하면 호출되는 메소드
//주변기기 알림상태가 변경되었을때
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{

    if (error) {
        NSLog(@"오류 발생 notification state: %@", error.localizedDescription);
    }else{
        
        //특성의 노티가 yes 면
        if (characteristic.isNotifying) {
            //정보를 받아오는 케릭터
            NSLog(@"Notification began on %@", characteristic);
            //_stateLabel.text = @"Notification began";
        } else {
            //정보를 던져야 하는 캐릭터
            NSLog(@"Notification finish on %@", characteristic);
            _characteristic = characteristic;
        };
        
    }

}


//주변기기가 던저 주는 데이터 받기 (0x01, 0x02)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"Error reading characteristics: %@", [error localizedDescription]);
        return;
    }

    if (characteristic.value != nil) {
        NSLog(@"characteristic.value : %@" ,characteristic.value);  //0x01(일반), 0x02(침수상태) 날라온다.
       
        NSLog(@"characteristic.value.description : %@" ,characteristic.value.description);
        
        NSString *peripheralSendSign = characteristic.value.description;
        
        if([peripheralSendSign containsString:@"0x02"]){
            NSLog(@"침수상황 sos!!");
            
            //긴급신고 화면 호출
            [self showSOSViewController];
            
            //주변기기가 던저 주는 데이터 종료 시키기 -
            
        }else if([peripheralSendSign containsString:@"0x01"]){
            NSLog(@"연결상황");
            
        }
        
    }
}




//주변기기 연결을 위한 상태 ON OFF 버튼
- (IBAction)scanBluetoothButton:(id)sender {
    
    //끄기(off) 이미지
    UIImage *btnOffImage = [UIImage imageNamed:@"icon_off.png"];
    //켜기(on) 이미지
    UIImage *btnOnImage = [UIImage imageNamed:@"icon_on.png"];
    
    
    //꺼져있으면
    if (_BleOnOffCheck == NO) {
        [_bleOnOffButton setImage:btnOnImage forState:UIControlStateNormal];
        _BleOnOffCheck = YES; //켬
        //센트럴 매니저 초기화 - > 스캔 시작
        [self initCentralManager];
        
        //정중앙 ble 이미지 연속 변경 로직
        _imagesList = @[@"siren_off_01.png", @"siren_off_02.png", @"siren_off_03.png", @"siren_off_04.png"];
        //타이머 시작
        _imageTimer = [NSTimer scheduledTimerWithTimeInterval:0.50
                                                       target:self
                                                       selector:@selector(changeImage)
                                                       userInfo:nil
                                                       repeats:YES];
      
    //켜져있으면
    }else if (_BleOnOffCheck == YES){
        
        [_bleOnOffButton setImage:btnOffImage forState:UIControlStateNormal];
        _BleOnOffCheck = NO; //끔
        //스캔 정지
        [_centralManager stopScan];
        //타이머 정지
        [_imageTimer invalidate];
        //센터 이미지 변경
        _bleCenterImage.image = [UIImage imageNamed:@"siren_off.png"];
        //좌측 상단 이미지 변경
        [_bleOnOffImage setImage:[UIImage imageNamed:@"bt_off.png"]];
        //중앙 상단 텍스트 변경.
        [_bleModeStateText setText:@"블루투스(BLE) 상태 확인중..."];
    }
}

//정중앙 이미지 변경
- (void)changeImage
{
  static int counter = 0;
  if([_imagesList count] == counter+1)
  {
      counter = 0;
  }
  _bleCenterImage.image = [UIImage imageNamed:[_imagesList objectAtIndex:counter]];

  counter++;
}



//취소 - 블루투스 기기 종료 시키기
- (IBAction)cancelButton:(UIButton *)sender {
    NSLog(@"취소 버튼이 눌렀습니다.");
    
    NSNumber *cancelNumber = [[NSNumber alloc]initWithInt:99];
    NSData *cancelData =  [NSData dataWithBytes:&cancelNumber length:1];
    
    //주변기기를 종료 시키기
    [_safetyPeripheral writeValue:cancelData forCharacteristic:_characteristic type:CBCharacteristicWriteWithoutResponse];
    
}


//물 속에 블루투스 기기가 입수되었을때, 긴급구조 화면 호출
-(void)showSOSViewController{
    
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    SosRequestViewController *sosVC = [storyboard instantiateViewControllerWithIdentifier:@"sosView"];
    [self presentViewController:sosVC animated:YES completion:^{
        NSLog(@"부모가 뷰컨트롤러를 뛰웠습니다.(완료)");
    }];
}


-(void)colorWord {
    NSMutableAttributedString * string = [[NSMutableAttributedString alloc]initWithString:_warningLabel.text];

    NSArray *words=[_warningLabel.text componentsSeparatedByString:@" "];

    for (NSString *word in words) {
        if ([word hasPrefix:@"허위 및 장난"]) {
            NSRange range=[_warningLabel.text rangeOfString:word];
            [string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
        }
    }
    [_warningLabel setAttributedText:string];
}





- (IBAction)segueTest:(id)sender {
    [self showSOSViewController];
    
}


@end



 
 



 

파일

BLETest 3.zip
5.73MB
DJAlertView-master.zip
0.07MB

반응형

댓글