[BLE] ⚡️ Peripheral 시뮬레이션 (2)
2025. 10. 12. 15:26ㆍ도메인/Bluetooth

시뮬레이션 - Act as a Peripheral
실제 대부분의 기기는 자체 펌웨어로 Peripheral 역할을 한다. Apple platform에서는 CBPeripheralManager를 통해 peripheral을 시뮬레이션할 수 있다. 해당 기능은 foreground에서만 동작한다는 제약이 있지만 학습해보는데는 충분하다.
CBPeripheralManager
let cbPeripheralManager = CBPeripheralManager(delegate: self, queue: nil)
- 서비스와 Charateristics를 광고
- central devices에게 데이터를 전송
- CBPeripheralManagerDelegate: device state + connected devices
- iOS, iPadOS, madOS can act as peripherals
WatchOS의 경우, 보안을 위해 Central 역할만 하며, 외부 BLE가 Watch Characteristic을 읽을 수 없다. 모든 외부 통신은 막혀있고, iPhone을 통해서만 간접적으로 정보를 얻을 수 있다. 이 때 iPhone과 통신을 위해 Watch Connectivity의 WCSession라는 기술을 이용하여 실시간 데이터 통신한다.
Adversitsing
let heartRateCharacteristic = CBMutableCharacteristic(
type: Gatt.Characteristic.heartRateMeasurement,
properties: [.notify],
value: nil,
permissions: [.readable]
)
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
setupHeartRateService()
startAdvertising()
}
}
전원이 들어오면 서비스를 활성화하고, 광고를 시작합니다.
서비스가 만들어지면 매니저의 스택에 쌓습니다.
func setupHeartRateService() {
let heartRateService = CBMutableService(
type: Gatt.Service.heartRate,
primary: true
)
heartRateService.characteristics = [heartRateCharacteristic]
cbPeripheralManager.add(heartRateService)
}
func startAdvertising() {
isAdvertising = true
let advertisementData: [String: Any] = [
CBAdvertisementDataServiceUUIDsKey: [Gatt.Service.heartRate]
]
cbPeripheralManager.startAdvertising(advertisementData)
}
Sending Data
정보를 주고 받은 이후 Central이 characteristic을 구독하면 광고를 중단하고, 값을 보냅니다.
func peripheralManager(
_ peripheral: CBPeripheralManager,
central: CBCentral,
didSubscribeTo characteristic: CBCharacteristic
) {
if characteristic.uuid == Gatt.Characteristic.heartRateMeasurement {
stopAdvertising()
repeatedlySendHeartRateValues()
}
}
func repeatedlySendHeartRateValues() {
guard sendHeartRateTask == nil else {
return
}
sendHeartRateTask = Task {
while !Task.isCancelled {
sendHeartRateMeasurement()
try? await Task.sleep(for: .seconds(1))
}
}
}
1초 주기로 값을 보내고는 Task를 생성하여 값을 방출합니다.
func sendHeartRateMeasurement() {
let variableHeartRate = UInt8.random(
in: (heartRateValue - 1) ... (heartRateValue + 1)
)
// Flags (0x00) + Heart Rate Value
let heartRateData = Data([0x00, variableHeartRate])
cbPeripheralManager.updateValue(
heartRateData,
for: heartRateCharacteristic,
onSubscribedCentrals: nil
)
}
임의로 만든 heartrate 식별 flag값과 임의로 생성한 심박수를 이용하여 패킷을 생성합니다. 생성한 peripheralManager를 통해 갱신합니다.
모든 디바이스가 아니라 특정 디바이스에게만 전송하고 싶으면, onSubscribedCentrals: nil 대신 위에서 얻은 Central 정보를 넣으면 됩니다.
'도메인 > Bluetooth' 카테고리의 다른 글
| [BLE] ⚡️ BLE Write와 State Restore (3) (0) | 2025.10.12 |
|---|---|
| [BLE] ⚡️ BLE란? Core Bluetooth (1) (0) | 2025.10.12 |