Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,35 @@ func scanAndConnect() async throws {
}
```

### Retrieving System-Connected Peripherals

Connect to peripherals that are already connected to the system by other apps or system services:

```swift
@MainActor
func retrieveConnectedPeripherals() async throws {
let central = BluetoothCentral()

// Retrieve peripherals already connected to Heart Rate service
let connectedPeripherals = try await central.retrieveConnectedPeripherals(
withServices: ["180D"], // Heart Rate service UUID
timeout: 10.0
)

// Process all successfully connected peripherals
for peripheral in connectedPeripherals {
print("Connected to system peripheral: \(peripheral.name ?? "Unknown")")

// Work with the peripheral normally
let services = try await peripheral.discoverServices(timeout: 5.0)
print("Discovered \(services.count) services")
}

// Note: This method uses best-effort approach - if one peripheral fails to connect,
// it will log the error and continue with the remaining peripherals
}
```

### Service and Characteristic Discovery

Complete discovery with flexible options:
Expand Down
61 changes: 61 additions & 0 deletions Sources/ActorCoreBluetooth/BluetoothCentral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,67 @@ public final class BluetoothCentral {
try await disconnect(peripheral.identifier, timeout: timeout)
}

/// Retrieve and connect to peripherals that are already connected at the system level
/// This is useful for peripherals connected by other apps or the system
public func retrieveConnectedPeripherals(
withServices services: [String],
timeout: TimeInterval? = nil
) async throws -> [ConnectedPeripheral] {
try await ensureCentralManagerInitialized()

guard let cbCentralManager = cbCentralManager else {
logger?.errorError("Cannot retrieve connected peripherals: CBCentralManager not initialized")
throw BluetoothError.centralManagerNotInitialized
}

let cbServices = services.compactMap { CBUUID(string: $0) }
let serviceInfo = services.joined(separator: ", ")

logger?.centralInfo("Retrieving system-connected peripherals", context: [
"services": serviceInfo,
"timeout": timeout as Any
])

let cbPeripherals = cbCentralManager.retrieveConnectedPeripherals(withServices: cbServices)

logger?.centralDebug("Found system-connected peripherals", context: [
"count": cbPeripherals.count,
"peripherals": cbPeripherals.map { $0.name ?? $0.identifier.uuidString }.joined(separator: ", ")
])

guard !cbPeripherals.isEmpty else {
logger?.centralInfo("No system-connected peripherals found for specified services")
return []
}

var connectedPeripherals: [ConnectedPeripheral] = []

for cbPeripheral in cbPeripherals {
do {
let connected = try await connectToRetrievedPeripheral(
cbPeripheral,
originalName: cbPeripheral.name,
timeout: timeout
)
connectedPeripherals.append(connected)
} catch {
logger?.connectionWarning("Failed to connect to system-connected peripheral", context: [
"peripheralName": cbPeripheral.name ?? "Unknown",
"peripheralID": cbPeripheral.identifier.uuidString,
"error": error.localizedDescription
])
// Continue with other peripherals rather than failing entirely
}
}

logger?.centralNotice("Retrieved connected peripherals", context: [
"requested": cbPeripherals.count,
"successful": connectedPeripherals.count
])

return connectedPeripherals
}

/// Get list of currently connected peripheral IDs
public var connectedPeripheralIDs: [UUID] {
let ids = Array(connectedPeripherals.keys)
Expand Down