2022-06-22 09:05:56 -07:00
//
// E x t e r n a l N o t i f i c a 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 / 2 2 / 2 2 .
//
import SwiftUI
struct ExternalNotificationConfig : View {
2023-03-06 10:33:18 -08:00
2022-06-22 09:05:56 -07:00
@ Environment ( \ . managedObjectContext ) var context
@ EnvironmentObject var bleManager : BLEManager
2022-12-09 18:19:00 -08:00
@ Environment ( \ . dismiss ) private var goBack
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-07-01 10:57:54 -07:00
@ State private var isPresentingSaveConfirm : Bool = false
@ State var hasChanges = false
2022-06-22 09:05:56 -07:00
@ State var enabled = false
@ State var alertBell = false
2022-12-23 11:30:55 -08:00
@ State var alertBellBuzzer = false
@ State var alertBellVibra = false
2022-07-01 10:57:54 -07:00
@ State var alertMessage = false
2022-12-23 11:30:55 -08:00
@ State var alertMessageBuzzer = false
@ State var alertMessageVibra = false
2022-07-01 10:57:54 -07:00
@ State var active = false
2022-12-23 14:00:48 -08:00
@ State var usePWM = false
2022-07-01 10:57:54 -07:00
@ State var output = 0
2022-12-23 11:30:55 -08:00
@ State var outputBuzzer = 0
@ State var outputVibra = 0
2022-07-01 10:57:54 -07:00
@ State var outputMilliseconds = 0
2022-12-23 11:30:55 -08:00
@ State var nagTimeout = 0
2023-12-20 10:24:01 -08:00
@ State var useI2SAsBuzzer = false
2023-03-06 10:33:18 -08:00
2022-06-22 09:05:56 -07:00
var body : some View {
2023-12-06 12:32:17 -08:00
VStack {
Form {
if node != nil && node ? . metadata = = nil && node ? . num ? ? 0 != bleManager . connectedPeripheral ? . num ? ? 0 {
Text ( " There has been no response to a request for device metadata over the admin channel for this node. " )
2023-03-13 19:17:43 -07:00
. font ( . callout )
. foregroundColor ( . orange )
2023-12-06 12:32:17 -08:00
} else if node != nil && node ? . num ? ? 0 != bleManager . connectedPeripheral ? . num ? ? 0 {
// L e t u s e r s k n o w w h a t i s g o i n g o n i f t h e y a r e u s i n g r e m o t e a d m i n a n d d o n ' t h a v e t h e c o n f i g y e t
if node ? . externalNotificationConfig = = nil {
Text ( " External notification config data was requested over the admin channel but no response has been returned from the remote node. You can check the status of admin message requests in the admin message log. " )
. font ( . callout )
. foregroundColor ( . orange )
} else {
Text ( " Remote administration for: \( node ? . user ? . longName ? ? " Unknown " ) " )
. font ( . title3 )
. onAppear {
setExternalNotificationValues ( )
2022-12-23 11:30:55 -08:00
}
2022-12-23 14:00:48 -08:00
}
2023-12-06 12:32:17 -08:00
} else if node != nil && node ? . num ? ? 0 = = bleManager . connectedPeripheral ? . num ? ? 0 {
Text ( " Configuration for: \( node ? . user ? . longName ? ? " Unknown " ) " )
. font ( . title3 )
} else {
Text ( " Please connect to a radio to configure settings. " )
. font ( . callout )
. foregroundColor ( . orange )
2022-12-23 11:30:55 -08:00
}
2023-12-06 12:32:17 -08:00
Section ( header : Text ( " options " ) ) {
Toggle ( isOn : $ enabled ) {
Label ( " enabled " , systemImage : " megaphone " )
2022-06-22 09:05:56 -07:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-12-06 12:32:17 -08:00
Toggle ( isOn : $ alertBell ) {
Label ( " Alert when receiving a bell " , systemImage : " bell " )
2022-06-22 09:05:56 -07:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-12-06 12:32:17 -08:00
Toggle ( isOn : $ alertMessage ) {
Label ( " Alert when receiving a message " , systemImage : " message " )
2022-06-22 09:05:56 -07:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-12-06 12:32:17 -08:00
Toggle ( isOn : $ usePWM ) {
Label ( " Use PWM Buzzer " , systemImage : " light.beacon.max.fill " )
2022-06-22 09:05:56 -07:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2023-12-06 12:32:17 -08:00
Text ( " Use a PWM output (like the RAK Buzzer) for tunes instead of an on/off output. This will ignore the output, output duration and active settings and use the device config buzzer GPIO option instead. " )
. font ( . caption )
2023-12-20 10:24:01 -08:00
Toggle ( isOn : $ useI2SAsBuzzer ) {
Label ( " Use I2S As Buzzer " , systemImage : " light.beacon.max.fill " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Text ( " Enables devices with native I2S audio output to use the RTTTL over speaker like a buzzer. T-Watch S3 and T-Deck for example have this capability. " )
. font ( . caption )
2023-12-06 12:32:17 -08:00
}
Section ( header : Text ( " Advanced GPIO Options " ) ) {
Section ( header : Text ( " Primary GPIO " )
. font ( . caption )
. foregroundColor ( . gray )
. textCase ( . uppercase ) ) {
Toggle ( isOn : $ active ) {
Label ( " Active " , systemImage : " togglepower " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Text ( " If enabled, the 'output' Pin will be pulled active high, disabled means active low. " )
. font ( . caption )
Picker ( " Output pin GPIO " , selection : $ output ) {
ForEach ( 0. . < 46 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
}
}
2022-06-22 15:52:51 -07:00
}
2023-12-06 12:32:17 -08:00
. pickerStyle ( DefaultPickerStyle ( ) )
Picker ( " GPIO Output Duration " , selection : $ outputMilliseconds ) {
ForEach ( OutputIntervals . allCases ) { oi in
Text ( oi . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " When using in GPIO mode, keep the output on for this long. " )
. font ( . caption )
Picker ( " Nag timeout " , selection : $ nagTimeout ) {
ForEach ( OutputIntervals . allCases ) { oi in
Text ( oi . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Text ( " Specifies how long the monitored GPIO should output. " )
. font ( . caption )
2022-06-22 09:05:56 -07:00
}
2023-12-06 12:32:17 -08:00
Section ( header : Text ( " Optional GPIO " )
. font ( . caption )
. foregroundColor ( . gray )
. textCase ( . uppercase ) ) {
Toggle ( isOn : $ alertBellBuzzer ) {
Label ( " Alert GPIO buzzer when receiving a bell " , systemImage : " bell " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Toggle ( isOn : $ alertBellVibra ) {
Label ( " Alert GPIO vibra motor when receiving a bell " , systemImage : " bell " )
2022-11-29 21:24:20 -08:00
}
2023-12-06 12:32:17 -08:00
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Toggle ( isOn : $ alertMessageBuzzer ) {
Label ( " Alert GPIO buzzer when receiving a message " , systemImage : " message " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Toggle ( isOn : $ alertMessageBuzzer ) {
Label ( " Alert GPIO vibra motor when receiving a message " , systemImage : " message " )
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
Picker ( " Output pin buzzer GPIO " , selection : $ outputBuzzer ) {
ForEach ( 0. . < 46 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Picker ( " Output pin vibra GPIO " , selection : $ outputVibra ) {
ForEach ( 0. . < 46 ) {
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
2022-06-29 20:04:20 -07:00
}
2022-07-01 10:57:54 -07:00
}
}
2023-12-06 12:32:17 -08:00
. disabled ( self . bleManager . connectedPeripheral = = nil || node ? . externalNotificationConfig = = nil )
2022-12-23 11:30:55 -08:00
}
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 ,
titleVisibility : . visible
) {
2023-02-22 20:31:08 -08:00
let connectedNode = getNodeInfo ( id : bleManager . connectedPeripheral ? . num ? ? - 1 , context : context )
2023-02-06 18:45:03 -08:00
if connectedNode != nil {
2023-05-05 09:27:24 -07:00
let nodeName = node ? . user ? . longName ? ? " unknown " . localized
let buttonText = String . localizedStringWithFormat ( " save.config %@ " . localized , nodeName )
2023-02-06 18:45:03 -08:00
Button ( buttonText ) {
var enc = ModuleConfig . ExternalNotificationConfig ( )
enc . enabled = enabled
enc . alertBell = alertBell
enc . alertBellBuzzer = alertBellBuzzer
enc . alertBellVibra = alertBellVibra
enc . alertMessage = alertMessage
enc . alertMessageBuzzer = alertMessageBuzzer
enc . alertMessageVibra = alertMessageVibra
enc . active = active
enc . output = UInt32 ( output )
2023-03-18 17:26:13 -07:00
enc . nagTimeout = UInt32 ( nagTimeout )
2023-02-06 18:45:03 -08:00
enc . outputBuzzer = UInt32 ( outputBuzzer )
enc . outputVibra = UInt32 ( outputVibra )
enc . outputMs = UInt32 ( outputMilliseconds )
enc . usePwm = usePWM
2023-12-20 10:24:01 -08:00
enc . useI2SAsBuzzer = useI2SAsBuzzer
2023-02-06 18:45:03 -08:00
let adminMessageId = bleManager . saveExternalNotificationModuleConfig ( config : enc , fromUser : connectedNode ! . user ! , toUser : node ! . user ! , adminIndex : connectedNode ? . myInfo ? . adminIndex ? ? 0 )
2023-03-06 10:33:18 -08:00
if adminMessageId > 0 {
2023-02-06 18:45:03 -08:00
// 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-07-11 16:18:16 -07:00
}
2022-07-02 12:34:45 -07:00
}
2022-12-23 11:30:55 -08:00
}
2022-12-30 11:08:59 -08:00
message : {
Text ( " config.save.confirm " )
}
2022-12-23 11:30:55 -08:00
. navigationTitle ( " external.notification.config " )
. navigationBarItems ( trailing :
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-12-23 11:30:55 -08:00
} )
. onAppear {
self . bleManager . context = context
2023-03-19 18:37:23 -07:00
setExternalNotificationValues ( )
2023-03-06 10:33:18 -08:00
2023-02-01 09:19:45 -08:00
// N e e d t o r e q u e s t a T e l e m e t r y M o d u l e 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
if bleManager . connectedPeripheral != nil && node ? . externalNotificationConfig = = nil {
print ( " empty external notification module config " )
let connectedNode = getNodeInfo ( id : bleManager . connectedPeripheral . num , context : context )
2023-03-05 14:40:07 -08:00
if node != nil && connectedNode != nil {
2023-02-06 18:45:03 -08:00
_ = bleManager . requestExternalNotificationModuleConfig ( fromUser : connectedNode ! . user ! , toUser : node ! . user ! , adminIndex : connectedNode ? . myInfo ? . adminIndex ? ? 0 )
2023-02-01 09:19:45 -08:00
}
}
2022-12-23 11:30:55 -08:00
}
. onChange ( of : enabled ) { newEnabled in
if node != nil && node ! . externalNotificationConfig != nil {
if newEnabled != node ! . externalNotificationConfig ! . enabled { hasChanges = true }
2022-07-02 12:34:45 -07:00
}
2022-12-23 11:30:55 -08:00
}
. onChange ( of : alertBell ) { newAlertBell in
if node != nil && node ! . externalNotificationConfig != nil {
if newAlertBell != node ! . externalNotificationConfig ! . alertBell { hasChanges = true }
2022-07-02 12:34:45 -07:00
}
2022-12-23 11:30:55 -08:00
}
. onChange ( of : alertBellBuzzer ) { newAlertBellBuzzer in
if node != nil && node ! . externalNotificationConfig != nil {
if newAlertBellBuzzer != node ! . externalNotificationConfig ! . alertBellBuzzer { hasChanges = true }
2022-07-02 12:34:45 -07:00
}
2022-12-23 11:30:55 -08:00
}
. onChange ( of : alertBellVibra ) { newAlertBellVibra in
if node != nil && node ! . externalNotificationConfig != nil {
if newAlertBellVibra != node ! . externalNotificationConfig ! . alertBellVibra { hasChanges = true }
2022-07-02 12:34:45 -07:00
}
2022-12-23 11:30:55 -08:00
}
. onChange ( of : alertMessage ) { newAlertMessage in
if node != nil && node ! . externalNotificationConfig != nil {
if newAlertMessage != node ! . externalNotificationConfig ! . alertMessage { hasChanges = true }
2022-06-22 09:05:56 -07:00
}
2022-12-23 11:30:55 -08:00
}
. onChange ( of : alertMessageBuzzer ) { newAlertMessageBuzzer in
if node != nil && node ! . externalNotificationConfig != nil {
if newAlertMessageBuzzer != node ! . externalNotificationConfig ! . alertMessageBuzzer { hasChanges = true }
}
}
. onChange ( of : alertMessageVibra ) { newAlertMessageVibra in
if node != nil && node ! . externalNotificationConfig != nil {
if newAlertMessageVibra != node ! . externalNotificationConfig ! . alertMessageVibra { hasChanges = true }
}
}
. onChange ( of : active ) { newActive in
if node != nil && node ! . externalNotificationConfig != nil {
if newActive != node ! . externalNotificationConfig ! . active { hasChanges = true }
}
}
. onChange ( of : output ) { newOutput in
if node != nil && node ! . externalNotificationConfig != nil {
if newOutput != node ! . externalNotificationConfig ! . output { hasChanges = true }
}
}
. onChange ( of : output ) { newOutputBuzzer in
if node != nil && node ! . externalNotificationConfig != nil {
if newOutputBuzzer != node ! . externalNotificationConfig ! . outputBuzzer { hasChanges = true }
}
}
. onChange ( of : output ) { newOutputVibra in
if node != nil && node ! . externalNotificationConfig != nil {
if newOutputVibra != node ! . externalNotificationConfig ! . outputVibra { hasChanges = true }
}
}
. onChange ( of : outputMilliseconds ) { newOutputMs in
if node != nil && node ! . externalNotificationConfig != nil {
if newOutputMs != node ! . externalNotificationConfig ! . outputMilliseconds { hasChanges = true }
}
}
. onChange ( of : usePWM ) { newUsePWM in
if node != nil && node ! . externalNotificationConfig != nil {
if newUsePWM != node ! . externalNotificationConfig ! . usePWM { hasChanges = true }
}
}
. onChange ( of : nagTimeout ) { newNagTimeout in
if node != nil && node ! . externalNotificationConfig != nil {
if newNagTimeout != node ! . externalNotificationConfig ! . nagTimeout { hasChanges = true }
2022-11-29 21:24:20 -08:00
}
2022-06-22 09:05:56 -07:00
}
2023-12-20 10:24:01 -08:00
. onChange ( of : useI2SAsBuzzer ) { newUseI2SAsBuzzer in
if node != nil && node ! . externalNotificationConfig != nil {
if newUseI2SAsBuzzer != node ! . externalNotificationConfig ! . useI2SAsBuzzer { hasChanges = true }
}
}
2022-06-22 09:05:56 -07:00
}
2023-03-19 18:37:23 -07:00
func setExternalNotificationValues ( ) {
self . enabled = node ? . externalNotificationConfig ? . enabled ? ? false
self . alertBell = node ? . externalNotificationConfig ? . alertBell ? ? false
self . alertBellBuzzer = node ? . externalNotificationConfig ? . alertBellBuzzer ? ? false
self . alertBellVibra = node ? . externalNotificationConfig ? . alertBellVibra ? ? false
self . alertMessage = node ? . externalNotificationConfig ? . alertMessage ? ? false
self . alertMessageBuzzer = node ? . externalNotificationConfig ? . alertMessageBuzzer ? ? false
self . alertMessageVibra = node ? . externalNotificationConfig ? . alertMessageVibra ? ? false
self . active = node ? . externalNotificationConfig ? . active ? ? false
self . output = Int ( node ? . externalNotificationConfig ? . output ? ? 0 )
self . outputBuzzer = Int ( node ? . externalNotificationConfig ? . outputBuzzer ? ? 0 )
self . outputVibra = Int ( node ? . externalNotificationConfig ? . outputVibra ? ? 0 )
self . outputMilliseconds = Int ( node ? . externalNotificationConfig ? . outputMilliseconds ? ? 0 )
self . nagTimeout = Int ( node ? . externalNotificationConfig ? . nagTimeout ? ? 0 )
self . usePWM = node ? . externalNotificationConfig ? . usePWM ? ? false
2023-12-20 10:24:01 -08:00
self . useI2SAsBuzzer = node ? . externalNotificationConfig ? . useI2SAsBuzzer ? ? false
2023-03-19 18:37:23 -07:00
self . hasChanges = false
}
2022-06-22 09:05:56 -07:00
}