import SwiftUI
import CoreBluetooth
import os
class BluetoothViewModel: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
@Published var peripherals: [CBPeripheral] = [] // List of discovered peripherals
@Published var connectedPeripheral: CBPeripheral? // The selected peripheral that is connected
@Published var discoveredServices: [CBService] = [] // List of discovered services
@Published var discoveredServiceNames: [String] = [] // List of names of discovered services
@Published var peripheralNames: [String] = [] // List of peripheral names found during scanning
@Published var filteredPeripheralNames: [String] = [] // List of filtered peripheral names
var cbManager: CBCentralManager?
private var peripheralNameReceived = false // Flag to track when the name is received
override init() {
super.init()
self.cbManager = CBCentralManager(delegate: self, queue: .main)
}
// Start scanning for peripherals (without connecting to them)
func startScanning() {
os_log("Start scanning for all peripherals.")
let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: NSNumber(value: false)]
cbManager?.scanForPeripherals(withServices: nil, options: options) // Scan for all peripherals
}
// Stop scanning for peripherals
func stopScanning() {
os_log("Stop scanning.")
cbManager?.stopScan()
}
// MARK: - CBCentralManagerDelegate Methods
// Called when the central manager's state changes
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
os_log("Bluetooth is powered on.")
case .poweredOff:
os_log("Bluetooth is powered off.")
case .unauthorized:
os_log("Bluetooth unauthorized.")
case .unknown:
os_log("Bluetooth state is unknown.")
case .resetting:
os_log("Bluetooth is resetting.")
case .unsupported:
os_log("Bluetooth is unsupported.")
@unknown default:
os_log("Unknown Bluetooth state.")
}
}
// Called when a peripheral is discovered (but no connection is made)
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi: NSNumber) {
os_log("Discovered peripheral: %@", peripheral.name ?? "Unknown")
// Filter out peripherals by name if found in the filtered list
if let name = peripheral.name {
if !isPeripheralNameFiltered(name) {
// Add name to the list if it is not filtered out
peripheralNames.append(name)
os_log("Peripheral name added: %@", name)
} else {
os_log("Peripheral name %@ is filtered out", name)
}
}
// Add peripheral to the list if it's not already there
if !peripherals.contains(peripheral) {
peripherals.append(peripheral)
}
}
// Function to check if a peripheral name is in the filtered list
func isPeripheralNameFiltered(_ name: String) -> Bool {
return filteredPeripheralNames.contains(name)
}
// Function to filter out a specific peripheral by name
func filterOutPeripheralName(_ name: String) {
if !filteredPeripheralNames.contains(name) {
filteredPeripheralNames.append(name)
os_log("Peripheral name %@ added to filtered list", name)
}
}
// Called when a peripheral is connected
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
os_log("Connected to peripheral: %@", peripheral.name ?? "Unknown")
// Set the peripheral delegate to discover its services
peripheral.delegate = self
connectedPeripheral = peripheral
// Discover all services on the connected peripheral
peripheral.discoverServices(nil) // Pass nil to discover all services
}
// Called when a peripheral connection fails
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
os_log("Failed to connect to peripheral: %@", peripheral.name ?? "Unknown")
}
// Called when a peripheral is disconnected
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
os_log("Disconnected from peripheral: %@", peripheral.name ?? "Unknown")
connectedPeripheral = nil
discoveredServices.removeAll()
discoveredServiceNames.removeAll()
peripheralNames.removeAll()
filteredPeripheralNames.removeAll()
}
// MARK: - CBPeripheralDelegate Methods
// Called when the peripheral discovers its services
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let error = error {
os_log("Failed to discover services: %@", error.localizedDescription)
return
}
os_log("Discovered services for peripheral: %@", peripheral.name ?? "Unknown")
// Define the UUIDs for Device Information and Battery Service
let deviceInformationServiceUUID = CBUUID(string: "180A") // Device Information
let batteryServiceUUID = CBUUID(string: "180F") // Battery Service
// Loop through discovered services and fetch their names
for service in peripheral.services ?? [] {
discoveredServices.append(service)
discoveredServiceNames.append(service.uuid.uuidString)
os_log("Service found: %@", service.uuid.uuidString)
// Check if the service is Device Information or Battery Service
if service.uuid == deviceInformationServiceUUID {
os_log("Device Information Service found")
} else if service.uuid == batteryServiceUUID {
os_log("Battery Service found")
} else {
os_log("Other service found: %@", service.uuid.uuidString)
}
// If device information service is found, discover characteristics
if service.uuid == deviceInformationServiceUUID {
peripheral.discoverCharacteristics([CBUUID(string: "2A00")], for: service) // Device Name characteristic
}
}
}
// Called when a peripheral discovers characteristics for a given service
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let error = error {
os_log("Failed to discover characteristics for service: %@", error.localizedDescription)
return
}
os_log("Discovered characteristics for service: %@", service.uuid.uuidString)
// If the Device Information Service is found, read the device name characteristic (2A00)
for characteristic in service.characteristics ?? [] {
if characteristic.uuid == CBUUID(string: "2A00") { // Device Name characteristic
peripheral.readValue(for: characteristic)
}
}
}
// Called when a characteristic's value is updated
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
os_log("Failed to read characteristic value: %@", error.localizedDescription)
return
}
if characteristic.uuid == CBUUID(string: "2A00") { // Device Name characteristic
if let nameData = characteristic.value, let deviceName = String(data: nameData, encoding: .utf8) {
os_log("Device Name from Device Info Service: %@", deviceName)
peripheralNames.append(deviceName) // Add device name to list
peripheralNameReceived = true // Mark the name as received
}
}
}
// Handle Manufacturer Data (custom name or metadata) if present
func peripheral(_ peripheral: CBPeripheral, didReadValueFor characteristic: CBCharacteristic, error: Error?) {
if let manufacturerData = characteristic.value, characteristic.uuid == CBUUID(string: "2A29") {
os_log("Manufacturer Data: %@", convertDataToHexString(manufacturerData))
}
}
// Helper function to convert Data to a hexadecimal string for logging
private func convertDataToHexString(_ data: Data) -> String {
return data.map { String(format: "%02hhx", $0) }.joined()
}
// A method to check if the name was received before moving on
func waitForName() {
while !peripheralNameReceived {
// Implement a small delay or check, or you can return here and handle other logic asynchronously
usleep(100000) // Sleep for 0.1 seconds for example
}
}
}
результаты,
Неизвестное отображается в настройках iOS с именем его устройства.
Обнаружено периферийное устройство: [TV] Cia tv
Добавлено имя периферийного устройства: [TV] Cia tv
Обнаружено периферийное устройство: Неизвестно
Обнаружено периферийное устройство: Неизвестно
Обнаружено периферийное устройство : [TV] Cia tv
Добавлено имя периферийного устройства: [TV] Cia tv
[code]import SwiftUI import CoreBluetooth import os
class BluetoothViewModel: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { @Published var peripherals: [CBPeripheral] = [] // List of discovered peripherals @Published var connectedPeripheral: CBPeripheral? // The selected peripheral that is connected @Published var discoveredServices: [CBService] = [] // List of discovered services @Published var discoveredServiceNames: [String] = [] // List of names of discovered services @Published var peripheralNames: [String] = [] // List of peripheral names found during scanning @Published var filteredPeripheralNames: [String] = [] // List of filtered peripheral names
var cbManager: CBCentralManager? private var peripheralNameReceived = false // Flag to track when the name is received
// Start scanning for peripherals (without connecting to them) func startScanning() { os_log("Start scanning for all peripherals.") let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: NSNumber(value: false)] cbManager?.scanForPeripherals(withServices: nil, options: options) // Scan for all peripherals }
// Called when the central manager's state changes func centralManagerDidUpdateState(_ central: CBCentralManager) { switch central.state { case .poweredOn: os_log("Bluetooth is powered on.") case .poweredOff: os_log("Bluetooth is powered off.") case .unauthorized: os_log("Bluetooth unauthorized.") case .unknown: os_log("Bluetooth state is unknown.") case .resetting: os_log("Bluetooth is resetting.") case .unsupported: os_log("Bluetooth is unsupported.") @unknown default: os_log("Unknown Bluetooth state.") } }
// Called when a peripheral is discovered (but no connection is made) func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi: NSNumber) { os_log("Discovered peripheral: %@", peripheral.name ?? "Unknown")
// Filter out peripherals by name if found in the filtered list if let name = peripheral.name { if !isPeripheralNameFiltered(name) { // Add name to the list if it is not filtered out peripheralNames.append(name) os_log("Peripheral name added: %@", name) } else { os_log("Peripheral name %@ is filtered out", name) } }
// Add peripheral to the list if it's not already there if !peripherals.contains(peripheral) { peripherals.append(peripheral) } }
// Function to check if a peripheral name is in the filtered list func isPeripheralNameFiltered(_ name: String) -> Bool { return filteredPeripheralNames.contains(name) }
// Function to filter out a specific peripheral by name func filterOutPeripheralName(_ name: String) { if !filteredPeripheralNames.contains(name) { filteredPeripheralNames.append(name) os_log("Peripheral name %@ added to filtered list", name) } }
// Called when a peripheral is connected func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { os_log("Connected to peripheral: %@", peripheral.name ?? "Unknown")
// Set the peripheral delegate to discover its services peripheral.delegate = self connectedPeripheral = peripheral
// Discover all services on the connected peripheral peripheral.discoverServices(nil) // Pass nil to discover all services }
// Called when a peripheral connection fails func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { os_log("Failed to connect to peripheral: %@", peripheral.name ?? "Unknown") }
// Called when a peripheral is disconnected func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { os_log("Disconnected from peripheral: %@", peripheral.name ?? "Unknown") connectedPeripheral = nil discoveredServices.removeAll() discoveredServiceNames.removeAll() peripheralNames.removeAll() filteredPeripheralNames.removeAll() }
// MARK: - CBPeripheralDelegate Methods
// Called when the peripheral discovers its services func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { if let error = error { os_log("Failed to discover services: %@", error.localizedDescription) return }
os_log("Discovered services for peripheral: %@", peripheral.name ?? "Unknown")
// Define the UUIDs for Device Information and Battery Service let deviceInformationServiceUUID = CBUUID(string: "180A") // Device Information let batteryServiceUUID = CBUUID(string: "180F") // Battery Service
// Loop through discovered services and fetch their names for service in peripheral.services ?? [] { discoveredServices.append(service) discoveredServiceNames.append(service.uuid.uuidString) os_log("Service found: %@", service.uuid.uuidString)
// Check if the service is Device Information or Battery Service if service.uuid == deviceInformationServiceUUID { os_log("Device Information Service found") } else if service.uuid == batteryServiceUUID { os_log("Battery Service found") } else { os_log("Other service found: %@", service.uuid.uuidString) }
// If device information service is found, discover characteristics if service.uuid == deviceInformationServiceUUID { peripheral.discoverCharacteristics([CBUUID(string: "2A00")], for: service) // Device Name characteristic } } }
// Called when a peripheral discovers characteristics for a given service func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let error = error { os_log("Failed to discover characteristics for service: %@", error.localizedDescription) return }
os_log("Discovered characteristics for service: %@", service.uuid.uuidString)
// If the Device Information Service is found, read the device name characteristic (2A00) for characteristic in service.characteristics ?? [] { if characteristic.uuid == CBUUID(string: "2A00") { // Device Name characteristic peripheral.readValue(for: characteristic) } } }
// Called when a characteristic's value is updated func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { os_log("Failed to read characteristic value: %@", error.localizedDescription) return }
if characteristic.uuid == CBUUID(string: "2A00") { // Device Name characteristic if let nameData = characteristic.value, let deviceName = String(data: nameData, encoding: .utf8) { os_log("Device Name from Device Info Service: %@", deviceName) peripheralNames.append(deviceName) // Add device name to list peripheralNameReceived = true // Mark the name as received } } }
// Handle Manufacturer Data (custom name or metadata) if present func peripheral(_ peripheral: CBPeripheral, didReadValueFor characteristic: CBCharacteristic, error: Error?) { if let manufacturerData = characteristic.value, characteristic.uuid == CBUUID(string: "2A29") { os_log("Manufacturer Data: %@", convertDataToHexString(manufacturerData)) } }
// Helper function to convert Data to a hexadecimal string for logging private func convertDataToHexString(_ data: Data) -> String { return data.map { String(format: "%02hhx", $0) }.joined() }
// A method to check if the name was received before moving on func waitForName() { while !peripheralNameReceived { // Implement a small delay or check, or you can return here and handle other logic asynchronously usleep(100000) // Sleep for 0.1 seconds for example } } } [/code] результаты, Неизвестное отображается в настройках iOS с именем его устройства. Обнаружено периферийное устройство: [TV] Cia tv Добавлено имя периферийного устройства: [TV] Cia tv
Обнаружено периферийное устройство: Неизвестно
Обнаружено периферийное устройство: Неизвестно
Обнаружено периферийное устройство : [TV] Cia tv
Добавлено имя периферийного устройства: [TV] Cia tv
class BluetoothViewModel: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
@Published var peripherals: = [] // List of discovered peripherals
@Published var...
Как я могу получить новое имя связанного устройства, которое было изменено в настройках Bluetooth? Можно ли отслеживать это изменение? val adapter = context.getSystemService()?.adapter
adapter.bondedDevices.forEach {it.name} - Имя не меняется (и...
Я строю кроссплатформенное приложение для диагностики автомобилей, используя Flutter (с возможным собственным кодом в Swift/Kotlin), и мне нужно устройство Bluetooth OBD-II, которое поддерживает BLE, работает как на Android, так и на iOS, и...
Мое приложение предлагает пользователю возможность импортировать контакты. Когда вы пытаетесь получить доступ к контактам, Apple показывает свой диалог конфиденциальности. Затем, если пользователь выбирает разрешить доступ к доступу и, в свою...
Я использую MAUI .NET. Я хочу сохранить все устройства Bluetooth в диапазоне устройства, на котором выполняется код, в коллекцию. Вот пример кода, вызываемый после нажатия кнопки.
private async void OnButtonBluetoothClicked(object sender, EventArgs...