[swift] Swift Core Bluetooth 디바이스의 제어 및 설정

Swift Core Bluetooth는 iOS 앱에서 블루투스 저에너지(BLE) 기기와 통신하는 기능을 제공합니다. 이를 통해 앱에서 BLE 디바이스를 검색하고 연결하며, 특성을 읽고 쓰는 등 다양한 기기 제어 및 설정 작업을 수행할 수 있습니다.

1. 디바이스 검색

BLE 디바이스 검색을 위해서는 CBCentralManager 객체를 사용합니다. 아래는 간단한 디바이스 검색 예제 코드입니다.

import CoreBluetooth

class DeviceScanner: NSObject, CBCentralManagerDelegate {
    var centralManager: CBCentralManager!
    
    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            // 스캔 시작
            central.scanForPeripherals(withServices: nil, options: nil)
        } else {
            // 블루투스를 켜세요
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        // 디바이스 검색 완료 후 처리할 로직
    }
}

DeviceScanner 클래스는 CBCentralManagerDelegate 프로토콜을 채용하여 디바이스를 검색할 수 있도록 합니다. centralManagerDidUpdateState 메서드에서 블루투스 상태를 확인하고, centralManager(_:didDiscover:advertisementData:rssi:) 메서드에서 검색된 디바이스를 처리할 수 있습니다.

2. 디바이스 연결

BLE 디바이스에 연결하기 위해서는 CBPeripheral 객체를 사용합니다. 연결을 위한 예제 코드는 다음과 같습니다.

import CoreBluetooth

class DeviceConnector: NSObject, CBPeripheralDelegate {
    var centralManager: CBCentralManager!
    var peripheral: CBPeripheral!
    
    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            // 스캔 시작
            central.scanForPeripherals(withServices: nil, options: nil)
        } else {
            // 블루투스를 켜세요
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        // 디바이스 검색 완료 후 처리할 로직
        if peripheral.name == "MyDevice" {
            self.peripheral = peripheral
            centralManager.connect(peripheral, options: nil)
        }
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        // 디바이스 연결 완료 후 처리할 로직
        peripheral.delegate = self
        peripheral.discoverServices(nil)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        // 서비스 검색 완료 후 처리할 로직
        if let services = peripheral.services {
            for service in services {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }
}

DeviceConnector 클래스는 CBCentralManagerDelegateCBPeripheralDelegate 프로토콜을 채용하여 디바이스 연결을 수행합니다. centralManager(_:didConnect:) 메서드에서 디바이스 연결 후 로직을 처리할 수 있으며, peripheral(_:didDiscoverServices:) 메서드에서 디바이스의 서비스를 검색하고, 해당 서비스의 특성을 검색합니다.

3. 특성 읽고 쓰기

BLE 디바이스의 특성은 CBCharacteristic 객체를 통해 읽고 쓸 수 있습니다. 예제 코드를 통해 특성 읽기와 쓰기를 살펴봅시다.

import CoreBluetooth

class DeviceController: NSObject, CBPeripheralDelegate {
    var centralManager: CBCentralManager!
    var peripheral: CBPeripheral!
    var targetCharacteristic: CBCharacteristic!
    
    override init() {
        super.init()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            // 스캔 시작
            central.scanForPeripherals(withServices: nil, options: nil)
        } else {
            // 블루투스를 켜세요
        }
    }
    
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        // 디바이스 검색 완료 후 처리할 로직
        if peripheral.name == "MyDevice" {
            self.peripheral = peripheral
            centralManager.connect(peripheral, options: nil)
        }
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        // 디바이스 연결 완료 후 처리할 로직
        peripheral.delegate = self
        peripheral.discoverServices(nil)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        // 서비스 검색 완료 후 처리할 로직
        if let services = peripheral.services {
            for service in services {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        // 특성 검색 완료 후 처리할 로직
        if let characteristics = service.characteristics {
            for characteristic in characteristics {
                if characteristic.uuid == CBUUID(string: "0000fff1-0000-1000-8000-00805f9b34fb") {
                    targetCharacteristic = characteristic
                    peripheral.readValue(for: characteristic)
                }
            }
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        // 특성 값 읽기/쓰기 후 처리할 로직
        if let value = characteristic.value {
            // 특성 값 사용
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        // 특성 값 쓰기 완료 후 처리할 로직
    }
}

위 코드에서는 didDiscoverCharacteristicsFor 메서드에서 특정 UUID를 가진 특성을 찾고, 해당 특성의 값을 읽습니다. 필요에 따라 값을 쓰고자 할 때는 peripheral(_:didWriteValueFor:error:) 메서드를 사용합니다.

Swift Core Bluetooth를 사용하여 BLE 디바이스를 제어하고 설정할 수 있는 기능에 대해 알아보았습니다. Core Bluetooth 프레임워크의 다양한 메서드와 이벤트를 활용하여 앱과 BLE 디바이스간에 데이터를 교환하고, 자신의 앱에서 사용할 수 있는 기능을 활용해보세요.

참고 자료