From 3f51b769ba5598de6a91de827aa74b692c00ec5b Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sat, 2 Oct 2021 23:06:46 -0700 Subject: [PATCH] Assorted updates, handle nil values on node details before checking for empty details --- Meshtastic Client.xcodeproj/project.pbxproj | 22 ++++++++++++- MeshtasticClient/Helpers/BLEHelper.swift | 32 +++++++++++++++++++ MeshtasticClient/Views/ContentView.swift | 9 +++++- MeshtasticClient/Views/Nodes/NodeDetail.swift | 8 ++--- .../Views/Settings/AppSettings.swift | 31 ++++++++++++++++++ .../Views/Settings/Configuration.swift | 8 +++++ 6 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 MeshtasticClient/Helpers/BLEHelper.swift create mode 100644 MeshtasticClient/Views/Settings/AppSettings.swift create mode 100644 MeshtasticClient/Views/Settings/Configuration.swift diff --git a/Meshtastic Client.xcodeproj/project.pbxproj b/Meshtastic Client.xcodeproj/project.pbxproj index f3d67173..f289cef2 100644 --- a/Meshtastic Client.xcodeproj/project.pbxproj +++ b/Meshtastic Client.xcodeproj/project.pbxproj @@ -18,6 +18,9 @@ DD47E3DB26F3901B00029299 /* Channels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DA26F3901A00029299 /* Channels.swift */; }; DD47E3DD26F390A000029299 /* Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DC26F390A000029299 /* Messages.swift */; }; DD47E3DF26F39D9F00029299 /* MyInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD47E3DE26F39D9F00029299 /* MyInfoModel.swift */; }; + DD4A911B2708303E00501B7E /* BLEHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911A2708303E00501B7E /* BLEHelper.swift */; }; + DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911D2708C65400501B7E /* AppSettings.swift */; }; + DD4A91202708C66600501B7E /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4A911F2708C66600501B7E /* Configuration.swift */; }; DD836AE726F6B38600ABCC23 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD836AE626F6B38600ABCC23 /* Connect.swift */; }; DD836AED26F858F900ABCC23 /* MeshData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD836AEC26F858F900ABCC23 /* MeshData.swift */; }; DD836AEF26F85D8D00ABCC23 /* NodeInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD836AEE26F85D8D00ABCC23 /* NodeInfoModel.swift */; }; @@ -75,6 +78,9 @@ DD47E3DA26F3901A00029299 /* Channels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channels.swift; sourceTree = ""; }; DD47E3DC26F390A000029299 /* Messages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Messages.swift; sourceTree = ""; }; DD47E3DE26F39D9F00029299 /* MyInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoModel.swift; sourceTree = ""; }; + DD4A911A2708303E00501B7E /* BLEHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BLEHelper.swift; sourceTree = ""; }; + DD4A911D2708C65400501B7E /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; + DD4A911F2708C66600501B7E /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; DD836AE626F6B38600ABCC23 /* Connect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Connect.swift; sourceTree = ""; }; DD836AEC26F858F900ABCC23 /* MeshData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshData.swift; sourceTree = ""; }; DD836AEE26F85D8D00ABCC23 /* NodeInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoModel.swift; sourceTree = ""; }; @@ -155,6 +161,15 @@ path = Bluetooth; sourceTree = ""; }; + DD4A911C2708C57100501B7E /* Settings */ = { + isa = PBXGroup; + children = ( + DD4A911D2708C65400501B7E /* AppSettings.swift */, + DD4A911F2708C66600501B7E /* Configuration.swift */, + ); + path = Settings; + sourceTree = ""; + }; DD8EDE9226F97A2B00A5A10B /* Frameworks */ = { isa = PBXGroup; children = ( @@ -245,11 +260,12 @@ DDC2E18726CE24E40042C5E4 /* Views */ = { isa = PBXGroup; children = ( + DDC2E18D26CE25CB0042C5E4 /* Helpers */, DD47E3D726F2F21A00029299 /* Bluetooth */, DD47E3CA26F0E50300029299 /* Nodes */, DDC2E18B26CE25A70042C5E4 /* Messages */, DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */, - DDC2E18D26CE25CB0042C5E4 /* Helpers */, + DD4A911C2708C57100501B7E /* Settings */, ); path = Views; sourceTree = ""; @@ -302,6 +318,7 @@ DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */, DDAF8C6D26ED19040058C060 /* Extensions.swift */, DD47E3D126F1210600029299 /* HelperFunctions.swift */, + DD4A911A2708303E00501B7E /* BLEHelper.swift */, ); path = Helpers; sourceTree = ""; @@ -453,9 +470,12 @@ DD47E3DB26F3901B00029299 /* Channels.swift in Sources */, DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */, DD23A51326FEF5D500D9B90C /* MessageData.swift in Sources */, + DD4A911B2708303E00501B7E /* BLEHelper.swift in Sources */, DD836AED26F858F900ABCC23 /* MeshData.swift in Sources */, DDAF8C6B26ED0DD80058C060 /* environmental_measurement.pb.swift in Sources */, DD90860C26F684AF00DC5189 /* BatteryIcon.swift in Sources */, + DD4A91202708C66600501B7E /* Configuration.swift in Sources */, + DD4A911E2708C65400501B7E /* AppSettings.swift in Sources */, DDAF8C6226ED0A230058C060 /* mqtt.pb.swift in Sources */, DDF924CA26FBB953009FE055 /* ConnectedDevice.swift in Sources */, DDAF8C5D26ED09490058C060 /* portnums.pb.swift in Sources */, diff --git a/MeshtasticClient/Helpers/BLEHelper.swift b/MeshtasticClient/Helpers/BLEHelper.swift new file mode 100644 index 00000000..70a2c263 --- /dev/null +++ b/MeshtasticClient/Helpers/BLEHelper.swift @@ -0,0 +1,32 @@ +import Foundation +import CoreData +import CoreBluetooth +import SwiftUI + +//--------------------------------------------------------------------------------------- +// Meshtastic BLE Device Manager +//--------------------------------------------------------------------------------------- +class BLEHelper: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate { + + var centralManager: CBCentralManager! + @Published var isSwitchedOn = false + @Published var peripherals = [Peripheral]() + + override init() { + + super.init() + centralManager = CBCentralManager(delegate: self, queue: nil) + centralManager.delegate = self + } + + // Check for Bluetooth Connectivity + func centralManagerDidUpdateState(_ central: CBCentralManager) { + if central.state == .poweredOn { + isSwitchedOn = true + } + else { + isSwitchedOn = false + } + } + +} diff --git a/MeshtasticClient/Views/ContentView.swift b/MeshtasticClient/Views/ContentView.swift index 6e0d8e8c..db235e63 100644 --- a/MeshtasticClient/Views/ContentView.swift +++ b/MeshtasticClient/Views/ContentView.swift @@ -12,6 +12,7 @@ struct ContentView: View { case map case ble case nodes + case settings } var body: some View { @@ -40,7 +41,13 @@ struct ContentView: View { Label("Bluetooth", systemImage: "dot.radiowaves.left.and.right") .symbolRenderingMode(.hierarchical) } - .tag(Tab.ble) + .tag(Tab.settings) + AppSettings() + .tabItem { + Label("Settings", systemImage: "gear") + .symbolRenderingMode(.hierarchical) + } + .tag(Tab.settings) } } } diff --git a/MeshtasticClient/Views/Nodes/NodeDetail.swift b/MeshtasticClient/Views/Nodes/NodeDetail.swift index 729cbb8e..6d885096 100644 --- a/MeshtasticClient/Views/Nodes/NodeDetail.swift +++ b/MeshtasticClient/Views/Nodes/NodeDetail.swift @@ -33,7 +33,6 @@ struct NodeDetail: View { }, set: { _ in } ) - let annotations = [MapLocation(name: node.user.shortName, coordinate: node.position.coordinate!)] Map(coordinateRegion: regionBinding, showsUserLocation: true, userTrackingMode: .none, annotationItems: annotations) { location in @@ -63,7 +62,7 @@ struct NodeDetail: View { } .padding([.leading, .trailing, .bottom]) Divider() - if node.snr! > 0 { + if node.snr != nil && node.snr! > 0 { VStack(alignment: .center) { Image(systemName: "waveform.path") @@ -79,7 +78,7 @@ struct NodeDetail: View { } VStack(alignment: .center) { BatteryIcon(batteryLevel: node.position.batteryLevel, font: .title, color: Color.blue) - if node.position.batteryLevel! > 0 { + if node.position.batteryLevel != nil && node.position.batteryLevel! > 0 { Text("Battery").font(.title2).fixedSize() Text(String(node.position.batteryLevel!) + "%") .font(.title2) @@ -112,9 +111,6 @@ struct NodeDetail: View { Image(systemName: "clock").font(.title2).foregroundColor(.blue) let lastHeard = Date(timeIntervalSince1970: TimeInterval(node.lastHeard)) - //Text("Last Heard:").font(.title3) - //Text(lastHeard, style: .relative).font(.title3) - //Text("ago").font(.title3) Text("Last Heard: \(lastHeard, style: .relative) ago").font(.title3) }.padding() Divider() diff --git a/MeshtasticClient/Views/Settings/AppSettings.swift b/MeshtasticClient/Views/Settings/AppSettings.swift new file mode 100644 index 00000000..5dad31c6 --- /dev/null +++ b/MeshtasticClient/Views/Settings/AppSettings.swift @@ -0,0 +1,31 @@ +import Foundation +import SwiftUI + +struct AppSettings: View { + + var body: some View { + NavigationView { + + GeometryReader { bounds in + + NavigationLink(destination: Messages()) { + + List{ + + } + } + } + .navigationTitle("App Settings") + } + } +} + +struct AppSettings_Previews: PreviewProvider { + static let meshData = MeshData() + + static var previews: some View { + Group { + AppSettings() + } + } +} diff --git a/MeshtasticClient/Views/Settings/Configuration.swift b/MeshtasticClient/Views/Settings/Configuration.swift new file mode 100644 index 00000000..3d811925 --- /dev/null +++ b/MeshtasticClient/Views/Settings/Configuration.swift @@ -0,0 +1,8 @@ +// +// Configuration.swift +// MeshtasticClient +// +// Created by Garth Vander Houwen on 10/2/21. +// + +import Foundation