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 .
//
2024-06-07 22:09:20 -05:00
import MeshtasticProtobufs
2024-06-03 02:17:55 -07:00
import OSLog
2024-06-07 22:09:20 -05:00
import SwiftUI
2022-06-22 09:05:56 -07:00
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 {
2024-02-17 22:39:22 -07:00
ConfigHeader ( title : " External notification " , config : \ . externalNotificationConfig , node : node , onAppear : setExternalNotificationValues )
2023-12-06 12:32:17 -08:00
Section ( header : Text ( " options " ) ) {
2024-05-29 16:40:07 -05:00
2023-12-06 12:32:17 -08:00
Toggle ( isOn : $ enabled ) {
Label ( " enabled " , systemImage : " megaphone " )
2022-06-22 09:05:56 -07:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2024-05-29 16:40:07 -05:00
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 ) )
2024-05-29 16:40:07 -05:00
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 ) )
2024-05-29 16:40:07 -05:00
2023-12-06 12:32:17 -08:00
Toggle ( isOn : $ usePWM ) {
Label ( " Use PWM Buzzer " , systemImage : " light.beacon.max.fill " )
2024-02-21 23:35:28 -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. " )
2022-06-22 09:05:56 -07:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2024-05-29 16:40:07 -05:00
2023-12-20 10:24:01 -08:00
Toggle ( isOn : $ useI2SAsBuzzer ) {
Label ( " Use I2S As Buzzer " , systemImage : " light.beacon.max.fill " )
2024-02-21 23:35:28 -08:00
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. " )
2023-12-20 10:24:01 -08:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
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 " )
2024-02-21 23:35:28 -08:00
Text ( " If enabled, the 'output' Pin will be pulled active high, disabled means active low. " )
2023-12-06 12:32:17 -08:00
}
. toggleStyle ( SwitchToggleStyle ( tint : . accentColor ) )
2024-05-29 16:40:07 -05:00
2023-12-06 12:32:17 -08:00
Picker ( " Output pin GPIO " , selection : $ output ) {
2024-01-22 13:21:17 -08:00
ForEach ( 0. . < 49 ) {
2023-12-06 12:32:17 -08:00
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 ( ) )
2024-02-21 23:35:28 -08:00
. listRowSeparator ( . visible )
2024-05-29 16:40:07 -05:00
2023-12-06 12:32:17 -08:00
Picker ( " GPIO Output Duration " , selection : $ outputMilliseconds ) {
ForEach ( OutputIntervals . allCases ) { oi in
Text ( oi . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
2024-02-21 23:35:28 -08:00
. listRowSeparator ( . hidden )
2023-12-06 12:32:17 -08:00
Text ( " When using in GPIO mode, keep the output on for this long. " )
2024-02-21 23:35:28 -08:00
. foregroundColor ( . gray )
. font ( . callout )
. listRowSeparator ( . visible )
2024-05-29 16:40:07 -05:00
2023-12-06 12:32:17 -08:00
Picker ( " Nag timeout " , selection : $ nagTimeout ) {
2024-05-31 20:25:37 -07:00
ForEach ( NagIntervals . allCases ) { oi in
2023-12-06 12:32:17 -08:00
Text ( oi . description )
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
2024-02-21 23:35:28 -08:00
. listRowSeparator ( . hidden )
2023-12-06 12:32:17 -08:00
Text ( " Specifies how long the monitored GPIO should output. " )
2024-02-21 23:35:28 -08:00
. foregroundColor ( . gray )
. font ( . callout )
2022-06-22 09:05:56 -07:00
}
2024-05-29 16:40:07 -05: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 ) {
2024-01-22 13:21:17 -08:00
ForEach ( 0. . < 49 ) {
2023-12-06 12:32:17 -08:00
if $0 = = 0 {
Text ( " unset " )
} else {
Text ( " Pin \( $0 ) " )
}
}
}
. pickerStyle ( DefaultPickerStyle ( ) )
Picker ( " Output pin vibra GPIO " , selection : $ outputVibra ) {
2024-01-22 13:21:17 -08:00
ForEach ( 0. . < 49 ) {
2023-12-06 12:32:17 -08:00
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
}
2024-02-18 00:03:34 -07:00
SaveConfigButton ( node : node , hasChanges : $ hasChanges ) {
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 {
2024-02-18 00:03:34 -07:00
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 )
enc . nagTimeout = UInt32 ( nagTimeout )
enc . outputBuzzer = UInt32 ( outputBuzzer )
enc . outputVibra = UInt32 ( outputVibra )
enc . outputMs = UInt32 ( outputMilliseconds )
enc . usePwm = usePWM
enc . useI2SAsBuzzer = useI2SAsBuzzer
let adminMessageId = bleManager . saveExternalNotificationModuleConfig ( config : enc , 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-07-11 16:18:16 -07:00
}
2022-07-02 12:34:45 -07:00
}
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 {
2023-03-19 18:37:23 -07:00
setExternalNotificationValues ( )
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 {
2024-06-03 02:17:55 -07:00
Logger . mesh . info ( " empty external notification module config " )
2023-02-01 09:19:45 -08:00
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
}