Bluetooth에 대한 무지에서 시작된 공부, 사실 Bluetooth의 경우 특별히 모듈이나 장치를 만들지 않으면 경험해보긴 쉽진 않기에, 근처의 주변기기를 탐색하고 연결정도 해보는 BluetoothManager를 구현해볼 예정이다.
사실 아두이노를 갖고 있고 어케 만드는지 알고 있어 아두이노로 만들면 되긴하는데,,,, 귀찮음 이슈로...
[iOS] BLE with CoreBluetooth 여기서 확인
// BluetoothManager.swift
import Foundation
import CoreBluetooth
final class BluetoothManager: NSObject, ObservableObject {
override init() {
super.init()
self.centralManager = CBCentralManager(delegate: self, queue: nil)
}
@Published var discoveredPeripherals: [CBPeripheral] = []
@Published var isScanning = false {
didSet {
switch isScanning {
case true:
startScanning()
case false:
stopScanning()
}
}
}
private var centralManager: CBCentralManager!
private var connectedPeripheral: CBPeripheral?
}
extension BluetoothManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("unknown")
case .resetting:
print("resetting")
case .unsupported:
print("unsupported")
case .unauthorized:
print("unauthorized")
case .poweredOff:
print("poweredOff")
case .poweredOn:
print("poweredOn")
@unknown default:
print("unknown default")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if !discoveredPeripherals.contains(where: { $0.identifier == peripheral.identifier }) {
discoveredPeripherals.append(peripheral)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
connectedPeripheral = peripheral
peripheral.delegate = self
peripheral.discoverServices(nil)
print(peripheral)
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
print("Failed to connect to \(peripheral.name ?? "a peripheral"): \(error?.localizedDescription ?? "Unknown error")")
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
if connectedPeripheral == peripheral {
connectedPeripheral = nil
}
}
private func startScanning() {
centralManager.scanForPeripherals(withServices: nil, options: nil)
}
private func stopScanning() {
centralManager.stopScan()
}
func connectToPeripheral(_ peripheral: CBPeripheral) {
centralManager.connect(peripheral, options: nil)
}
}
extension BluetoothManager: CBPeripheralDelegate {
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 {
peripheral.readValue(for: characteristic)
peripheral.setNotifyValue(true, for: characteristic)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let value = characteristic.value {
print(value.base64EncodedData())
}
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
print("Error writing value for characteristic \(characteristic.uuid): \(error.localizedDescription)")
} else {
print("Successfully wrote value for characteristic \(characteristic.uuid)")
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
print("Error updating notification state for characteristic \(characteristic.uuid): \(error.localizedDescription)")
} else {
print("Notification state updated for characteristic \(characteristic.uuid)")
}
}
}
// ContentView.swift
import SwiftUI
struct ContentView: View {
@StateObject private var bluetoothManger = BluetoothManager()
var body: some View {
VStack {
Toggle(isOn: $bluetoothManger.isScanning) {
Text("스위치")
}
.padding()
List(bluetoothManger.discoveredPeripherals, id: \.identifier) { item in
Button {
bluetoothManger.connectToPeripheral(item)
} label: {
Text(item.name ?? item.identifier.uuidString)
}
}
}
}
}
Toggle을 통해 스위치를 열면 주변의 기기들을 찾아주고, 항목을 탭 하게 되면 연결된다.
<CBPeripheral: 0x302339040, identifier = 3E853202-F2D7-7117-ADFB-FEA5E8158B54, name = A_Mcflurry의 노트북, mtu = 23, state = connected>
QXBwbGUgSW5jLg==
Error updating notification state for characteristic Manufacturer Name String: The request is not supported.
TWFjQm9va1BybzE4LDM=
Error updating notification state for characteristic Model Number String: The request is not supported.
Notification state updated for characteristic Continuity
LQAgBAAEAFrxsfkAAAAAsAL//+oDAAACBAUoAQMDBgEBCAoVHyN7AAAAAAQCAAA=
LQAgBAAEAFrxsfkAAAAAsAL//7aVAAACBAUoAQMDBgEBCAoVH1bpAAAAAAQCAAA=
Peripheral의 정보와 데이터를 수신받게 되는데, 저 데이터가 무슨 데이터인질 아직 잘 모르겠다.
간단한 토이프로젝트로 CoreBluetooth를 이용한 탐색과 연결을 해보았다. Bluetooth 연결에 대한 개념을 학습할 수 있었고, 간단한 플젝으로 연결도 성공, 데이터도 수신받아보았다.
삐뽀 잔다 😴