2022-06-22 09:05:56 -07:00
|
|
|
//
|
|
|
|
|
// External Notification Config.swift
|
|
|
|
|
// Meshtastic Apple
|
|
|
|
|
//
|
|
|
|
|
// Copyright (c) Garth Vander Houwen 6/22/22.
|
|
|
|
|
//
|
|
|
|
|
import SwiftUI
|
|
|
|
|
|
2022-06-29 20:04:20 -07:00
|
|
|
enum OutputIntervals: Int, CaseIterable, Identifiable {
|
|
|
|
|
|
2022-09-10 18:27:44 -07:00
|
|
|
case oneSecond = 1000
|
2022-06-29 20:04:20 -07:00
|
|
|
case twoSeconds = 2000
|
|
|
|
|
case threeSeconds = 3000
|
|
|
|
|
case fourSeconds = 4000
|
|
|
|
|
case fiveSeconds = 5000
|
|
|
|
|
case tenSeconds = 10000
|
|
|
|
|
case fifteenSeconds = 15000
|
|
|
|
|
case thirtySeconds = 30000
|
|
|
|
|
case oneMinute = 60000
|
|
|
|
|
|
|
|
|
|
var id: Int { self.rawValue }
|
|
|
|
|
var description: String {
|
|
|
|
|
get {
|
|
|
|
|
switch self {
|
|
|
|
|
|
|
|
|
|
case .oneSecond:
|
|
|
|
|
return "One Second"
|
|
|
|
|
case .twoSeconds:
|
|
|
|
|
return "Two Seconds"
|
|
|
|
|
case .threeSeconds:
|
|
|
|
|
return "Three Seconds"
|
|
|
|
|
case .fourSeconds:
|
|
|
|
|
return "Four Seconds"
|
|
|
|
|
case .fiveSeconds:
|
|
|
|
|
return "Five Seconds"
|
|
|
|
|
case .tenSeconds:
|
|
|
|
|
return "Ten Seconds"
|
|
|
|
|
case .fifteenSeconds:
|
|
|
|
|
return "Fifteen Seconds"
|
|
|
|
|
case .thirtySeconds:
|
|
|
|
|
return "Thirty Seconds"
|
|
|
|
|
case .oneMinute:
|
|
|
|
|
return "One Minute"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-22 09:05:56 -07:00
|
|
|
struct ExternalNotificationConfig: View {
|
|
|
|
|
|
|
|
|
|
@Environment(\.managedObjectContext) var context
|
|
|
|
|
@EnvironmentObject var bleManager: BLEManager
|
|
|
|
|
|
2022-07-07 00:29:52 -07:00
|
|
|
var node: NodeInfoEntity?
|
2022-06-22 09:05:56 -07:00
|
|
|
|
2022-07-01 10:57:54 -07:00
|
|
|
@State private var isPresentingSaveConfirm: Bool = false
|
|
|
|
|
@State var initialLoad: Bool = true
|
|
|
|
|
@State var hasChanges = false
|
|
|
|
|
|
2022-06-22 09:05:56 -07:00
|
|
|
@State var enabled = false
|
|
|
|
|
@State var alertBell = false
|
2022-07-01 10:57:54 -07:00
|
|
|
@State var alertMessage = false
|
|
|
|
|
@State var active = false
|
|
|
|
|
@State var output = 0
|
|
|
|
|
@State var outputMilliseconds = 0
|
2022-06-22 09:05:56 -07:00
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
|
|
|
|
|
|
VStack {
|
|
|
|
|
|
|
|
|
|
Form {
|
|
|
|
|
|
|
|
|
|
Section(header: Text("Options")) {
|
|
|
|
|
|
|
|
|
|
Toggle(isOn: $enabled) {
|
|
|
|
|
|
2022-06-22 15:52:51 -07:00
|
|
|
Label("Enabled", systemImage: "megaphone")
|
2022-06-22 09:05:56 -07:00
|
|
|
}
|
|
|
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
|
|
|
|
|
|
|
|
Toggle(isOn: $alertBell) {
|
|
|
|
|
|
|
|
|
|
Label("Alert when receiving a bell", systemImage: "bell")
|
|
|
|
|
}
|
|
|
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
|
|
|
|
|
|
|
|
Toggle(isOn: $alertMessage) {
|
|
|
|
|
|
|
|
|
|
Label("Alert when receiving a message", systemImage: "message")
|
|
|
|
|
}
|
|
|
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Section(header: Text("GPIO")) {
|
|
|
|
|
|
|
|
|
|
Toggle(isOn: $active) {
|
|
|
|
|
|
|
|
|
|
Label("Active", systemImage: "togglepower")
|
|
|
|
|
}
|
|
|
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
|
|
|
Text("Specifies whether the external circuit is triggered when the device's GPIO is low or high.")
|
|
|
|
|
.font(.caption)
|
|
|
|
|
.listRowSeparator(.visible)
|
|
|
|
|
|
|
|
|
|
Picker("GPIO to monitor", selection: $output) {
|
2022-06-22 15:52:51 -07:00
|
|
|
ForEach(0..<40) {
|
2022-06-22 09:05:56 -07:00
|
|
|
|
2022-06-22 15:52:51 -07:00
|
|
|
if $0 == 0 {
|
|
|
|
|
|
|
|
|
|
Text("Unset")
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
Text("Pin \($0)")
|
|
|
|
|
}
|
2022-06-22 09:05:56 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.pickerStyle(DefaultPickerStyle())
|
|
|
|
|
Text("Specifies the GPIO that your external circuit is attached to on the device.")
|
|
|
|
|
.font(.caption)
|
2022-06-29 20:04:20 -07:00
|
|
|
|
|
|
|
|
Picker("GPIO Output Duration", selection: $outputMilliseconds ) {
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
}
|
2022-07-14 07:14:43 -07:00
|
|
|
.disabled(bleManager.connectedPeripheral == nil)
|
2022-07-01 10:57:54 -07:00
|
|
|
|
|
|
|
|
Button {
|
|
|
|
|
|
|
|
|
|
isPresentingSaveConfirm = true
|
|
|
|
|
|
|
|
|
|
} label: {
|
|
|
|
|
|
|
|
|
|
Label("Save", systemImage: "square.and.arrow.down")
|
|
|
|
|
}
|
2022-08-04 19:43:03 -07:00
|
|
|
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
2022-07-01 10:57:54 -07:00
|
|
|
.buttonStyle(.bordered)
|
|
|
|
|
.buttonBorderShape(.capsule)
|
|
|
|
|
.controlSize(.large)
|
|
|
|
|
.padding()
|
|
|
|
|
.confirmationDialog(
|
|
|
|
|
|
|
|
|
|
"Are you sure?",
|
|
|
|
|
isPresented: $isPresentingSaveConfirm
|
|
|
|
|
) {
|
|
|
|
|
Button("Save External Notification Module Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
|
|
|
|
|
|
|
|
|
var enc = ModuleConfig.ExternalNotificationConfig()
|
|
|
|
|
enc.enabled = enabled
|
|
|
|
|
enc.alertBell = alertBell
|
|
|
|
|
enc.alertMessage = alertMessage
|
|
|
|
|
enc.active = active
|
|
|
|
|
enc.output = UInt32(output)
|
|
|
|
|
enc.outputMs = UInt32(outputMilliseconds)
|
|
|
|
|
|
2022-08-11 23:34:09 -07:00
|
|
|
let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: node!.user!, toUser: node!.user!)
|
2022-07-02 12:34:45 -07:00
|
|
|
|
|
|
|
|
if adminMessageId > 0{
|
2022-07-01 10:57:54 -07:00
|
|
|
|
|
|
|
|
// Should show a saved successfully alert once I know that to be true
|
|
|
|
|
// for now just disable the button after a successful save
|
|
|
|
|
hasChanges = false
|
|
|
|
|
|
2022-07-02 12:34:45 -07:00
|
|
|
} else {
|
2022-07-01 10:57:54 -07:00
|
|
|
|
2022-07-02 12:34:45 -07:00
|
|
|
}
|
2022-07-01 10:57:54 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-22 09:05:56 -07:00
|
|
|
.navigationTitle("External Notification Config")
|
|
|
|
|
.navigationBarItems(trailing:
|
|
|
|
|
|
|
|
|
|
ZStack {
|
|
|
|
|
|
2022-07-01 19:44:25 -07:00
|
|
|
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
2022-06-22 09:05:56 -07:00
|
|
|
})
|
|
|
|
|
.onAppear {
|
|
|
|
|
|
2022-07-02 12:34:45 -07:00
|
|
|
if self.initialLoad{
|
|
|
|
|
|
|
|
|
|
self.bleManager.context = context
|
|
|
|
|
|
2022-09-27 22:18:50 -07:00
|
|
|
self.enabled = node?.externalNotificationConfig?.enabled ?? false
|
|
|
|
|
self.alertBell = node?.externalNotificationConfig?.alertBell ?? false
|
|
|
|
|
self.alertMessage = node?.externalNotificationConfig?.alertMessage ?? false
|
|
|
|
|
self.active = node?.externalNotificationConfig?.active ?? false
|
|
|
|
|
self.output = Int(node?.externalNotificationConfig?.output ?? 0)
|
|
|
|
|
self.outputMilliseconds = Int(node?.externalNotificationConfig?.outputMilliseconds ?? 0)
|
2022-07-02 12:34:45 -07:00
|
|
|
|
|
|
|
|
self.hasChanges = false
|
|
|
|
|
self.initialLoad = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.onChange(of: enabled) { newEnabled in
|
|
|
|
|
|
2022-07-11 16:18:16 -07:00
|
|
|
if node != nil && node!.externalNotificationConfig != nil {
|
|
|
|
|
|
|
|
|
|
if newEnabled != node!.externalNotificationConfig!.enabled { hasChanges = true }
|
|
|
|
|
}
|
2022-07-02 12:34:45 -07:00
|
|
|
}
|
|
|
|
|
.onChange(of: alertBell) { newAlertBell in
|
|
|
|
|
|
2022-07-11 16:18:16 -07:00
|
|
|
if node != nil && node!.externalNotificationConfig != nil {
|
|
|
|
|
|
|
|
|
|
if newAlertBell != node!.externalNotificationConfig!.alertBell { hasChanges = true }
|
|
|
|
|
}
|
2022-07-02 12:34:45 -07:00
|
|
|
}
|
|
|
|
|
.onChange(of: alertMessage) { newAlertMessage in
|
|
|
|
|
|
2022-07-11 16:18:16 -07:00
|
|
|
if node != nil && node!.externalNotificationConfig != nil {
|
|
|
|
|
|
|
|
|
|
if newAlertMessage != node!.externalNotificationConfig!.alertMessage { hasChanges = true }
|
|
|
|
|
}
|
2022-07-02 12:34:45 -07:00
|
|
|
}
|
|
|
|
|
.onChange(of: active) { newActuve in
|
|
|
|
|
|
2022-07-11 16:18:16 -07:00
|
|
|
if node != nil && node!.externalNotificationConfig != nil {
|
|
|
|
|
|
|
|
|
|
if newActuve != node!.externalNotificationConfig!.active { hasChanges = true }
|
|
|
|
|
}
|
2022-07-02 12:34:45 -07:00
|
|
|
}
|
|
|
|
|
.onChange(of: output) { newOutput in
|
|
|
|
|
|
2022-07-11 16:18:16 -07:00
|
|
|
if node != nil && node!.externalNotificationConfig != nil {
|
|
|
|
|
|
|
|
|
|
if newOutput != node!.externalNotificationConfig!.output { hasChanges = true }
|
|
|
|
|
}
|
2022-07-02 12:34:45 -07:00
|
|
|
}
|
|
|
|
|
.onChange(of: outputMilliseconds) { newOutputMs in
|
|
|
|
|
|
2022-07-11 16:18:16 -07:00
|
|
|
if node != nil && node!.externalNotificationConfig != nil {
|
|
|
|
|
|
|
|
|
|
if newOutputMs != node!.externalNotificationConfig!.outputMilliseconds { hasChanges = true }
|
|
|
|
|
}
|
2022-06-22 09:05:56 -07:00
|
|
|
}
|
|
|
|
|
.navigationViewStyle(StackNavigationViewStyle())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|