Files
Companion/Sources/scoobytag/BluetoothManager.swift

152 lines
4.2 KiB
Swift

import SwiftUI
import CoreBluetooth
struct Constants {
static let scbtSvcUuid = "00010F2C-DEAD-BEEF-A455-DEAD69BEEF69";
static let scbtPetUuid: String = "00010F2D-DEAD-BEEF-A455-DEAD69BEEF69";
}
final class BluetoothManager: NSObject, ObservableObject {
private var centralManager: CBCentralManager!
private var myPeripheral: CBPeripheral?
@Published var status = "Starting..."
override init() {
super.init()
periphManager = CBPeripheralManager(delegate: self, queue: nil)
}
}
extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
guard central.state == .poweredOn else {
status = "Bluetooth OFF"
return
}
let uuid = CBUUID(string: Constants.scbtSvcUuid)
centralManager.scanForPeripherals(
withServices: [uuid],
options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false
]
)
}
// Discovery callback
func centralManager(
_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String: Any],
rssi RSSI: NSNumber
) {
if (peripheral.name != nil) {
status = "Found: \(peripheral.name!)"
} else {
status = "Found: \(peripheral.identifier)"
}
myPeripheral = peripheral
central.stopScan()
central.connect(peripheral)
}
// Connection callback
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
status = "Connected"
let uuid = CBUUID(string: Constants.scbtSvcUuid)
peripheral.discoverServices([uuid])
peripheral.delegate = self
}
// Connection failure callback
func centralManager(
_ central: CBCentralManager,
didFailToConnect peripheral: CBPeripheral,
error: Error?
) {
let error2: String
if (error == nil) { error2 = "unknown" }
else { error2 = "\(error!)" }
status = "Failed: \(error2)"
}
// Disconnection callback
func centralManager(
_ central: CBCentralManager,
didDisconnectPeripheral peripheral: CBPeripheral,
error: Error?
) {
let error2: String
if (error == nil) { error2 = "unknown" }
else { error2 = "\(error!)" }
status = "Disconnected: \(error2)"
}
// Service callback
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverServices error: Error?
) {
guard let services = peripheral.services else { return }
status = "Service found"
let scbtSvc = CBUUID(string: Constants.scbtSvcUuid)
let scbtPet = CBUUID(string: Constants.scbtPetUuid)
for service in services {
// Ignore non scbtSvc
if (service.uuid != scbtSvc) { continue }
peripheral.discoverCharacteristics([scbtPet], for: service)
}
}
// Characteristic callback
func peripheral(
_ perihperal: CBPeripheral,
didDiscoverCharacteristicsFor service: CBService,
error: Error?
) {
if (error != nil) {
status = "\(error!)"
return
}
guard let characteristics = service.characteristics else { return }
status = "Characteristics found (\(characteristics.count))"
let scbtPet = CBUUID(string: Constants.scbtPetUuid)
for characteristic in characteristics {
// Ignore non pet
if (characteristic.uuid != scbtPet) { continue }
var value: UInt32 = 0
let data = Data(bytes: &value, count: MemoryLayout<UInt32>.size)
perihperal.writeValue(data, for: characteristic, type: .withResponse)
status = "Written \(data)"
}
}
// Characteristic write callback
func peripheral(
_ perihperal: CBPeripheral,
didWriteValueFor characteristic: CBCharacteristic,
error: (any Error)?
) {
if (error == nil) {
status = "Write success"
}
else {
status = "Write failed: \(error!)"
}
}
}