New mqtt root size

This commit is contained in:
Garth Vander Houwen 2024-03-13 20:47:18 -07:00
parent 387e594d45
commit 5d7693b40d
7 changed files with 308 additions and 4 deletions

View file

@ -94,8 +94,22 @@ struct DeviceProfile {
fileprivate var _moduleConfig: LocalModuleConfig? = nil
}
///
/// A heartbeat message is sent by a node to indicate that it is still alive.
/// This is currently only needed to keep serial connections alive.
struct Heartbeat {
// 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.
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension DeviceProfile: @unchecked Sendable {}
extension Heartbeat: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
@ -161,3 +175,22 @@ extension DeviceProfile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa
return true
}
}
extension Heartbeat: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".Heartbeat"
static let _protobuf_nameMap = SwiftProtobuf._NameMap()
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let _ = try decoder.nextFieldNumber() {
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: Heartbeat, rhs: Heartbeat) -> Bool {
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View file

@ -376,6 +376,43 @@ struct ModuleConfig {
/// If true, we can use the connected phone / client to proxy messages to MQTT instead of a direct connection
var proxyToClientEnabled: Bool = false
///
/// If true, we will periodically report unencrypted information about our node to a map via MQTT
var mapReportingEnabled: Bool = false
///
/// Settings for reporting information about our node to a map via MQTT
var mapReportSettings: ModuleConfig.MapReportSettings {
get {return _mapReportSettings ?? ModuleConfig.MapReportSettings()}
set {_mapReportSettings = newValue}
}
/// Returns true if `mapReportSettings` has been explicitly set.
var hasMapReportSettings: Bool {return self._mapReportSettings != nil}
/// Clears the value of `mapReportSettings`. Subsequent reads from it will return its default value.
mutating func clearMapReportSettings() {self._mapReportSettings = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _mapReportSettings: ModuleConfig.MapReportSettings? = nil
}
///
/// Settings for reporting unencrypted information about our node to a map via MQTT
struct MapReportSettings {
// 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.
///
/// How often we should report our info to the map (in seconds)
var publishIntervalSecs: UInt32 = 0
///
/// Bits of precision for the location sent (default of 32 is full precision).
var positionPrecision: UInt32 = 0
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
@ -1207,6 +1244,7 @@ extension RemoteHardwarePinType: @unchecked Sendable {}
extension ModuleConfig: @unchecked Sendable {}
extension ModuleConfig.OneOf_PayloadVariant: @unchecked Sendable {}
extension ModuleConfig.MQTTConfig: @unchecked Sendable {}
extension ModuleConfig.MapReportSettings: @unchecked Sendable {}
extension ModuleConfig.RemoteHardwareConfig: @unchecked Sendable {}
extension ModuleConfig.NeighborInfoConfig: @unchecked Sendable {}
extension ModuleConfig.DetectionSensorConfig: @unchecked Sendable {}
@ -1518,6 +1556,8 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
7: .standard(proto: "tls_enabled"),
8: .same(proto: "root"),
9: .standard(proto: "proxy_to_client_enabled"),
10: .standard(proto: "map_reporting_enabled"),
11: .standard(proto: "map_report_settings"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1535,12 +1575,18 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
case 7: try { try decoder.decodeSingularBoolField(value: &self.tlsEnabled) }()
case 8: try { try decoder.decodeSingularStringField(value: &self.root) }()
case 9: try { try decoder.decodeSingularBoolField(value: &self.proxyToClientEnabled) }()
case 10: try { try decoder.decodeSingularBoolField(value: &self.mapReportingEnabled) }()
case 11: try { try decoder.decodeSingularMessageField(value: &self._mapReportSettings) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(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.enabled != false {
try visitor.visitSingularBoolField(value: self.enabled, fieldNumber: 1)
}
@ -1568,6 +1614,12 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
if self.proxyToClientEnabled != false {
try visitor.visitSingularBoolField(value: self.proxyToClientEnabled, fieldNumber: 9)
}
if self.mapReportingEnabled != false {
try visitor.visitSingularBoolField(value: self.mapReportingEnabled, fieldNumber: 10)
}
try { if let v = self._mapReportSettings {
try visitor.visitSingularMessageField(value: v, fieldNumber: 11)
} }()
try unknownFields.traverse(visitor: &visitor)
}
@ -1581,6 +1633,46 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
if lhs.tlsEnabled != rhs.tlsEnabled {return false}
if lhs.root != rhs.root {return false}
if lhs.proxyToClientEnabled != rhs.proxyToClientEnabled {return false}
if lhs.mapReportingEnabled != rhs.mapReportingEnabled {return false}
if lhs._mapReportSettings != rhs._mapReportSettings {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension ModuleConfig.MapReportSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = ModuleConfig.protoMessageName + ".MapReportSettings"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "publish_interval_secs"),
2: .standard(proto: "position_precision"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(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.publishIntervalSecs) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.positionPrecision) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.publishIntervalSecs != 0 {
try visitor.visitSingularUInt32Field(value: self.publishIntervalSecs, fieldNumber: 1)
}
if self.positionPrecision != 0 {
try visitor.visitSingularUInt32Field(value: self.positionPrecision, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: ModuleConfig.MapReportSettings, rhs: ModuleConfig.MapReportSettings) -> Bool {
if lhs.publishIntervalSecs != rhs.publishIntervalSecs {return false}
if lhs.positionPrecision != rhs.positionPrecision {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}

View file

@ -55,8 +55,75 @@ struct ServiceEnvelope {
fileprivate var _packet: MeshPacket? = nil
}
///
/// Information about a node intended to be reported unencrypted to a map using MQTT.
struct MapReport {
// 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 full name for this user, i.e. "Kevin Hester"
var longName: String = String()
///
/// A VERY short name, ideally two characters.
/// Suitable for a tiny OLED screen
var shortName: String = String()
///
/// Role of the node that applies specific settings for a particular use-case
var role: Config.DeviceConfig.Role = .client
///
/// Hardware model of the node, i.e. T-Beam, Heltec V3, etc...
var hwModel: HardwareModel = .unset
///
/// Device firmware version string
var firmwareVersion: String = String()
///
/// The region code for the radio (US, CN, EU433, etc...)
var region: Config.LoRaConfig.RegionCode = .unset
///
/// Modem preset used by the radio (LongFast, MediumSlow, etc...)
var modemPreset: Config.LoRaConfig.ModemPreset = .longFast
///
/// Whether the node has a channel with default PSK and name (LongFast, MediumSlow, etc...)
/// and it uses the default frequency slot given the region and modem preset.
var hasDefaultChannel_p: Bool = false
///
/// Latitude: multiply by 1e-7 to get degrees in floating point
var latitudeI: Int32 = 0
///
/// Longitude: multiply by 1e-7 to get degrees in floating point
var longitudeI: Int32 = 0
///
/// Altitude in meters above MSL
var altitude: Int32 = 0
///
/// Indicates the bits of precision for latitude and longitude set by the sending node
var positionPrecision: UInt32 = 0
///
/// Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT)
var numOnlineLocalNodes: UInt32 = 0
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension ServiceEnvelope: @unchecked Sendable {}
extension MapReport: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
@ -110,3 +177,107 @@ extension ServiceEnvelope: SwiftProtobuf.Message, SwiftProtobuf._MessageImplemen
return true
}
}
extension MapReport: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".MapReport"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "long_name"),
2: .standard(proto: "short_name"),
3: .same(proto: "role"),
4: .standard(proto: "hw_model"),
5: .standard(proto: "firmware_version"),
6: .same(proto: "region"),
7: .standard(proto: "modem_preset"),
8: .standard(proto: "has_default_channel"),
9: .standard(proto: "latitude_i"),
10: .standard(proto: "longitude_i"),
11: .same(proto: "altitude"),
12: .standard(proto: "position_precision"),
13: .standard(proto: "num_online_local_nodes"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(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.longName) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.shortName) }()
case 3: try { try decoder.decodeSingularEnumField(value: &self.role) }()
case 4: try { try decoder.decodeSingularEnumField(value: &self.hwModel) }()
case 5: try { try decoder.decodeSingularStringField(value: &self.firmwareVersion) }()
case 6: try { try decoder.decodeSingularEnumField(value: &self.region) }()
case 7: try { try decoder.decodeSingularEnumField(value: &self.modemPreset) }()
case 8: try { try decoder.decodeSingularBoolField(value: &self.hasDefaultChannel_p) }()
case 9: try { try decoder.decodeSingularSFixed32Field(value: &self.latitudeI) }()
case 10: try { try decoder.decodeSingularSFixed32Field(value: &self.longitudeI) }()
case 11: try { try decoder.decodeSingularInt32Field(value: &self.altitude) }()
case 12: try { try decoder.decodeSingularUInt32Field(value: &self.positionPrecision) }()
case 13: try { try decoder.decodeSingularUInt32Field(value: &self.numOnlineLocalNodes) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.longName.isEmpty {
try visitor.visitSingularStringField(value: self.longName, fieldNumber: 1)
}
if !self.shortName.isEmpty {
try visitor.visitSingularStringField(value: self.shortName, fieldNumber: 2)
}
if self.role != .client {
try visitor.visitSingularEnumField(value: self.role, fieldNumber: 3)
}
if self.hwModel != .unset {
try visitor.visitSingularEnumField(value: self.hwModel, fieldNumber: 4)
}
if !self.firmwareVersion.isEmpty {
try visitor.visitSingularStringField(value: self.firmwareVersion, fieldNumber: 5)
}
if self.region != .unset {
try visitor.visitSingularEnumField(value: self.region, fieldNumber: 6)
}
if self.modemPreset != .longFast {
try visitor.visitSingularEnumField(value: self.modemPreset, fieldNumber: 7)
}
if self.hasDefaultChannel_p != false {
try visitor.visitSingularBoolField(value: self.hasDefaultChannel_p, fieldNumber: 8)
}
if self.latitudeI != 0 {
try visitor.visitSingularSFixed32Field(value: self.latitudeI, fieldNumber: 9)
}
if self.longitudeI != 0 {
try visitor.visitSingularSFixed32Field(value: self.longitudeI, fieldNumber: 10)
}
if self.altitude != 0 {
try visitor.visitSingularInt32Field(value: self.altitude, fieldNumber: 11)
}
if self.positionPrecision != 0 {
try visitor.visitSingularUInt32Field(value: self.positionPrecision, fieldNumber: 12)
}
if self.numOnlineLocalNodes != 0 {
try visitor.visitSingularUInt32Field(value: self.numOnlineLocalNodes, fieldNumber: 13)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: MapReport, rhs: MapReport) -> Bool {
if lhs.longName != rhs.longName {return false}
if lhs.shortName != rhs.shortName {return false}
if lhs.role != rhs.role {return false}
if lhs.hwModel != rhs.hwModel {return false}
if lhs.firmwareVersion != rhs.firmwareVersion {return false}
if lhs.region != rhs.region {return false}
if lhs.modemPreset != rhs.modemPreset {return false}
if lhs.hasDefaultChannel_p != rhs.hasDefaultChannel_p {return false}
if lhs.latitudeI != rhs.latitudeI {return false}
if lhs.longitudeI != rhs.longitudeI {return false}
if lhs.altitude != rhs.altitude {return false}
if lhs.positionPrecision != rhs.positionPrecision {return false}
if lhs.numOnlineLocalNodes != rhs.numOnlineLocalNodes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View file

@ -181,6 +181,10 @@ enum PortNum: SwiftProtobuf.Enum {
/// Portnum for payloads from the official Meshtastic ATAK plugin
case atakPlugin // = 72
///
/// Provides unencrypted information about a node for consumption by a map via MQTT
case mapReportApp // = 73
///
/// Private applications should use portnums >= 256.
/// To simplify initial development and testing you can use "PRIVATE_APP"
@ -226,6 +230,7 @@ enum PortNum: SwiftProtobuf.Enum {
case 70: self = .tracerouteApp
case 71: self = .neighborinfoApp
case 72: self = .atakPlugin
case 73: self = .mapReportApp
case 256: self = .privateApp
case 257: self = .atakForwarder
case 511: self = .max
@ -258,6 +263,7 @@ enum PortNum: SwiftProtobuf.Enum {
case .tracerouteApp: return 70
case .neighborinfoApp: return 71
case .atakPlugin: return 72
case .mapReportApp: return 73
case .privateApp: return 256
case .atakForwarder: return 257
case .max: return 511
@ -295,6 +301,7 @@ extension PortNum: CaseIterable {
.tracerouteApp,
.neighborinfoApp,
.atakPlugin,
.mapReportApp,
.privateApp,
.atakForwarder,
.max,
@ -334,6 +341,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
70: .same(proto: "TRACEROUTE_APP"),
71: .same(proto: "NEIGHBORINFO_APP"),
72: .same(proto: "ATAK_PLUGIN"),
73: .same(proto: "MAP_REPORT_APP"),
256: .same(proto: "PRIVATE_APP"),
257: .same(proto: "ATAK_FORWARDER"),
511: .same(proto: "MAX"),

View file

@ -43,7 +43,7 @@ struct DeviceMetricsLog: View {
.accessibilityLabel("Line Series")
.accessibilityValue("X: \(point.time!), Y: \(point.batteryLevel)")
.foregroundStyle(batteryChartColor)
.interpolationMethod(.cardinal)
.interpolationMethod(.linear)
Plot {
PointMark(

View file

@ -166,8 +166,8 @@ struct MQTTConfig: View {
.onChange(of: root, perform: { _ in
let totalBytes = root.utf8.count
// Only mess with the value if it is too big
if totalBytes > 15 {
let firstNBytes = Data(root.utf8.prefix(15))
if totalBytes > 30 {
let firstNBytes = Data(root.utf8.prefix(30))
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
// Set the shortName back to the last place where it was the right size
root = maxBytesString

@ -1 +1 @@
Subproject commit 5a97acb17543a10e114675a205e3274a83e721af
Subproject commit 7e3ee8cd96740910d0611433cb9a05a7a692568c