diff --git a/.sourcekit-lsp/config.json b/.sourcekit-lsp/config.json
index e7c9738..1e535c7 100644
--- a/.sourcekit-lsp/config.json
+++ b/.sourcekit-lsp/config.json
@@ -1,5 +1,5 @@
{
"swiftPM": {
- "swiftSDK": "arm64-apple-ios"
+ "swiftSDK": "darwin"
}
}
diff --git a/Info_extra_tags.plist b/Info_extra_tags.plist
index 08b6cf1..788546d 100644
--- a/Info_extra_tags.plist
+++ b/Info_extra_tags.plist
@@ -6,5 +6,7 @@
This app uses Bluetooth to connect to the collar tag.
NSBluetoothPeripheralUsageDescription
This app uses Bluetooth to connect to the collar tag.
+ UIBackgroundModes
+ bluetooth-central
diff --git a/Package.swift b/Package.swift
index afd682b..6b0d4b1 100644
--- a/Package.swift
+++ b/Package.swift
@@ -6,7 +6,6 @@ let package = Package(
name: "ScoobyTag",
platforms: [
.iOS(.v15),
- .macOS(.v14),
],
products: [
// An xtool project should contain exactly one library product,
diff --git a/Sources/scoobytag/BluetoothManager.swift b/Sources/scoobytag/BluetoothManager.swift
index 9573e4e..3a8d71a 100644
--- a/Sources/scoobytag/BluetoothManager.swift
+++ b/Sources/scoobytag/BluetoothManager.swift
@@ -8,12 +8,39 @@ struct Constants {
final class BluetoothManager: NSObject, ObservableObject {
private var centralManager: CBCentralManager!
- private var myPeripheral: CBPeripheral?
+ private var tagPerihp: CBPeripheral?
+ private var scbtSvc: CBService?
+ private var petChar: CBCharacteristic?
@Published var status = "Starting..."
override init() {
super.init()
- periphManager = CBPeripheralManager(delegate: self, queue: nil)
+ 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)
}
}
@@ -40,13 +67,9 @@ extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
advertisementData: [String: Any],
rssi RSSI: NSNumber
) {
- if (peripheral.name != nil) {
- status = "Found: \(peripheral.name!)"
- } else {
- status = "Found: \(peripheral.identifier)"
- }
-
- myPeripheral = peripheral
+ let name = peripheral.name ?? peripheral.identifier.uuidString
+ status = "Found \(name)"
+ tagPerihp = peripheral
central.stopScan()
central.connect(peripheral)
}
@@ -56,7 +79,8 @@ extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
_ central: CBCentralManager,
didConnect peripheral: CBPeripheral
) {
- status = "Connected"
+ let name = peripheral.name ?? peripheral.identifier.uuidString
+ status = "Connected to \(name)"
let uuid = CBUUID(string: Constants.scbtSvcUuid)
peripheral.discoverServices([uuid])
peripheral.delegate = self
@@ -72,6 +96,9 @@ extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
if (error == nil) { error2 = "unknown" }
else { error2 = "\(error!)" }
status = "Failed: \(error2)"
+
+ tagPerihp = nil
+ petChar = nil
}
// Disconnection callback
@@ -84,6 +111,9 @@ extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
if (error == nil) { error2 = "unknown" }
else { error2 = "\(error!)" }
status = "Disconnected: \(error2)"
+
+ tagPerihp = nil
+ petChar = nil
}
// Service callback
@@ -93,16 +123,18 @@ extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
) {
guard let services = peripheral.services else { return }
- status = "Service found"
-
- let scbtSvc = CBUUID(string: Constants.scbtSvcUuid)
- let scbtPet = CBUUID(string: Constants.scbtPetUuid)
+ let svcUUID = CBUUID(string: Constants.scbtSvcUuid)
+ let petUUID = CBUUID(string: Constants.scbtPetUuid)
for service in services {
- // Ignore non scbtSvc
- if (service.uuid != scbtSvc) { continue }
+ if (service.uuid == svcUUID) {
+ scbtSvc = service
+ peripheral.discoverCharacteristics([petUUID], for: service)
+ }
+ }
- peripheral.discoverCharacteristics([scbtPet], for: service)
+ if scbtSvc == nil {
+ status = "Could not find scbt service"
}
}
@@ -118,20 +150,17 @@ extension BluetoothManager: CBCentralManagerDelegate, CBPeripheralDelegate {
}
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 }
+ for characteristic: CBCharacteristic in characteristics {
+ if (characteristic.uuid == scbtPet) {
+ petChar = characteristic
+ status = "Found pet characteristic"
+ }
+ }
- var value: UInt32 = 0
- let data = Data(bytes: &value, count: MemoryLayout.size)
-
- perihperal.writeValue(data, for: characteristic, type: .withResponse)
- status = "Written \(data)"
+ if petChar == nil {
+ status = "Could not find pet characteristic"
}
}
diff --git a/Sources/scoobytag/ContentView.swift b/Sources/scoobytag/ContentView.swift
index dffd709..72fb0b0 100644
--- a/Sources/scoobytag/ContentView.swift
+++ b/Sources/scoobytag/ContentView.swift
@@ -5,12 +5,15 @@ struct ContentView: View {
var body: some View {
VStack {
- Image(systemName: "globe")
- .imageScale(.large)
- .foregroundStyle(.tint)
- Text("Hello, world!")
Text(bluetoothManager.status)
+ Button(action: bluetoothManager.led_on) {
+ Text("LED On")
+ }
+ Button(action: bluetoothManager.led_off) {
+ Text("LED Off")
+ }
}
.padding()
+ .buttonStyle(BorderedButtonStyle())
}
}