diff --git a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift index 20b719c53..f6c42f704 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/config.pb.swift @@ -220,9 +220,6 @@ public struct Config { /// The wifi radio and the oled screen will be put to sleep. /// This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. case router // = 2 - - /// - /// Description: Combination of both ROUTER and CLIENT. Not for mobile devices. case routerClient // = 3 /// diff --git a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift index c257be0ac..2b9f69c6d 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/mesh.pb.swift @@ -304,6 +304,23 @@ public enum HardwareModel: SwiftProtobuf.Enum { /// Heltec Capsule Sensor V3 with ESP32-S3 CPU, Portable LoRa device that can replace GNSS modules or sensors case heltecCapsuleSensorV3 // = 65 + /// + /// Heltec Vision Master T190 with ESP32-S3 CPU, and a 1.90 inch TFT display + case heltecVisionMasterT190 // = 66 + + /// + /// Heltec Vision Master E213 with ESP32-S3 CPU, and a 2.13 inch E-Ink display + case heltecVisionMasterE213 // = 67 + + /// + /// Heltec Vision Master E290 with ESP32-S3 CPU, and a 2.9 inch E-Ink display + case heltecVisionMasterE290 // = 68 + + /// + /// Heltec Mesh Node T114 board with nRF52840 CPU, and a 1.14 inch TFT display, Ultimate low-power design, + /// specifically adapted for the Meshtatic project + case heltecMeshNodeT114 // = 69 + /// /// ------------------------------------------------------------------------------------------------------------------------------------------ /// 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. @@ -382,6 +399,10 @@ public enum HardwareModel: SwiftProtobuf.Enum { case 63: self = .nrf52PromicroDiy case 64: self = .radiomaster900BanditNano case 65: self = .heltecCapsuleSensorV3 + case 66: self = .heltecVisionMasterT190 + case 67: self = .heltecVisionMasterE213 + case 68: self = .heltecVisionMasterE290 + case 69: self = .heltecMeshNodeT114 case 255: self = .privateHw default: self = .UNRECOGNIZED(rawValue) } @@ -454,6 +475,10 @@ public enum HardwareModel: SwiftProtobuf.Enum { case .nrf52PromicroDiy: return 63 case .radiomaster900BanditNano: return 64 case .heltecCapsuleSensorV3: return 65 + case .heltecVisionMasterT190: return 66 + case .heltecVisionMasterE213: return 67 + case .heltecVisionMasterE290: return 68 + case .heltecMeshNodeT114: return 69 case .privateHw: return 255 case .UNRECOGNIZED(let i): return i } @@ -531,6 +556,10 @@ extension HardwareModel: CaseIterable { .nrf52PromicroDiy, .radiomaster900BanditNano, .heltecCapsuleSensorV3, + .heltecVisionMasterT190, + .heltecVisionMasterE213, + .heltecVisionMasterE290, + .heltecMeshNodeT114, .privateHw, ] } @@ -2286,6 +2315,16 @@ public struct FromRadio { set {_uniqueStorage()._payloadVariant = .mqttClientProxyMessage(newValue)} } + /// + /// File system manifest messages + public var fileInfo: FileInfo { + get { + if case .fileInfo(let v)? = _storage._payloadVariant {return v} + return FileInfo() + } + set {_uniqueStorage()._payloadVariant = .fileInfo(newValue)} + } + public var unknownFields = SwiftProtobuf.UnknownStorage() /// @@ -2338,6 +2377,9 @@ public struct FromRadio { /// /// MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) case mqttClientProxyMessage(MqttClientProxyMessage) + /// + /// File system manifest messages + case fileInfo(FileInfo) #if !swift(>=4.1) public static func ==(lhs: FromRadio.OneOf_PayloadVariant, rhs: FromRadio.OneOf_PayloadVariant) -> Bool { @@ -2397,6 +2439,10 @@ public struct FromRadio { guard case .mqttClientProxyMessage(let l) = lhs, case .mqttClientProxyMessage(let r) = rhs else { preconditionFailure() } return l == r }() + case (.fileInfo, .fileInfo): return { + guard case .fileInfo(let l) = lhs, case .fileInfo(let r) = rhs else { preconditionFailure() } + return l == r + }() default: return false } } @@ -2408,6 +2454,26 @@ public struct FromRadio { fileprivate var _storage = _StorageClass.defaultInstance } +/// +/// Individual File info for the device +public struct FileInfo { + // 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 fully qualified path of the file + public var fileName: String = String() + + /// + /// The size of the file in bytes + public var sizeBytes: UInt32 = 0 + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} +} + /// /// Packets/commands to the radio will be written (reliably) to the toRadio characteristic. /// Once the write completes the phone can assume it is handled. @@ -2879,6 +2945,7 @@ extension LogRecord.Level: @unchecked Sendable {} extension QueueStatus: @unchecked Sendable {} extension FromRadio: @unchecked Sendable {} extension FromRadio.OneOf_PayloadVariant: @unchecked Sendable {} +extension FileInfo: @unchecked Sendable {} extension ToRadio: @unchecked Sendable {} extension ToRadio.OneOf_PayloadVariant: @unchecked Sendable {} extension Compressed: @unchecked Sendable {} @@ -2964,6 +3031,10 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding { 63: .same(proto: "NRF52_PROMICRO_DIY"), 64: .same(proto: "RADIOMASTER_900_BANDIT_NANO"), 65: .same(proto: "HELTEC_CAPSULE_SENSOR_V3"), + 66: .same(proto: "HELTEC_VISION_MASTER_T190"), + 67: .same(proto: "HELTEC_VISION_MASTER_E213"), + 68: .same(proto: "HELTEC_VISION_MASTER_E290"), + 69: .same(proto: "HELTEC_MESH_NODE_T114"), 255: .same(proto: "PRIVATE_HW"), ] } @@ -4229,6 +4300,7 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation 12: .same(proto: "xmodemPacket"), 13: .same(proto: "metadata"), 14: .same(proto: "mqttClientProxyMessage"), + 15: .same(proto: "fileInfo"), ] fileprivate class _StorageClass { @@ -4428,6 +4500,19 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation _storage._payloadVariant = .mqttClientProxyMessage(v) } }() + case 15: try { + var v: FileInfo? + var hadOneofValue = false + if let current = _storage._payloadVariant { + hadOneofValue = true + if case .fileInfo(let m) = current {v = m} + } + try decoder.decodeSingularMessageField(value: &v) + if let v = v { + if hadOneofValue {try decoder.handleConflictingOneOf()} + _storage._payloadVariant = .fileInfo(v) + } + }() default: break } } @@ -4496,6 +4581,10 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation guard case .mqttClientProxyMessage(let v)? = _storage._payloadVariant else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 14) }() + case .fileInfo?: try { + guard case .fileInfo(let v)? = _storage._payloadVariant else { preconditionFailure() } + try visitor.visitSingularMessageField(value: v, fieldNumber: 15) + }() case nil: break } } @@ -4518,6 +4607,44 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation } } +extension FileInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".FileInfo" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "file_name"), + 2: .standard(proto: "size_bytes"), + ] + + 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.decodeSingularStringField(value: &self.fileName) }() + case 2: try { try decoder.decodeSingularUInt32Field(value: &self.sizeBytes) }() + default: break + } + } + } + + public func traverse(visitor: inout V) throws { + if !self.fileName.isEmpty { + try visitor.visitSingularStringField(value: self.fileName, fieldNumber: 1) + } + if self.sizeBytes != 0 { + try visitor.visitSingularUInt32Field(value: self.sizeBytes, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: FileInfo, rhs: FileInfo) -> Bool { + if lhs.fileName != rhs.fileName {return false} + if lhs.sizeBytes != rhs.sizeBytes {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + extension ToRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".ToRadio" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ diff --git a/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift index 71777a1b0..c728c961b 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/portnums.pb.swift @@ -185,6 +185,10 @@ public enum PortNum: SwiftProtobuf.Enum { /// Provides unencrypted information about a node for consumption by a map via MQTT case mapReportApp // = 73 + /// + /// PowerStress based monitoring support (for automated power consumption testing) + case powerstressApp // = 74 + /// /// Private applications should use portnums >= 256. /// To simplify initial development and testing you can use "PRIVATE_APP" @@ -231,6 +235,7 @@ public enum PortNum: SwiftProtobuf.Enum { case 71: self = .neighborinfoApp case 72: self = .atakPlugin case 73: self = .mapReportApp + case 74: self = .powerstressApp case 256: self = .privateApp case 257: self = .atakForwarder case 511: self = .max @@ -264,6 +269,7 @@ public enum PortNum: SwiftProtobuf.Enum { case .neighborinfoApp: return 71 case .atakPlugin: return 72 case .mapReportApp: return 73 + case .powerstressApp: return 74 case .privateApp: return 256 case .atakForwarder: return 257 case .max: return 511 @@ -302,6 +308,7 @@ extension PortNum: CaseIterable { .neighborinfoApp, .atakPlugin, .mapReportApp, + .powerstressApp, .privateApp, .atakForwarder, .max, @@ -342,6 +349,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding { 71: .same(proto: "NEIGHBORINFO_APP"), 72: .same(proto: "ATAK_PLUGIN"), 73: .same(proto: "MAP_REPORT_APP"), + 74: .same(proto: "POWERSTRESS_APP"), 256: .same(proto: "PRIVATE_APP"), 257: .same(proto: "ATAK_FORWARDER"), 511: .same(proto: "MAX"), diff --git a/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift b/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift index 1da844845..5f51e9485 100644 --- a/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift +++ b/MeshtasticProtobufs/Sources/meshtastic/powermon.pb.swift @@ -132,9 +132,186 @@ extension PowerMon.State: CaseIterable { #endif // swift(>=4.2) +/// +/// PowerStress testing support via the C++ PowerStress module +public struct PowerStressMessage { + // 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. + + /// + /// What type of HardwareMessage is this? + public var cmd: PowerStressMessage.Opcode = .unset + + public var numSeconds: Float = 0 + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + /// + /// What operation would we like the UUT to perform. + ///note: senders should probably set want_response in their request packets, so that they can know when the state + ///machine has started processing their request + public enum Opcode: SwiftProtobuf.Enum { + public typealias RawValue = Int + + /// + /// Unset/unused + case unset // = 0 + + /// Print board version slog and send an ack that we are alive and ready to process commands + case printInfo // = 1 + + /// Try to turn off all automatic processing of packets, screen, sleeping, etc (to make it easier to measure in isolation) + case forceQuiet // = 2 + + /// Stop powerstress processing - probably by just rebooting the board + case endQuiet // = 3 + + /// Turn the screen on + case screenOn // = 16 + + /// Turn the screen off + case screenOff // = 17 + + /// Let the CPU run but we assume mostly idling for num_seconds + case cpuIdle // = 32 + + /// Force deep sleep for FIXME seconds + case cpuDeepsleep // = 33 + + /// Spin the CPU as fast as possible for num_seconds + case cpuFullon // = 34 + + /// Turn the LED on for num_seconds (and leave it on - for baseline power measurement purposes) + case ledOn // = 48 + + /// Force the LED off for num_seconds + case ledOff // = 49 + + /// Completely turn off the LORA radio for num_seconds + case loraOff // = 64 + + /// Send Lora packets for num_seconds + case loraTx // = 65 + + /// Receive Lora packets for num_seconds (node will be mostly just listening, unless an external agent is helping stress this by sending packets on the current channel) + case loraRx // = 66 + + /// Turn off the BT radio for num_seconds + case btOff // = 80 + + /// Turn on the BT radio for num_seconds + case btOn // = 81 + + /// Turn off the WIFI radio for num_seconds + case wifiOff // = 96 + + /// Turn on the WIFI radio for num_seconds + case wifiOn // = 97 + + /// Turn off the GPS radio for num_seconds + case gpsOff // = 112 + + /// Turn on the GPS radio for num_seconds + case gpsOn // = 113 + case UNRECOGNIZED(Int) + + public init() { + self = .unset + } + + public init?(rawValue: Int) { + switch rawValue { + case 0: self = .unset + case 1: self = .printInfo + case 2: self = .forceQuiet + case 3: self = .endQuiet + case 16: self = .screenOn + case 17: self = .screenOff + case 32: self = .cpuIdle + case 33: self = .cpuDeepsleep + case 34: self = .cpuFullon + case 48: self = .ledOn + case 49: self = .ledOff + case 64: self = .loraOff + case 65: self = .loraTx + case 66: self = .loraRx + case 80: self = .btOff + case 81: self = .btOn + case 96: self = .wifiOff + case 97: self = .wifiOn + case 112: self = .gpsOff + case 113: self = .gpsOn + default: self = .UNRECOGNIZED(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .unset: return 0 + case .printInfo: return 1 + case .forceQuiet: return 2 + case .endQuiet: return 3 + case .screenOn: return 16 + case .screenOff: return 17 + case .cpuIdle: return 32 + case .cpuDeepsleep: return 33 + case .cpuFullon: return 34 + case .ledOn: return 48 + case .ledOff: return 49 + case .loraOff: return 64 + case .loraTx: return 65 + case .loraRx: return 66 + case .btOff: return 80 + case .btOn: return 81 + case .wifiOff: return 96 + case .wifiOn: return 97 + case .gpsOff: return 112 + case .gpsOn: return 113 + case .UNRECOGNIZED(let i): return i + } + } + + } + + public init() {} +} + +#if swift(>=4.2) + +extension PowerStressMessage.Opcode: CaseIterable { + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [PowerStressMessage.Opcode] = [ + .unset, + .printInfo, + .forceQuiet, + .endQuiet, + .screenOn, + .screenOff, + .cpuIdle, + .cpuDeepsleep, + .cpuFullon, + .ledOn, + .ledOff, + .loraOff, + .loraTx, + .loraRx, + .btOff, + .btOn, + .wifiOff, + .wifiOn, + .gpsOff, + .gpsOn, + ] +} + +#endif // swift(>=4.2) + #if swift(>=5.5) && canImport(_Concurrency) extension PowerMon: @unchecked Sendable {} extension PowerMon.State: @unchecked Sendable {} +extension PowerStressMessage: @unchecked Sendable {} +extension PowerStressMessage.Opcode: @unchecked Sendable {} #endif // swift(>=5.5) && canImport(_Concurrency) // MARK: - Code below here is support for the SwiftProtobuf runtime. @@ -177,3 +354,66 @@ extension PowerMon.State: SwiftProtobuf._ProtoNameProviding { 2048: .same(proto: "GPS_Active"), ] } + +extension PowerStressMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".PowerStressMessage" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "cmd"), + 2: .standard(proto: "num_seconds"), + ] + + 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.decodeSingularEnumField(value: &self.cmd) }() + case 2: try { try decoder.decodeSingularFloatField(value: &self.numSeconds) }() + default: break + } + } + } + + public func traverse(visitor: inout V) throws { + if self.cmd != .unset { + try visitor.visitSingularEnumField(value: self.cmd, fieldNumber: 1) + } + if self.numSeconds != 0 { + try visitor.visitSingularFloatField(value: self.numSeconds, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: PowerStressMessage, rhs: PowerStressMessage) -> Bool { + if lhs.cmd != rhs.cmd {return false} + if lhs.numSeconds != rhs.numSeconds {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension PowerStressMessage.Opcode: SwiftProtobuf._ProtoNameProviding { + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "UNSET"), + 1: .same(proto: "PRINT_INFO"), + 2: .same(proto: "FORCE_QUIET"), + 3: .same(proto: "END_QUIET"), + 16: .same(proto: "SCREEN_ON"), + 17: .same(proto: "SCREEN_OFF"), + 32: .same(proto: "CPU_IDLE"), + 33: .same(proto: "CPU_DEEPSLEEP"), + 34: .same(proto: "CPU_FULLON"), + 48: .same(proto: "LED_ON"), + 49: .same(proto: "LED_OFF"), + 64: .same(proto: "LORA_OFF"), + 65: .same(proto: "LORA_TX"), + 66: .same(proto: "LORA_RX"), + 80: .same(proto: "BT_OFF"), + 81: .same(proto: "BT_ON"), + 96: .same(proto: "WIFI_OFF"), + 97: .same(proto: "WIFI_ON"), + 112: .same(proto: "GPS_OFF"), + 113: .same(proto: "GPS_ON"), + ] +} diff --git a/protobufs b/protobufs index 4da558d0f..1198b7dba 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 4da558d0f73c46ef91b74431facee73c09affbfc +Subproject commit 1198b7dbabf9768cb0143d2897707b4c7a51a5da