2022-06-12 01:25:42 -07:00
//
// L o R a 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 ) b y G a r t h V a n d e r H o u w e n 6 / 1 1 / 2 2 .
//
import SwiftUI
2023-03-05 15:13:23 -08:00
import CoreData
2024-06-07 22:09:20 -05:00
import MeshtasticProtobufs
2024-06-03 02:17:55 -07:00
import OSLog
2022-06-12 01:25:42 -07:00
struct LoRaConfig : View {
2023-03-06 10:33:18 -08:00
2023-03-05 15:13:23 -08:00
enum Field : Hashable {
case channelNum
2023-10-25 18:54:52 -07:00
case frequencyOverride
2023-03-05 15:13:23 -08:00
}
2023-03-05 23:01:09 -08:00
2023-03-05 05:42:25 -08:00
let formatter : NumberFormatter = {
let formatter = NumberFormatter ( )
formatter . numberStyle = . decimal
2023-03-05 23:39:06 -08:00
formatter . groupingSeparator = " "
2023-03-05 05:42:25 -08:00
return formatter
} ( )
2023-03-06 10:33:18 -08:00
2022-06-12 01:25:42 -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
2023-03-05 15:13:23 -08:00
@ FocusState var focusedField : Field ?
2023-03-06 10:33:18 -08:00
2022-07-07 00:29:52 -07:00
var node : NodeInfoEntity ?
2023-03-06 10:33:18 -08:00
2022-06-21 01:12:08 -07:00
@ State var hasChanges = false
2023-03-19 18:37:23 -07:00
@ State var region : Int = 0
2023-03-05 15:13:23 -08:00
@ State var modemPreset = 0
2023-04-22 22:55:58 -07:00
@ State var hopLimit = 3
2023-03-05 15:13:23 -08:00
@ State var txPower = 0
2022-09-18 08:56:08 -07:00
@ State var txEnabled = true
@ State var usePreset = true
2023-03-05 15:13:23 -08:00
@ State var channelNum = 0
2023-03-05 23:01:09 -08:00
@ State var bandwidth = 0
2023-03-05 15:13:23 -08:00
@ State var spreadFactor = 0
@ State var codingRate = 0
2023-03-08 21:14:46 -08:00
@ State var rxBoostedGain = false
2023-10-25 18:54:52 -07:00
@ State var overrideFrequency : Float = 0.0
2024-01-20 17:34:57 -08:00
@ State var ignoreMqtt = false
2023-10-25 18:54:52 -07:00
let floatFormatter : NumberFormatter = {
let formatter = NumberFormatter ( )
formatter . numberStyle = . decimal
return formatter
} ( )
2023-03-06 10:33:18 -08:00
2022-06-12 01:25:42 -07:00
var body : some View {
VStack {
Form {
2024-02-17 22:39:22 -07:00
ConfigHeader ( title : " LoRa " , config : \ . loRaConfig , node : node , onAppear : setLoRaValues )
2024-02-18 00:03:34 -07:00
2023-03-05 04:47:17 -08:00
Section ( header : Text ( " Options " ) ) {
2023-03-05 05:01:10 -08:00
2024-02-21 20:41:27 -08:00
VStack ( alignment : . leading ) {
Picker ( " Region " , selection : $ region ) {
ForEach ( RegionCodes . allCases ) { r in
Text ( r . description )
}
2022-06-12 01:25:42 -07:00
}
2024-02-21 20:41:27 -08:00
. fixedSize ( )
Text ( " The region where you will be using your radios. " )
. foregroundColor ( . gray )
2024-02-21 23:35:28 -08:00
. font ( . callout )
2022-06-12 01:25:42 -07:00
}
2024-02-21 23:35:28 -08:00
. pickerStyle ( DefaultPickerStyle ( ) )
2024-05-29 16:40:07 -05:00
2023-03-05 04:47:17 -08:00
Toggle ( isOn : $ usePreset ) {
Label ( " Use Preset " , systemImage : " list.bullet.rectangle " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-03-06 10:33:18 -08:00
2023-03-05 04:47:17 -08:00
if usePreset {
2024-02-21 20:41:27 -08:00
VStack ( alignment : . leading ) {
Picker ( " Presets " , selection : $ modemPreset ) {
ForEach ( ModemPresets . allCases ) { m in
Text ( m . description )
}
2023-03-05 04:47:17 -08:00
}
2024-02-21 20:41:27 -08:00
. pickerStyle ( DefaultPickerStyle ( ) )
. fixedSize ( )
Text ( " Available modem presets, default is Long Fast. " )
. foregroundColor ( . gray )
2024-02-21 23:35:28 -08:00
. font ( . callout )
2023-03-05 04:47:17 -08:00
}
2023-03-05 05:01:10 -08:00
}
}
Section ( header : Text ( " Advanced " ) ) {
2024-05-29 16:40:07 -05:00
2024-01-20 17:34:57 -08:00
Toggle ( isOn : $ ignoreMqtt ) {
Label ( " Ignore MQTT " , systemImage : " server.rack " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-03-06 10:33:18 -08:00
2023-03-05 05:01:10 -08:00
Toggle ( isOn : $ txEnabled ) {
Label ( " Transmit Enabled " , systemImage : " waveform.path " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-03-06 10:33:18 -08:00
2023-03-05 05:01:10 -08:00
if ! usePreset {
2023-03-05 05:42:25 -08:00
HStack {
2023-04-18 00:09:13 -07:00
Picker ( " Bandwidth " , selection : $ bandwidth ) {
ForEach ( Bandwidths . allCases ) { bw in
Text ( bw . description )
. tag ( bw . rawValue = = 250 ? 0 : bw . rawValue )
}
2023-03-05 16:01:39 -08:00
}
2023-03-05 05:42:25 -08:00
}
HStack {
2023-03-05 16:01:39 -08:00
Picker ( " Spread Factor " , selection : $ spreadFactor ) {
ForEach ( 7. . < 13 ) {
Text ( " \( $0 ) " )
. tag ( $0 = = 12 ? 0 : $0 )
2023-03-05 15:13:23 -08:00
}
2023-03-05 16:01:39 -08:00
}
2023-03-05 05:42:25 -08:00
}
HStack {
2023-03-05 16:01:39 -08:00
Picker ( " Coding Rate " , selection : $ codingRate ) {
ForEach ( 5. . < 9 ) {
Text ( " \( $0 ) " )
. tag ( $0 = = 8 ? 0 : $0 )
2023-03-05 15:13:23 -08:00
}
2023-03-05 16:01:39 -08:00
}
2023-03-05 05:42:25 -08:00
}
2022-06-12 01:25:42 -07:00
}
2024-02-21 20:41:27 -08:00
VStack ( alignment : . leading ) {
Picker ( " Number of hops " , selection : $ hopLimit ) {
2024-03-17 09:07:11 -07:00
ForEach ( 0. . < 8 ) {
2024-02-21 20:41:27 -08:00
Text ( " \( $0 ) " )
2024-03-17 09:07:11 -07:00
. tag ( $0 )
2024-02-21 20:41:27 -08:00
}
2022-06-12 22:07:58 -07:00
}
2024-03-17 09:07:11 -07:00
Text ( " Sets the maximum number of hops, default is 3. Increasing hops also increases congestion and should be used carefully. O hop broadcast messages will not get ACKs. " )
2024-02-21 20:41:27 -08:00
. foregroundColor ( . gray )
2024-02-21 23:35:28 -08:00
. font ( . callout )
2022-06-12 22:07:58 -07:00
}
2024-02-21 23:35:28 -08:00
. pickerStyle ( DefaultPickerStyle ( ) )
2024-05-29 16:40:07 -05:00
2024-02-21 20:41:27 -08:00
VStack ( alignment : . leading ) {
HStack {
Text ( " Frequency Slot " )
. fixedSize ( )
TextField ( " Frequency Slot " , value : $ channelNum , formatter : formatter )
. toolbar {
ToolbarItemGroup ( placement : . keyboard ) {
Button ( " dismiss.keyboard " ) {
focusedField = nil
}
. font ( . subheadline )
2023-03-05 15:13:23 -08:00
}
}
2024-02-21 20:41:27 -08:00
. keyboardType ( . decimalPad )
. scrollDismissesKeyboard ( . immediately )
. focused ( $ focusedField , equals : . channelNum )
. disabled ( overrideFrequency > 0.0 )
}
Text ( " This determines the actual frequency you are transmitting on in the band. If set to 0 this value will be calculated automatically based on the primary channel name. " )
. foregroundColor ( . gray )
2024-02-21 23:35:28 -08:00
. font ( . callout )
2023-03-05 04:47:17 -08:00
}
2024-05-29 16:40:07 -05:00
2023-03-08 21:14:46 -08:00
Toggle ( isOn : $ rxBoostedGain ) {
Label ( " RX Boosted Gain " , systemImage : " waveform.badge.plus " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2024-05-29 16:40:07 -05:00
2023-10-25 18:54:52 -07:00
HStack {
2023-11-08 22:01:24 -08:00
Label ( " Frequency Override " , systemImage : " waveform.path.ecg " )
2023-10-25 18:54:52 -07:00
Spacer ( )
TextField ( " Frequency Override " , value : $ overrideFrequency , formatter : floatFormatter )
. keyboardType ( . decimalPad )
. scrollDismissesKeyboard ( . immediately )
. focused ( $ focusedField , equals : . frequencyOverride )
}
2024-05-29 16:40:07 -05:00
2023-11-26 12:54:45 -08:00
HStack {
Image ( systemName : " antenna.radiowaves.left.and.right " )
. foregroundColor ( . accentColor )
2024-03-13 05:52:31 -07:00
Stepper ( " \( txPower ) dBm Transmit Power " , value : $ txPower , in : 1. . . 30 , step : 1 )
2023-11-26 12:54:45 -08:00
. padding ( 5 )
}
2022-06-12 22:07:58 -07:00
}
2022-06-12 01:25:42 -07:00
}
2023-01-31 22:08:03 -08:00
. disabled ( self . bleManager . connectedPeripheral = = nil || node ? . loRaConfig = = nil )
2023-03-06 10:33:18 -08:00
2024-02-18 00:03:34 -07:00
SaveConfigButton ( node : node , hasChanges : $ hasChanges ) {
2024-07-10 16:03:38 -05:00
let connectedNode = queryCoreDataController . getNodeInfo ( id : bleManager . connectedPeripheral ? . num ? ? 0 )
2024-02-18 00:03:34 -07:00
if connectedNode != nil {
var lc = Config . LoRaConfig ( )
lc . hopLimit = UInt32 ( hopLimit )
lc . region = RegionCodes ( rawValue : region ) ! . protoEnumValue ( )
lc . modemPreset = ModemPresets ( rawValue : modemPreset ) ! . protoEnumValue ( )
lc . usePreset = usePreset
lc . txEnabled = txEnabled
lc . txPower = Int32 ( txPower )
lc . channelNum = UInt32 ( channelNum )
lc . bandwidth = UInt32 ( bandwidth )
lc . codingRate = UInt32 ( codingRate )
lc . spreadFactor = UInt32 ( spreadFactor )
lc . sx126XRxBoostedGain = rxBoostedGain
lc . overrideFrequency = overrideFrequency
lc . ignoreMqtt = ignoreMqtt
2024-03-09 23:37:00 -08:00
if connectedNode ? . num ? ? - 1 = = node ? . user ? . num ? ? 0 {
UserDefaults . modemPreset = modemPreset
}
2024-02-18 00:03:34 -07:00
let adminMessageId = bleManager . saveLoRaConfig ( config : lc , fromUser : connectedNode ! . user ! , toUser : node ! . user ! , adminIndex : connectedNode ? . myInfo ? . adminIndex ? ? 0 )
if adminMessageId > 0 {
// S h o u l d s h o w a s a v e d s u c c e s s f u l l y a l e r t o n c e I k n o w t h a t t o b e t r u e
// f o r n o w j u s t 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 ( )
2022-06-20 12:51:55 -07:00
}
}
}
2022-06-12 01:25:42 -07:00
}
2022-12-13 07:49:46 -08:00
. navigationTitle ( " lora.config " )
2022-06-12 01:25:42 -07:00
. navigationBarItems ( trailing :
2023-03-05 04:47:17 -08:00
ZStack {
2023-09-02 17:37:35 -07:00
ConnectedDevice ( bluetoothOn : bleManager . isSwitchedOn , deviceConnected : bleManager . connectedPeripheral != nil , name : ( bleManager . connectedPeripheral != nil ) ? bleManager . connectedPeripheral . shortName : " ? " )
2022-06-12 01:25:42 -07:00
} )
. onAppear {
2023-03-19 18:37:23 -07:00
setLoRaValues ( )
2023-01-20 19:14:49 -08:00
// N e e d t o r e q u e s t a L o R a 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
2023-01-31 10:50:17 -08:00
if bleManager . connectedPeripheral != nil && node ? . loRaConfig = = nil {
2024-06-03 02:17:55 -07:00
Logger . mesh . info ( " empty lora config " )
2024-07-10 16:03:38 -05:00
let connectedNode = queryCoreDataController . getNodeInfo ( id : bleManager . connectedPeripheral . num )
2023-03-06 10:33:18 -08:00
if node != nil && connectedNode != nil {
2023-02-06 18:45:03 -08:00
_ = bleManager . requestLoRaConfig ( fromUser : connectedNode ! . user ! , toUser : node ! . user ! , adminIndex : connectedNode ? . myInfo ? . adminIndex ? ? 0 )
2023-01-31 10:50:17 -08:00
}
2023-01-20 19:14:49 -08:00
}
2022-06-12 01:25:42 -07:00
}
2022-06-20 22:48:38 -07:00
. onChange ( of : region ) { newRegion in
2022-07-11 16:18:16 -07:00
if node != nil && node ! . loRaConfig != nil {
2022-07-07 00:29:52 -07:00
if newRegion != node ! . loRaConfig ! . regionCode { hasChanges = true }
2022-06-20 23:48:47 -07:00
}
2022-06-20 00:13:04 -07:00
}
2023-03-05 04:47:17 -08:00
. onChange ( of : usePreset ) { newUsePreset in
if node != nil && node ! . loRaConfig != nil {
if newUsePreset != node ! . loRaConfig ! . usePreset { hasChanges = true }
}
}
2022-06-20 00:13:04 -07:00
. onChange ( of : modemPreset ) { newModemPreset in
2022-07-11 16:18:16 -07:00
if node != nil && node ! . loRaConfig != nil {
2022-07-07 00:29:52 -07:00
if newModemPreset != node ! . loRaConfig ! . modemPreset { hasChanges = true }
2022-06-20 23:48:47 -07:00
}
2022-06-20 00:13:04 -07:00
}
. onChange ( of : hopLimit ) { newHopLimit in
2022-07-11 16:18:16 -07:00
if node != nil && node ! . loRaConfig != nil {
2022-07-07 00:29:52 -07:00
if newHopLimit != node ! . loRaConfig ! . hopLimit { hasChanges = true }
2022-06-20 23:48:47 -07:00
}
2022-06-20 00:13:04 -07:00
}
2023-03-05 04:47:17 -08:00
. onChange ( of : channelNum ) { newChannelNum in
if node != nil && node ! . loRaConfig != nil {
if newChannelNum != node ! . loRaConfig ! . channelNum { hasChanges = true }
}
}
2023-03-05 05:42:25 -08:00
. onChange ( of : bandwidth ) { newBandwidth in
if node != nil && node ! . loRaConfig != nil {
2023-03-05 23:01:09 -08:00
if newBandwidth != node ! . loRaConfig ! . bandwidth { hasChanges = true }
2023-03-05 05:42:25 -08:00
}
}
. onChange ( of : codingRate ) { newCodingRate in
if node != nil && node ! . loRaConfig != nil {
if newCodingRate != node ! . loRaConfig ! . codingRate { hasChanges = true }
}
}
. onChange ( of : spreadFactor ) { newSpreadFactor in
if node != nil && node ! . loRaConfig != nil {
if newSpreadFactor != node ! . loRaConfig ! . spreadFactor { hasChanges = true }
}
}
2023-03-08 21:14:46 -08:00
. onChange ( of : rxBoostedGain ) { newRxBoostedGain in
if node != nil && node ! . loRaConfig != nil {
if newRxBoostedGain != node ! . loRaConfig ! . sx126xRxBoostedGain { hasChanges = true }
}
}
2023-11-08 22:01:24 -08:00
. onChange ( of : overrideFrequency ) { newOverrideFrequency in
if node != nil && node ! . loRaConfig != nil {
if newOverrideFrequency != node ! . loRaConfig ! . overrideFrequency { hasChanges = true }
}
}
2023-11-26 12:54:45 -08:00
. onChange ( of : txPower ) { newTxPower in
if node != nil && node ! . loRaConfig != nil {
if newTxPower != node ! . loRaConfig ! . txPower { hasChanges = true }
}
}
2023-12-28 15:37:08 -08:00
. onChange ( of : txEnabled ) { newTxEnabled in
if node != nil && node ! . loRaConfig != nil {
if newTxEnabled != node ! . loRaConfig ! . txEnabled { hasChanges = true }
}
}
2024-01-20 17:34:57 -08:00
. onChange ( of : ignoreMqtt ) { newIgnoreMqtt in
if node != nil && node ! . loRaConfig != nil {
if newIgnoreMqtt != node ! . loRaConfig ! . ignoreMqtt { hasChanges = true }
}
}
2022-06-12 01:25:42 -07:00
}
2023-03-19 18:37:23 -07:00
func setLoRaValues ( ) {
2023-04-22 22:55:58 -07:00
self . hopLimit = Int ( node ? . loRaConfig ? . hopLimit ? ? 3 )
2023-03-19 18:37:23 -07:00
self . region = Int ( node ? . loRaConfig ? . regionCode ? ? 0 )
self . usePreset = node ? . loRaConfig ? . usePreset ? ? true
self . modemPreset = Int ( node ? . loRaConfig ? . modemPreset ? ? 0 )
self . txEnabled = node ? . loRaConfig ? . txEnabled ? ? true
self . txPower = Int ( node ? . loRaConfig ? . txPower ? ? 0 )
self . channelNum = Int ( node ? . loRaConfig ? . channelNum ? ? 0 )
self . bandwidth = Int ( node ? . loRaConfig ? . bandwidth ? ? 0 )
self . codingRate = Int ( node ? . loRaConfig ? . codingRate ? ? 0 )
self . spreadFactor = Int ( node ? . loRaConfig ? . spreadFactor ? ? 0 )
self . rxBoostedGain = node ? . loRaConfig ? . sx126xRxBoostedGain ? ? false
2023-11-08 22:01:24 -08:00
self . overrideFrequency = node ? . loRaConfig ? . overrideFrequency ? ? 0.0
2024-01-20 17:34:57 -08:00
self . ignoreMqtt = node ? . loRaConfig ? . ignoreMqtt ? ? false
2023-03-19 18:37:23 -07:00
self . hasChanges = false
}
2022-06-12 01:25:42 -07:00
}