Files
Companion/Sources/scoobytag/BluetoothManager.swift

181 lines
4.9 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 tagPerihp: CBPeripheral?
private var scbtSvc: CBService?
private var petChar: CBCharacteristic?
@Published var status = "Starting..."
override init() {
super.init()
centralManager = CBCentralManager(
delegate: self,
queue: nil,
//options: [
// CBCentralManagerOptionRestoreIdentifierKey: "DogCollarCentral"
//]
)
}
func led_on() {
pet_write(0)
}
func led_off() {
pet_write(1)
}
func pet_write(_ value: UInt32) {
if tagPerihp == nil || petChar == nil {
status = "Not connected!"
return
}
var lvalue = value
let data = Data(bytes: &lvalue, count: MemoryLayout<UInt32>.size)
tagPerihp!.writeValue(data, for: petChar!, type: .withResponse)
}
}
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
) {
let name = peripheral.name ?? peripheral.identifier.uuidString
status = "Found \(name)"
tagPerihp = peripheral
central.stopScan()
central.connect(peripheral)
}
// Connection callback
func centralManager(
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
let name = peripheral.name ?? peripheral.identifier.uuidString
status = "Connected to \(name)"
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)"
tagPerihp = nil
petChar = nil
}
// 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)"
tagPerihp = nil
petChar = nil
}
// Service callback
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverServices error: Error?
) {
guard let services = peripheral.services else { return }
let svcUUID = CBUUID(string: Constants.scbtSvcUuid)
let petUUID = CBUUID(string: Constants.scbtPetUuid)
for service in services {
if (service.uuid == svcUUID) {
scbtSvc = service
peripheral.discoverCharacteristics([petUUID], for: service)
}
}
if scbtSvc == nil {
status = "Could not find scbt 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 }
let scbtPet = CBUUID(string: Constants.scbtPetUuid)
for characteristic: CBCharacteristic in characteristics {
if (characteristic.uuid == scbtPet) {
petChar = characteristic
status = "Found pet characteristic"
}
}
if petChar == nil {
status = "Could not find pet characteristic"
}
}
// Characteristic write callback
func peripheral(
_ perihperal: CBPeripheral,
didWriteValueFor characteristic: CBCharacteristic,
error: (any Error)?
) {
if (error == nil) {
status = "Write success"
}
else {
status = "Write failed: \(error!)"
}
}
}