Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save blainerothrock/a10b8796d613e770755d17fe8fc248b7 to your computer and use it in GitHub Desktop.
Save blainerothrock/a10b8796d613e770755d17fe8fc248b7 to your computer and use it in GitHub Desktop.
import Foundation
import CoreBluetooth
/*
This Swift script scans for Bluetooth devices and prints information about the active Bluetooth adapter.
It uses the CoreBluetooth framework to manage Bluetooth operations and the system_profiler command to fetch adapter details.
To compile & run:
```bash
swiftc -framework CoreBluetooth main.swift -o BLEScanner
./BLEScanner
```
Tested with Swift Version 6.1.2 (swiftlang-6.1.2.1.2 clang-1700.0.13.5) & macOS 15.5 (24F74) on Apple M2 Pro
Example output (third party Bluetooth device):
```txt
./BLEScanner
📡 Fetching active Bluetooth adapter info...
Bluetooth:
Bluetooth Controller:
Address: 00:25:BF:71:62:24
State: On
Chipset: THIRD_PARTY_DONGLE
Discoverable: Off
Firmware Version: v13083 c13083
Product ID: 0x4A11
Supported services: 0x392039 < HFP AVRCP A2DP HID Braille LEA AACP GATT SerialPort >
Transport: PCIe
Vendor ID: 0x004C (Apple)
Bluetooth is powered on. Starting scan.
```
example output (Apple Bluetooth device):
```txt
./BLEScanner
📡 Fetching active Bluetooth adapter info...
Bluetooth:
Bluetooth Controller:
Address: 5C:E9:1E:99:EB:EF
State: On
Chipset: BCM_4388
Discoverable: Off
Firmware Version: 22.5.542.2777
Product ID: 0x4A11
Supported services: 0x392039 < HFP AVRCP A2DP HID Braille LEA AACP GATT SerialPort >
Transport: PCIe
Vendor ID: 0x004C (Apple)
Not Connected:
8BitDo Lite gamepad:
Address: E4:17:D8:CF:9B:15
Vendor ID: 0x045E
Product ID: 0x02E0
Firmware Version: 9.0.3
Minor Type: Gamepad
MX Anywhere 3S:
Address: D8:74:CD:2F:11:40
Minor Type: Mouse
MX Anywhere 3S:
Address: D6:2F:DE:72:0F:12
Minor Type: Mouse
MX Keys Mini:
Address: D1:5A:18:16:6B:FB
Minor Type: Keyboard
MX KEYS S MAC:
Address: DF:CC:F5:0A:90:3A
Minor Type: Keyboard
Pro Controller:
Address: E4:17:D8:78:0C:62
Vendor ID: 0x057E
Product ID: 0x2009
Firmware Version: 0.0.1
Minor Type: Gamepad
Bluetooth is powered on. Starting scan.
Discovered: IOTWF790 - RSSI: -82
Discovered: Unknown - RSSI: -72
Discovered: M720 Triathlon - RSSI: -47
Discovered: M720 Triathlon - RSSI: -47
Discovered: Unknown - RSSI: -69
Discovered: Unknown - RSSI: -71
Discovered: Unknown - RSSI: -71
Discovered: Unknown - RSSI: -65
Discovered: Alex's Whoop - RSSI: -87
Discovered: wee-adv - RSSI: -46
Discovered: wee-adv - RSSI: -46
````
*/
func printAdapterInfo() {
print("📡 Fetching active Bluetooth adapter info...\n")
let task = Process()
task.executableURL = URL(fileURLWithPath: "/usr/sbin/system_profiler")
task.arguments = ["SPBluetoothDataType"]
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
do {
try task.run()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
if let output = String(data: data, encoding: .utf8) {
print(output)
}
} catch {
print("Failed to fetch adapter info: \(error)")
}
}
class Scanner: NSObject, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("Bluetooth is powered on. Starting scan.")
centralManager.scanForPeripherals(withServices: nil, options: nil)
} else {
print("Bluetooth not available: \(central.state.rawValue)")
}
}
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi RSSI: NSNumber) {
print("Discovered: \(peripheral.name ?? "Unknown") - RSSI: \(RSSI)")
}
}
// Keep the program alive
printAdapterInfo()
let scanner = Scanner()
RunLoop.main.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment