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.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!)" } } }