From 096930efd79e780e04e135f8ad8bb90a6319cdff Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 1 Aug 2022 21:57:03 -0700 Subject: [PATCH] Start of wifi config --- Meshtastic.xcodeproj/project.pbxproj | 4 + .../contents | 12 +- Meshtastic/Views/Bluetooth/Connect.swift | 2 +- .../Views/Settings/Config/WiFiConfig.swift | 147 ++++++++++++++++++ Meshtastic/Views/Settings/Settings.swift | 14 +- Meshtastic/Views/Settings/ShareChannel.swift | 1 + 6 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 Meshtastic/Views/Settings/Config/WiFiConfig.swift diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index f8a5d04a..205b9eb3 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD86D4102881D16900BAEB7A /* WriteCsvFile.swift */; }; DD882F5D2772E4640005BF05 /* Contacts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD882F5C2772E4640005BF05 /* Contacts.swift */; }; DD8EBF43285058FA00426DCA /* DisplayConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8EBF42285058FA00426DCA /* DisplayConfig.swift */; }; + DD8ED9C52898D51F00B3B0AB /* WiFiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8ED9C42898D51F00B3B0AB /* WiFiConfig.swift */; }; DD90860C26F684AF00DC5189 /* BatteryIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860B26F684AF00DC5189 /* BatteryIcon.swift */; }; DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860D26F69BAE00DC5189 /* NodeMap.swift */; }; DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */; }; @@ -146,6 +147,7 @@ DD882F5C2772E4640005BF05 /* Contacts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contacts.swift; sourceTree = ""; }; DD8EBF42285058FA00426DCA /* DisplayConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayConfig.swift; sourceTree = ""; }; DD8ED9C328978D9D00B3B0AB /* MeshtasticDataModel v 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModel v 5.xcdatamodel"; sourceTree = ""; }; + DD8ED9C42898D51F00B3B0AB /* WiFiConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WiFiConfig.swift; sourceTree = ""; }; DD90860A26F645B700DC5189 /* Meshtastic.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Meshtastic.entitlements; sourceTree = ""; }; DD90860B26F684AF00DC5189 /* BatteryIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryIcon.swift; sourceTree = ""; }; DD90860D26F69BAE00DC5189 /* NodeMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeMap.swift; sourceTree = ""; }; @@ -275,6 +277,7 @@ DD8EBF42285058FA00426DCA /* DisplayConfig.swift */, DD2553562855B02500E55709 /* LoRaConfig.swift */, DD2553582855B52700E55709 /* PositionConfig.swift */, + DD8ED9C42898D51F00B3B0AB /* WiFiConfig.swift */, DD61937B2863877A00E59241 /* Module */, ); path = Config; @@ -680,6 +683,7 @@ C9483F6D2773017500998F6B /* MapView.swift in Sources */, DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */, DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */, + DD8ED9C52898D51F00B3B0AB /* WiFiConfig.swift in Sources */, DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */, DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */, DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */, diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 5.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 5.xcdatamodel/contents index cc2670e5..7acb195b 100644 --- a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 5.xcdatamodel/contents +++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModel v 5.xcdatamodel/contents @@ -106,6 +106,7 @@ + @@ -190,6 +191,14 @@ + + + + + + + + @@ -198,7 +207,7 @@ - + @@ -206,5 +215,6 @@ + \ No newline at end of file diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index b8e59b63..8672b5d7 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -22,7 +22,7 @@ struct Connect: View { @State var isPreferredRadio: Bool = false @State var firmwareVersion = "0.0.0" - @State var minimumVersion = "1.3.27" + @State var minimumVersion = "1.3.28" @State var invalidVersion = false diff --git a/Meshtastic/Views/Settings/Config/WiFiConfig.swift b/Meshtastic/Views/Settings/Config/WiFiConfig.swift new file mode 100644 index 00000000..92aa068d --- /dev/null +++ b/Meshtastic/Views/Settings/Config/WiFiConfig.swift @@ -0,0 +1,147 @@ +// +// WiFiConfig.swift +// Meshtastic +// +// Copyright (c) Garth Vander Houwen 8/1/2022 +// + +import SwiftUI + +struct WiFiConfig: View { + + @Environment(\.managedObjectContext) var context + @EnvironmentObject var bleManager: BLEManager + + var node: NodeInfoEntity? + + @State private var isPresentingSaveConfirm: Bool = false + @State var initialLoad: Bool = true + @State var hasChanges: Bool = false + + @State var ssid = "" + @State var password = "" + + @State var apMode = false + @State var apHidden = false + + var body: some View { + + VStack { + + Text("Enabling WiFi will disable bluetooth, only one connection method works at a time. Saving these settings will disconnect your device from the app.") + .font(.title3) + .padding() + + Form { + + Section(header: Text("SSID & Password")) { + + + } + Section(header: Text("AP Settings")) { + + Toggle(isOn: $apMode) { + + Label("Soft AP Mode", systemImage: "wifi") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + Text("If set the software access point mode will be activated.") + .font(.caption) + + Toggle(isOn: $apHidden) { + + Label("Hidden AP", systemImage: "eye.slash") + } + .toggleStyle(SwitchToggleStyle(tint: .accentColor)) + Text("If set the SSID for the AP will be hidden.") + .font(.caption) + + } + } + .disabled(bleManager.connectedPeripheral == nil) + + Button { + + isPresentingSaveConfirm = true + + } label: { + + Label("Save", systemImage: "square.and.arrow.down") + } + .disabled(bleManager.connectedPeripheral == nil || !hasChanges) + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.large) + .padding() + .confirmationDialog( + + "Are you sure?", + isPresented: $isPresentingSaveConfirm + ) { + Button("Save WiFI Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") { + + var wifi = Config.WiFiConfig() + wifi.ssid = ssid + wifi.psk = password + wifi.apMode = apMode + wifi.apHidden = apHidden + + //let adminMessageId = bleManager.saveWiFiConfig(config: wiFi, fromUser: node!.user!, toUser: node!.user!, wantResponse: true) + let adminMessageId = 0 + if adminMessageId > 0 { + + // Should show a saved successfully alert once I know that to be true + // for now just disable the button after a successful save + hasChanges = false + + } else { + + } + } + } + } + .navigationTitle("WiFi Config") + .navigationBarItems(trailing: + + ZStack { + + ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????") + }) + .onAppear { + + if self.initialLoad{ + + self.bleManager.context = context + + self.ssid = node!.wiFiConfig?.ssid ?? "" + self.password = node!.wiFiConfig?.password ?? "" + self.apMode = (node!.wiFiConfig?.apMode ?? false) + self.apHidden = (node!.wiFiConfig?.apHidden ?? false) + + self.hasChanges = false + self.initialLoad = false + } + } + .onChange(of: ssid) { newSsid in + + hasChanges = true + //if node != nil && node!.wiFiConfig != nil { newSsid != node!.wiFiConfig.ssid { hasChanges = true }} + } + .onChange(of: password) { newPassword in + + hasChanges = true + //if node != nil && node!.wiFiConfig != nil { newPassword != node!.wiFiConfig!.password { hasChanges = true }} + } + .onChange(of: apMode) { newAPMode in + + hasChanges = true + //if node != nil && node!.wiFiConfig != nil { newAPMode != node!.wiFiConfig!.apMode { self.hasChanges = true }} + } + .onChange(of: apHidden) { newAPHidden in + + hasChanges = true + //if node != nil && node!.wiFiConfig != nil { newAPHidden != node!.wiFiConfig!.apHidden { hasChanges = true }} + } + .navigationViewStyle(StackNavigationViewStyle()) + } +} diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 8eb6180c..d656b809 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -100,6 +100,17 @@ struct Settings: View { } .disabled(bleManager.connectedPeripheral == nil) + NavigationLink { + WiFiConfig(node: nodes.first(where: { $0.num == connectedNodeNum })) + } label: { + + Image(systemName: "wifi") + .symbolRenderingMode(.hierarchical) + + Text("WiFi") + } + .disabled(bleManager.connectedPeripheral == nil) + Text("Default settings values are prefered as they consume no bandwidth when sent over the mesh.") .font(.caption2) .fixedSize(horizontal: false, vertical: true) @@ -193,8 +204,7 @@ struct Settings: View { // Not Implemented: // Store Forward Config - Not Working, TBEAM Only - // WiFi Config - Would break connection to device - // MQTT Config - Part of WiFi + // MQTT Config - Can do from WebUI once WiFi is enabled } .onAppear { diff --git a/Meshtastic/Views/Settings/ShareChannel.swift b/Meshtastic/Views/Settings/ShareChannel.swift index 0615b803..d2eb08e0 100644 --- a/Meshtastic/Views/Settings/ShareChannel.swift +++ b/Meshtastic/Views/Settings/ShareChannel.swift @@ -70,6 +70,7 @@ struct ShareChannel: View { ) Spacer() Text("Channel Name (Long/Slow)").font(.title) + Text(String(node!.myInfo!.maxChannels)) Spacer() } .frame(width: bounds.size.width, height: bounds.size.height)