Meshtastic-Apple/MeshtasticClient/Views/Bluetooth/Connect.swift

296 lines
10 KiB
Swift
Raw Normal View History

2021-08-20 07:56:05 -07:00
//
2021-11-29 21:35:23 -08:00
// Connect.swift
2021-08-20 07:56:05 -07:00
// MeshtasticClient
//
// Created by Garth Vander Houwen on 8/18/21.
//
// Abstract:
// A view allowing you to interact with nearby meshtastic nodes
2021-08-20 07:56:05 -07:00
import SwiftUI
import MapKit
import CoreLocation
import CoreBluetooth
2021-08-20 07:56:05 -07:00
2021-09-18 17:10:22 -07:00
struct Connect: View {
2021-11-29 15:59:06 -08:00
2021-12-12 17:17:46 -08:00
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
2021-11-29 15:59:06 -08:00
2021-10-17 15:08:12 -07:00
@State var isPreferredRadio: Bool = false
2021-11-29 15:59:06 -08:00
2021-08-20 07:56:05 -07:00
var body: some View {
let firmwareVersion = bleManager.lastConnnectionVersion
2022-06-07 07:07:47 -07:00
let minimumVersion = "1.3.16"
let supportedVersion = firmwareVersion == "0.0.0" || minimumVersion.compare(firmwareVersion, options: .numeric) == .orderedAscending || minimumVersion.compare(firmwareVersion, options: .numeric) == .orderedSame
2021-10-17 15:08:12 -07:00
NavigationView {
2021-11-29 15:59:06 -08:00
2021-09-10 07:41:26 -07:00
VStack {
if bleManager.isSwitchedOn {
2021-11-29 15:59:06 -08:00
List {
if supportedVersion == false {
Section(header: Text("Upgrade your Firmware").font(.title)) {
2022-06-07 07:07:47 -07:00
Text("🚨 1.3 ALPHA PREVIEW Your firmware version is unsupported by the preview the minimum firmware version is \(minimumVersion).").font(.subheadline).foregroundColor(.red)
}
.textCase(nil)
}
if bleManager.lastConnectionError.count > 0 {
2021-11-29 15:59:06 -08:00
Section(header: Text("Connection Error").font(.title)) {
2021-11-29 15:59:06 -08:00
Text(bleManager.lastConnectionError).font(.title3).foregroundColor(.red)
}
.textCase(nil)
}
2021-11-29 15:59:06 -08:00
Section(header: Text("Connected Radio").font(.title)) {
2021-11-29 15:59:06 -08:00
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == .connected {
HStack {
2021-11-29 15:59:06 -08:00
2021-09-21 20:49:12 -07:00
Image(systemName: "antenna.radiowaves.left.and.right")
.symbolRenderingMode(.hierarchical)
.imageScale(.large).foregroundColor(.green)
.padding(.trailing)
2021-11-29 15:59:06 -08:00
VStack(alignment: .leading) {
2021-12-15 23:53:45 -08:00
if bleManager.connectedPeripheral != nil {
2021-11-29 15:59:06 -08:00
Text(bleManager.connectedPeripheral.name).font(.title2)
2021-12-25 23:48:12 -08:00
}
2022-01-11 06:43:41 -08:00
Text("BLE Name: ").font(.caption)+Text(bleManager.connectedPeripheral.peripheral.name ?? "Unknown")
2021-12-16 14:13:54 -08:00
.font(.caption).foregroundColor(Color.gray)
2021-12-15 23:53:45 -08:00
if bleManager.connectedPeripheral != nil {
2021-12-16 14:13:54 -08:00
Text("FW Version: ").font(.caption)+Text(bleManager.connectedPeripheral.firmwareVersion)
.font(.caption).foregroundColor(Color.gray)
Text("Bitrate: ").font(.caption)+Text(String(format: "%.2f", bleManager.connectedPeripheral.bitrate ?? 0.00))
.font(.caption).foregroundColor(Color.gray)
Text("Channel Utilization: ").font(.caption)+Text(String(format: "%.2f", bleManager.connectedPeripheral.channelUtilization ?? 0.00))
.font(.caption).foregroundColor(Color.gray)
Text("Air Time: ").font(.caption)+Text(String(format: "%.2f", bleManager.connectedPeripheral.airTime ?? 0.00))
.font(.caption).foregroundColor(Color.gray)
}
2021-11-17 07:34:37 -08:00
if bleManager.connectedPeripheral.subscribed {
Text("Properly Subscribed").font(.caption)
}
}
Spacer()
2021-11-29 15:59:06 -08:00
VStack(alignment: .center) {
2021-11-29 15:59:06 -08:00
Text("Preferred").font(.caption2)
Text("Radio").font(.caption2)
Toggle("Preferred Radio", isOn: $isPreferredRadio)
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
.labelsHidden()
.onChange(of: isPreferredRadio) { value in
if value {
2021-11-29 15:59:06 -08:00
2021-12-15 23:53:45 -08:00
if bleManager.connectedPeripheral != nil {
2021-12-25 23:48:12 -08:00
2021-12-15 23:53:45 -08:00
let deviceName = (bleManager.connectedPeripheral.peripheral.name ?? "")
userSettings.preferredPeripheralName = deviceName
2021-12-25 23:48:12 -08:00
2021-10-17 15:08:12 -07:00
} else {
2021-12-25 23:48:12 -08:00
userSettings.preferredPeripheralName = bleManager.connectedPeripheral.longName
2021-10-17 15:08:12 -07:00
}
2021-11-29 15:59:06 -08:00
userSettings.preferredPeripheralId = bleManager.connectedPeripheral!.peripheral.identifier.uuidString
} else {
2021-11-29 15:59:06 -08:00
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.identifier.uuidString == userSettings.preferredPeripheralId {
2021-11-29 15:59:06 -08:00
userSettings.preferredPeripheralId = ""
userSettings.preferredPeripheralName = ""
2021-10-17 15:08:12 -07:00
}
}
}
}
}
2021-10-17 15:08:12 -07:00
.swipeActions {
2021-11-29 15:59:06 -08:00
2021-10-17 15:08:12 -07:00
Button(role: .destructive) {
2021-11-29 15:59:06 -08:00
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected {
2021-11-21 13:48:28 -08:00
bleManager.disconnectPeripheral()
isPreferredRadio = false
2021-10-17 15:08:12 -07:00
}
} label: {
Label("Disconnect", systemImage: "antenna.radiowaves.left.and.right.slash")
2021-10-17 15:08:12 -07:00
}
}
.padding([.top, .bottom])
2021-11-29 15:59:06 -08:00
} else {
HStack {
2021-09-21 20:49:12 -07:00
Image(systemName: "antenna.radiowaves.left.and.right.slash")
.symbolRenderingMode(.hierarchical)
.imageScale(.large).foregroundColor(.red)
.padding(.trailing)
Text("No device connected").font(.title3)
}
.padding()
}
2021-11-29 15:59:06 -08:00
}
.textCase(nil)
2021-11-29 15:59:06 -08:00
if bleManager.peripherals.count > 0 {
Section(header: Text("Available Radios").font(.title)) {
2021-11-16 10:14:20 -08:00
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name < $1.name })) { peripheral in
HStack {
Image(systemName: "circle.fill")
.imageScale(.large).foregroundColor(.gray)
.padding(.trailing)
Button(action: {
self.bleManager.stopScanning()
2021-11-29 15:59:06 -08:00
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected {
2021-11-21 13:48:28 -08:00
self.bleManager.disconnectPeripheral()
}
self.bleManager.connectTo(peripheral: peripheral.peripheral)
if userSettings.preferredPeripheralId == peripheral.peripheral.identifier.uuidString {
2021-11-29 15:59:06 -08:00
isPreferredRadio = true
2021-11-29 15:59:06 -08:00
} else {
isPreferredRadio = false
}
}) {
Text(peripheral.name).font(.title3)
}
Spacer()
Text(String(peripheral.rssi) + " dB").font(.title3)
2021-11-29 15:59:06 -08:00
}.padding([.bottom, .top])
}
}.textCase(nil)
}
}
2021-11-29 15:59:06 -08:00
HStack(alignment: .center) {
Spacer()
Button(action: {
self.bleManager.startScanning()
}) {
Image(systemName: "play.circle")
.symbolRenderingMode(.hierarchical)
.imageScale(.large)
.foregroundColor(self.bleManager.isScanning ? .gray : .accentColor)
Text("Start Scanning").font(.caption)
.font(.caption)
2021-09-10 21:50:54 -07:00
}
.disabled(self.bleManager.isScanning)
.padding()
.background(Color(.systemGray6))
.clipShape(Capsule())
Button(action: {
self.bleManager.stopScanning()
}) {
Image(systemName: "stop.circle")
.symbolRenderingMode(.hierarchical)
.imageScale(.large)
.foregroundColor(!self.bleManager.isScanning ? .gray : .accentColor)
Text("Stop Scanning")
.font(.caption)
}
.disabled(!self.bleManager.isScanning)
.padding()
.background(Color(.systemGray6))
.clipShape(Capsule())
#if targetEnvironment(macCatalyst)
if bleManager.connectedPeripheral != nil {
Button(role: .destructive, action: {
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected {
bleManager.disconnectPeripheral()
isPreferredRadio = false
}
}) {
Image(systemName: "antenna.radiowaves.left.and.right.slash")
.symbolRenderingMode(.hierarchical)
.imageScale(.large)
.foregroundColor(.red)
Text("Disconnect").font(.caption)
.font(.caption)
}
.padding()
.background(Color(.systemGray6))
.clipShape(Capsule())
}
#endif
Spacer()
}
.padding(.bottom, 10)
2021-11-29 15:59:06 -08:00
} else {
Text("Bluetooth: OFF")
.foregroundColor(.red)
.font(.title)
2021-09-10 07:41:26 -07:00
}
}
.navigationTitle("Bluetooth Radios")
2021-09-18 21:11:54 -07:00
.navigationBarItems(trailing:
2021-11-29 15:59:06 -08:00
2021-10-12 17:54:10 -07:00
ZStack {
2021-12-25 23:48:12 -08:00
2021-12-16 14:13:54 -08:00
ConnectedDevice(
2022-01-01 08:18:36 -08:00
bluetoothOn: self.bleManager.isSwitchedOn,
deviceConnected: self.bleManager.connectedPeripheral != nil,
name: (bleManager.connectedPeripheral != nil) ? self.bleManager.connectedPeripheral.lastFourCode :
"????")
}
2021-09-18 21:11:54 -07:00
)
2021-10-05 09:33:10 -07:00
}
2021-10-12 17:54:10 -07:00
.navigationViewStyle(StackNavigationViewStyle())
2021-10-17 15:08:12 -07:00
.onAppear(perform: {
2021-12-12 17:17:46 -08:00
self.bleManager.context = context
2022-02-22 09:08:06 -10:00
self.bleManager.userSettings = userSettings
2021-12-12 17:17:46 -08:00
2022-01-01 08:18:36 -08:00
if self.bleManager.connectedPeripheral != nil && userSettings.preferredPeripheralId == self.bleManager.connectedPeripheral.peripheral.identifier.uuidString {
2021-10-17 15:08:12 -07:00
isPreferredRadio = true
2021-11-29 15:59:06 -08:00
} else {
isPreferredRadio = false
2021-10-17 15:08:12 -07:00
}
})
2021-08-20 07:56:05 -07:00
}
}
2021-09-18 21:11:54 -07:00
struct Connect_Previews: PreviewProvider {
static var previews: some View {
Connect()
.environmentObject(BLEManager())
2021-09-18 21:11:54 -07:00
}
}