mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #205 from meshtastic/1.3.43_Protos
Bump Version to manage UUID update
This commit is contained in:
commit
8b7b35c1ea
7 changed files with 75 additions and 155 deletions
|
|
@ -964,7 +964,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.43;
|
||||
MARKETING_VERSION = 1.3.44;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -996,7 +996,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.43;
|
||||
MARKETING_VERSION = 1.3.44;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ enum ConfigPresets : Int, CaseIterable, Identifiable {
|
|||
|
||||
case unset = 0
|
||||
case rakRotaryEncoder = 1
|
||||
case tbeamThreeButtonScreen = 2
|
||||
case cardKB = 3
|
||||
case facesKB = 4
|
||||
case cardKB = 2
|
||||
case facesKB = 3
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
|
|
@ -23,8 +22,6 @@ enum ConfigPresets : Int, CaseIterable, Identifiable {
|
|||
return "Manual Configuration"
|
||||
case .rakRotaryEncoder:
|
||||
return "RAK Rotary Encoder Module"
|
||||
case .tbeamThreeButtonScreen:
|
||||
return "TBEAM 3 Button OLED Screen"
|
||||
case .cardKB:
|
||||
return "M5 Stack Card KeyBoard"
|
||||
case .facesKB:
|
||||
|
|
@ -37,35 +34,35 @@ enum ConfigPresets : Int, CaseIterable, Identifiable {
|
|||
// Default of 0 is off
|
||||
enum InputEventChars: Int, CaseIterable, Identifiable {
|
||||
|
||||
case keyNone = 0
|
||||
case keyUp = 17
|
||||
case keyDown = 18
|
||||
case keyLeft = 19
|
||||
case keyRight = 20
|
||||
case keySelect = 10
|
||||
case keyBack = 27
|
||||
case keyCancel = 24
|
||||
case none = 0
|
||||
case up = 17
|
||||
case down = 18
|
||||
case left = 19
|
||||
case right = 20
|
||||
case select = 10
|
||||
case back = 27
|
||||
case cancel = 24
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .keyNone:
|
||||
case .none:
|
||||
return "None"
|
||||
case .keyUp:
|
||||
case .up:
|
||||
return "Up"
|
||||
case .keyDown:
|
||||
case .down:
|
||||
return "Down"
|
||||
case .keyLeft:
|
||||
case .left:
|
||||
return "Left"
|
||||
case .keyRight:
|
||||
case .right:
|
||||
return "Right"
|
||||
case .keySelect:
|
||||
case .select:
|
||||
return "Select"
|
||||
case .keyBack:
|
||||
case .back:
|
||||
return "Back"
|
||||
case .keyCancel:
|
||||
case .cancel:
|
||||
return "Cancel"
|
||||
}
|
||||
}
|
||||
|
|
@ -74,21 +71,21 @@ enum InputEventChars: Int, CaseIterable, Identifiable {
|
|||
|
||||
switch self {
|
||||
|
||||
case .keyNone:
|
||||
case .none:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.none
|
||||
case .keyUp:
|
||||
case .up:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.up
|
||||
case .keyDown:
|
||||
case .down:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.down
|
||||
case .keyLeft:
|
||||
case .left:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.left
|
||||
case .keyRight:
|
||||
case .right:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.right
|
||||
case .keySelect:
|
||||
case .select:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.select
|
||||
case .keyBack:
|
||||
case .back:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.back
|
||||
case .keyCancel:
|
||||
case .cancel:
|
||||
return ModuleConfig.CannedMessageConfig.InputEventChar.cancel
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
let meshtasticServiceCBUUID = CBUUID(string: "0x6BA1B218-15A8-461F-9FA8-5DCAE273EAFD")
|
||||
let TORADIO_UUID = CBUUID(string: "0xF75C76D2-129E-4DAD-A1DD-7866124401E7")
|
||||
let FROMRADIO_UUID = CBUUID(string: "2c55e69e-4993-11ed-b878-0242ac120002")
|
||||
let FROMRADIO_UUID = CBUUID(string: "0x2C55E69E-4993-11ED-B878-0242AC120002")
|
||||
let EOL_FROMRADIO_UUID = CBUUID(string: "0x8BA2BCC2-EE02-4A55-A531-C525C5E454D5")
|
||||
let FROMNUM_UUID = CBUUID(string: "0xED9DA18C-A800-4F66-A670-AA7547E34453")
|
||||
|
||||
|
|
@ -235,7 +235,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
self.isConnecting = false
|
||||
self.isConnected = true
|
||||
|
||||
if userSettings?.preferredPeripheralId.count ?? 0 < 1 {
|
||||
self.userSettings?.preferredPeripheralId = peripheral.identifier.uuidString
|
||||
self.preferredPeripheral = true
|
||||
|
|
@ -244,41 +243,32 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
} else {
|
||||
print("Trying to connect a non prefered peripheral")
|
||||
}
|
||||
|
||||
// Invalidate and reset connection timer count, remove any connection errors
|
||||
self.lastConnectionError = ""
|
||||
self.timeoutTimerCount = 0
|
||||
if self.timeoutTimer != nil {
|
||||
|
||||
self.timeoutTimer!.invalidate()
|
||||
}
|
||||
|
||||
// Map the peripheral to the connectedPeripheral ObservedObjects
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier == peripheral.identifier }).first
|
||||
|
||||
if connectedPeripheral != nil {
|
||||
|
||||
connectedPeripheral.peripheral.delegate = self
|
||||
}
|
||||
else {
|
||||
|
||||
// we are null just disconnect and start over
|
||||
self.lastConnectionError = "Bluetooth connection error, please try again."
|
||||
self.disconnectPeripheral()
|
||||
return
|
||||
}
|
||||
|
||||
// Discover Services
|
||||
peripheral.discoverServices([meshtasticServiceCBUUID, DFUSERVICE_UUID])
|
||||
if meshLoggingEnabled { MeshLogger.log("✅ BLE Connected: \(peripheral.name ?? "Unknown")") }
|
||||
|
||||
MeshLogger.log("✅ BLE Connected: \(peripheral.name ?? "Unknown")")
|
||||
}
|
||||
|
||||
// Called when a Peripheral fails to connect
|
||||
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🚫 BLE Failed to Connect: \(peripheral.name ?? "Unknown")") }
|
||||
disconnectPeripheral()
|
||||
MeshLogger.log("🚫 BLE Failed to Connect: \(peripheral.name ?? "Unknown")")
|
||||
}
|
||||
|
||||
// Disconnect Peripheral Event
|
||||
|
|
@ -287,83 +277,53 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
self.startScanning()
|
||||
self.connectedPeripheral = nil
|
||||
self.isConnecting = false
|
||||
|
||||
if let e = error {
|
||||
|
||||
// https://developer.apple.com/documentation/corebluetooth/cberror/code
|
||||
let errorCode = (e as NSError).code
|
||||
// unknown = 0,
|
||||
|
||||
if errorCode == 6 { // CBError.Code.connectionTimeout The connection has timed out unexpectedly.
|
||||
|
||||
// Happens when device is manually reset / powered off
|
||||
// We will try and re-connect to this device
|
||||
lastConnectionError = "🚨 \(e.localizedDescription) The app will automatically reconnect to the preferred radio if it reappears within one minute."
|
||||
if peripheral.identifier.uuidString == UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" {
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ BLE Reconnecting: \(peripheral.name ?? "Unknown")") }
|
||||
self.connectTo(peripheral: peripheral)
|
||||
MeshLogger.log("ℹ️ BLE Reconnecting: \(peripheral.name ?? "Unknown")")
|
||||
}
|
||||
|
||||
} else if errorCode == 7 { // CBError.Code.peripheralDisconnected The specified device has disconnected from us.
|
||||
|
||||
// Seems to be what is received when a tbeam sleeps, immediately recconnecting does not work.
|
||||
lastConnectionError = e.localizedDescription
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)") }
|
||||
MeshLogger.log("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)")
|
||||
|
||||
} else if errorCode == 14 { // Peer removed pairing information
|
||||
|
||||
// Forgetting and reconnecting seems to be necessary so we need to show the user an error telling them to do that
|
||||
lastConnectionError = "🚨 \(e.localizedDescription) This error usually cannot be fixed without forgetting the device unders Settings > Bluetooth and re-connecting to the radio."
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(lastConnectionError)") }
|
||||
|
||||
MeshLogger.log("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(lastConnectionError)")
|
||||
} else {
|
||||
|
||||
lastConnectionError = e.localizedDescription
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)") }
|
||||
MeshLogger.log("🚨 BLE Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode) Error: \(e.localizedDescription)")
|
||||
}
|
||||
} else {
|
||||
|
||||
// Disconnected without error which indicates user intent to disconnect
|
||||
// Happens when swiping to disconnect
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ BLE Disconnected: \(peripheral.name ?? "Unknown"): User Initiated Disconnect") }
|
||||
MeshLogger.log("ℹ️ BLE Disconnected: \(peripheral.name ?? "Unknown"): User Initiated Disconnect")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Peripheral Services functions
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
|
||||
|
||||
if let e = error {
|
||||
|
||||
print("🚫 Discover Services error \(e)")
|
||||
}
|
||||
|
||||
guard let services = peripheral.services else { return }
|
||||
|
||||
for service in services {
|
||||
|
||||
if service.uuid == meshtasticServiceCBUUID {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("✅ BLE Service for Meshtastic discovered by \(peripheral.name ?? "Unknown")") }
|
||||
//peripheral.discoverCharacteristics(nil, for: service)
|
||||
peripheral.discoverCharacteristics([TORADIO_UUID, FROMRADIO_UUID, FROMNUM_UUID], for: service)
|
||||
|
||||
MeshLogger.log("✅ BLE Service for Meshtastic discovered by \(peripheral.name ?? "Unknown")")
|
||||
} else if (service.uuid == DFUSERVICE_UUID) {
|
||||
|
||||
print("✅ Meshtastic DFU service discovered OK")
|
||||
if meshLoggingEnabled { MeshLogger.log("✅ BLE Service for Meshtastic DFU discovered by \(peripheral.name ?? "Unknown")") }
|
||||
peripheral.discoverCharacteristics([DFUDATA_UUID, DFUSIZE_UUID, DFUREGION_UUID, DFURESULT_UUID, DFUCRC32_UUID], for: service)
|
||||
|
||||
peripheral.discoverCharacteristics([DFUDATA_UUID, DFUSIZE_UUID, DFUREGION_UUID, DFURESULT_UUID, DFUCRC32_UUID], for: service)
|
||||
MeshLogger.log("✅ BLE Service for Meshtastic DFU discovered by \(peripheral.name ?? "Unknown")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
|
||||
|
||||
print(invalidatedServices)
|
||||
}
|
||||
|
||||
// MARK: Discover Characteristics Event
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
||||
|
|
@ -658,19 +618,19 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
case .adminApp:
|
||||
adminAppPacket(packet: decodedInfo.packet, meshLogging: meshLoggingEnabled, context: context!)
|
||||
case .replyApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Reply App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
MeshLogger.log("ℹ️ MESH PACKET received for Reply App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .ipTunnelApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for IP Tunnel App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
MeshLogger.log("ℹ️ MESH PACKET received for IP Tunnel App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .serialApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Serial App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
MeshLogger.log("ℹ️ MESH PACKET received for Serial App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .storeForwardApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Store Forward App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
MeshLogger.log("ℹ️ MESH PACKET received for Store Forward App UNHANDLED \(try! decodedInfo.packet.jsonString())")
|
||||
case .rangeTestApp:
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Range Test App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
case .telemetryApp:
|
||||
|
||||
if !invalidVersion {
|
||||
|
||||
|
||||
telemetryPacket(packet: decodedInfo.packet, meshLogging: meshLoggingEnabled, context: context!)
|
||||
}
|
||||
case .textMessageCompressedApp:
|
||||
|
|
@ -687,7 +647,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if meshLoggingEnabled { MeshLogger.log("ℹ️ MESH PACKET received for Other App UNHANDLED \(try! decodedInfo.packet.jsonString())") }
|
||||
case .max:
|
||||
print("MAX PORT NUM OF 511")
|
||||
|
||||
}
|
||||
|
||||
// MARK: Check for an All / Broadcast User
|
||||
|
|
@ -696,7 +655,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
do {
|
||||
let fetchedUser = try context?.fetch(fetchBCUserRequest) as! [UserEntity]
|
||||
|
||||
if fetchedUser.isEmpty {
|
||||
// Save the broadcast user if it does not exist
|
||||
let bcu: UserEntity = UserEntity(context: context!)
|
||||
|
|
@ -709,7 +667,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
|
||||
} catch {
|
||||
|
||||
print("💥 Error Saving the All - Broadcast User")
|
||||
}
|
||||
|
||||
|
|
@ -717,7 +674,6 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Use context to pass the radio name with the timer
|
||||
// Use a RunLoop to prevent the timer from running on the main UI thread
|
||||
if userSettings?.provideLocation ?? false {
|
||||
|
||||
if self.positionTimer != nil {
|
||||
|
||||
self.positionTimer!.invalidate()
|
||||
|
|
@ -728,40 +684,18 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
|
||||
if decodedInfo.configCompleteID != 0 && decodedInfo.configCompleteID == configNonce {
|
||||
|
||||
invalidVersion = false
|
||||
lastConnectionError = ""
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("🤜 BLE Config Complete Packet Id: \(decodedInfo.configCompleteID)") }
|
||||
self.connectedPeripheral.subscribed = true
|
||||
peripherals.removeAll(where: { $0.peripheral.state == CBPeripheralState.disconnected })
|
||||
// Config conplete returns so we don't read the characteristic again
|
||||
return
|
||||
// Get all the channels
|
||||
// var i: UInt32 = 1;
|
||||
// let max: Int32 = self.connectedPeripheral.maxChannels
|
||||
//
|
||||
// Timer.scheduledTimer(withTimeInterval: 0.4, repeats: true) { timer in
|
||||
//
|
||||
// if i == (max + 1) {
|
||||
// timer.invalidate() // invalidate the timer
|
||||
// } else {
|
||||
//
|
||||
// if self.connectedPeripheral != nil {
|
||||
//
|
||||
// _ = self.getChannel(channelIndex: i, nodeNum: self.connectedPeripheral.num, wantResponse: true)
|
||||
// i+=1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
case FROMNUM_UUID :
|
||||
|
||||
print("🗞️ BLE FROMNUM (Notify) characteristic, value will be read next")
|
||||
|
||||
print("🗞️ BLE (Notify) characteristic, value will be read next")
|
||||
default:
|
||||
|
||||
print("🚨 Unhandled Characteristic UUID: \(characteristic.uuid)")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -818,7 +818,7 @@ func myInfoPacket (myInfo: MyNodeInfo, meshLogging: Bool, context: NSManagedObje
|
|||
return nil
|
||||
}
|
||||
|
||||
func channelPacket (channel: Channel, fromNum: Int64, meshLogging: Bool, context: NSManagedObjectContext) -> NodeInfoEntity? {
|
||||
func channelPacket (channel: Channel, fromNum: Int64, meshLogging: Bool, context: NSManagedObjectContext) {
|
||||
|
||||
if channel.isInitialized && channel.hasSettings {
|
||||
|
||||
|
|
@ -864,13 +864,6 @@ func channelPacket (channel: Channel, fromNum: Int64, meshLogging: Bool, context
|
|||
print("💥 Error Saving MyInfo Channel from ADMIN_APP \(nsError)")
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func nodeInfoPacket (nodeInfo: NodeInfo, meshLogging: Bool, context: NSManagedObjectContext) -> NodeInfoEntity? {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ struct MeshtasticAppleApp: App {
|
|||
.environmentObject(userSettings)
|
||||
.sheet(isPresented: $saveChannels) {
|
||||
|
||||
SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL", validUrl: true)
|
||||
SaveChannelQRCode(channelHash: channelSettings ?? "Empty Channel URL")
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ struct CannedMessagesConfig: View {
|
|||
|
||||
} else if updown1Enabled {
|
||||
|
||||
cmc.allowInputSource = "upDownEnc1"
|
||||
cmc.allowInputSource = "_any"
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -313,12 +313,12 @@ struct CannedMessagesConfig: View {
|
|||
// RAK Rotary Encoder
|
||||
updown1Enabled = false
|
||||
rotary1Enabled = false
|
||||
inputbrokerPinA = 32
|
||||
inputbrokerPinB = 38
|
||||
inputbrokerPinPress = 37
|
||||
inputbrokerEventCw = InputEventChars.keyUp.rawValue
|
||||
inputbrokerEventCcw = InputEventChars.keyDown.rawValue
|
||||
inputbrokerEventPress = InputEventChars.keySelect.rawValue
|
||||
inputbrokerPinA = 4
|
||||
inputbrokerPinB = 10
|
||||
inputbrokerPinPress = 9
|
||||
inputbrokerEventCw = InputEventChars.down.rawValue
|
||||
inputbrokerEventCcw = InputEventChars.up.rawValue
|
||||
inputbrokerEventPress = InputEventChars.select.rawValue
|
||||
|
||||
} else if newPreset == 2 {
|
||||
|
||||
|
|
@ -328,9 +328,9 @@ struct CannedMessagesConfig: View {
|
|||
inputbrokerPinA = 25
|
||||
inputbrokerPinB = 39
|
||||
inputbrokerPinPress = 36
|
||||
inputbrokerEventCw = InputEventChars.keyUp.rawValue
|
||||
inputbrokerEventCcw = InputEventChars.keyDown.rawValue
|
||||
inputbrokerEventPress = InputEventChars.keySelect.rawValue
|
||||
inputbrokerEventCw = InputEventChars.up.rawValue
|
||||
inputbrokerEventCcw = InputEventChars.down.rawValue
|
||||
inputbrokerEventPress = InputEventChars.select.rawValue
|
||||
}
|
||||
|
||||
hasChanges = true
|
||||
|
|
|
|||
|
|
@ -8,38 +8,34 @@ import SwiftUI
|
|||
|
||||
struct SaveChannelQRCode: View {
|
||||
var channelHash: String
|
||||
var validUrl: Bool
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if validUrl {
|
||||
Text("Save Channel Settings?")
|
||||
.font(.title)
|
||||
Text("These settings will replace the current settings on your radio.")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
.padding()
|
||||
Text("Save Channel Settings?")
|
||||
.font(.title)
|
||||
Text("These settings will replace the current LoRa Config and Channel Settings on your radio. After everything saves your device will reboot.")
|
||||
.foregroundColor(.gray)
|
||||
.font(.callout)
|
||||
.padding()
|
||||
Text(channelHash)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.gray)
|
||||
.padding()
|
||||
|
||||
Button {
|
||||
|
||||
Text(channelHash)
|
||||
.font(.caption2)
|
||||
.padding()
|
||||
} label: {
|
||||
|
||||
} else {
|
||||
Text("Invalid Channel Settings Url")
|
||||
.font(.title)
|
||||
|
||||
Text("Error Message")
|
||||
.font(.callout)
|
||||
.foregroundColor(.red)
|
||||
.padding()
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
}
|
||||
.onChange(of: channelHash) { newSettings in
|
||||
|
||||
var decodedString = newSettings.base64urlToBase64()
|
||||
|
||||
if let decodedData = Data(base64Encoded: decodedString) {
|
||||
decodedString = String(data: decodedData, encoding: .utf8)!
|
||||
do {
|
||||
var channelSet: ChannelSet = try ChannelSet(serializedData: decodedData)
|
||||
print(channelSet)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue