From ad2eefcb50487030f01960812ba5f11a0f002c98 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sun, 20 Oct 2024 08:48:36 -0700 Subject: [PATCH 1/6] Remove specific version numbers --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index de9af2a2..c0b76df3 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,7 @@ open Meshtastic.xcworkspace ### Supported Operating Systems -The last two operating system versions are supported. Currently that is 16 and 17. - -* iOS 16.6+ -* iPadOS 16.6+ -* macOS 13+ +The last two major operating system versions are supported. ### Code Standards From 4d897da1b556cc7bc37b2dc5914df64363abbb5b Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sun, 20 Oct 2024 08:49:58 -0700 Subject: [PATCH 2/6] Bump version --- Meshtastic.xcodeproj/project.pbxproj | 8 ++++---- README.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index c82b37b5..6ea81c15 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -1704,7 +1704,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.5.9; + MARKETING_VERSION = 2.5.10; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1738,7 +1738,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.5.9; + MARKETING_VERSION = 2.5.10; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = YES; @@ -1770,7 +1770,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.5.9; + MARKETING_VERSION = 2.5.10; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1803,7 +1803,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.5.9; + MARKETING_VERSION = 2.5.10; PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/README.md b/README.md index c0b76df3..c9d083bd 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ open Meshtastic.xcworkspace ### Supported Operating Systems -The last two major operating system versions are supported. +The last two major operating system versions are supported on iOS, iPadOS and macOS. ### Code Standards From e3dac4e4bd3b572e8c8df7a24196ecfe4fa7794d Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Wed, 30 Oct 2024 22:59:47 -0700 Subject: [PATCH 3/6] Channel form cleanup --- Meshtastic/Views/Settings/Channels/ChannelForm.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Meshtastic/Views/Settings/Channels/ChannelForm.swift b/Meshtastic/Views/Settings/Channels/ChannelForm.swift index 72d6f58b..06a4a260 100644 --- a/Meshtastic/Views/Settings/Channels/ChannelForm.swift +++ b/Meshtastic/Views/Settings/Channels/ChannelForm.swift @@ -138,7 +138,7 @@ struct ChannelForm: View { } if positionsEnabled { - if channelKey != "AQ==" && channelRole > 0 { + if (channelKey != "AQ==" && channelKeySize > 1) && channelRole > 0 { VStack(alignment: .leading) { Toggle(isOn: $preciseLocation) { Label("Precise Location", systemImage: "scope") @@ -212,12 +212,11 @@ struct ChannelForm: View { } .onChange(of: preciseLocation) { _, loc in if loc == true { - if channelKey == "AQ==" { + if channelKey == "AQ==" || channelKeySize <= 1 { preciseLocation = false } else { positionPrecision = 32 } - positionPrecision = 32 } else { positionPrecision = 14 } From 5c508ad764b267c4e38edf65aff72b4bf947391f Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sun, 10 Nov 2024 15:06:38 -0800 Subject: [PATCH 4/6] Update protobufs --- .../Sources/meshtastic/admin.pb.swift | 108 +++ .../Sources/meshtastic/config.pb.swift | 48 ++ .../Sources/meshtastic/device_ui.pb.swift | 718 ++++++++++++++++++ .../Sources/meshtastic/deviceonly.pb.swift | 207 +---- .../Sources/meshtastic/mesh.pb.swift | 226 +++++- .../Sources/meshtastic/module_config.pb.swift | 13 +- .../Sources/meshtastic/telemetry.pb.swift | 28 +- protobufs | 2 +- 8 files changed, 1138 insertions(+), 212 deletions(-) create mode 100644 MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift diff --git a/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift index 53d244d1..9e7fe0c5 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift @@ -386,6 +386,36 @@ public struct AdminMessage { set {payloadVariant = .setTimeOnly(newValue)} } + /// + /// Tell the node to send the stored ui data. + public var getUiConfigRequest: Bool { + get { + if case .getUiConfigRequest(let v)? = payloadVariant {return v} + return false + } + set {payloadVariant = .getUiConfigRequest(newValue)} + } + + /// + /// Reply stored device ui data. + public var getUiConfigResponse: DeviceUIConfig { + get { + if case .getUiConfigResponse(let v)? = payloadVariant {return v} + return DeviceUIConfig() + } + set {payloadVariant = .getUiConfigResponse(newValue)} + } + + /// + /// Tell the node to store UI data persistently. + public var storeUiConfig: DeviceUIConfig { + get { + if case .storeUiConfig(let v)? = payloadVariant {return v} + return DeviceUIConfig() + } + set {payloadVariant = .storeUiConfig(newValue)} + } + /// /// Begins an edit transaction for config, module config, owner, and channel settings changes /// This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) @@ -594,6 +624,15 @@ public struct AdminMessage { /// Convenience method to set the time on the node (as Net quality) without any other position data case setTimeOnly(UInt32) /// + /// Tell the node to send the stored ui data. + case getUiConfigRequest(Bool) + /// + /// Reply stored device ui data. + case getUiConfigResponse(DeviceUIConfig) + /// + /// Tell the node to store UI data persistently. + case storeUiConfig(DeviceUIConfig) + /// /// Begins an edit transaction for config, module config, owner, and channel settings changes /// This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) case beginEditSettings(Bool) @@ -766,6 +805,18 @@ public struct AdminMessage { guard case .setTimeOnly(let l) = lhs, case .setTimeOnly(let r) = rhs else { preconditionFailure() } return l == r }() + case (.getUiConfigRequest, .getUiConfigRequest): return { + guard case .getUiConfigRequest(let l) = lhs, case .getUiConfigRequest(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.getUiConfigResponse, .getUiConfigResponse): return { + guard case .getUiConfigResponse(let l) = lhs, case .getUiConfigResponse(let r) = rhs else { preconditionFailure() } + return l == r + }() + case (.storeUiConfig, .storeUiConfig): return { + guard case .storeUiConfig(let l) = lhs, case .storeUiConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() case (.beginEditSettings, .beginEditSettings): return { guard case .beginEditSettings(let l) = lhs, case .beginEditSettings(let r) = rhs else { preconditionFailure() } return l == r @@ -845,6 +896,10 @@ public struct AdminMessage { /// TODO: REPLACE case securityConfig // = 7 case sessionkeyConfig // = 8 + + /// + /// device-ui config + case deviceuiConfig // = 9 case UNRECOGNIZED(Int) public init() { @@ -862,6 +917,7 @@ public struct AdminMessage { case 6: self = .bluetoothConfig case 7: self = .securityConfig case 8: self = .sessionkeyConfig + case 9: self = .deviceuiConfig default: self = .UNRECOGNIZED(rawValue) } } @@ -877,6 +933,7 @@ public struct AdminMessage { case .bluetoothConfig: return 6 case .securityConfig: return 7 case .sessionkeyConfig: return 8 + case .deviceuiConfig: return 9 case .UNRECOGNIZED(let i): return i } } @@ -1002,6 +1059,7 @@ extension AdminMessage.ConfigType: CaseIterable { .bluetoothConfig, .securityConfig, .sessionkeyConfig, + .deviceuiConfig, ] } @@ -1123,6 +1181,9 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat 41: .standard(proto: "set_fixed_position"), 42: .standard(proto: "remove_fixed_position"), 43: .standard(proto: "set_time_only"), + 44: .standard(proto: "get_ui_config_request"), + 45: .standard(proto: "get_ui_config_response"), + 46: .standard(proto: "store_ui_config"), 64: .standard(proto: "begin_edit_settings"), 65: .standard(proto: "commit_edit_settings"), 94: .standard(proto: "factory_reset_device"), @@ -1477,6 +1538,40 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat self.payloadVariant = .setTimeOnly(v) } }() + case 44: try { + var v: Bool? + try decoder.decodeSingularBoolField(value: &v) + if let v = v { + if self.payloadVariant != nil {try decoder.handleConflictingOneOf()} + self.payloadVariant = .getUiConfigRequest(v) + } + }() + case 45: try { + var v: DeviceUIConfig? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .getUiConfigResponse(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .getUiConfigResponse(v) + } + }() + case 46: try { + var v: DeviceUIConfig? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .storeUiConfig(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .storeUiConfig(v) + } + }() case 64: try { var v: Bool? try decoder.decodeSingularBoolField(value: &v) @@ -1697,6 +1792,18 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat guard case .setTimeOnly(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularFixed32Field(value: v, fieldNumber: 43) }() + case .getUiConfigRequest?: try { + guard case .getUiConfigRequest(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularBoolField(value: v, fieldNumber: 44) + }() + case .getUiConfigResponse?: try { + guard case .getUiConfigResponse(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 45) + }() + case .storeUiConfig?: try { + guard case .storeUiConfig(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 46) + }() case .beginEditSettings?: try { guard case .beginEditSettings(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularBoolField(value: v, fieldNumber: 64) @@ -1760,6 +1867,7 @@ extension AdminMessage.ConfigType: SwiftProtobuf._ProtoNameProviding { 6: .same(proto: "BLUETOOTH_CONFIG"), 7: .same(proto: "SECURITY_CONFIG"), 8: .same(proto: "SESSIONKEY_CONFIG"), + 9: .same(proto: "DEVICEUI_CONFIG"), ] } diff --git a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift index 38df8ea0..49f405f1 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift @@ -101,6 +101,14 @@ public struct Config { set {payloadVariant = .sessionkey(newValue)} } + public var deviceUi: DeviceUIConfig { + get { + if case .deviceUi(let v)? = payloadVariant {return v} + return DeviceUIConfig() + } + set {payloadVariant = .deviceUi(newValue)} + } + public var unknownFields = SwiftProtobuf.UnknownStorage() /// @@ -115,6 +123,7 @@ public struct Config { case bluetooth(Config.BluetoothConfig) case security(Config.SecurityConfig) case sessionkey(Config.SessionkeyConfig) + case deviceUi(DeviceUIConfig) #if !swift(>=4.1) public static func ==(lhs: Config.OneOf_PayloadVariant, rhs: Config.OneOf_PayloadVariant) -> Bool { @@ -158,6 +167,10 @@ public struct Config { guard case .sessionkey(let l) = lhs, case .sessionkey(let r) = rhs else { preconditionFailure() } return l == r }() + case (.deviceUi, .deviceUi): return { + guard case .deviceUi(let l) = lhs, case .deviceUi(let r) = rhs else { preconditionFailure() } + return l == r + }() default: return false } } @@ -359,6 +372,15 @@ public struct Config { /// Ignores observed messages from foreign meshes like LOCAL_ONLY, /// but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) case knownOnly // = 3 + + /// + /// Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role. + case none // = 4 + + /// + /// Ignores packets from non-standard portnums such as: TAK, RangeTest, PaxCounter, etc. + /// Only rebroadcasts packets with standard portnums: NodeInfo, Text, Position, Telemetry, and Routing. + case corePortnumsOnly // = 5 case UNRECOGNIZED(Int) public init() { @@ -371,6 +393,8 @@ public struct Config { case 1: self = .allSkipDecoding case 2: self = .localOnly case 3: self = .knownOnly + case 4: self = .none + case 5: self = .corePortnumsOnly default: self = .UNRECOGNIZED(rawValue) } } @@ -381,6 +405,8 @@ public struct Config { case .allSkipDecoding: return 1 case .localOnly: return 2 case .knownOnly: return 3 + case .none: return 4 + case .corePortnumsOnly: return 5 case .UNRECOGNIZED(let i): return i } } @@ -1652,6 +1678,8 @@ extension Config.DeviceConfig.RebroadcastMode: CaseIterable { .allSkipDecoding, .localOnly, .knownOnly, + .none, + .corePortnumsOnly, ] } @@ -1841,6 +1869,7 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas 7: .same(proto: "bluetooth"), 8: .same(proto: "security"), 9: .same(proto: "sessionkey"), + 10: .standard(proto: "device_ui"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -1966,6 +1995,19 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas self.payloadVariant = .sessionkey(v) } }() + case 10: try { + var v: DeviceUIConfig? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .deviceUi(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .deviceUi(v) + } + }() default: break } } @@ -2013,6 +2055,10 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas guard case .sessionkey(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 9) }() + case .deviceUi?: try { + guard case .deviceUi(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) + }() case nil: break } try unknownFields.traverse(visitor: &visitor) @@ -2139,6 +2185,8 @@ extension Config.DeviceConfig.RebroadcastMode: SwiftProtobuf._ProtoNameProviding 1: .same(proto: "ALL_SKIP_DECODING"), 2: .same(proto: "LOCAL_ONLY"), 3: .same(proto: "KNOWN_ONLY"), + 4: .same(proto: "NONE"), + 5: .same(proto: "CORE_PORTNUMS_ONLY"), ] } diff --git a/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift new file mode 100644 index 00000000..f677d644 --- /dev/null +++ b/MeshtasticProtobufs/Sources/meshtastic/device_ui.pb.swift @@ -0,0 +1,718 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: meshtastic/device_ui.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +public enum Theme: SwiftProtobuf.Enum { + public typealias RawValue = Int + + /// + /// Dark + case dark // = 0 + + /// + /// Light + case light // = 1 + + /// + /// Red + case red // = 2 + case UNRECOGNIZED(Int) + + public init() { + self = .dark + } + + public init?(rawValue: Int) { + switch rawValue { + case 0: self = .dark + case 1: self = .light + case 2: self = .red + default: self = .UNRECOGNIZED(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .dark: return 0 + case .light: return 1 + case .red: return 2 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension Theme: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Theme] = [ + .dark, + .light, + .red, + ] +} + +#endif // swift(>=4.2) + +/// +/// Localization +public enum Language: SwiftProtobuf.Enum { + public typealias RawValue = Int + + /// + /// English + case english // = 0 + + /// + /// French + case french // = 1 + + /// + /// German + case german // = 2 + + /// + /// Italian + case italian // = 3 + + /// + /// Portuguese + case portuguese // = 4 + + /// + /// Spanish + case spanish // = 5 + + /// + /// Swedish + case swedish // = 6 + + /// + /// Finnish + case finnish // = 7 + + /// + /// Polish + case polish // = 8 + + /// + /// Turkish + case turkish // = 9 + + /// + /// Serbian + case serbian // = 10 + + /// + /// Russian + case russian // = 11 + + /// + /// Dutch + case dutch // = 12 + + /// + /// Greek + case greek // = 13 + + /// + /// Simplified Chinese (experimental) + case simplifiedChinese // = 30 + + /// + /// Traditional Chinese (experimental) + case traditionalChinese // = 31 + case UNRECOGNIZED(Int) + + public init() { + self = .english + } + + public init?(rawValue: Int) { + switch rawValue { + case 0: self = .english + case 1: self = .french + case 2: self = .german + case 3: self = .italian + case 4: self = .portuguese + case 5: self = .spanish + case 6: self = .swedish + case 7: self = .finnish + case 8: self = .polish + case 9: self = .turkish + case 10: self = .serbian + case 11: self = .russian + case 12: self = .dutch + case 13: self = .greek + case 30: self = .simplifiedChinese + case 31: self = .traditionalChinese + default: self = .UNRECOGNIZED(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .english: return 0 + case .french: return 1 + case .german: return 2 + case .italian: return 3 + case .portuguese: return 4 + case .spanish: return 5 + case .swedish: return 6 + case .finnish: return 7 + case .polish: return 8 + case .turkish: return 9 + case .serbian: return 10 + case .russian: return 11 + case .dutch: return 12 + case .greek: return 13 + case .simplifiedChinese: return 30 + case .traditionalChinese: return 31 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension Language: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Language] = [ + .english, + .french, + .german, + .italian, + .portuguese, + .spanish, + .swedish, + .finnish, + .polish, + .turkish, + .serbian, + .russian, + .dutch, + .greek, + .simplifiedChinese, + .traditionalChinese, + ] +} + +#endif // swift(>=4.2) + +public struct DeviceUIConfig { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// + /// A version integer used to invalidate saved files when we make incompatible changes. + public var version: UInt32 { + get {return _storage._version} + set {_uniqueStorage()._version = newValue} + } + + /// + /// TFT display brightness 1..255 + public var screenBrightness: UInt32 { + get {return _storage._screenBrightness} + set {_uniqueStorage()._screenBrightness = newValue} + } + + /// + /// Screen timeout 0..900 + public var screenTimeout: UInt32 { + get {return _storage._screenTimeout} + set {_uniqueStorage()._screenTimeout = newValue} + } + + /// + /// Screen/Settings lock enabled + public var screenLock: Bool { + get {return _storage._screenLock} + set {_uniqueStorage()._screenLock = newValue} + } + + public var settingsLock: Bool { + get {return _storage._settingsLock} + set {_uniqueStorage()._settingsLock = newValue} + } + + public var pinCode: UInt32 { + get {return _storage._pinCode} + set {_uniqueStorage()._pinCode = newValue} + } + + /// + /// Color theme + public var theme: Theme { + get {return _storage._theme} + set {_uniqueStorage()._theme = newValue} + } + + /// + /// Audible message, banner and ring tone + public var alertEnabled: Bool { + get {return _storage._alertEnabled} + set {_uniqueStorage()._alertEnabled = newValue} + } + + public var bannerEnabled: Bool { + get {return _storage._bannerEnabled} + set {_uniqueStorage()._bannerEnabled = newValue} + } + + public var ringToneID: UInt32 { + get {return _storage._ringToneID} + set {_uniqueStorage()._ringToneID = newValue} + } + + /// + /// Localization + public var language: Language { + get {return _storage._language} + set {_uniqueStorage()._language = newValue} + } + + /// + /// Node list filter + public var nodeFilter: NodeFilter { + get {return _storage._nodeFilter ?? NodeFilter()} + set {_uniqueStorage()._nodeFilter = newValue} + } + /// Returns true if `nodeFilter` has been explicitly set. + public var hasNodeFilter: Bool {return _storage._nodeFilter != nil} + /// Clears the value of `nodeFilter`. Subsequent reads from it will return its default value. + public mutating func clearNodeFilter() {_uniqueStorage()._nodeFilter = nil} + + /// + /// Node list highlightening + public var nodeHighlight: NodeHighlight { + get {return _storage._nodeHighlight ?? NodeHighlight()} + set {_uniqueStorage()._nodeHighlight = newValue} + } + /// Returns true if `nodeHighlight` has been explicitly set. + public var hasNodeHighlight: Bool {return _storage._nodeHighlight != nil} + /// Clears the value of `nodeHighlight`. Subsequent reads from it will return its default value. + public mutating func clearNodeHighlight() {_uniqueStorage()._nodeHighlight = nil} + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +public struct NodeFilter { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// + /// Filter unknown nodes + public var unknownSwitch: Bool = false + + /// + /// Filter offline nodes + public var offlineSwitch: Bool = false + + /// + /// Filter nodes w/o public key + public var publicKeySwitch: Bool = false + + /// + /// Filter based on hops away + public var hopsAway: Int32 = 0 + + /// + /// Filter nodes w/o position + public var positionSwitch: Bool = false + + /// + /// Filter nodes by matching name string + public var nodeName: String = String() + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} +} + +public struct NodeHighlight { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// + /// Hightlight nodes w/ active chat + public var chatSwitch: Bool = false + + /// + /// Highlight nodes w/ position + public var positionSwitch: Bool = false + + /// + /// Highlight nodes w/ telemetry data + public var telemetrySwitch: Bool = false + + /// + /// Highlight nodes w/ iaq data + public var iaqSwitch: Bool = false + + /// + /// Highlight nodes by matching name string + public var nodeName: String = String() + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} +} + +#if swift(>=5.5) && canImport(_Concurrency) +extension Theme: @unchecked Sendable {} +extension Language: @unchecked Sendable {} +extension DeviceUIConfig: @unchecked Sendable {} +extension NodeFilter: @unchecked Sendable {} +extension NodeHighlight: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +fileprivate let _protobuf_package = "meshtastic" + +extension Theme: SwiftProtobuf._ProtoNameProviding { + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "DARK"), + 1: .same(proto: "LIGHT"), + 2: .same(proto: "RED"), + ] +} + +extension Language: SwiftProtobuf._ProtoNameProviding { + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "ENGLISH"), + 1: .same(proto: "FRENCH"), + 2: .same(proto: "GERMAN"), + 3: .same(proto: "ITALIAN"), + 4: .same(proto: "PORTUGUESE"), + 5: .same(proto: "SPANISH"), + 6: .same(proto: "SWEDISH"), + 7: .same(proto: "FINNISH"), + 8: .same(proto: "POLISH"), + 9: .same(proto: "TURKISH"), + 10: .same(proto: "SERBIAN"), + 11: .same(proto: "RUSSIAN"), + 12: .same(proto: "DUTCH"), + 13: .same(proto: "GREEK"), + 30: .same(proto: "SIMPLIFIED_CHINESE"), + 31: .same(proto: "TRADITIONAL_CHINESE"), + ] +} + +extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".DeviceUIConfig" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "version"), + 2: .standard(proto: "screen_brightness"), + 3: .standard(proto: "screen_timeout"), + 4: .standard(proto: "screen_lock"), + 5: .standard(proto: "settings_lock"), + 6: .standard(proto: "pin_code"), + 7: .same(proto: "theme"), + 8: .standard(proto: "alert_enabled"), + 9: .standard(proto: "banner_enabled"), + 10: .standard(proto: "ring_tone_id"), + 11: .same(proto: "language"), + 12: .standard(proto: "node_filter"), + 13: .standard(proto: "node_highlight"), + ] + + fileprivate class _StorageClass { + var _version: UInt32 = 0 + var _screenBrightness: UInt32 = 0 + var _screenTimeout: UInt32 = 0 + var _screenLock: Bool = false + var _settingsLock: Bool = false + var _pinCode: UInt32 = 0 + var _theme: Theme = .dark + var _alertEnabled: Bool = false + var _bannerEnabled: Bool = false + var _ringToneID: UInt32 = 0 + var _language: Language = .english + var _nodeFilter: NodeFilter? = nil + var _nodeHighlight: NodeHighlight? = nil + + #if swift(>=5.10) + // This property is used as the initial default value for new instances of the type. + // The type itself is protecting the reference to its storage via CoW semantics. + // This will force a copy to be made of this reference when the first mutation occurs; + // hence, it is safe to mark this as `nonisolated(unsafe)`. + static nonisolated(unsafe) let defaultInstance = _StorageClass() + #else + static let defaultInstance = _StorageClass() + #endif + + private init() {} + + init(copying source: _StorageClass) { + _version = source._version + _screenBrightness = source._screenBrightness + _screenTimeout = source._screenTimeout + _screenLock = source._screenLock + _settingsLock = source._settingsLock + _pinCode = source._pinCode + _theme = source._theme + _alertEnabled = source._alertEnabled + _bannerEnabled = source._bannerEnabled + _ringToneID = source._ringToneID + _language = source._language + _nodeFilter = source._nodeFilter + _nodeHighlight = source._nodeHighlight + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + public mutating func decodeMessage(decoder: inout D) throws { + _ = _uniqueStorage() + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularUInt32Field(value: &_storage._version) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &_storage._screenBrightness) }() + case 3: try { try decoder.decodeSingularUInt32Field(value: &_storage._screenTimeout) }() + case 4: try { try decoder.decodeSingularBoolField(value: &_storage._screenLock) }() + case 5: try { try decoder.decodeSingularBoolField(value: &_storage._settingsLock) }() + case 6: try { try decoder.decodeSingularUInt32Field(value: &_storage._pinCode) }() + case 7: try { try decoder.decodeSingularEnumField(value: &_storage._theme) }() + case 8: try { try decoder.decodeSingularBoolField(value: &_storage._alertEnabled) }() + case 9: try { try decoder.decodeSingularBoolField(value: &_storage._bannerEnabled) }() + case 10: try { try decoder.decodeSingularUInt32Field(value: &_storage._ringToneID) }() + case 11: try { try decoder.decodeSingularEnumField(value: &_storage._language) }() + case 12: try { try decoder.decodeSingularMessageField(value: &_storage._nodeFilter) }() + case 13: try { try decoder.decodeSingularMessageField(value: &_storage._nodeHighlight) }() + default: break + } + } + } + } + + public func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if _storage._version != 0 { + try visitor.visitSingularUInt32Field(value: _storage._version, fieldNumber: 1) + } + if _storage._screenBrightness != 0 { + try visitor.visitSingularUInt32Field(value: _storage._screenBrightness, fieldNumber: 2) + } + if _storage._screenTimeout != 0 { + try visitor.visitSingularUInt32Field(value: _storage._screenTimeout, fieldNumber: 3) + } + if _storage._screenLock != false { + try visitor.visitSingularBoolField(value: _storage._screenLock, fieldNumber: 4) + } + if _storage._settingsLock != false { + try visitor.visitSingularBoolField(value: _storage._settingsLock, fieldNumber: 5) + } + if _storage._pinCode != 0 { + try visitor.visitSingularUInt32Field(value: _storage._pinCode, fieldNumber: 6) + } + if _storage._theme != .dark { + try visitor.visitSingularEnumField(value: _storage._theme, fieldNumber: 7) + } + if _storage._alertEnabled != false { + try visitor.visitSingularBoolField(value: _storage._alertEnabled, fieldNumber: 8) + } + if _storage._bannerEnabled != false { + try visitor.visitSingularBoolField(value: _storage._bannerEnabled, fieldNumber: 9) + } + if _storage._ringToneID != 0 { + try visitor.visitSingularUInt32Field(value: _storage._ringToneID, fieldNumber: 10) + } + if _storage._language != .english { + try visitor.visitSingularEnumField(value: _storage._language, fieldNumber: 11) + } + try { if let v = _storage._nodeFilter { + try visitor.visitSingularMessageField(value: v, fieldNumber: 12) + } }() + try { if let v = _storage._nodeHighlight { + try visitor.visitSingularMessageField(value: v, fieldNumber: 13) + } }() + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: DeviceUIConfig, rhs: DeviceUIConfig) -> Bool { + if lhs._storage !== rhs._storage { + let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in + let _storage = _args.0 + let rhs_storage = _args.1 + if _storage._version != rhs_storage._version {return false} + if _storage._screenBrightness != rhs_storage._screenBrightness {return false} + if _storage._screenTimeout != rhs_storage._screenTimeout {return false} + if _storage._screenLock != rhs_storage._screenLock {return false} + if _storage._settingsLock != rhs_storage._settingsLock {return false} + if _storage._pinCode != rhs_storage._pinCode {return false} + if _storage._theme != rhs_storage._theme {return false} + if _storage._alertEnabled != rhs_storage._alertEnabled {return false} + if _storage._bannerEnabled != rhs_storage._bannerEnabled {return false} + if _storage._ringToneID != rhs_storage._ringToneID {return false} + if _storage._language != rhs_storage._language {return false} + if _storage._nodeFilter != rhs_storage._nodeFilter {return false} + if _storage._nodeHighlight != rhs_storage._nodeHighlight {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension NodeFilter: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".NodeFilter" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "unknown_switch"), + 2: .standard(proto: "offline_switch"), + 3: .standard(proto: "public_key_switch"), + 4: .standard(proto: "hops_away"), + 5: .standard(proto: "position_switch"), + 6: .standard(proto: "node_name"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularBoolField(value: &self.unknownSwitch) }() + case 2: try { try decoder.decodeSingularBoolField(value: &self.offlineSwitch) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.publicKeySwitch) }() + case 4: try { try decoder.decodeSingularInt32Field(value: &self.hopsAway) }() + case 5: try { try decoder.decodeSingularBoolField(value: &self.positionSwitch) }() + case 6: try { try decoder.decodeSingularStringField(value: &self.nodeName) }() + default: break + } + } + } + + public func traverse(visitor: inout V) throws { + if self.unknownSwitch != false { + try visitor.visitSingularBoolField(value: self.unknownSwitch, fieldNumber: 1) + } + if self.offlineSwitch != false { + try visitor.visitSingularBoolField(value: self.offlineSwitch, fieldNumber: 2) + } + if self.publicKeySwitch != false { + try visitor.visitSingularBoolField(value: self.publicKeySwitch, fieldNumber: 3) + } + if self.hopsAway != 0 { + try visitor.visitSingularInt32Field(value: self.hopsAway, fieldNumber: 4) + } + if self.positionSwitch != false { + try visitor.visitSingularBoolField(value: self.positionSwitch, fieldNumber: 5) + } + if !self.nodeName.isEmpty { + try visitor.visitSingularStringField(value: self.nodeName, fieldNumber: 6) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: NodeFilter, rhs: NodeFilter) -> Bool { + if lhs.unknownSwitch != rhs.unknownSwitch {return false} + if lhs.offlineSwitch != rhs.offlineSwitch {return false} + if lhs.publicKeySwitch != rhs.publicKeySwitch {return false} + if lhs.hopsAway != rhs.hopsAway {return false} + if lhs.positionSwitch != rhs.positionSwitch {return false} + if lhs.nodeName != rhs.nodeName {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension NodeHighlight: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".NodeHighlight" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "chat_switch"), + 2: .standard(proto: "position_switch"), + 3: .standard(proto: "telemetry_switch"), + 4: .standard(proto: "iaq_switch"), + 5: .standard(proto: "node_name"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularBoolField(value: &self.chatSwitch) }() + case 2: try { try decoder.decodeSingularBoolField(value: &self.positionSwitch) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.telemetrySwitch) }() + case 4: try { try decoder.decodeSingularBoolField(value: &self.iaqSwitch) }() + case 5: try { try decoder.decodeSingularStringField(value: &self.nodeName) }() + default: break + } + } + } + + public func traverse(visitor: inout V) throws { + if self.chatSwitch != false { + try visitor.visitSingularBoolField(value: self.chatSwitch, fieldNumber: 1) + } + if self.positionSwitch != false { + try visitor.visitSingularBoolField(value: self.positionSwitch, fieldNumber: 2) + } + if self.telemetrySwitch != false { + try visitor.visitSingularBoolField(value: self.telemetrySwitch, fieldNumber: 3) + } + if self.iaqSwitch != false { + try visitor.visitSingularBoolField(value: self.iaqSwitch, fieldNumber: 4) + } + if !self.nodeName.isEmpty { + try visitor.visitSingularStringField(value: self.nodeName, fieldNumber: 5) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: NodeHighlight, rhs: NodeHighlight) -> Bool { + if lhs.chatSwitch != rhs.chatSwitch {return false} + if lhs.positionSwitch != rhs.positionSwitch {return false} + if lhs.telemetrySwitch != rhs.telemetrySwitch {return false} + if lhs.iaqSwitch != rhs.iaqSwitch {return false} + if lhs.nodeName != rhs.nodeName {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift index 3dd965f2..3349c2c9 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/deviceonly.pb.swift @@ -20,61 +20,6 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP typealias Version = _2 } -/// -/// Font sizes for the device screen -public enum ScreenFonts: SwiftProtobuf.Enum { - public typealias RawValue = Int - - /// - /// TODO: REPLACE - case fontSmall // = 0 - - /// - /// TODO: REPLACE - case fontMedium // = 1 - - /// - /// TODO: REPLACE - case fontLarge // = 2 - case UNRECOGNIZED(Int) - - public init() { - self = .fontSmall - } - - public init?(rawValue: Int) { - switch rawValue { - case 0: self = .fontSmall - case 1: self = .fontMedium - case 2: self = .fontLarge - default: self = .UNRECOGNIZED(rawValue) - } - } - - public var rawValue: Int { - switch self { - case .fontSmall: return 0 - case .fontMedium: return 1 - case .fontLarge: return 2 - case .UNRECOGNIZED(let i): return i - } - } - -} - -#if swift(>=4.2) - -extension ScreenFonts: CaseIterable { - // The compiler won't synthesize support with the UNRECOGNIZED case. - public static let allCases: [ScreenFonts] = [ - .fontSmall, - .fontMedium, - .fontLarge, - ] -} - -#endif // swift(>=4.2) - /// /// Position with static location information only for NodeDBLite public struct PositionLite { @@ -233,7 +178,7 @@ public struct NodeInfoLite { } /// - /// Number of hops away from us this node is (0 if adjacent) + /// Number of hops away from us this node is (0 if direct neighbor) public var hopsAway: UInt32 { get {return _storage._hopsAway ?? 0} set {_uniqueStorage()._hopsAway = newValue} @@ -392,90 +337,18 @@ public struct ChannelFile { public init() {} } -/// -/// This can be used for customizing the firmware distribution. If populated, -/// show a secondary bootup screen with custom logo and text for 2.5 seconds. -public struct OEMStore { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// - /// The Logo width in Px - public var oemIconWidth: UInt32 = 0 - - /// - /// The Logo height in Px - public var oemIconHeight: UInt32 = 0 - - /// - /// The Logo in XBM bytechar format - public var oemIconBits: Data = Data() - - /// - /// Use this font for the OEM text. - public var oemFont: ScreenFonts = .fontSmall - - /// - /// Use this font for the OEM text. - public var oemText: String = String() - - /// - /// The default device encryption key, 16 or 32 byte - public var oemAesKey: Data = Data() - - /// - /// A Preset LocalConfig to apply during factory reset - public var oemLocalConfig: LocalConfig { - get {return _oemLocalConfig ?? LocalConfig()} - set {_oemLocalConfig = newValue} - } - /// Returns true if `oemLocalConfig` has been explicitly set. - public var hasOemLocalConfig: Bool {return self._oemLocalConfig != nil} - /// Clears the value of `oemLocalConfig`. Subsequent reads from it will return its default value. - public mutating func clearOemLocalConfig() {self._oemLocalConfig = nil} - - /// - /// A Preset LocalModuleConfig to apply during factory reset - public var oemLocalModuleConfig: LocalModuleConfig { - get {return _oemLocalModuleConfig ?? LocalModuleConfig()} - set {_oemLocalModuleConfig = newValue} - } - /// Returns true if `oemLocalModuleConfig` has been explicitly set. - public var hasOemLocalModuleConfig: Bool {return self._oemLocalModuleConfig != nil} - /// Clears the value of `oemLocalModuleConfig`. Subsequent reads from it will return its default value. - public mutating func clearOemLocalModuleConfig() {self._oemLocalModuleConfig = nil} - - public var unknownFields = SwiftProtobuf.UnknownStorage() - - public init() {} - - fileprivate var _oemLocalConfig: LocalConfig? = nil - fileprivate var _oemLocalModuleConfig: LocalModuleConfig? = nil -} - #if swift(>=5.5) && canImport(_Concurrency) -extension ScreenFonts: @unchecked Sendable {} extension PositionLite: @unchecked Sendable {} extension UserLite: @unchecked Sendable {} extension NodeInfoLite: @unchecked Sendable {} extension DeviceState: @unchecked Sendable {} extension ChannelFile: @unchecked Sendable {} -extension OEMStore: @unchecked Sendable {} #endif // swift(>=5.5) && canImport(_Concurrency) // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "meshtastic" -extension ScreenFonts: SwiftProtobuf._ProtoNameProviding { - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 0: .same(proto: "FONT_SMALL"), - 1: .same(proto: "FONT_MEDIUM"), - 2: .same(proto: "FONT_LARGE"), - ] -} - extension PositionLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".PositionLite" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -933,81 +806,3 @@ extension ChannelFile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati return true } } - -extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".OEMStore" - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .standard(proto: "oem_icon_width"), - 2: .standard(proto: "oem_icon_height"), - 3: .standard(proto: "oem_icon_bits"), - 4: .standard(proto: "oem_font"), - 5: .standard(proto: "oem_text"), - 6: .standard(proto: "oem_aes_key"), - 7: .standard(proto: "oem_local_config"), - 8: .standard(proto: "oem_local_module_config"), - ] - - public mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularUInt32Field(value: &self.oemIconWidth) }() - case 2: try { try decoder.decodeSingularUInt32Field(value: &self.oemIconHeight) }() - case 3: try { try decoder.decodeSingularBytesField(value: &self.oemIconBits) }() - case 4: try { try decoder.decodeSingularEnumField(value: &self.oemFont) }() - case 5: try { try decoder.decodeSingularStringField(value: &self.oemText) }() - case 6: try { try decoder.decodeSingularBytesField(value: &self.oemAesKey) }() - case 7: try { try decoder.decodeSingularMessageField(value: &self._oemLocalConfig) }() - case 8: try { try decoder.decodeSingularMessageField(value: &self._oemLocalModuleConfig) }() - default: break - } - } - } - - public func traverse(visitor: inout V) throws { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - if self.oemIconWidth != 0 { - try visitor.visitSingularUInt32Field(value: self.oemIconWidth, fieldNumber: 1) - } - if self.oemIconHeight != 0 { - try visitor.visitSingularUInt32Field(value: self.oemIconHeight, fieldNumber: 2) - } - if !self.oemIconBits.isEmpty { - try visitor.visitSingularBytesField(value: self.oemIconBits, fieldNumber: 3) - } - if self.oemFont != .fontSmall { - try visitor.visitSingularEnumField(value: self.oemFont, fieldNumber: 4) - } - if !self.oemText.isEmpty { - try visitor.visitSingularStringField(value: self.oemText, fieldNumber: 5) - } - if !self.oemAesKey.isEmpty { - try visitor.visitSingularBytesField(value: self.oemAesKey, fieldNumber: 6) - } - try { if let v = self._oemLocalConfig { - try visitor.visitSingularMessageField(value: v, fieldNumber: 7) - } }() - try { if let v = self._oemLocalModuleConfig { - try visitor.visitSingularMessageField(value: v, fieldNumber: 8) - } }() - try unknownFields.traverse(visitor: &visitor) - } - - public static func ==(lhs: OEMStore, rhs: OEMStore) -> Bool { - if lhs.oemIconWidth != rhs.oemIconWidth {return false} - if lhs.oemIconHeight != rhs.oemIconHeight {return false} - if lhs.oemIconBits != rhs.oemIconBits {return false} - if lhs.oemFont != rhs.oemFont {return false} - if lhs.oemText != rhs.oemText {return false} - if lhs.oemAesKey != rhs.oemAesKey {return false} - if lhs._oemLocalConfig != rhs._oemLocalConfig {return false} - if lhs._oemLocalModuleConfig != rhs._oemLocalModuleConfig {return false} - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} diff --git a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift index f604d4a7..154d8a6b 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift @@ -862,7 +862,141 @@ extension CriticalErrorCode: CaseIterable { #endif // swift(>=4.2) /// -/// a gps position +/// Enum for modules excluded from a device's configuration. +/// Each value represents a ModuleConfigType that can be toggled as excluded +/// by setting its corresponding bit in the `excluded_modules` bitmask field. +public enum ExcludedModules: SwiftProtobuf.Enum { + public typealias RawValue = Int + + /// + /// Default value of 0 indicates no modules are excluded. + case excludedNone // = 0 + + /// + /// MQTT module + case mqttConfig // = 1 + + /// + /// Serial module + case serialConfig // = 2 + + /// + /// External Notification module + case extnotifConfig // = 4 + + /// + /// Store and Forward module + case storeforwardConfig // = 8 + + /// + /// Range Test module + case rangetestConfig // = 16 + + /// + /// Telemetry module + case telemetryConfig // = 32 + + /// + /// Canned Message module + case cannedmsgConfig // = 64 + + /// + /// Audio module + case audioConfig // = 128 + + /// + /// Remote Hardware module + case remotehardwareConfig // = 256 + + /// + /// Neighbor Info module + case neighborinfoConfig // = 512 + + /// + /// Ambient Lighting module + case ambientlightingConfig // = 1024 + + /// + /// Detection Sensor module + case detectionsensorConfig // = 2048 + + /// + /// Paxcounter module + case paxcounterConfig // = 4096 + case UNRECOGNIZED(Int) + + public init() { + self = .excludedNone + } + + public init?(rawValue: Int) { + switch rawValue { + case 0: self = .excludedNone + case 1: self = .mqttConfig + case 2: self = .serialConfig + case 4: self = .extnotifConfig + case 8: self = .storeforwardConfig + case 16: self = .rangetestConfig + case 32: self = .telemetryConfig + case 64: self = .cannedmsgConfig + case 128: self = .audioConfig + case 256: self = .remotehardwareConfig + case 512: self = .neighborinfoConfig + case 1024: self = .ambientlightingConfig + case 2048: self = .detectionsensorConfig + case 4096: self = .paxcounterConfig + default: self = .UNRECOGNIZED(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .excludedNone: return 0 + case .mqttConfig: return 1 + case .serialConfig: return 2 + case .extnotifConfig: return 4 + case .storeforwardConfig: return 8 + case .rangetestConfig: return 16 + case .telemetryConfig: return 32 + case .cannedmsgConfig: return 64 + case .audioConfig: return 128 + case .remotehardwareConfig: return 256 + case .neighborinfoConfig: return 512 + case .ambientlightingConfig: return 1024 + case .detectionsensorConfig: return 2048 + case .paxcounterConfig: return 4096 + case .UNRECOGNIZED(let i): return i + } + } + +} + +#if swift(>=4.2) + +extension ExcludedModules: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [ExcludedModules] = [ + .excludedNone, + .mqttConfig, + .serialConfig, + .extnotifConfig, + .storeforwardConfig, + .rangetestConfig, + .telemetryConfig, + .cannedmsgConfig, + .audioConfig, + .remotehardwareConfig, + .neighborinfoConfig, + .ambientlightingConfig, + .detectionsensorConfig, + .paxcounterConfig, + ] +} + +#endif // swift(>=4.2) + +/// +/// A GPS Position public struct Position { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for @@ -1846,7 +1980,7 @@ public struct MeshPacket { } /// - /// If unset treated as zero (no forwarding, send to adjacent nodes only) + /// If unset treated as zero (no forwarding, send to direct neighbor nodes only) /// if 1, allow hopping through one node, etc... /// For our usecase real world topologies probably have a max of about 3. /// This field is normally placed into a few of bits in the header. @@ -2218,7 +2352,7 @@ public struct NodeInfo { } /// - /// Number of hops away from us this node is (0 if adjacent) + /// Number of hops away from us this node is (0 if direct neighbor) public var hopsAway: UInt32 { get {return _storage._hopsAway ?? 0} set {_uniqueStorage()._hopsAway = newValue} @@ -2267,6 +2401,14 @@ public struct MyNodeInfo { /// Phone/PC apps should compare this to their build number and if too low tell the user they must update their app public var minAppVersion: UInt32 = 0 + /// + /// Unique hardware identifier for this device + public var deviceID: Data = Data() + + /// + /// The PlatformIO environment used to build this firmware + public var pioEnv: String = String() + public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} @@ -2586,6 +2728,16 @@ public struct FromRadio { set {payloadVariant = .clientNotification(newValue)} } + /// + /// Persistent data for device-ui + public var deviceuiConfig: DeviceUIConfig { + get { + if case .deviceuiConfig(let v)? = payloadVariant {return v} + return DeviceUIConfig() + } + set {payloadVariant = .deviceuiConfig(newValue)} + } + public var unknownFields = SwiftProtobuf.UnknownStorage() /// @@ -2644,6 +2796,9 @@ public struct FromRadio { /// /// Notification message to the client case clientNotification(ClientNotification) + /// + /// Persistent data for device-ui + case deviceuiConfig(DeviceUIConfig) #if !swift(>=4.1) public static func ==(lhs: FromRadio.OneOf_PayloadVariant, rhs: FromRadio.OneOf_PayloadVariant) -> Bool { @@ -2711,6 +2866,10 @@ public struct FromRadio { guard case .clientNotification(let l) = lhs, case .clientNotification(let r) = rhs else { preconditionFailure() } return l == r }() + case (.deviceuiConfig, .deviceuiConfig): return { + guard case .deviceuiConfig(let l) = lhs, case .deviceuiConfig(let r) = rhs else { preconditionFailure() } + return l == r + }() default: return false } } @@ -3058,6 +3217,11 @@ public struct DeviceMetadata { /// Has PKC capabilities public var hasPkc_p: Bool = false + /// + /// Bit field of boolean for excluded modules + /// (bitwise OR of ExcludedModules) + public var excludedModules: UInt32 = 0 + public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} @@ -3232,6 +3396,7 @@ public struct ChunkedPayloadResponse { extension HardwareModel: @unchecked Sendable {} extension Constants: @unchecked Sendable {} extension CriticalErrorCode: @unchecked Sendable {} +extension ExcludedModules: @unchecked Sendable {} extension Position: @unchecked Sendable {} extension Position.LocSource: @unchecked Sendable {} extension Position.AltSource: @unchecked Sendable {} @@ -3391,6 +3556,25 @@ extension CriticalErrorCode: SwiftProtobuf._ProtoNameProviding { ] } +extension ExcludedModules: SwiftProtobuf._ProtoNameProviding { + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "EXCLUDED_NONE"), + 1: .same(proto: "MQTT_CONFIG"), + 2: .same(proto: "SERIAL_CONFIG"), + 4: .same(proto: "EXTNOTIF_CONFIG"), + 8: .same(proto: "STOREFORWARD_CONFIG"), + 16: .same(proto: "RANGETEST_CONFIG"), + 32: .same(proto: "TELEMETRY_CONFIG"), + 64: .same(proto: "CANNEDMSG_CONFIG"), + 128: .same(proto: "AUDIO_CONFIG"), + 256: .same(proto: "REMOTEHARDWARE_CONFIG"), + 512: .same(proto: "NEIGHBORINFO_CONFIG"), + 1024: .same(proto: "AMBIENTLIGHTING_CONFIG"), + 2048: .same(proto: "DETECTIONSENSOR_CONFIG"), + 4096: .same(proto: "PAXCOUNTER_CONFIG"), + ] +} + extension Position: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Position" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -4525,6 +4709,8 @@ extension MyNodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio 1: .standard(proto: "my_node_num"), 8: .standard(proto: "reboot_count"), 11: .standard(proto: "min_app_version"), + 12: .standard(proto: "device_id"), + 13: .standard(proto: "pio_env"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -4536,6 +4722,8 @@ extension MyNodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio case 1: try { try decoder.decodeSingularUInt32Field(value: &self.myNodeNum) }() case 8: try { try decoder.decodeSingularUInt32Field(value: &self.rebootCount) }() case 11: try { try decoder.decodeSingularUInt32Field(value: &self.minAppVersion) }() + case 12: try { try decoder.decodeSingularBytesField(value: &self.deviceID) }() + case 13: try { try decoder.decodeSingularStringField(value: &self.pioEnv) }() default: break } } @@ -4551,6 +4739,12 @@ extension MyNodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio if self.minAppVersion != 0 { try visitor.visitSingularUInt32Field(value: self.minAppVersion, fieldNumber: 11) } + if !self.deviceID.isEmpty { + try visitor.visitSingularBytesField(value: self.deviceID, fieldNumber: 12) + } + if !self.pioEnv.isEmpty { + try visitor.visitSingularStringField(value: self.pioEnv, fieldNumber: 13) + } try unknownFields.traverse(visitor: &visitor) } @@ -4558,6 +4752,8 @@ extension MyNodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio if lhs.myNodeNum != rhs.myNodeNum {return false} if lhs.rebootCount != rhs.rebootCount {return false} if lhs.minAppVersion != rhs.minAppVersion {return false} + if lhs.deviceID != rhs.deviceID {return false} + if lhs.pioEnv != rhs.pioEnv {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -4694,6 +4890,7 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation 14: .same(proto: "mqttClientProxyMessage"), 15: .same(proto: "fileInfo"), 16: .same(proto: "clientNotification"), + 17: .same(proto: "deviceuiConfig"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -4888,6 +5085,19 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation self.payloadVariant = .clientNotification(v) } }() + case 17: try { + var v: DeviceUIConfig? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .deviceuiConfig(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .deviceuiConfig(v) + } + }() default: break } } @@ -4962,6 +5172,10 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation guard case .clientNotification(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 16) }() + case .deviceuiConfig?: try { + guard case .deviceuiConfig(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 17) + }() case nil: break } try unknownFields.traverse(visitor: &visitor) @@ -5351,6 +5565,7 @@ extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement 9: .standard(proto: "hw_model"), 10: .same(proto: "hasRemoteHardware"), 11: .same(proto: "hasPKC"), + 12: .standard(proto: "excluded_modules"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -5370,6 +5585,7 @@ extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement case 9: try { try decoder.decodeSingularEnumField(value: &self.hwModel) }() case 10: try { try decoder.decodeSingularBoolField(value: &self.hasRemoteHardware_p) }() case 11: try { try decoder.decodeSingularBoolField(value: &self.hasPkc_p) }() + case 12: try { try decoder.decodeSingularUInt32Field(value: &self.excludedModules) }() default: break } } @@ -5409,6 +5625,9 @@ extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement if self.hasPkc_p != false { try visitor.visitSingularBoolField(value: self.hasPkc_p, fieldNumber: 11) } + if self.excludedModules != 0 { + try visitor.visitSingularUInt32Field(value: self.excludedModules, fieldNumber: 12) + } try unknownFields.traverse(visitor: &visitor) } @@ -5424,6 +5643,7 @@ extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement if lhs.hwModel != rhs.hwModel {return false} if lhs.hasRemoteHardware_p != rhs.hasRemoteHardware_p {return false} if lhs.hasPkc_p != rhs.hasPkc_p {return false} + if lhs.excludedModules != rhs.excludedModules {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift index 30a8e0a4..4238811f 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/module_config.pb.swift @@ -455,9 +455,14 @@ public struct ModuleConfig { /// /// Interval in seconds of how often we should try to send our - /// Neighbor Info to the mesh + /// Neighbor Info (minimum is 14400, i.e., 4 hours) public var updateInterval: UInt32 = 0 + /// + /// Whether in addition to sending it to MQTT and the PhoneAPI, our NeighborInfo should be transmitted over LoRa. + /// Note that this is not available on a channel with default key and name. + public var transmitOverLora: Bool = false + public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} @@ -1825,6 +1830,7 @@ extension ModuleConfig.NeighborInfoConfig: SwiftProtobuf.Message, SwiftProtobuf. public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 1: .same(proto: "enabled"), 2: .standard(proto: "update_interval"), + 3: .standard(proto: "transmit_over_lora"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -1835,6 +1841,7 @@ extension ModuleConfig.NeighborInfoConfig: SwiftProtobuf.Message, SwiftProtobuf. switch fieldNumber { case 1: try { try decoder.decodeSingularBoolField(value: &self.enabled) }() case 2: try { try decoder.decodeSingularUInt32Field(value: &self.updateInterval) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.transmitOverLora) }() default: break } } @@ -1847,12 +1854,16 @@ extension ModuleConfig.NeighborInfoConfig: SwiftProtobuf.Message, SwiftProtobuf. if self.updateInterval != 0 { try visitor.visitSingularUInt32Field(value: self.updateInterval, fieldNumber: 2) } + if self.transmitOverLora != false { + try visitor.visitSingularBoolField(value: self.transmitOverLora, fieldNumber: 3) + } try unknownFields.traverse(visitor: &visitor) } public static func ==(lhs: ModuleConfig.NeighborInfoConfig, rhs: ModuleConfig.NeighborInfoConfig) -> Bool { if lhs.enabled != rhs.enabled {return false} if lhs.updateInterval != rhs.updateInterval {return false} + if lhs.transmitOverLora != rhs.transmitOverLora {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift index ec5faaa4..e67b5272 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift @@ -150,8 +150,12 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum { case max30102 // = 30 /// - /// MLX90614 non-contact IR temperature sensor. + /// MLX90614 non-contact IR temperature sensor case mlx90614 // = 31 + + /// + /// SCD40/SCD41 CO2, humidity, temperature sensor + case scd4X // = 32 case UNRECOGNIZED(Int) public init() { @@ -192,6 +196,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum { case 29: self = .customSensor case 30: self = .max30102 case 31: self = .mlx90614 + case 32: self = .scd4X default: self = .UNRECOGNIZED(rawValue) } } @@ -230,6 +235,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum { case .customSensor: return 29 case .max30102: return 30 case .mlx90614: return 31 + case .scd4X: return 32 case .UNRECOGNIZED(let i): return i } } @@ -273,6 +279,7 @@ extension TelemetrySensorType: CaseIterable { .customSensor, .max30102, .mlx90614, + .scd4X, ] } @@ -778,6 +785,17 @@ public struct AirQualityMetrics { /// Clears the value of `particles100Um`. Subsequent reads from it will return its default value. public mutating func clearParticles100Um() {self._particles100Um = nil} + /// + /// 10.0um Particle Count + public var co2: UInt32 { + get {return _co2 ?? 0} + set {_co2 = newValue} + } + /// Returns true if `co2` has been explicitly set. + public var hasCo2: Bool {return self._co2 != nil} + /// Clears the value of `co2`. Subsequent reads from it will return its default value. + public mutating func clearCo2() {self._co2 = nil} + public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} @@ -794,6 +812,7 @@ public struct AirQualityMetrics { fileprivate var _particles25Um: UInt32? = nil fileprivate var _particles50Um: UInt32? = nil fileprivate var _particles100Um: UInt32? = nil + fileprivate var _co2: UInt32? = nil } /// @@ -1108,6 +1127,7 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding { 29: .same(proto: "CUSTOM_SENSOR"), 30: .same(proto: "MAX30102"), 31: .same(proto: "MLX90614"), + 32: .same(proto: "SCD4X"), ] } @@ -1456,6 +1476,7 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem 10: .standard(proto: "particles_25um"), 11: .standard(proto: "particles_50um"), 12: .standard(proto: "particles_100um"), + 13: .same(proto: "co2"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -1476,6 +1497,7 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem case 10: try { try decoder.decodeSingularUInt32Field(value: &self._particles25Um) }() case 11: try { try decoder.decodeSingularUInt32Field(value: &self._particles50Um) }() case 12: try { try decoder.decodeSingularUInt32Field(value: &self._particles100Um) }() + case 13: try { try decoder.decodeSingularUInt32Field(value: &self._co2) }() default: break } } @@ -1522,6 +1544,9 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem try { if let v = self._particles100Um { try visitor.visitSingularUInt32Field(value: v, fieldNumber: 12) } }() + try { if let v = self._co2 { + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 13) + } }() try unknownFields.traverse(visitor: &visitor) } @@ -1538,6 +1563,7 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if lhs._particles25Um != rhs._particles25Um {return false} if lhs._particles50Um != rhs._particles50Um {return false} if lhs._particles100Um != rhs._particles100Um {return false} + if lhs._co2 != rhs._co2 {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/protobufs b/protobufs index c9ae7fd4..04f21f5c 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit c9ae7fd478bffe5f954b30de6cb140821fe9ff52 +Subproject commit 04f21f5c7238b8e02f794d9282c4786752634b3c From 696d197f40d2f70bb52fd5ab96c4d371cb987b59 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 12 Nov 2024 08:27:57 -0800 Subject: [PATCH 5/6] Update device hardware json --- Meshtastic/Resources/DeviceHardware.json | 372 +++++++++++++++++++---- 1 file changed, 321 insertions(+), 51 deletions(-) diff --git a/Meshtastic/Resources/DeviceHardware.json b/Meshtastic/Resources/DeviceHardware.json index 0b88202d..5e0135b9 100644 --- a/Meshtastic/Resources/DeviceHardware.json +++ b/Meshtastic/Resources/DeviceHardware.json @@ -5,7 +5,10 @@ "platformioTarget": "tlora-v2", "architecture": "esp32", "activelySupported": false, - "displayName": "LILYGO T-LoRa V2" + "displayName": "LILYGO T-LoRa V2", + "tags": [ + "LilyGo" + ] }, { "hwModel": 2, @@ -13,7 +16,10 @@ "platformioTarget": "tlora-v1", "architecture": "esp32", "activelySupported": false, - "displayName": "LILYGO T-LoRa V1" + "displayName": "LILYGO T-LoRa V1", + "tags": [ + "LilyGo" + ] }, { "hwModel": 3, @@ -21,7 +27,14 @@ "platformioTarget": "tlora-v2-1-1_6", "architecture": "esp32", "activelySupported": true, - "displayName": "LILYGO T-LoRa V2.1-1.6" + "supportLevel": 1, + "displayName": "LILYGO T-LoRa V2.1-1.6", + "tags": [ + "LilyGo" + ], + "images": [ + "tlora-v2-1-1_6.svg" + ] }, { "hwModel": 4, @@ -29,7 +42,14 @@ "platformioTarget": "tbeam", "architecture": "esp32", "activelySupported": true, - "displayName": "LILYGO T-Beam" + "supportLevel": 1, + "displayName": "LILYGO T-Beam", + "tags": [ + "LilyGo" + ], + "images": [ + "tbeam.svg" + ] }, { "hwModel": 5, @@ -37,7 +57,10 @@ "platformioTarget": "heltec-v2_0", "architecture": "esp32", "activelySupported": false, - "displayName": "Heltec V2.0" + "displayName": "Heltec V2.0", + "tags": [ + "Heltec" + ] }, { "hwModel": 6, @@ -45,15 +68,25 @@ "platformioTarget": "tbeam0_7", "architecture": "esp32", "activelySupported": false, - "displayName": "LILYGO T-Beam V0.7" + "displayName": "LILYGO T-Beam V0.7", + "tags": [ + "LilyGo" + ] }, { "hwModel": 7, "hwModelSlug": "T_ECHO", "platformioTarget": "t-echo", "architecture": "nrf52840", + "supportLevel": 1, "activelySupported": true, - "displayName": "LILYGO T-Echo" + "displayName": "LILYGO T-Echo", + "tags": [ + "LilyGo" + ], + "images": [ + "t-echo.svg" + ] }, { "hwModel": 8, @@ -61,7 +94,10 @@ "platformioTarget": "tlora-v1_3", "architecture": "esp32", "activelySupported": false, - "displayName": "LILYGO T-LoRa V1.1-1.3" + "displayName": "LILYGO T-LoRa V1.1-1.3", + "tags": [ + "LilyGo" + ] }, { "hwModel": 9, @@ -69,7 +105,15 @@ "platformioTarget": "rak4631", "architecture": "nrf52840", "activelySupported": true, - "displayName": "RAK WisBlock 4631" + "supportLevel": 1, + "displayName": "RAK WisBlock 4631", + "tags": [ + "RAK" + ], + "images": [ + "rak4631.svg", + "rak4631_case.svg" + ] }, { "hwModel": 10, @@ -77,7 +121,10 @@ "platformioTarget": "heltec-v2_1", "architecture": "esp32", "activelySupported": false, - "displayName": "Heltec V2.1" + "displayName": "Heltec V2.1", + "tags": [ + "Heltec" + ] }, { "hwModel": 11, @@ -85,7 +132,10 @@ "platformioTarget": "heltec-v1", "architecture": "esp32", "activelySupported": false, - "displayName": "Heltec V1" + "displayName": "Heltec V1", + "tags": [ + "Heltec" + ] }, { "hwModel": 12, @@ -93,7 +143,14 @@ "platformioTarget": "tbeam-s3-core", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "LILYGO T-Beam S3 Core" + "supportLevel": 1, + "displayName": "LILYGO T-Beam Supreme", + "tags": [ + "LilyGo" + ], + "images": [ + "tbeam-s3-core.svg" + ] }, { "hwModel": 13, @@ -101,7 +158,10 @@ "platformioTarget": "rak11200", "architecture": "esp32", "activelySupported": false, - "displayName": "RAK WisBlock 11200" + "displayName": "RAK WisBlock 11200", + "tags": [ + "RAK" + ] }, { "hwModel": 14, @@ -109,7 +169,11 @@ "platformioTarget": "nano-g1", "architecture": "esp32", "activelySupported": true, - "displayName": "Nano G1" + "supportLevel": 3, + "displayName": "Nano G1", + "tags": [ + "B&Q" + ] }, { "hwModel": 15, @@ -117,7 +181,15 @@ "platformioTarget": "tlora-v2-1-1_8", "architecture": "esp32", "activelySupported": true, - "displayName": "LILYGO T-LoRa V2.1-1.8" + "supportLevel": 2, + "displayName": "LILYGO T-LoRa V2.1-1.8", + "tags": [ + "LilyGo", + "2.4G LoRA" + ], + "images": [ + "tlora-v2-1-1_8.svg" + ] }, { "hwModel": 16, @@ -125,7 +197,14 @@ "platformioTarget": "tlora-t3s3-v1", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "LILYGO T-LoRa T3-S3" + "displayName": "LILYGO T-LoRa T3-S3", + "supportLevel": 1, + "tags": [ + "LilyGo" + ], + "images": [ + "tlora-t3s3-v1.svg" + ] }, { "hwModel": 16, @@ -133,7 +212,14 @@ "platformioTarget": "tlora-t3s3-epaper", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "LILYGO T-LoRa T3-S3 E-Paper" + "supportLevel": 1, + "displayName": "LILYGO T-LoRa T3-S3 E-Ink", + "tags": [ + "LilyGo" + ], + "images": [ + "tlora-t3s3-epaper.svg" + ] }, { "hwModel": 17, @@ -141,7 +227,11 @@ "platformioTarget": "nano-g1-explorer", "architecture": "esp32", "activelySupported": true, - "displayName": "Nano G1 Explorer" + "supportLevel": 3, + "displayName": "Nano G1 Explorer", + "tags": [ + "B&Q" + ] }, { "hwModel": 18, @@ -149,7 +239,11 @@ "platformioTarget": "nano-g2-ultra", "architecture": "nrf52840", "activelySupported": true, - "displayName": "Nano G2 Ultra" + "supportLevel": 2, + "displayName": "Nano G2 Ultra", + "tags": [ + "B&Q" + ] }, { "hwModel": 21, @@ -157,7 +251,14 @@ "platformioTarget": "wio-tracker-wm1110", "architecture": "nrf52840", "activelySupported": true, - "displayName": "Seeed Wio WM1110 Tracker" + "supportLevel": 1, + "displayName": "Seeed Wio WM1110 Tracker", + "tags": [ + "Seeed" + ], + "images": [ + "wio-tracker-wm1110.svg" + ] }, { "hwModel": 25, @@ -165,7 +266,11 @@ "platformioTarget": "station-g1", "architecture": "esp32", "activelySupported": true, - "displayName": "Station G1" + "supportLevel": 3, + "displayName": "Station G1", + "tags": [ + "B&Q" + ] }, { "hwModel": 26, @@ -173,7 +278,11 @@ "platformioTarget": "rak11310", "architecture": "rp2040", "activelySupported": true, - "displayName": "RAK WisBlock 11310" + "supportLevel": 2, + "displayName": "RAK WisBlock 11310", + "tags": [ + "RAK" + ] }, { "hwModel": 29, @@ -181,7 +290,11 @@ "platformioTarget": "canaryone", "architecture": "nrf52840", "activelySupported": true, - "displayName": "Canary One" + "supportLevel": 3, + "displayName": "Canary One", + "tags": [ + "Canary" + ] }, { "hwModel": 30, @@ -189,7 +302,11 @@ "platformioTarget": "rp2040-lora", "architecture": "rp2040", "activelySupported": true, - "displayName": "RP2040 LoRa" + "supportLevel": 2, + "displayName": "RP2040 LoRa", + "tags": [ + "Waveshare" + ] }, { "hwModel": 31, @@ -197,7 +314,11 @@ "platformioTarget": "station-g2", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Station G2" + "supportLevel": 2, + "displayName": "Station G2", + "tags": [ + "B&Q" + ] }, { "hwModel": 39, @@ -205,7 +326,11 @@ "platformioTarget": "meshtastic-diy-v1", "architecture": "esp32", "activelySupported": true, - "displayName": "DIY V1" + "supportLevel": 3, + "displayName": "DIY V1", + "tags": [ + "DIY" + ] }, { "hwModel": 39, @@ -213,15 +338,22 @@ "platformioTarget": "hydra", "architecture": "esp32", "activelySupported": true, - "displayName": "Hydra" + "supportLevel": 3, + "displayName": "Hydra", + "tags": [ + "DIY" + ] }, { "hwModel": 41, "hwModelSlug": "DR_DEV", "platformioTarget": "meshtastic-dr-dev", "architecture": "esp32", - "activelySupported": true, - "displayName": "DR-DEV" + "activelySupported": false, + "displayName": "DR-DEV", + "tags": [ + "DIY" + ] }, { "hwModel": 42, @@ -229,7 +361,11 @@ "platformioTarget": "m5stack-core", "architecture": "esp32", "activelySupported": true, - "displayName": "M5 Stack" + "supportLevel": 3, + "displayName": "M5 Stack", + "tags": [ + "M5Stack" + ] }, { "hwModel": 43, @@ -237,7 +373,15 @@ "platformioTarget": "heltec-v3", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec V3" + "supportLevel": 1, + "displayName": "Heltec V3", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-v3.svg", + "heltec-v3-case.svg" + ] }, { "hwModel": 44, @@ -245,7 +389,14 @@ "platformioTarget": "heltec-wsl-v3", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Wireless Stick Lite V3" + "supportLevel": 1, + "displayName": "Heltec Wireless Stick Lite V3", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-wsl-v3.svg" + ] }, { "hwModel": 47, @@ -253,7 +404,12 @@ "platformioTarget": "pico", "architecture": "rp2040", "activelySupported": true, - "displayName": "Raspberry Pi Pico" + "supportLevel": 3, + "displayName": "Raspberry Pi Pico", + "tags": [ + "Raspberry Pi", + "DIY" + ] }, { "hwModel": 47, @@ -261,7 +417,12 @@ "platformioTarget": "picow", "architecture": "rp2040", "activelySupported": true, - "displayName": "Raspberry Pi Pico W" + "supportLevel": 3, + "displayName": "Raspberry Pi Pico W", + "tags": [ + "Raspberry Pi", + "DIY" + ] }, { "hwModel": 48, @@ -269,7 +430,14 @@ "platformioTarget": "heltec-wireless-tracker", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Wireless Tracker V1.1" + "supportLevel": 1, + "displayName": "Heltec Wireless Tracker V1.1", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-wireless-tracker.svg" + ] }, { "hwModel": 58, @@ -277,7 +445,11 @@ "platformioTarget": "heltec-wireless-tracker-V1-0", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Wireless Tracker V1.0" + "supportLevel": 3, + "displayName": "Heltec Wireless Tracker V1.0", + "images": [ + "heltec-wireless-tracker.svg" + ] }, { "hwModel": 49, @@ -285,7 +457,14 @@ "platformioTarget": "heltec-wireless-paper", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Wireless Paper" + "supportLevel": 1, + "displayName": "Heltec Wireless Paper", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-wireless-paper.svg" + ] }, { "hwModel": 50, @@ -293,7 +472,14 @@ "platformioTarget": "t-deck", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "LILYGO T-Deck" + "supportLevel": 1, + "displayName": "LILYGO T-Deck", + "tags": [ + "LilyGo" + ], + "images": [ + "t-deck.svg" + ] }, { "hwModel": 51, @@ -301,7 +487,14 @@ "platformioTarget": "t-watch-s3", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "LILYGO T-Watch S3" + "supportLevel": 1, + "displayName": "LILYGO T-Watch S3", + "tags": [ + "LilyGo" + ], + "images": [ + "t-watch-s3.svg" + ] }, { "hwModel": 52, @@ -309,6 +502,7 @@ "platformioTarget": "picomputer-s3", "architecture": "esp32-s3", "activelySupported": true, + "supportLevel": 3, "displayName": "Pi Computer S3" }, { @@ -316,8 +510,15 @@ "hwModelSlug": "HELTEC_HT62", "platformioTarget": "heltec-ht62-esp32c3-sx1262", "architecture": "esp32-c3", + "supportLevel": 1, "activelySupported": true, - "displayName": "Heltec HT62" + "displayName": "Heltec HT62", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-ht62-esp32c3-sx1262.svg" + ] }, { "hwModel": 57, @@ -325,7 +526,14 @@ "platformioTarget": "heltec-wireless-paper-v1_0", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Wireless Paper V1.0" + "supportLevel": 3, + "tags": [ + "Heltec" + ], + "displayName": "Heltec Wireless Paper V1.0", + "images": [ + "heltec-wireless-paper-v1_0.svg" + ] }, { "hwModel": 59, @@ -333,6 +541,7 @@ "platformioTarget": "unphone", "architecture": "esp32-s3", "activelySupported": true, + "supportLevel": 3, "displayName": "unPhone" }, { @@ -341,6 +550,7 @@ "platformioTarget": "tracksenger", "architecture": "esp32-s3", "activelySupported": true, + "supportLevel": 3, "displayName": "TrackSenger (small TFT)" }, { @@ -349,6 +559,7 @@ "platformioTarget": "tracksenger-lcd", "architecture": "esp32-s3", "activelySupported": true, + "supportLevel": 3, "displayName": "TrackSenger (big TFT)" }, { @@ -357,6 +568,7 @@ "platformioTarget": "tracksenger-oled", "architecture": "esp32-s3", "activelySupported": true, + "supportLevel": 3, "displayName": "TrackSenger (big OLED)" }, { @@ -365,7 +577,11 @@ "platformioTarget": "CDEBYTE_EoRa-S3", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "EBYTE EoRa-S3" + "supportLevel": 3, + "displayName": "EBYTE EoRa-S3", + "tags": [ + "EByte" + ] }, { "hwModel": 64, @@ -373,7 +589,11 @@ "platformioTarget": "radiomaster_900_bandit_nano", "architecture": "esp32", "activelySupported": true, - "displayName": "RadioMaster 900 Bandit Nano" + "supportLevel": 2, + "displayName": "RadioMaster 900 Bandit Nano", + "tags": [ + "RadioMaster" + ] }, { "hwModel": 66, @@ -381,7 +601,14 @@ "platformioTarget": "heltec-vision-master-t190", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Vision Master T190" + "supportLevel": 1, + "displayName": "Heltec Vision Master T190", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-vision-master-t190.svg" + ] }, { "hwModel": 67, @@ -389,7 +616,14 @@ "platformioTarget": "heltec-vision-master-e213", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Vision Master E213" + "supportLevel": 1, + "displayName": "Heltec Vision Master E213", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-vision-master-e213.svg" + ] }, { "hwModel": 68, @@ -397,15 +631,30 @@ "platformioTarget": "heltec-vision-master-e290", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Heltec Vision Master E290" + "supportLevel": 1, + "displayName": "Heltec Vision Master E290", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-vision-master-e290.svg" + ] }, { "hwModel": 69, "hwModelSlug": "HELTEC_MESH_NODE_T114", "platformioTarget": "heltec-mesh-node-t114", "architecture": "nrf52840", - "activelySupported": false, - "displayName": "Heltec Mesh Node T114" + "activelySupported": true, + "supportLevel": 1, + "displayName": "Heltec Mesh Node T114", + "tags": [ + "Heltec" + ], + "images": [ + "heltec-mesh-node-t114.svg", + "heltec-mesh-node-t114-case.svg" + ] }, { "hwModel": 70, @@ -413,7 +662,14 @@ "platformioTarget": "seeed-sensecap-indicator", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "SenseCAP Indicator" + "supportLevel": 1, + "displayName": "Seeed SenseCAP Indicator", + "tags": [ + "Seeed" + ], + "images": [ + "seeed-sensecap-indicator.svg" + ] }, { "hwModel": 71, @@ -421,7 +677,14 @@ "platformioTarget": "tracker-t1000-e", "architecture": "nrf52840", "activelySupported": true, - "displayName": "Seeed Card Tracker T1000-E" + "supportLevel": 1, + "displayName": "Seeed Card Tracker T1000-E", + "tags": [ + "Seeed" + ], + "images": [ + "tracker-t1000-e.svg" + ] }, { "hwModel": 72, @@ -429,6 +692,13 @@ "platformioTarget": "seeed-xiao-s3", "architecture": "esp32-s3", "activelySupported": true, - "displayName": "Seeed XIAO S3" + "supportLevel": 1, + "displayName": "Seeed Xiao ESP32-S3", + "tags": [ + "Seeed" + ], + "images": [ + "seeed-xiao-s3.svg" + ] } ] From 2c4cf4cc57844acd6c916f71344d72021c9b1556 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Thu, 14 Nov 2024 08:11:49 -0800 Subject: [PATCH 6/6] Admin key fixes --- Meshtastic/Persistence/UpdateCoreData.swift | 5 +++++ Meshtastic/Views/Settings/Config/SecurityConfig.swift | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index 6ddd664c..9feecf6d 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -831,6 +831,11 @@ func upsertSecurityConfigPacket(config: Config.SecurityConfig, nodeNum: Int64, s fetchedNode[0].securityConfig?.privateKey = config.privateKey if config.adminKey.count > 0 { fetchedNode[0].securityConfig?.adminKey = config.adminKey[0] + if config.adminKey.count > 1 { + fetchedNode[0].securityConfig?.adminKey = config.adminKey[1] + } else if config.adminKey.count > 2 { + fetchedNode[0].securityConfig?.adminKey = config.adminKey[2] + } } fetchedNode[0].securityConfig?.isManaged = config.isManaged fetchedNode[0].securityConfig?.serialEnabled = config.serialEnabled diff --git a/Meshtastic/Views/Settings/Config/SecurityConfig.swift b/Meshtastic/Views/Settings/Config/SecurityConfig.swift index 8ddd5816..206b0de0 100644 --- a/Meshtastic/Views/Settings/Config/SecurityConfig.swift +++ b/Meshtastic/Views/Settings/Config/SecurityConfig.swift @@ -85,7 +85,7 @@ struct SecurityConfig: View { .font(idiom == .phone ? .caption : .callout) Divider() Label("Tertiary Admin Key", systemImage: "key.viewfinder") - SecureInput("Tertiary Admin Key", text: $adminKey2, isValid: $hasValidAdminKey2) + SecureInput("Tertiary Admin Key", text: $adminKey3, isValid: $hasValidAdminKey2) .background( RoundedRectangle(cornerRadius: 10.0) .stroke(hasValidAdminKey3 ? Color.clear : Color.red, lineWidth: 2.0) @@ -259,8 +259,8 @@ struct SecurityConfig: View { self.publicKey = node?.securityConfig?.publicKey?.base64EncodedString() ?? "" self.privateKey = node?.securityConfig?.privateKey?.base64EncodedString() ?? "" self.adminKey = node?.securityConfig?.adminKey?.base64EncodedString() ?? "" - self.adminKey2 = node?.securityConfig?.adminKey?.base64EncodedString() ?? "" - self.adminKey3 = node?.securityConfig?.adminKey?.base64EncodedString() ?? "" + self.adminKey2 = node?.securityConfig?.adminKey2?.base64EncodedString() ?? "" + self.adminKey3 = node?.securityConfig?.adminKey3?.base64EncodedString() ?? "" self.isManaged = node?.securityConfig?.isManaged ?? false self.serialEnabled = node?.securityConfig?.serialEnabled ?? false self.debugLogApiEnabled = node?.securityConfig?.debugLogApiEnabled ?? false