반응형
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
파일
반응형
'ios 뽀개기 > objective-c' 카테고리의 다른 글
CALayer 관련 참고 페이지 (166) | 2019.10.18 |
---|---|
ios 로컬 음악파일 간단하게 재생하기 (195) | 2019.10.18 |
protocol 개념 - 1 (565) | 2019.10.09 |
AVCaptureVideoDataOutput을 이용해서 카메라 만들기 3 - 녹화 (924) | 2019.04.17 |
AVCaptureVideoDataOutput을 이용해서 카메라 만들기 2 - 녹화 (0) | 2019.04.17 |
댓글