116 lines
4.1 KiB
Swift
116 lines
4.1 KiB
Swift
//
|
|
// BluetoothManager.swift
|
|
// mcrl-app
|
|
//
|
|
// Created by Simon Oberzier on 17.02.26.
|
|
//
|
|
|
|
import CoreBluetooth
|
|
import Combine
|
|
|
|
class BluetoothManager: NSObject, ObservableObject {
|
|
@Published var sensorValues = SensorData()
|
|
@Published var connectionStatus = "Disconnected"
|
|
|
|
var centralManager: CBCentralManager!
|
|
var picoPeripheral: CBPeripheral?
|
|
|
|
let serviceUUID = CBUUID(string: "0000FF00-0000-1000-8000-00805F9B34FB")
|
|
let charUUID = CBUUID(string: "0000FF01-0000-1000-8000-00805F9B34FB")
|
|
|
|
override init() {
|
|
super.init()
|
|
centralManager = CBCentralManager(delegate: self, queue: nil)
|
|
}
|
|
|
|
func parseSensorString(_ str: String) {
|
|
let cleanStr = str.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let components = cleanStr.components(separatedBy: ",")
|
|
|
|
guard components.count >= 7, components[0] == "S" else {
|
|
print("Received malformed string: \(cleanStr)")
|
|
return
|
|
}
|
|
|
|
DispatchQueue.main.async {
|
|
self.sensorValues.ax = Double(components[1]) ?? 0
|
|
self.sensorValues.ay = Double(components[2]) ?? 0
|
|
self.sensorValues.az = Double(components[3]) ?? 0
|
|
self.sensorValues.lat = Double(components[4]) ?? 0
|
|
self.sensorValues.lon = Double(components[5]) ?? 0
|
|
self.sensorValues.hasFix = components[6].contains("1")
|
|
}
|
|
}
|
|
}
|
|
|
|
extension BluetoothManager: CBCentralManagerDelegate {
|
|
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
|
switch central.state {
|
|
case .poweredOn:
|
|
connectionStatus = "Scanning..."
|
|
// Scanning with nil finds EVERYTHING. Safer for debugging.
|
|
centralManager.scanForPeripherals(withServices: nil, options: nil)
|
|
case .poweredOff:
|
|
connectionStatus = "Bluetooth is Off"
|
|
case .unauthorized:
|
|
connectionStatus = "Permission Denied"
|
|
default:
|
|
connectionStatus = "Unknown State"
|
|
}
|
|
}
|
|
|
|
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
|
let name = peripheral.name ?? "Unknown"
|
|
|
|
if name.contains("Pico") {
|
|
print("Discovered: \(name)")
|
|
connectionStatus = "Pico Found!"
|
|
|
|
picoPeripheral = peripheral
|
|
picoPeripheral?.delegate = self
|
|
|
|
centralManager.stopScan()
|
|
centralManager.connect(peripheral, options: nil)
|
|
}
|
|
}
|
|
|
|
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
|
connectionStatus = "Connected"
|
|
print("Connected to \(peripheral.name ?? "Device")")
|
|
peripheral.discoverServices([serviceUUID])
|
|
}
|
|
|
|
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
|
|
connectionStatus = "Disconnected"
|
|
print("Disconnected. Restarting scan...")
|
|
centralManager.scanForPeripherals(withServices: nil, options: nil)
|
|
}
|
|
}
|
|
|
|
extension BluetoothManager: CBPeripheralDelegate {
|
|
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
|
|
guard let services = peripheral.services else { return }
|
|
for service in services {
|
|
print("Service discovered: \(service.uuid)")
|
|
peripheral.discoverCharacteristics([charUUID], for: service)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
|
guard let characteristics = service.characteristics else { return }
|
|
for characteristic in characteristics {
|
|
if characteristic.uuid == charUUID {
|
|
print("Found Data Characteristic!")
|
|
peripheral.setNotifyValue(true, for: characteristic)
|
|
}
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
|
|
if let data = characteristic.value,
|
|
let str = String(data: data, encoding: .utf8) {
|
|
parseSensorString(str)
|
|
}
|
|
}
|
|
}
|