mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
New mqtt root size
This commit is contained in:
parent
387e594d45
commit
5d7693b40d
7 changed files with 308 additions and 4 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue