I have a very cheap Bluetooth-connected printer. And I want to print out a word or two via Core Bluetooth. It's an iOS app with the SwiftUI framework. The following is what I have for an ObservableObject class.
import Foundation import CoreBluetooth class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { @Published var connectedDevices: [CBPeripheral] = [] @Published var powerOn = false @Published var peripheralConnected = false private var centralManager: CBCentralManager! private var peripheralName = "LX-D02" private var connectedPeripheral: CBPeripheral? private var writeCharacteristic: CBCharacteristic? private let serviceUUID = CBUUID(string:"5833FF01-9B8B-5191-6142-22A4536EF123") private let characteristicUUID = CBUUID(string: "FFE1") override init() { super.init() self.centralManager = CBCentralManager(delegate: self, queue: nil) } func startScanning() { if centralManager.state == .poweredOn { centralManager.scanForPeripherals(withServices: nil, options: nil) } } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { powerOn = true print("Bluetooth is powered on") } else { print("Bluetooth is not available") } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if !connectedDevices.contains(peripheral) { if let localName = advertisementData["kCBAdvDataLocalName"] as? String { if localName == peripheralName { connectedDevices.append(peripheral) centralManager.connect(peripheral, options: nil) centralManager.stopScan() peripheralConnected = true print("Connected: \(peripheral.identifier.uuidString)") } } } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { connectedPeripheral = peripheral peripheral.delegate = self let services = [serviceUUID] peripheral.discoverServices(services) //discoverServices(peripheral: peripheral) } func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: (any Error)?) { guard let error = error else { print("Failed connection unobserved") return } print("Error: \(error.localizedDescription)") } func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { if let error = error { print("Failing to discover servies: \(error.localizedDescription)") return } discoverCharacteristics(peripheral: peripheral) } /* Return all available services */ private func discoverServices(peripheral: CBPeripheral) { peripheral.discoverServices(nil) } private func discoverCharacteristics(peripheral: CBPeripheral) { guard let services = peripheral.services else { return } for service in services { peripheral.discoverCharacteristics(nil, for: service) } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { return } for characteristic in characteristics { let characteristicUUID = characteristic.uuid print("Discovered characteristic: \(characteristicUUID)") peripheral.setNotifyValue(true, for: characteristic) if characteristic.properties.contains(.writeWithoutResponse) { writeCharacteristic = characteristic print("You can write!!!") // Never read... } if characteristic.properties.contains(.write) { print("You can write?") writeCharacteristic = characteristic // Being read... } } func writeToPrinter() { guard let peripheral = connectedPeripheral else { print("Ughhh...") return } if let characteristic = writeCharacteristic { if let data = "Hello".data(using: .utf8, allowLossyConversion: true) { peripheral.writeValue(data, for: characteristic, type: .withoutResponse) peripheral.writeValue(data, for: characteristic, type: .withResponse) // -> Message sent successfully } } } func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { print("Writing error: \(error.localizedDescription)") return } print("Message sent successfully") } }
My app has no trouble connecting to the bluetooth-connected printer. Initially, I called
discoverServices(peripheral:)
to get all services And I get a service identifier (5833FF01-9B8B-5191-6142-22A4536EF123) for my printer. peripheral(_:didDiscoverCharacteristicsFor:error:) doesn't return a thing for .writeWithoutResponse but does return a characteristic for .write. Eventually, if I call writeToPrinter(),
peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
returns
WARNING: Characteristic <CBCharacteristic: 0x3019040c0, UUID = 5833FF02-9B8B-5191-6142-22A4536EF123, properties = 0x8, value = (null), notifying = NO> does not specify the "Write Without Response" property - ignoring response-less write
If I call
peripheral.writeValue(data, for: characteristic, type: .withResponse)
, there is no error. But I get no output from the printer. What am I doing wrong? Thanks.