import Foundation import CoreBluetooth let SERVICE_UUID: CBUUID = CBUUID(string: "76a3a3fa-b8d3-451a-9c78-bf5d7434d3cc") let CHARACTERISTIC_UUID: CBUUID = CBUUID(string: "bffe9d64-0ee6-472b-849c-ab98182bd592") final class ContentViewModel: NSObject, ObservableObject { @Published var centralManager: CBCentralManager? @Published var discoveredPeripherals = [CBPeripheral]() @Published var connectedPeripheral: CBPeripheral? @Published var isStateActive = false @Published var isConnected = false private var characteristic: CBCharacteristic? private var messagesTimer: Timer? override init() { super.init() centralManager = CBCentralManager(delegate: self, queue: nil) } func connectToPeripheral(_ peripheral: CBPeripheral) { if centralManager?.isScanning == true { centralManager?.stopScan() } centralManager?.connect(peripheral, options: nil) } private func startWritingMessages() { messagesTimerFired() messagesTimer = Timer.scheduledTimer(timeInterval: 15, target: self, selector: #selector(messagesTimerFired), userInfo: nil, repeats: true) } @objc private func messagesTimerFired() { guard let peripheral = connectedPeripheral, let data = "Sample Data".data(using: .utf8), let characteristic = characteristic else { print("Error sending message") return } print("write message...") peripheral.writeValue(data, for: characteristic, type: .withResponse) } } extension ContentViewModel: CBCentralManagerDelegate { func centralManagerDidUpdateState(_ central: CBCentralManager) { switch central.state { case .poweredOn: isStateActive = true centralManager?.scanForPeripherals(withServices: [SERVICE_UUID], options: nil) default: isStateActive = false } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if !self.discoveredPeripherals.contains(peripheral) { self.discoveredPeripherals.append(peripheral) } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { isConnected = true connectedPeripheral = peripheral connectedPeripheral?.delegate = self connectedPeripheral?.discoverServices([SERVICE_UUID]) } func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: (any Error)?) { print("Failed to connect: \(error?.localizedDescription ?? "Unknown error")") isConnected = false } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: (any Error)?) { // MARK: HERE I GET THE ERROR print("Disconnected: \(error?.localizedDescription ?? "Unknown error")") isConnected = false } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, timestamp: CFAbsoluteTime, isReconnecting: Bool, error: (any Error)?) { print("Disconnected: \(error?.localizedDescription ?? "Unknown error")") isConnected = false } } extension ContentViewModel: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: (any Error)?) { if let error = error { print("Error discovering services: \(error.localizedDescription)") return } guard let services = peripheral.services else { print("Error services nil") return } for service in services { peripheral.discoverCharacteristics([CHARACTERISTIC_UUID], for: service) } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: (any Error)?) { if let error = error { print("Error discovering characteristic: \(error.localizedDescription)") return } guard let characteristics = service.characteristics else { print("Error characteristics nil") return } characteristic = characteristics.first { $0.uuid == CHARACTERISTIC_UUID } if characteristic == nil { print("Error characteristic not found") return } startWritingMessages() } }