Initial commit

This commit is contained in:
2026-02-20 20:50:24 +01:00
commit 3c2c562983
14 changed files with 725 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
//
// 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)
}
}
}