Reputation: 2168
I have set a basic Arduino project with HM-10 BLE module for sending some data as String (actually some temperature mesurements) and I see it works if I use an iOS app like BluetoothForArduino. I want to get this data using macOs : for this I've implemented the following snippet based on AsyncBluetooth library:
func test() async throws {
let centralManager = CentralManager()
try await centralManager.waitUntilReady()
let serviceUUID = CBUUID(string: "FFE0")
let characteristicsUUID = CBUUID(string: "FFE1")
let deviceName = "HMSoft"
let scanDataStream = try await centralManager.scanForPeripherals(withServices: [serviceUUID])
if let foundDevice = await scanDataStream.first(
where: { $0.peripheral.name?.hasPrefix(deviceName) == true }
) {
await centralManager.stopScan()
let peripheral = foundDevice.peripheral
print("Found device : \(peripheral.name ?? "no name"), RSSI = \(foundDevice.rssi)")
print("Connecting...")
try await centralManager.connect(peripheral)
print("Ok")
try await peripheral.discoverServices(nil)
if let service = peripheral.discoveredServices?.first {
try await peripheral.discoverCharacteristics(nil, for: service)
service.discoveredCharacteristics?.forEach{
print($0)
}
print("Services UUIDs discovered : \(service.uuid)")
if let characteristics = service.discoveredCharacteristics?
.first(where: { $0.uuid == characteristicsUUID }) {
print("Characteristics UUIDs discovered : \(characteristics.uuid)")
try await peripheral.setNotifyValue(
true,
forCharacteristicWithCBUUID: characteristicsUUID,
ofServiceWithCBUUID : serviceUUID
)
print("Notifications enabled")
// try await peripheral.writeValue(
// "s".data(using: .ascii)!,
// for: characteristics,
// type: .withoutResponse
// )
if let data: Data = try await peripheral.readValue(
forCharacteristicWithCBUUID: characteristicsUUID,
ofServiceWithCBUUID: serviceUUID
) {
data.forEach {
print($0)
}
}
}
}
print("Disconnecting...")
try await centralManager.cancelPeripheralConnection(foundDevice.peripheral)
print("Ok")
}
}
try await test()
The issue is that I always get the same 6 bytes from the device (at the same time I get the service and it's characteristics in the right way). What am I doing wrong? Can anybody share a snippet to establish a simple echo example with Core Bluetooth?
Upvotes: 0
Views: 37
Reputation: 2168
The final solution looks as follows :
func test() async throws {
let centralManager = CentralManager()
try await centralManager.waitUntilReady()
let serviceUUID = CBUUID(string: "FFE0")
let characteristicsUUID = CBUUID(string: "FFE1")
let deviceName = "HMSoft"
var cancellables = Set<AnyCancellable>()
let scanDataStream = try await centralManager.scanForPeripherals(withServices: [serviceUUID])
if let foundDevice = await scanDataStream.first(
where: { $0.peripheral.name?.hasPrefix(deviceName) == true }
) {
await centralManager.stopScan()
let peripheral = foundDevice.peripheral
print("Found device : \(peripheral.name ?? "no name"), RSSI = \(foundDevice.rssi)")
print("Connecting...")
try await centralManager.connect(peripheral)
print("Ok")
try await peripheral.discoverServices(nil)
if let service = peripheral.discoveredServices?.first {
try await peripheral.discoverCharacteristics(nil, for: service)
service.discoveredCharacteristics?.forEach{
print($0)
}
print("Services UUIDs discovered : \(service.uuid)")
if let characteristics = service.discoveredCharacteristics?
.first(where: { $0.uuid == characteristicsUUID }) {
print("Characteristics UUIDs discovered : \(characteristics.uuid)")
try await peripheral.setNotifyValue(
true,
forCharacteristicWithCBUUID: characteristicsUUID,
ofServiceWithCBUUID : serviceUUID
)
print("Notifications enabled")
try await peripheral.writeValue(
"s".data(using: .ascii)!,
for: characteristics,
type: .withoutResponse
)
print("Value updater establishing...")
peripheral.characteristicValueUpdatedPublisher
.filter { $0.characteristic.uuid == characteristicsUUID }
.map { try? $0.parsedValue() as String? }
.sink { value in
print(value ?? "no data")
}
.store(in: &cancellables)
print("done. Waiting for packets...")
try await Task.sleep(for: .seconds(20))
cancellables.forEach { $0.cancel() }
}
}
print("Disconnecting...")
try await centralManager.cancelPeripheralConnection(foundDevice.peripheral)
print("Ok")
}
}
Upvotes: 0