2022-06-12 07:38:08 -07:00
//
// P o s i t i o n C o n f i g . s w i f t
// M e s h t a s t i c A p p l e
//
// C o p y r i g h t ( c ) G a r t h V a n d e r H o u w e n 6 / 1 1 / 2 2 .
//
import SwiftUI
2024-06-07 22:09:20 -05:00
import MeshtasticProtobufs
2024-06-03 02:17:55 -07:00
import OSLog
2022-06-12 07:38:08 -07:00
2023-03-06 10:33:18 -08:00
struct PositionFlags : OptionSet {
2022-09-01 11:54:39 -07:00
let rawValue : Int
2022-09-23 21:41:07 -07:00
static let Altitude = PositionFlags ( rawValue : 1 )
static let AltitudeMsl = PositionFlags ( rawValue : 2 )
2022-09-30 17:10:03 -07:00
static let GeoidalSeparation = PositionFlags ( rawValue : 4 )
2022-09-23 21:41:07 -07:00
static let Dop = PositionFlags ( rawValue : 8 )
static let Hvdop = PositionFlags ( rawValue : 16 )
static let Satsinview = PositionFlags ( rawValue : 32 )
2022-10-04 18:10:40 -07:00
static let SeqNo = PositionFlags ( rawValue : 64 )
2022-09-23 21:41:07 -07:00
static let Timestamp = PositionFlags ( rawValue : 128 )
static let Speed = PositionFlags ( rawValue : 256 )
static let Heading = PositionFlags ( rawValue : 512 )
2022-09-01 11:54:39 -07:00
}
2022-06-12 07:38:08 -07:00
struct PositionConfig : View {
2023-03-06 10:33:18 -08:00
2022-06-12 07:38:08 -07:00
@ Environment ( \ . managedObjectContext ) var context
@ EnvironmentObject var bleManager : BLEManager
2024-07-10 16:03:38 -05:00
@ EnvironmentObject var queryCoreDataController : QueryCoreDataController
2022-12-09 18:19:00 -08:00
@ Environment ( \ . dismiss ) private var goBack
2022-07-07 00:29:52 -07:00
var node : NodeInfoEntity ?
2022-06-21 10:15:47 -07:00
@ State var hasChanges = false
2022-10-04 18:10:40 -07:00
@ State var hasFlagChanges = false
2022-06-12 10:28:26 -07:00
@ State var smartPositionEnabled = true
@ State var deviceGpsEnabled = true
2024-02-05 21:46:16 -08:00
@ State var gpsMode = 0
2023-03-27 10:43:01 -07:00
@ State var rxGpio = 0
@ State var txGpio = 0
2023-12-21 11:31:40 -08:00
@ State var gpsEnGpio = 0
2022-06-12 10:28:26 -07:00
@ State var fixedPosition = false
2024-02-05 21:46:16 -08:00
@ State var gpsUpdateInterval = 0
2022-06-12 22:07:58 -07:00
@ State var positionBroadcastSeconds = 0
2023-03-27 10:43:01 -07:00
@ State var broadcastSmartMinimumDistance = 0
@ State var broadcastSmartMinimumIntervalSecs = 0
2024-02-05 21:46:16 -08:00
@ State var positionFlags = 811
2023-03-06 10:33:18 -08:00
2022-07-13 08:32:34 -07:00
// / P o s i t i o n F l a g s
// / A l t i t u d e v a l u e - 1
2022-09-23 21:41:07 -07:00
@ State var includeAltitude = false
2022-07-13 08:32:34 -07:00
// / A l t i t u d e v a l u e i s M S L - 2
2022-09-23 21:41:07 -07:00
@ State var includeAltitudeMsl = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e g e o i d a l s e p a r a t i o n - 4
2022-09-30 17:10:03 -07:00
@ State var includeGeoidalSeparation = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e t h e D O P v a l u e ; P D O P u s e d b y d e f a u l t , s e e b e l o w - 8
2022-09-23 21:41:07 -07:00
@ State var includeDop = false
2022-07-13 08:32:34 -07:00
// / I f P O S _ D O P s e t , s e n d s e p a r a t e H D O P / V D O P v a l u e s i n s t e a d o f P D O P - 1 6
2022-09-23 21:41:07 -07:00
@ State var includeHvdop = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e n u m b e r o f " s a t e l l i t e s i n v i e w " - 3 2
2022-09-23 21:41:07 -07:00
@ State var includeSatsinview = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e a s e q u e n c e n u m b e r i n c r e m e n t e d p e r p a c k e t - 6 4
2022-09-30 17:10:03 -07:00
@ State var includeSeqNo = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e p o s i t i o n a l t i m e s t a m p ( f r o m G P S s o l u t i o n ) - 1 2 8
2022-09-23 21:41:07 -07:00
@ State var includeTimestamp = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e p o s i t i o n a l h e a d i n g - 2 5 6
// / I n t e n d e d f o r u s e w i t h v e h i c l e n o t w a l k i n g s p e e d s
// / w a l k i n g s p e e d s a r e l i k e l y t o b e e r r o r p r o n e l i k e t h e c o m p a s s
2022-09-23 21:41:07 -07:00
@ State var includeSpeed = false
2022-07-13 08:32:34 -07:00
// / I n c l u d e p o s i t i o n a l s p e e d - 5 1 2
// / I n t e n d e d f o r u s e w i t h v e h i c l e n o t w a l k i n g s p e e d s
// / w a l k i n g s p e e d s a r e l i k e l y t o b e e r r o r p r o n e l i k e t h e c o m p a s s
2022-09-23 21:41:07 -07:00
@ State var includeHeading = false
2024-03-25 15:21:38 -07:00
// / M i n i m u m V e r s i o n f o r f i x e d p o s t i o n a d m i n m e s s a g e s
2024-03-27 16:06:24 -07:00
@ State var minimumVersion = " 2.3.3 "
2024-03-25 15:21:38 -07:00
@ State private var supportedVersion = true
2024-03-26 23:36:11 -07:00
@ State private var showingSetFixedAlert = false
2024-05-29 16:40:07 -05:00
// @ S t a t e p r i v a t e v a r s h o w i n g R e m o v e F i x e d A l e r t = f a l s e
2024-06-23 14:40:28 -07:00
@ ViewBuilder
var positionPacketSection : some View {
Section ( header : Text ( " Position Packet " ) ) {
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
VStack ( alignment : . leading ) {
Picker ( " Broadcast Interval " , selection : $ positionBroadcastSeconds ) {
ForEach ( UpdateIntervals . allCases ) { at in
if at . rawValue >= 300 {
Text ( at . description )
2022-06-12 10:28:26 -07:00
}
}
2024-06-23 14:40:28 -07:00
}
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " The maximum interval that can elapse without a node broadcasting a position " )
. foregroundColor ( . gray )
. font ( . callout )
}
2024-05-29 16:40:07 -05:00
2024-06-23 14:40:28 -07:00
Toggle ( isOn : $ smartPositionEnabled ) {
Label ( " Smart Position " , systemImage : " brain " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2024-05-29 16:40:07 -05:00
2024-06-23 14:40:28 -07:00
if smartPositionEnabled {
VStack ( alignment : . leading ) {
Picker ( " Minimum Interval " , selection : $ broadcastSmartMinimumIntervalSecs ) {
ForEach ( UpdateIntervals . allCases ) { at in
2024-02-05 21:46:16 -08:00
Text ( at . description )
}
}
2024-06-23 14:40:28 -07:00
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " The fastest that position updates will be sent if the minimum distance has been satisfied " )
2024-05-04 16:03:38 -07:00
. foregroundColor ( . gray )
. font ( . callout )
2024-06-23 14:40:28 -07:00
}
VStack ( alignment : . leading ) {
Picker ( " Minimum Distance " , selection : $ broadcastSmartMinimumDistance ) {
ForEach ( 10. . < 151 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
if $0 . isMultiple ( of : 5 ) {
Text ( " \( $0 ) " )
. tag ( $0 )
2024-02-21 20:41:27 -08:00
}
2024-02-05 21:46:16 -08:00
}
}
2024-03-27 16:06:24 -07:00
}
2024-06-23 14:40:28 -07:00
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " The minimum distance change in meters to be considered for a smart position broadcast. " )
. foregroundColor ( . gray )
. font ( . callout )
}
}
}
}
2024-05-29 16:40:07 -05:00
2024-06-23 14:40:28 -07:00
@ ViewBuilder
var deviceGPSSection : some View {
Section ( header : Text ( " Device GPS " ) ) {
Picker ( " " , selection : $ gpsMode ) {
ForEach ( GpsMode . allCases , id : \ . self ) { at in
Text ( at . description )
. tag ( at . id )
}
}
. pickerStyle ( SegmentedPickerStyle ( ) )
. padding ( . top , 5 )
. padding ( . bottom , 5 )
. disabled ( fixedPosition && ! ( gpsMode = = 1 ) )
if gpsMode = = 1 {
Text ( " Positions will be provided by your device GPS, if you select disabled or not present you can set a fixed position. " )
. foregroundColor ( . gray )
. font ( . callout )
VStack ( alignment : . leading ) {
Picker ( " Update Interval " , selection : $ gpsUpdateInterval ) {
ForEach ( GpsUpdateIntervals . allCases ) { ui in
Text ( ui . description )
2024-03-26 23:36:11 -07:00
}
2024-02-05 21:46:16 -08:00
}
2024-06-23 14:40:28 -07:00
Text ( " How often should we try to get a GPS position. " )
2024-02-21 20:41:27 -08:00
. foregroundColor ( . gray )
2024-02-21 23:35:28 -08:00
. font ( . callout )
2024-06-23 14:40:28 -07:00
}
}
if ( gpsMode != 1 && node ? . num ? ? 0 = = bleManager . connectedPeripheral ? . num ? ? - 1 ) || fixedPosition {
VStack ( alignment : . leading ) {
Toggle ( isOn : $ fixedPosition ) {
Label ( " Fixed Position " , systemImage : " location.square.fill " )
if ! ( node ? . positionConfig ? . fixedPosition ? ? false ) {
Text ( " Your current location will be set as the fixed position and broadcast over the mesh on the position interval. " )
} else {
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
}
2022-06-20 12:51:55 -07:00
}
2022-06-21 01:12:08 -07:00
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2024-06-23 14:40:28 -07:00
}
}
}
}
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
@ ViewBuilder
var positionFlagsSection : some View {
Section ( header : Text ( " Position Flags " ) ) {
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
Text ( " Optional fields to include when assembling position messages. the more fields are included, the larger the message will be - leading to longer airtime and a higher risk of packet loss " )
. foregroundColor ( . gray )
. font ( . callout )
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
Toggle ( isOn : $ includeAltitude ) {
Label ( " Altitude " , systemImage : " arrow.up " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
Toggle ( isOn : $ includeSatsinview ) {
Label ( " Number of satellites " , systemImage : " skew " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
Toggle ( isOn : $ includeSeqNo ) { // 6 4
Label ( " Sequence number " , systemImage : " number " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2022-06-14 16:45:43 -07:00
2024-06-23 14:40:28 -07:00
Toggle ( isOn : $ includeTimestamp ) { // 1 2 8
Label ( " timestamp " , systemImage : " clock " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Toggle ( isOn : $ includeHeading ) { // 1 2 8
Label ( " Vehicle heading " , systemImage : " location.circle " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Toggle ( isOn : $ includeSpeed ) { // 1 2 8
Label ( " Vehicle speed " , systemImage : " speedometer " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
}
}
@ ViewBuilder
var advancedPositionFlagsSection : some View {
Section ( header : Text ( " Advanced Position Flags " ) ) {
if includeAltitude {
Toggle ( isOn : $ includeAltitudeMsl ) {
Label ( " Altitude is Mean Sea Level " , systemImage : " arrow.up.to.line.compact " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Toggle ( isOn : $ includeGeoidalSeparation ) {
Label ( " Altitude Geoidal Separation " , systemImage : " globe.americas " )
2022-07-13 08:32:34 -07:00
}
2024-06-23 14:40:28 -07:00
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
}
2024-05-29 16:40:07 -05:00
2024-06-23 14:40:28 -07:00
Toggle ( isOn : $ includeDop ) {
Text ( " Dilution of precision (DOP) PDOP used by default " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
if includeDop {
Toggle ( isOn : $ includeHvdop ) {
Text ( " If DOP is set, use HDOP / VDOP values instead of PDOP " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
}
}
}
2023-03-06 10:33:18 -08:00
2024-06-23 14:40:28 -07:00
@ ViewBuilder
var advancedDeviceGPSSection : some View {
Section ( header : Text ( " Advanced Device GPS " ) ) {
Picker ( " GPS Receive GPIO " , selection : $ rxGpio ) {
ForEach ( 0. . < 49 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Picker ( " GPS Transmit GPIO " , selection : $ txGpio ) {
ForEach ( 0. . < 49 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
2022-07-13 08:32:34 -07:00
}
2022-06-12 07:38:08 -07:00
}
2024-06-23 14:40:28 -07:00
}
. pickerStyle ( DefaultPickerStyle ( ) )
Picker ( " GPS EN GPIO " , selection : $ gpsEnGpio ) {
ForEach ( 0. . < 49 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " (Re)define PIN_GPS_EN for your board. " )
. font ( . caption )
}
}
2024-05-29 16:40:07 -05:00
2024-06-23 14:40:28 -07:00
var saveButton : some View {
SaveConfigButton ( node : node , hasChanges : $ hasChanges ) {
if fixedPosition && ! supportedVersion {
_ = bleManager . sendPosition ( channel : 0 , destNum : node ? . num ? ? 0 , wantResponse : true )
}
2024-07-10 16:03:38 -05:00
let connectedNode = queryCoreDataController . getNodeInfo ( id : bleManager . connectedPeripheral ! . num )
2024-06-23 14:40:28 -07:00
if connectedNode != nil {
var pc = Config . PositionConfig ( )
pc . positionBroadcastSmartEnabled = smartPositionEnabled
pc . gpsEnabled = gpsMode = = 1
pc . gpsMode = Config . PositionConfig . GpsMode ( rawValue : gpsMode ) ? ? Config . PositionConfig . GpsMode . notPresent
pc . fixedPosition = fixedPosition
pc . gpsUpdateInterval = UInt32 ( gpsUpdateInterval )
pc . positionBroadcastSecs = UInt32 ( positionBroadcastSeconds )
pc . broadcastSmartMinimumIntervalSecs = UInt32 ( broadcastSmartMinimumIntervalSecs )
pc . broadcastSmartMinimumDistance = UInt32 ( broadcastSmartMinimumDistance )
pc . rxGpio = UInt32 ( rxGpio )
pc . txGpio = UInt32 ( txGpio )
pc . gpsEnGpio = UInt32 ( gpsEnGpio )
var pf : PositionFlags = [ ]
if includeAltitude { pf . insert ( . Altitude ) }
if includeAltitudeMsl { pf . insert ( . AltitudeMsl ) }
if includeGeoidalSeparation { pf . insert ( . GeoidalSeparation ) }
if includeDop { pf . insert ( . Dop ) }
if includeHvdop { pf . insert ( . Hvdop ) }
if includeSatsinview { pf . insert ( . Satsinview ) }
if includeSeqNo { pf . insert ( . SeqNo ) }
if includeTimestamp { pf . insert ( . Timestamp ) }
if includeSpeed { pf . insert ( . Speed ) }
if includeHeading { pf . insert ( . Heading ) }
pc . positionFlags = UInt32 ( pf . rawValue )
let adminMessageId = bleManager . savePositionConfig ( config : pc , fromUser : connectedNode ! . user ! , toUser : node ! . user ! , adminIndex : connectedNode ? . myInfo ? . adminIndex ? ? 0 )
if adminMessageId > 0 {
// D i s a b l e t h e b u t t o n a f t e r a s u c c e s s f u l s a v e
hasChanges = false
goBack ( )
}
}
}
}
var setFixedAlertTitle : String {
if node ? . positionConfig ? . fixedPosition = = true {
return " Remove Fixed Position "
} else {
return " Set Fixed Position "
}
}
var body : some View {
VStack {
Form {
ConfigHeader ( title : " Position " , config : \ . positionConfig , node : node , onAppear : setPositionValues )
positionPacketSection
deviceGPSSection
positionFlagsSection
advancedPositionFlagsSection
2024-02-05 21:46:16 -08:00
if gpsMode = = 1 {
2024-06-23 14:40:28 -07:00
advancedDeviceGPSSection
2023-03-27 17:41:34 -07:00
}
2022-06-12 07:38:08 -07:00
}
2023-01-31 22:59:43 -08:00
. disabled ( self . bleManager . connectedPeripheral = = nil || node ? . positionConfig = = nil )
2024-06-23 14:40:28 -07:00
. alert ( setFixedAlertTitle , isPresented : $ showingSetFixedAlert ) {
2024-03-27 16:06:24 -07:00
Button ( " Cancel " , role : . cancel ) {
fixedPosition = ! fixedPosition
}
if node ? . positionConfig ? . fixedPosition ? ? false {
Button ( " Remove " , role : . destructive ) {
2024-06-23 14:40:28 -07:00
removeFixedPosition ( )
2024-03-27 16:06:24 -07:00
}
} else {
Button ( " Set " ) {
2024-06-23 14:40:28 -07:00
setFixedPosition ( )
2024-03-27 16:06:24 -07:00
}
}
} message : {
Text ( node ? . positionConfig ? . fixedPosition ? ? false ? " This will disable fixed position and remove the currently set position. " : " This will send a current position from your phone and enable fixed position. " )
}
2024-06-23 14:40:28 -07:00
saveButton
2022-06-12 07:38:08 -07:00
}
2022-12-13 07:49:46 -08:00
. navigationTitle ( " position.config " )
2024-06-23 14:40:28 -07:00
. navigationBarItems (
trailing : ZStack {
ConnectedDevice (
bluetoothOn : bleManager . isSwitchedOn ,
deviceConnected : bleManager . connectedPeripheral != nil ,
name : bleManager . connectedPeripheral ? . shortName ? ? " ? "
)
}
)
2022-06-12 07:38:08 -07:00
. onAppear {
2023-03-19 18:37:23 -07:00
setPositionValues ( )
2024-03-25 15:21:38 -07:00
supportedVersion = bleManager . connectedVersion = = " 0.0.0 " || self . minimumVersion . compare ( bleManager . connectedVersion , options : . numeric ) = = . orderedAscending || minimumVersion . compare ( bleManager . connectedVersion , options : . numeric ) = = . orderedSame
2023-01-31 22:08:03 -08:00
// N e e d t o r e q u e s t a P o s i t i o n C o n f i g f r o m t h e r e m o t e n o d e b e f o r e a l l o w i n g c h a n g e s
2024-06-23 14:40:28 -07:00
if let connectedPeripheral = bleManager . connectedPeripheral , node ? . positionConfig = = nil {
2024-06-03 02:17:55 -07:00
Logger . mesh . info ( " empty position config " )
2024-07-10 16:03:38 -05:00
let connectedNode = queryCoreDataController . getNodeInfo ( id : connectedPeripheral . num )
2024-06-23 14:40:28 -07:00
if let node , let connectedNode {
_ = bleManager . requestPositionConfig (
fromUser : connectedNode . user ! ,
toUser : node . user ! ,
adminIndex : connectedNode . myInfo ? . adminIndex ? ? 0
)
2023-01-31 22:08:03 -08:00
}
}
2022-06-21 13:10:30 -07:00
}
2024-03-27 16:06:24 -07:00
. onChange ( of : fixedPosition ) { newFixed in
if supportedVersion {
2024-06-23 14:40:28 -07:00
if let positionConfig = node ? . positionConfig {
2024-03-27 16:06:24 -07:00
// / F i x e d P o s i t i o n i s o f f t o s t a r t
2024-06-23 14:40:28 -07:00
if ! positionConfig . fixedPosition && newFixed {
2024-03-27 16:06:24 -07:00
showingSetFixedAlert = true
2024-06-23 14:40:28 -07:00
} else if positionConfig . fixedPosition && ! newFixed {
2024-03-27 16:06:24 -07:00
// / F i x e d P o s i t i o n i s o n t o s t a r t
showingSetFixedAlert = true
}
}
}
}
2024-06-23 14:40:28 -07:00
. onChange ( of : gpsMode ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : rxGpio ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : txGpio ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : gpsEnGpio ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : smartPositionEnabled ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : positionBroadcastSeconds ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : broadcastSmartMinimumIntervalSecs ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : broadcastSmartMinimumDistance ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : gpsUpdateInterval ) { _ in
handleChanges ( )
2022-10-04 18:10:40 -07:00
}
2024-06-23 14:40:28 -07:00
. onChange ( of : positionFlags ) { _ in
handleChanges ( )
2022-09-01 18:37:41 -07:00
}
2022-06-12 07:38:08 -07:00
}
2024-06-23 14:40:28 -07:00
func handleChanges ( ) {
guard let positionConfig = node ? . positionConfig else { return }
let pf = PositionFlags ( rawValue : self . positionFlags )
hasChanges = positionConfig . deviceGpsEnabled != deviceGpsEnabled ||
positionConfig . gpsMode != gpsMode ||
positionConfig . rxGpio != rxGpio ||
positionConfig . txGpio != txGpio ||
positionConfig . gpsEnGpio != gpsEnGpio ||
positionConfig . smartPositionEnabled != smartPositionEnabled ||
positionConfig . positionBroadcastSeconds != positionBroadcastSeconds ||
positionConfig . broadcastSmartMinimumIntervalSecs != broadcastSmartMinimumIntervalSecs ||
positionConfig . broadcastSmartMinimumDistance != broadcastSmartMinimumDistance ||
positionConfig . gpsUpdateInterval != gpsUpdateInterval ||
pf . contains ( . Altitude ) ||
pf . contains ( . AltitudeMsl ) ||
pf . contains ( . Satsinview ) ||
pf . contains ( . SeqNo ) ||
pf . contains ( . Timestamp ) ||
pf . contains ( . Speed ) ||
pf . contains ( . Heading ) ||
pf . contains ( . GeoidalSeparation ) ||
pf . contains ( . Dop ) ||
pf . contains ( . Hvdop )
}
2023-03-19 18:37:23 -07:00
func setPositionValues ( ) {
self . smartPositionEnabled = node ? . positionConfig ? . smartPositionEnabled ? ? true
2024-02-05 21:46:16 -08:00
self . deviceGpsEnabled = node ? . positionConfig ? . deviceGpsEnabled ? ? false
self . gpsMode = Int ( node ? . positionConfig ? . gpsMode ? ? 0 )
if node ? . positionConfig ? . deviceGpsEnabled ? ? false && gpsMode != 1 {
self . gpsMode = 1
}
2023-03-27 10:43:01 -07:00
self . rxGpio = Int ( node ? . positionConfig ? . rxGpio ? ? 0 )
self . txGpio = Int ( node ? . positionConfig ? . txGpio ? ? 0 )
2023-12-21 11:31:40 -08:00
self . gpsEnGpio = Int ( node ? . positionConfig ? . gpsEnGpio ? ? 0 )
2023-03-19 18:37:23 -07:00
self . fixedPosition = node ? . positionConfig ? . fixedPosition ? ? false
2024-02-05 21:46:16 -08:00
self . gpsUpdateInterval = Int ( node ? . positionConfig ? . gpsUpdateInterval ? ? 30 )
2023-03-19 18:37:23 -07:00
self . positionBroadcastSeconds = Int ( node ? . positionConfig ? . positionBroadcastSeconds ? ? 900 )
2023-03-27 10:43:01 -07:00
self . broadcastSmartMinimumIntervalSecs = Int ( node ? . positionConfig ? . broadcastSmartMinimumIntervalSecs ? ? 30 )
2023-03-27 17:04:24 -07:00
self . broadcastSmartMinimumDistance = Int ( node ? . positionConfig ? . broadcastSmartMinimumDistance ? ? 50 )
2023-03-19 18:37:23 -07:00
self . positionFlags = Int ( node ? . positionConfig ? . positionFlags ? ? 3 )
let pf = PositionFlags ( rawValue : self . positionFlags )
2024-06-23 14:40:28 -07:00
self . includeAltitude = pf . contains ( . Altitude )
self . includeAltitudeMsl = pf . contains ( . AltitudeMsl )
self . includeGeoidalSeparation = pf . contains ( . GeoidalSeparation )
self . includeDop = pf . contains ( . Dop )
self . includeHvdop = pf . contains ( . Hvdop )
self . includeSatsinview = pf . contains ( . Satsinview )
self . includeSeqNo = pf . contains ( . SeqNo )
self . includeTimestamp = pf . contains ( . Timestamp )
self . includeSpeed = pf . contains ( . Speed )
self . includeHeading = pf . contains ( . Heading )
2023-03-19 18:37:23 -07:00
self . hasChanges = false
}
2024-06-23 14:40:28 -07:00
private func setFixedPosition ( ) {
guard let nodeNum = bleManager . connectedPeripheral ? . num ,
nodeNum > 0 else { return }
if ! bleManager . setFixedPosition ( fromUser : node ! . user ! , channel : 0 ) {
Logger . mesh . error ( " Set Position Failed " )
}
node ? . positionConfig ? . fixedPosition = true
do {
try context . save ( )
Logger . data . info ( " 💾 Updated Position Config with Fixed Position = true " )
} catch {
context . rollback ( )
let nsError = error as NSError
Logger . data . error ( " Error Saving Position Config Entity \( nsError ) " )
}
}
private func removeFixedPosition ( ) {
guard let nodeNum = bleManager . connectedPeripheral ? . num ,
nodeNum > 0 else { return }
if ! bleManager . removeFixedPosition ( fromUser : node ! . user ! , channel : 0 ) {
Logger . mesh . error ( " Remove Fixed Position Failed " )
}
let mutablePositions = node ? . positions ? . mutableCopy ( ) as ? NSMutableOrderedSet
mutablePositions ? . removeAllObjects ( )
node ? . positions = mutablePositions
node ? . positionConfig ? . fixedPosition = false
do {
try context . save ( )
Logger . data . info ( " 💾 Updated Position Config with Fixed Position = false " )
} catch {
context . rollback ( )
let nsError = error as NSError
Logger . data . error ( " Error Saving Position Config Entity \( nsError ) " )
}
}
2022-06-12 07:38:08 -07:00
}