티스토리 뷰
이번 포스트에서는 실생활에서 많이 쓰이는 블루투스 통신의 기본을 알아볼까합니다.
블루투스의 경우에는 내용이 많기도 하고
두가지로 나누어 설명하는게 좋을것 같아서
1편 CBCentralManagerDelegate
2편 CBPeripheralDelegate
으로 나누어 진행하겠습니다.
CBCentralManagerDelegate
주변 장치의 검색 및 관리를 위한 업데이트를 제공하는 프로토콜
간단히 말씀드리면 이 친구는 블루투스 장비를 검색하고 연결하는 걸 도와주는 친구입니다.
CBPeripheralDelegate
주변 장치의 서비스 사용에 대한 업데이트를 제공하는 프로토콜
마찬가지로 간단히 말씀드리면 이 친구는 연결된 블루투스 장비와 통신하는 걸 도와주는 친구입니다.
일단 이번에는 블루투스 기기를 찾아 연결하는 것까지 진행하는 걸 목표로 하겠습니다.
시작전에 필요한 권한부터 먼저 넣어줍시다.
권한은 총 두가지인데 위와 같은 맥락으로 이해하시면 됩니다.
( 블루투스 통신 연결 관련 / 연결 기기와의 통신 관련 )
* 일반적으로 Peripheral 라는 단어가 있으면 연결된 기기와 관련된거라고 생각하시면 됩니다.
* 참고로 저는 회사에서 준 블루투스 기기와 연결을 해야하는 상황이라 UUID 정보를 가지고 있는 상태에서 제작했습니다.
코드를 본격적으로 작성하기전에 아래 코드를 반드시 추가해주세요.
import CoreBluetooth // 블루투스의 경우 필수
연결해야하는 UUID 정보가 있으면 미리 만들어 두는걸 추천드립니다. 아래처럼
// 저는 문서에 적힌 UUID를 미리 아래처럼 만들어 사용했습니다.
// UUID를 가지신 분들은 아래를 참고하여 미리 작성하시길 권고 드립니다.
static let ServiceUUid : [CBUUID] = [CBUUID(string: "??????"))]
static let TXCharUUid : [CBUUID] = [CBUUID(string: "????")]
static let RXCharUUid : [CBUUID] = [CBUUID(string: "?????")]
만약 UUID 가 없으시면 기기 이름 보고 연결하셔도 되긴 합니다.
그리고 연결된 기기 정보를 가져와야 할때를 대비해 아래처럼 변수 하나를 미리 만들어둡시다.
(저의 경우에는 사정이 있어 두개로 나눠져있지만 필요에따라 그냥 하나로 통일하셔도 됩니다.)
var bluefruitPeripheral: CBPeripheral? // 연결된 기기
var connectedPeripheral: CBPeripheral? // 연결된 기기
var connectedService: CBService? // 이 부분은 2편에서 말씀드릴께요.
이제 본격적으로 시작해 봅시다.
1. 주변기기 찾기
- 일단 연결을 하려면 주변에 있는지 부터 확인해야겠죠?
- 그걸 도와줄 친구 (CBCentralManager) 도 부릅시다
class ViewController: UIViewController {
var centralManager : CBCentralManager!
.
.
.
func setBasicBLE(){
// delegate 작성
self.centralManager = CBCentralManager(delegate: self, queue: nil)
}
}
- 탐색을 시작하는 명령어와 종료하는 명령어입니다.
func searchConnect(){
// 연결 가능한 기기 검색 (필터링 기능을 함)
// UUID 기준으로 필터 가능 없으면 nil 을 넣으면 됩니다(전체 탐색)
print("[ViewController] 블루투스 기기 검색 시작")
self.centralManager.scanForPeripherals(withServices: nil)
// self.centralManager.scanForPeripherals(withServices: self.ServiceUUid)
}
func stopSearch(){
print("[ViewController] 블루투스 기기 검색 중지")
self.centralManager.stopScan()
}
2. 찾은 기기 정보확인
- delegate 를 해놨기 때문에 저희는 아래처럼 받아서 응용할 수 있습니다.
extension ViewController : CBCentralManagerDelegate{
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("[ViewController] 블루투스 연결 완료")
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
// 블루투스 설정 확인
switch central.state{
case .poweredOn:
print("[ViewController] 블루투스 poweredOn")
case .poweredOff:
print("[ViewController] 블루투스 poweredOff")
let alertVC = UIAlertController(title: "Bluetooth Required", message: "블루투스 설정을 확인해주세요.", preferredStyle: UIAlertController.Style.alert)
let action = UIAlertAction(title: "확인", style: UIAlertAction.Style.default, handler: { (action: UIAlertAction) -> Void in
self.dismiss(animated: true, completion: nil)
})
alertVC.addAction(action)
self.present(alertVC, animated: true, completion: nil)
case .unsupported:
print("[ViewController] 블루투스 unsupported")
case .unknown:
print("[ViewController] 블루투스 unknown")
case .resetting:
print("[ViewController] 블루투스 resetting")
case .unauthorized:
print("[ViewController] 블루투스 unauthorized")
@unknown default:
print("[ViewController] 블루투스 Error")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("[ViewController] 장비 찾음")
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
print("[ViewController] 블루투스 연결 종료")
}
}
저희는 여기서 didDiscover 부분을 따로 뜯어보겠습니다.
아래처럼 코드를 짜시면 찾은 기기 정보가 찍히게 됩니다.
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
// 찾은 기기 정보 출력
print(peripheral.name) // 장비 이름
print(peripheral.identifier.uuidString) // 장비 고유 코드
print(RSSI) // 장비와의 거리를 의미합니다.
//RSSI 값을 통해 추상적이긴해도 거리계산이 가능하다고 합니다.
//https://stackoverflow.com/questions/45173454/how-can-ios-detect-bluetooth-signal-strength-similar-to-airpods
// 위링크 참고
}
만약 앞에서 탐색하는 부분에 nil 을 넣으신 분들은 여기서 바로 연결이 아니라 정보를 확인하시고 연결하시는걸 권장드릴께요
예를 들면 아래처럼 작성해야겠죠?
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
// 찾은 기기 정보 출력
if(peripheral.identifier == 자신의기기 UUID){
// 조건이 맞으면 연결 및 해당 기기 정보 가져오기
self.connectOurDevice()
}
}
func connectOurDevice(){
print("[ViewController] 블루투스 기기 연결 시작")
if(self.bluefruitPeripheral != nil){
self.bluefruitPeripheral = peripheral
self.bluefruitPeripheral.delegate = self // 기기 delegate 연결
// 해당 부분은 2편에서 다룰 예정
self.centralManager.connect(self.bluefruitPeripheral) // 기기 통신 연결
}
}
눈치 빠르신 분들은 벌써 눈치채셨겠지만 아래 부분이 기기와 연결하는 명령어입니다.
self.centralManager.connect(self.bluefruitPeripheral) // 기기 통신 연결
3. 기기 정보 확인 및 연결
- 기기 연결이 완료되면 didConnect 라는 함수에 신호가 잡히게 됩니다.
- 기기 연결이 되면 더이상 다른 기기를 스캔할 필요가 없기때문에 연결은 끊어줍시다
- 불필요한 탐색은 우리들의 귀한 배터리가 많이 소모 될수있습니다.
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("[ViewController] 블루투스 연결 완료")
self.connectedPeripheral = self.bluefruitPeripheral
self.connectedPeripheral.discoverServices(self.ServiceUUid)// 없으시면 nil 넣어주세요
// nil 로 넣으시면 모든 반응(Service)을 가져옵니다.
print("[ViewController] 블루투스 기기 검색 중지")
self.centralManager.stopScan()
}
4. 연결 종료 확인
- 연결을 했으면 언젠가 끊어지겠죠?
- 만약 연결이 끊어지면 didDisconnectPeripheral에서 감지하게 됩니다.
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
print("[ViewController] 블루투스 연결 종료")
self.bluefruitPeripheral = nil
self.connectedPeripheral = self.bluefruitPeripheral
}
블루투스 기기와 실제 통신을 주고 받는 부분에 대한 설명은
2편에서 마저 다루도록 하겠습니다.
누군가에게는 도움이 되길 바라며
오늘도 파이팅입니다~
'iOS개발 > Swift 통신' 카테고리의 다른 글
Swift webview input 으로 파일 가져오기 (0) | 2024.06.07 |
---|---|
Swift 블루투스 통신 2편 (CBPeripheralDelegate) (0) | 2023.06.14 |
Swift Local Push Notification 이해하기 (0) | 2023.05.24 |
Swift Synchronous URL loading of 보라색 경고 (Xcode 14 이상) (0) | 2023.05.23 |
Swift Alamofire UIImage 전송하기 (0) | 2022.12.29 |