181 lines
4.9 KiB
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!)"
|
|
}
|
|
}
|
|
}
|