diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 5cdd8853..9339e55d 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -187,6 +187,7 @@ DDDB445429F8AD1600EE2349 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB445329F8AD1600EE2349 /* Data.swift */; }; DDDC22382BA92344002C44F1 /* MeshMapContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC22372BA92344002C44F1 /* MeshMapContent.swift */; }; DDDCD5702BB26F5C00BE6B60 /* NodeListFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDCD56F2BB26F5C00BE6B60 /* NodeListFilter.swift */; }; + DDDCD5722BB3E46400BE6B60 /* BLEManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C5226EB1DF10058C060 /* BLEManager.swift */; }; DDDE59F529AF163D00490C6C /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD41A61C29AE7E8E003C5A37 /* WidgetKit.framework */; }; DDDE59F629AF163D00490C6C /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD41A61E29AE7E8F003C5A37 /* SwiftUI.framework */; }; DDDE59F929AF163D00490C6C /* WidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDE59F829AF163D00490C6C /* WidgetsBundle.swift */; }; @@ -1404,6 +1405,7 @@ buildActionMask = 2147483647; files = ( DDD3BBD5292D763200D609B3 /* MeshtasticTests.swift in Sources */, + DDDCD5722BB3E46400BE6B60 /* BLEManager.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index 980e2870..9327ebc8 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -983,9 +983,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate return success } - public func sendPosition(channel: Int32, destNum: Int64, wantResponse: Bool) -> Bool { - var success = false - let fromNodeNum = connectedPeripheral.num + public func getPositionFromPhoneGPS(channel: Int32, destNum: Int64) -> Position? { var positionPacket = Position() let fetchChannelRequest: NSFetchRequest = NSFetchRequest.init(entityName: "ChannelEntity") @@ -993,7 +991,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate do { guard let fetchedChannel = try context!.fetch(fetchChannelRequest) as? [ChannelEntity] else { - return false + return nil } if #available(iOS 17.0, macOS 14.0, *) { @@ -1019,8 +1017,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } } else { - if fromNodeNum <= 0 || LocationHelper.currentLocation.distance(from: LocationHelper.DefaultLocation) == 0.0 { - return false + if destNum <= 0 || LocationHelper.currentLocation.distance(from: LocationHelper.DefaultLocation) == 0.0 { + return nil } positionPacket.latitudeI = Int32(LocationHelper.currentLocation.latitude * 1e7) positionPacket.longitudeI = Int32(LocationHelper.currentLocation.longitude * 1e7) @@ -1041,6 +1039,61 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } } catch { + return nil + } + + return positionPacket + } + + public func setFixedPosition(fromUser: UserEntity, channel: Int32) -> Bool { + var adminPacket = AdminMessage() + guard let positionPacket = getPositionFromPhoneGPS(channel: channel, destNum: fromUser.num) else { + return false + } + adminPacket.setFixedPosition = positionPacket + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(fromUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { + var adminPacket = AdminMessage() + adminPacket.removeFixedPosition = true + var meshPacket: MeshPacket = MeshPacket() + meshPacket.to = UInt32(fromUser.num) + meshPacket.from = UInt32(fromUser.num) + meshPacket.id = UInt32.random(in: UInt32(UInt8.max).. Bool { + var success = false + let fromNodeNum = connectedPeripheral.num + guard let positionPacket = getPositionFromPhoneGPS(channel: channel, destNum: destNum) else { return false } diff --git a/Meshtastic/Views/Settings/Config/PositionConfig.swift b/Meshtastic/Views/Settings/Config/PositionConfig.swift index b18ff5e6..37bb12e7 100644 --- a/Meshtastic/Views/Settings/Config/PositionConfig.swift +++ b/Meshtastic/Views/Settings/Config/PositionConfig.swift @@ -73,8 +73,10 @@ struct PositionConfig: View { @State var includeHeading = false /// Minimum Version for fixed postion admin messages - @State var minimumVersion = "2.3.3" + @State var minimumVersion = "2.3.2" @State private var supportedVersion = true + @State private var showingSetFixedAlert = false + @State private var showingRemoveFixedAlert = false var body: some View { VStack { @@ -160,19 +162,45 @@ struct PositionConfig: View { VStack(alignment: .leading) { Toggle(isOn: $fixedPosition) { Label("Fixed Position", systemImage: "location.square.fill") - Text("If enabled your current phone location will be sent to the device and will broadcast over the mesh on the position interval. Fixed position will always use the most recent position the device has.") + Text("If enabled your current phone location will be sent to the device and will broadcast over the mesh on the position interval.") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) - } .onChange(of: fixedPosition) { newFixed in if node != nil && node!.positionConfig != nil { - if newFixed != node!.positionConfig!.fixedPosition { hasChanges = true } - } - if supportedVersion && hasChanges && !newFixed { - // Send Admin message to remove the fixed position + /// Fixed Position is off to start + if !node!.positionConfig!.fixedPosition && newFixed && supportedVersion { + showingSetFixedAlert = true + } else if node!.positionConfig!.fixedPosition && newFixed && supportedVersion { + /// Fixed Position is on to start + showingRemoveFixedAlert = true + } } } + .alert(isPresented: $showingSetFixedAlert) { + Alert( + title: Text("Set Fixed Position"), + message: Text("This will send a current position from your phone and enable fixed position."), + primaryButton: .default(Text("Set")) { + print("Set a fixed position here") + }, + secondaryButton: .cancel(Text("Cancel")) { + fixedPosition = false + } + ) + } + .alert(isPresented: $showingRemoveFixedAlert) { + Alert( + title: Text("Remove Fixed Position"), + message: Text("This will disable fixed position and remove the currently set position."), + primaryButton: .destructive(Text("Remove")) { + print("Remove a fixed position here") + }, + secondaryButton: .cancel(Text("Cancel")) { + fixedPosition = true + } + ) + } } } Section(header: Text("Position Flags")) {