From fff3b6e8df7fa25ffed9a00c8158a69c94c1fab7 Mon Sep 17 00:00:00 2001 From: Blake McAnally Date: Mon, 15 Jul 2024 20:42:47 -0500 Subject: [PATCH 1/3] Update App Icon to support iOS 18 dark & tinted mode --- .../AppIcon.appiconset/Contents.json | 24 ++++++++++++++++++ .../AppIcon.appiconset/logo-dark.png | Bin 0 -> 29213 bytes .../AppIcon.appiconset/logo-tinted.png | Bin 0 -> 22823 bytes 3 files changed, 24 insertions(+) create mode 100644 Meshtastic/Assets.xcassets/AppIcon.appiconset/logo-dark.png create mode 100644 Meshtastic/Assets.xcassets/AppIcon.appiconset/logo-tinted.png diff --git a/Meshtastic/Assets.xcassets/AppIcon.appiconset/Contents.json b/Meshtastic/Assets.xcassets/AppIcon.appiconset/Contents.json index 937092d63..241cfb2bd 100644 --- a/Meshtastic/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Meshtastic/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -5,6 +5,30 @@ "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "logo-dark.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "filename" : "logo-tinted.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" } ], "info" : { diff --git a/Meshtastic/Assets.xcassets/AppIcon.appiconset/logo-dark.png b/Meshtastic/Assets.xcassets/AppIcon.appiconset/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9942a312f00dac9ba4fca00c0a5a438bfb50a099 GIT binary patch literal 29213 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 &v&@NbnS~xqbjq9ajx-hVn2Ourc`KfnFBjh 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 D31RPq literal 0 HcmV?d00001 diff --git a/Meshtastic/Assets.xcassets/AppIcon.appiconset/logo-tinted.png b/Meshtastic/Assets.xcassets/AppIcon.appiconset/logo-tinted.png new file mode 100644 index 0000000000000000000000000000000000000000..8591564379d0de5908f89c2e2f6d0a1b45d7f4f8 GIT binary patch literal 22823 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 Date: Mon, 9 Sep 2024 11:38:07 -0700 Subject: [PATCH 2/3] Merge from main --- protobufs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobufs b/protobufs index b62376294..4da558d0f 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit b623762940ebdb1887a3b31b86f4d9cdaa7e6ecf +Subproject commit 4da558d0f73c46ef91b74431facee73c09affbfc From 37d652cb39ea3c19cda21c17dbdea184d4ac3990 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sat, 14 Sep 2024 08:48:09 -0700 Subject: [PATCH 3/3] Update protobufs --- .../Sources/meshtastic/admin.pb.swift | 5 + .../Sources/meshtastic/config.pb.swift | 119 ++++++++++++------ .../Sources/meshtastic/mesh.pb.swift | 65 ++++++++++ .../Sources/meshtastic/telemetry.pb.swift | 8 ++ protobufs | 2 +- 5 files changed, 161 insertions(+), 38 deletions(-) diff --git a/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift index 0f1c35869..53d244d17 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/admin.pb.swift @@ -844,6 +844,7 @@ public struct AdminMessage { /// /// TODO: REPLACE case securityConfig // = 7 + case sessionkeyConfig // = 8 case UNRECOGNIZED(Int) public init() { @@ -860,6 +861,7 @@ public struct AdminMessage { case 5: self = .loraConfig case 6: self = .bluetoothConfig case 7: self = .securityConfig + case 8: self = .sessionkeyConfig default: self = .UNRECOGNIZED(rawValue) } } @@ -874,6 +876,7 @@ public struct AdminMessage { case .loraConfig: return 5 case .bluetoothConfig: return 6 case .securityConfig: return 7 + case .sessionkeyConfig: return 8 case .UNRECOGNIZED(let i): return i } } @@ -998,6 +1001,7 @@ extension AdminMessage.ConfigType: CaseIterable { .loraConfig, .bluetoothConfig, .securityConfig, + .sessionkeyConfig, ] } @@ -1755,6 +1759,7 @@ extension AdminMessage.ConfigType: SwiftProtobuf._ProtoNameProviding { 5: .same(proto: "LORA_CONFIG"), 6: .same(proto: "BLUETOOTH_CONFIG"), 7: .same(proto: "SECURITY_CONFIG"), + 8: .same(proto: "SESSIONKEY_CONFIG"), ] } diff --git a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift index 4b9534701..37832baad 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift @@ -93,6 +93,14 @@ public struct Config { set {payloadVariant = .security(newValue)} } + public var sessionkey: Config.SessionkeyConfig { + get { + if case .sessionkey(let v)? = payloadVariant {return v} + return Config.SessionkeyConfig() + } + set {payloadVariant = .sessionkey(newValue)} + } + public var unknownFields = SwiftProtobuf.UnknownStorage() /// @@ -106,6 +114,7 @@ public struct Config { case lora(Config.LoRaConfig) case bluetooth(Config.BluetoothConfig) case security(Config.SecurityConfig) + case sessionkey(Config.SessionkeyConfig) #if !swift(>=4.1) public static func ==(lhs: Config.OneOf_PayloadVariant, rhs: Config.OneOf_PayloadVariant) -> Bool { @@ -145,6 +154,10 @@ public struct Config { guard case .security(let l) = lhs, case .security(let r) = rhs else { preconditionFailure() } return l == r }() + case (.sessionkey, .sessionkey): return { + guard case .sessionkey(let l) = lhs, case .sessionkey(let r) = rhs else { preconditionFailure() } + return l == r + }() default: return false } } @@ -167,12 +180,6 @@ public struct Config { /// Moved to SecurityConfig public var serialEnabled: Bool = false - /// - /// By default we turn off logging as soon as an API client connects (to keep shared serial link quiet). - /// Set this to true to leave the debug log outputting even when API is active. - /// Moved to SecurityConfig - public var debugLogEnabled: Bool = false - /// /// For boards without a hard wired button, this is the pin number that will be used /// Boards that have more than one button can swap the function with this one. defaults to BUTTON_PIN if defined. @@ -1250,6 +1257,13 @@ public struct Config { set {_uniqueStorage()._ignoreMqtt = newValue} } + /// + /// Sets the ok_to_mqtt bit on outgoing packets + public var configOkToMqtt: Bool { + get {return _storage._configOkToMqtt} + set {_uniqueStorage()._configOkToMqtt = newValue} + } + public var unknownFields = SwiftProtobuf.UnknownStorage() public enum RegionCode: SwiftProtobuf.Enum { @@ -1492,11 +1506,6 @@ public struct Config { /// Specified PIN for PairingMode.FixedPin public var fixedPin: UInt32 = 0 - /// - /// Enables device (serial style logs) over Bluetooth - /// Moved to SecurityConfig - public var deviceLoggingEnabled: Bool = false - public var unknownFields = SwiftProtobuf.UnknownStorage() public enum PairingMode: SwiftProtobuf.Enum { @@ -1559,7 +1568,7 @@ public struct Config { /// /// The public key authorized to send admin messages to this node. - public var adminKey: Data = Data() + public var adminKey: [Data] = [] /// /// If true, device is considered to be "managed" by a mesh administrator via admin messages @@ -1572,13 +1581,9 @@ public struct Config { /// /// By default we turn off logging as soon as an API client connects (to keep shared serial link quiet). - /// Output live debug logging over serial. + /// Output live debug logging over serial or bluetooth is set to true. public var debugLogApiEnabled: Bool = false - /// - /// Enables device (serial style logs) over Bluetooth - public var bluetoothLoggingEnabled: Bool = false - /// /// Allow incoming device control over the insecure legacy admin channel. public var adminChannelEnabled: Bool = false @@ -1588,6 +1593,18 @@ public struct Config { public init() {} } + /// + /// Blank config request, strictly for getting the session key + public struct SessionkeyConfig { + // 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. + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} + } + public init() {} } @@ -1784,6 +1801,7 @@ extension Config.LoRaConfig.ModemPreset: @unchecked Sendable {} extension Config.BluetoothConfig: @unchecked Sendable {} extension Config.BluetoothConfig.PairingMode: @unchecked Sendable {} extension Config.SecurityConfig: @unchecked Sendable {} +extension Config.SessionkeyConfig: @unchecked Sendable {} #endif // swift(>=5.5) && canImport(_Concurrency) // MARK: - Code below here is support for the SwiftProtobuf runtime. @@ -1801,6 +1819,7 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas 6: .same(proto: "lora"), 7: .same(proto: "bluetooth"), 8: .same(proto: "security"), + 9: .same(proto: "sessionkey"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -1913,6 +1932,19 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas self.payloadVariant = .security(v) } }() + case 9: try { + var v: Config.SessionkeyConfig? + var hadOneofValue = false + if let current = self.payloadVariant { + hadOneofValue = true + if case .sessionkey(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + self.payloadVariant = .sessionkey(v) + } + }() default: break } } @@ -1956,6 +1988,10 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas guard case .security(let v)? = self.payloadVariant else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 8) }() + case .sessionkey?: try { + guard case .sessionkey(let v)? = self.payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 9) + }() case nil: break } try unknownFields.traverse(visitor: &visitor) @@ -1973,7 +2009,6 @@ extension Config.DeviceConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 1: .same(proto: "role"), 2: .standard(proto: "serial_enabled"), - 3: .standard(proto: "debug_log_enabled"), 4: .standard(proto: "button_gpio"), 5: .standard(proto: "buzzer_gpio"), 6: .standard(proto: "rebroadcast_mode"), @@ -1993,7 +2028,6 @@ extension Config.DeviceConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl switch fieldNumber { case 1: try { try decoder.decodeSingularEnumField(value: &self.role) }() case 2: try { try decoder.decodeSingularBoolField(value: &self.serialEnabled) }() - case 3: try { try decoder.decodeSingularBoolField(value: &self.debugLogEnabled) }() case 4: try { try decoder.decodeSingularUInt32Field(value: &self.buttonGpio) }() case 5: try { try decoder.decodeSingularUInt32Field(value: &self.buzzerGpio) }() case 6: try { try decoder.decodeSingularEnumField(value: &self.rebroadcastMode) }() @@ -2015,9 +2049,6 @@ extension Config.DeviceConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl if self.serialEnabled != false { try visitor.visitSingularBoolField(value: self.serialEnabled, fieldNumber: 2) } - if self.debugLogEnabled != false { - try visitor.visitSingularBoolField(value: self.debugLogEnabled, fieldNumber: 3) - } if self.buttonGpio != 0 { try visitor.visitSingularUInt32Field(value: self.buttonGpio, fieldNumber: 4) } @@ -2051,7 +2082,6 @@ extension Config.DeviceConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl public static func ==(lhs: Config.DeviceConfig, rhs: Config.DeviceConfig) -> Bool { if lhs.role != rhs.role {return false} if lhs.serialEnabled != rhs.serialEnabled {return false} - if lhs.debugLogEnabled != rhs.debugLogEnabled {return false} if lhs.buttonGpio != rhs.buttonGpio {return false} if lhs.buzzerGpio != rhs.buzzerGpio {return false} if lhs.rebroadcastMode != rhs.rebroadcastMode {return false} @@ -2595,6 +2625,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem 15: .standard(proto: "pa_fan_disabled"), 103: .standard(proto: "ignore_incoming"), 104: .standard(proto: "ignore_mqtt"), + 105: .standard(proto: "config_ok_to_mqtt"), ] fileprivate class _StorageClass { @@ -2615,6 +2646,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem var _paFanDisabled: Bool = false var _ignoreIncoming: [UInt32] = [] var _ignoreMqtt: Bool = false + var _configOkToMqtt: Bool = false #if swift(>=5.10) // This property is used as the initial default value for new instances of the type. @@ -2646,6 +2678,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem _paFanDisabled = source._paFanDisabled _ignoreIncoming = source._ignoreIncoming _ignoreMqtt = source._ignoreMqtt + _configOkToMqtt = source._configOkToMqtt } } @@ -2681,6 +2714,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem case 15: try { try decoder.decodeSingularBoolField(value: &_storage._paFanDisabled) }() case 103: try { try decoder.decodeRepeatedUInt32Field(value: &_storage._ignoreIncoming) }() case 104: try { try decoder.decodeSingularBoolField(value: &_storage._ignoreMqtt) }() + case 105: try { try decoder.decodeSingularBoolField(value: &_storage._configOkToMqtt) }() default: break } } @@ -2740,6 +2774,9 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if _storage._ignoreMqtt != false { try visitor.visitSingularBoolField(value: _storage._ignoreMqtt, fieldNumber: 104) } + if _storage._configOkToMqtt != false { + try visitor.visitSingularBoolField(value: _storage._configOkToMqtt, fieldNumber: 105) + } } try unknownFields.traverse(visitor: &visitor) } @@ -2766,6 +2803,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem if _storage._paFanDisabled != rhs_storage._paFanDisabled {return false} if _storage._ignoreIncoming != rhs_storage._ignoreIncoming {return false} if _storage._ignoreMqtt != rhs_storage._ignoreMqtt {return false} + if _storage._configOkToMqtt != rhs_storage._configOkToMqtt {return false} return true } if !storagesAreEqual {return false} @@ -2819,7 +2857,6 @@ extension Config.BluetoothConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageI 1: .same(proto: "enabled"), 2: .same(proto: "mode"), 3: .standard(proto: "fixed_pin"), - 4: .standard(proto: "device_logging_enabled"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -2831,7 +2868,6 @@ extension Config.BluetoothConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageI case 1: try { try decoder.decodeSingularBoolField(value: &self.enabled) }() case 2: try { try decoder.decodeSingularEnumField(value: &self.mode) }() case 3: try { try decoder.decodeSingularUInt32Field(value: &self.fixedPin) }() - case 4: try { try decoder.decodeSingularBoolField(value: &self.deviceLoggingEnabled) }() default: break } } @@ -2847,9 +2883,6 @@ extension Config.BluetoothConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageI if self.fixedPin != 0 { try visitor.visitSingularUInt32Field(value: self.fixedPin, fieldNumber: 3) } - if self.deviceLoggingEnabled != false { - try visitor.visitSingularBoolField(value: self.deviceLoggingEnabled, fieldNumber: 4) - } try unknownFields.traverse(visitor: &visitor) } @@ -2857,7 +2890,6 @@ extension Config.BluetoothConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageI if lhs.enabled != rhs.enabled {return false} if lhs.mode != rhs.mode {return false} if lhs.fixedPin != rhs.fixedPin {return false} - if lhs.deviceLoggingEnabled != rhs.deviceLoggingEnabled {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -2880,7 +2912,6 @@ extension Config.SecurityConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm 4: .standard(proto: "is_managed"), 5: .standard(proto: "serial_enabled"), 6: .standard(proto: "debug_log_api_enabled"), - 7: .standard(proto: "bluetooth_logging_enabled"), 8: .standard(proto: "admin_channel_enabled"), ] @@ -2892,11 +2923,10 @@ extension Config.SecurityConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm switch fieldNumber { case 1: try { try decoder.decodeSingularBytesField(value: &self.publicKey) }() case 2: try { try decoder.decodeSingularBytesField(value: &self.privateKey) }() - case 3: try { try decoder.decodeSingularBytesField(value: &self.adminKey) }() + case 3: try { try decoder.decodeRepeatedBytesField(value: &self.adminKey) }() case 4: try { try decoder.decodeSingularBoolField(value: &self.isManaged) }() case 5: try { try decoder.decodeSingularBoolField(value: &self.serialEnabled) }() case 6: try { try decoder.decodeSingularBoolField(value: &self.debugLogApiEnabled) }() - case 7: try { try decoder.decodeSingularBoolField(value: &self.bluetoothLoggingEnabled) }() case 8: try { try decoder.decodeSingularBoolField(value: &self.adminChannelEnabled) }() default: break } @@ -2911,7 +2941,7 @@ extension Config.SecurityConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm try visitor.visitSingularBytesField(value: self.privateKey, fieldNumber: 2) } if !self.adminKey.isEmpty { - try visitor.visitSingularBytesField(value: self.adminKey, fieldNumber: 3) + try visitor.visitRepeatedBytesField(value: self.adminKey, fieldNumber: 3) } if self.isManaged != false { try visitor.visitSingularBoolField(value: self.isManaged, fieldNumber: 4) @@ -2922,9 +2952,6 @@ extension Config.SecurityConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm if self.debugLogApiEnabled != false { try visitor.visitSingularBoolField(value: self.debugLogApiEnabled, fieldNumber: 6) } - if self.bluetoothLoggingEnabled != false { - try visitor.visitSingularBoolField(value: self.bluetoothLoggingEnabled, fieldNumber: 7) - } if self.adminChannelEnabled != false { try visitor.visitSingularBoolField(value: self.adminChannelEnabled, fieldNumber: 8) } @@ -2938,9 +2965,27 @@ extension Config.SecurityConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm if lhs.isManaged != rhs.isManaged {return false} if lhs.serialEnabled != rhs.serialEnabled {return false} if lhs.debugLogApiEnabled != rhs.debugLogApiEnabled {return false} - if lhs.bluetoothLoggingEnabled != rhs.bluetoothLoggingEnabled {return false} if lhs.adminChannelEnabled != rhs.adminChannelEnabled {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } } + +extension Config.SessionkeyConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = Config.protoMessageName + ".SessionkeyConfig" + public static let _protobuf_nameMap = SwiftProtobuf._NameMap() + + public mutating func decodeMessage(decoder: inout D) throws { + while let _ = try decoder.nextFieldNumber() { + } + } + + public func traverse(visitor: inout V) throws { + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: Config.SessionkeyConfig, rhs: Config.SessionkeyConfig) -> Bool { + 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 ba12908dc..c7e8dc079 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift @@ -346,6 +346,19 @@ public enum HardwareModel: SwiftProtobuf.Enum { /// Minewsemi ME25LS01 (ME25LE01_V1.0). NRF52840 w/ LR1110 radio, buttons and leds and pins. case me25Ls014Y10Td // = 75 + /// + /// RP2040_FEATHER_RFM95 + /// Adafruit Feather RP2040 with RFM95 LoRa Radio RFM95 with SX1272, SSD1306 OLED + /// https://www.adafruit.com/product/5714 + /// https://www.adafruit.com/product/326 + /// https://www.adafruit.com/product/938 + /// ^^^ short A0 to switch to I2C address 0x3C + case rp2040FeatherRfm95 // = 76 + + /// M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ + case m5StackCorebasic // = 77 + case m5StackCore2 // = 78 + /// /// ------------------------------------------------------------------------------------------------------------------------------------------ /// Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. @@ -434,6 +447,9 @@ public enum HardwareModel: SwiftProtobuf.Enum { case 73: self = .wioE5 case 74: self = .radiomaster900Bandit case 75: self = .me25Ls014Y10Td + case 76: self = .rp2040FeatherRfm95 + case 77: self = .m5StackCorebasic + case 78: self = .m5StackCore2 case 255: self = .privateHw default: self = .UNRECOGNIZED(rawValue) } @@ -516,6 +532,9 @@ public enum HardwareModel: SwiftProtobuf.Enum { case .wioE5: return 73 case .radiomaster900Bandit: return 74 case .me25Ls014Y10Td: return 75 + case .rp2040FeatherRfm95: return 76 + case .m5StackCorebasic: return 77 + case .m5StackCore2: return 78 case .privateHw: return 255 case .UNRECOGNIZED(let i): return i } @@ -603,6 +622,9 @@ extension HardwareModel: CaseIterable { .wioE5, .radiomaster900Bandit, .me25Ls014Y10Td, + .rp2040FeatherRfm95, + .m5StackCorebasic, + .m5StackCore2, .privateHw, ] } @@ -1520,9 +1542,22 @@ public struct DataMessage { /// a message a heart or poop emoji. public var emoji: UInt32 = 0 + /// + /// Bitfield for extra flags. First use is to indicate that user approves the packet being uploaded to MQTT. + public var bitfield: UInt32 { + get {return _bitfield ?? 0} + set {_bitfield = newValue} + } + /// Returns true if `bitfield` has been explicitly set. + public var hasBitfield: Bool {return self._bitfield != nil} + /// Clears the value of `bitfield`. Subsequent reads from it will return its default value. + public mutating func clearBitfield() {self._bitfield = nil} + public var unknownFields = SwiftProtobuf.UnknownStorage() public init() {} + + fileprivate var _bitfield: UInt32? = nil } /// @@ -1907,6 +1942,15 @@ public struct MeshPacket { /// assume it is important and use a slightly higher priority case reliable // = 70 + /// + /// If priority is unset but the packet is a response to a request, we want it to get there relatively quickly. + /// Furthermore, responses stop relaying packets directed to a node early. + case response // = 80 + + /// + /// Higher priority for specific message types (portnums) to distinguish between other reliable packets. + case high // = 100 + /// /// Ack/naks are sent with very high priority to ensure that retransmission /// stops as soon as possible @@ -1928,6 +1972,8 @@ public struct MeshPacket { case 10: self = .background case 64: self = .default case 70: self = .reliable + case 80: self = .response + case 100: self = .high case 120: self = .ack case 127: self = .max default: self = .UNRECOGNIZED(rawValue) @@ -1941,6 +1987,8 @@ public struct MeshPacket { case .background: return 10 case .default: return 64 case .reliable: return 70 + case .response: return 80 + case .high: return 100 case .ack: return 120 case .max: return 127 case .UNRECOGNIZED(let i): return i @@ -2006,6 +2054,8 @@ extension MeshPacket.Priority: CaseIterable { .background, .default, .reliable, + .response, + .high, .ack, .max, ] @@ -3241,6 +3291,9 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding { 73: .same(proto: "WIO_E5"), 74: .same(proto: "RADIOMASTER_900_BANDIT"), 75: .same(proto: "ME25LS01_4Y10TD"), + 76: .same(proto: "RP2040_FEATHER_RFM95"), + 77: .same(proto: "M5STACK_COREBASIC"), + 78: .same(proto: "M5STACK_CORE2"), 255: .same(proto: "PRIVATE_HW"), ] } @@ -3779,6 +3832,7 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati 6: .standard(proto: "request_id"), 7: .standard(proto: "reply_id"), 8: .same(proto: "emoji"), + 9: .same(proto: "bitfield"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -3795,12 +3849,17 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati case 6: try { try decoder.decodeSingularFixed32Field(value: &self.requestID) }() case 7: try { try decoder.decodeSingularFixed32Field(value: &self.replyID) }() case 8: try { try decoder.decodeSingularFixed32Field(value: &self.emoji) }() + case 9: try { try decoder.decodeSingularUInt32Field(value: &self._bitfield) }() 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.portnum != .unknownApp { try visitor.visitSingularEnumField(value: self.portnum, fieldNumber: 1) } @@ -3825,6 +3884,9 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati if self.emoji != 0 { try visitor.visitSingularFixed32Field(value: self.emoji, fieldNumber: 8) } + try { if let v = self._bitfield { + try visitor.visitSingularUInt32Field(value: v, fieldNumber: 9) + } }() try unknownFields.traverse(visitor: &visitor) } @@ -3837,6 +3899,7 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati if lhs.requestID != rhs.requestID {return false} if lhs.replyID != rhs.replyID {return false} if lhs.emoji != rhs.emoji {return false} + if lhs._bitfield != rhs._bitfield {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } @@ -4224,6 +4287,8 @@ extension MeshPacket.Priority: SwiftProtobuf._ProtoNameProviding { 10: .same(proto: "BACKGROUND"), 64: .same(proto: "DEFAULT"), 70: .same(proto: "RELIABLE"), + 80: .same(proto: "RESPONSE"), + 100: .same(proto: "HIGH"), 120: .same(proto: "ACK"), 127: .same(proto: "MAX"), ] diff --git a/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift index e4b9ee087..dc1d6ccee 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/telemetry.pb.swift @@ -140,6 +140,10 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum { /// /// MAX17048 1S lipo battery sensor (voltage, state of charge, time to go) case max17048 // = 28 + + /// + /// Custom I2C sensor implementation based on https://github.com/meshtastic/i2c-sensor + case customSensor // = 29 case UNRECOGNIZED(Int) public init() { @@ -177,6 +181,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum { case 26: self = .bmp3Xx case 27: self = .icm20948 case 28: self = .max17048 + case 29: self = .customSensor default: self = .UNRECOGNIZED(rawValue) } } @@ -212,6 +217,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum { case .bmp3Xx: return 26 case .icm20948: return 27 case .max17048: return 28 + case .customSensor: return 29 case .UNRECOGNIZED(let i): return i } } @@ -252,6 +258,7 @@ extension TelemetrySensorType: CaseIterable { .bmp3Xx, .icm20948, .max17048, + .customSensor, ] } @@ -1003,6 +1010,7 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding { 26: .same(proto: "BMP3XX"), 27: .same(proto: "ICM20948"), 28: .same(proto: "MAX17048"), + 29: .same(proto: "CUSTOM_SENSOR"), ] } diff --git a/protobufs b/protobufs index 4da558d0f..0acaec6ef 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 4da558d0f73c46ef91b74431facee73c09affbfc +Subproject commit 0acaec6eff00e748beeae89148093221f131cd9c