Assorted updates

This commit is contained in:
Garth Vander Houwen 2023-05-01 10:39:49 -07:00
parent f4a24d95e0
commit 6f05bbe7f3
11 changed files with 354 additions and 5 deletions

View file

@ -61,6 +61,7 @@ enum GpsUpdateIntervals: Int, CaseIterable, Identifiable {
case twentySeconds = 20
case twentyFiveSeconds = 25
case thirtySeconds = 30
case fortyFiveSeconds = 45
case oneMinute = 60
case twoMinutes = 120
case fiveMinutes = 300
@ -90,6 +91,8 @@ enum GpsUpdateIntervals: Int, CaseIterable, Identifiable {
return NSLocalizedString("interval.thirty.seconds", comment: "Thirty Seconds")
case .oneMinute:
return NSLocalizedString("interval.one.minute", comment: "One Minute")
case .fortyFiveSeconds:
return NSLocalizedString("interval.fortyfive.seconds", comment: "Forty Five Seconds")
case .twoMinutes:
return NSLocalizedString("interval.two.minutes", comment: "Two Minutes")
case .fiveMinutes:
@ -123,6 +126,7 @@ enum GpsAttemptTimes: Int, CaseIterable, Identifiable {
case twentySeconds = 20
case twentyFiveSeconds = 25
case thirtySeconds = 30
case fortyFiveSeconds = 45
case oneMinute = 60
case twoMinutes = 120
case fiveMinutes = 300
@ -146,6 +150,8 @@ enum GpsAttemptTimes: Int, CaseIterable, Identifiable {
return NSLocalizedString("interval.twentyfive.seconds", comment: "Twenty Five Seconds")
case .thirtySeconds:
return NSLocalizedString("interval.thirty.seconds", comment: "Thirty Seconds")
case .fortyFiveSeconds:
return NSLocalizedString("interval.fortyfive.seconds", comment: "Forty Five Seconds")
case .oneMinute:
return NSLocalizedString("interval.one.minute", comment: "One Minute")
case .twoMinutes:

View file

@ -0,0 +1,163 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: meshtastic/clientonly.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
}
///
/// This abstraction is used to contain any configuration for provisioning a node on any client.
/// It is useful for importing and exporting configurations.
struct DeviceProfile {
// 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.
///
/// Long name for the node
var longName: String {
get {return _longName ?? String()}
set {_longName = newValue}
}
/// Returns true if `longName` has been explicitly set.
var hasLongName: Bool {return self._longName != nil}
/// Clears the value of `longName`. Subsequent reads from it will return its default value.
mutating func clearLongName() {self._longName = nil}
///
/// Short name of the node
var shortName: String {
get {return _shortName ?? String()}
set {_shortName = newValue}
}
/// Returns true if `shortName` has been explicitly set.
var hasShortName: Bool {return self._shortName != nil}
/// Clears the value of `shortName`. Subsequent reads from it will return its default value.
mutating func clearShortName() {self._shortName = nil}
///
/// The url of the channels from our node
var channelURL: String {
get {return _channelURL ?? String()}
set {_channelURL = newValue}
}
/// Returns true if `channelURL` has been explicitly set.
var hasChannelURL: Bool {return self._channelURL != nil}
/// Clears the value of `channelURL`. Subsequent reads from it will return its default value.
mutating func clearChannelURL() {self._channelURL = nil}
///
/// The Config of the node
var config: LocalConfig {
get {return _config ?? LocalConfig()}
set {_config = newValue}
}
/// Returns true if `config` has been explicitly set.
var hasConfig: Bool {return self._config != nil}
/// Clears the value of `config`. Subsequent reads from it will return its default value.
mutating func clearConfig() {self._config = nil}
///
/// The ModuleConfig of the node
var moduleConfig: LocalModuleConfig {
get {return _moduleConfig ?? LocalModuleConfig()}
set {_moduleConfig = newValue}
}
/// Returns true if `moduleConfig` has been explicitly set.
var hasModuleConfig: Bool {return self._moduleConfig != nil}
/// Clears the value of `moduleConfig`. Subsequent reads from it will return its default value.
mutating func clearModuleConfig() {self._moduleConfig = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _longName: String? = nil
fileprivate var _shortName: String? = nil
fileprivate var _channelURL: String? = nil
fileprivate var _config: LocalConfig? = nil
fileprivate var _moduleConfig: LocalModuleConfig? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
extension DeviceProfile: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
extension DeviceProfile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".DeviceProfile"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "long_name"),
2: .standard(proto: "short_name"),
3: .standard(proto: "channel_url"),
4: .same(proto: "config"),
5: .standard(proto: "module_config"),
]
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.decodeSingularStringField(value: &self._channelURL) }()
case 4: try { try decoder.decodeSingularMessageField(value: &self._config) }()
case 5: try { try decoder.decodeSingularMessageField(value: &self._moduleConfig) }()
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
try { if let v = self._longName {
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
} }()
try { if let v = self._shortName {
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
} }()
try { if let v = self._channelURL {
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
} }()
try { if let v = self._config {
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
} }()
try { if let v = self._moduleConfig {
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
} }()
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: DeviceProfile, rhs: DeviceProfile) -> Bool {
if lhs._longName != rhs._longName {return false}
if lhs._shortName != rhs._shortName {return false}
if lhs._channelURL != rhs._channelURL {return false}
if lhs._config != rhs._config {return false}
if lhs._moduleConfig != rhs._moduleConfig {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View file

@ -159,6 +159,19 @@ struct DeviceState {
set {_uniqueStorage()._didGpsReset = newValue}
}
///
/// We keep the last received waypoint stored in the device flash,
/// so we can show it on the screen.
/// Might be null
var rxWaypoint: MeshPacket {
get {return _storage._rxWaypoint ?? MeshPacket()}
set {_uniqueStorage()._rxWaypoint = newValue}
}
/// Returns true if `rxWaypoint` has been explicitly set.
var hasRxWaypoint: Bool {return _storage._rxWaypoint != nil}
/// Clears the value of `rxWaypoint`. Subsequent reads from it will return its default value.
mutating func clearRxWaypoint() {_uniqueStorage()._rxWaypoint = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
@ -280,6 +293,7 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
7: .standard(proto: "rx_text_message"),
9: .standard(proto: "no_save"),
11: .standard(proto: "did_gps_reset"),
12: .standard(proto: "rx_waypoint"),
]
fileprivate class _StorageClass {
@ -291,6 +305,7 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
var _rxTextMessage: MeshPacket? = nil
var _noSave: Bool = false
var _didGpsReset: Bool = false
var _rxWaypoint: MeshPacket? = nil
static let defaultInstance = _StorageClass()
@ -305,6 +320,7 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
_rxTextMessage = source._rxTextMessage
_noSave = source._noSave
_didGpsReset = source._didGpsReset
_rxWaypoint = source._rxWaypoint
}
}
@ -331,6 +347,7 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
case 8: try { try decoder.decodeSingularUInt32Field(value: &_storage._version) }()
case 9: try { try decoder.decodeSingularBoolField(value: &_storage._noSave) }()
case 11: try { try decoder.decodeSingularBoolField(value: &_storage._didGpsReset) }()
case 12: try { try decoder.decodeSingularMessageField(value: &_storage._rxWaypoint) }()
default: break
}
}
@ -367,6 +384,9 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
if _storage._didGpsReset != false {
try visitor.visitSingularBoolField(value: _storage._didGpsReset, fieldNumber: 11)
}
try { if let v = _storage._rxWaypoint {
try visitor.visitSingularMessageField(value: v, fieldNumber: 12)
} }()
}
try unknownFields.traverse(visitor: &visitor)
}
@ -384,6 +404,7 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
if _storage._rxTextMessage != rhs_storage._rxTextMessage {return false}
if _storage._noSave != rhs_storage._noSave {return false}
if _storage._didGpsReset != rhs_storage._didGpsReset {return false}
if _storage._rxWaypoint != rhs_storage._rxWaypoint {return false}
return true
}
if !storagesAreEqual {return false}

View file

@ -2231,6 +2231,50 @@ struct Compressed {
init() {}
}
///
/// Full info on edges for a single node
struct NeighborInfo {
// 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 node ID of the node sending info on its neighbors
var nodeID: UInt32 = 0
///
/// Field to pass neighbor info for the next sending cycle
var lastSentByID: UInt32 = 0
///
/// The list of out edges from this node
var neighbors: [Neighbor] = []
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
///
/// A single edge in the mesh
struct Neighbor {
// 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.
///
/// Node ID of neighbor
var nodeID: UInt32 = 0
///
/// SNR of last heard message
var snr: Float = 0
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
///
/// Device metadata response
struct DeviceMetadata {
@ -2307,6 +2351,8 @@ extension FromRadio.OneOf_PayloadVariant: @unchecked Sendable {}
extension ToRadio: @unchecked Sendable {}
extension ToRadio.OneOf_PayloadVariant: @unchecked Sendable {}
extension Compressed: @unchecked Sendable {}
extension NeighborInfo: @unchecked Sendable {}
extension Neighbor: @unchecked Sendable {}
extension DeviceMetadata: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
@ -3896,6 +3942,88 @@ extension Compressed: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
}
}
extension NeighborInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".NeighborInfo"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "node_id"),
2: .standard(proto: "last_sent_by_id"),
3: .same(proto: "neighbors"),
]
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.nodeID) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.lastSentByID) }()
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.neighbors) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.nodeID != 0 {
try visitor.visitSingularUInt32Field(value: self.nodeID, fieldNumber: 1)
}
if self.lastSentByID != 0 {
try visitor.visitSingularUInt32Field(value: self.lastSentByID, fieldNumber: 2)
}
if !self.neighbors.isEmpty {
try visitor.visitRepeatedMessageField(value: self.neighbors, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: NeighborInfo, rhs: NeighborInfo) -> Bool {
if lhs.nodeID != rhs.nodeID {return false}
if lhs.lastSentByID != rhs.lastSentByID {return false}
if lhs.neighbors != rhs.neighbors {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Neighbor: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".Neighbor"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "node_id"),
2: .same(proto: "snr"),
]
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.nodeID) }()
case 2: try { try decoder.decodeSingularFloatField(value: &self.snr) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.nodeID != 0 {
try visitor.visitSingularUInt32Field(value: self.nodeID, fieldNumber: 1)
}
if self.snr != 0 {
try visitor.visitSingularFloatField(value: self.snr, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: Neighbor, rhs: Neighbor) -> Bool {
if lhs.nodeID != rhs.nodeID {return false}
if lhs.snr != rhs.snr {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".DeviceMetadata"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [

View file

@ -246,6 +246,11 @@ struct ModuleConfig {
/// If true, we attempt to establish a secure connection using TLS
var tlsEnabled: Bool = false
///
/// The root topic to use for MQTT messages. Default is "msh".
/// This is useful if you want to use a single MQTT server for multiple meshtastic networks and separate them via ACLs
var root: String = String()
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
@ -1114,6 +1119,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
5: .standard(proto: "encryption_enabled"),
6: .standard(proto: "json_enabled"),
7: .standard(proto: "tls_enabled"),
8: .same(proto: "root"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1129,6 +1135,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
case 5: try { try decoder.decodeSingularBoolField(value: &self.encryptionEnabled) }()
case 6: try { try decoder.decodeSingularBoolField(value: &self.jsonEnabled) }()
case 7: try { try decoder.decodeSingularBoolField(value: &self.tlsEnabled) }()
case 8: try { try decoder.decodeSingularStringField(value: &self.root) }()
default: break
}
}
@ -1156,6 +1163,9 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
if self.tlsEnabled != false {
try visitor.visitSingularBoolField(value: self.tlsEnabled, fieldNumber: 7)
}
if !self.root.isEmpty {
try visitor.visitSingularStringField(value: self.root, fieldNumber: 8)
}
try unknownFields.traverse(visitor: &visitor)
}
@ -1167,6 +1177,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
if lhs.encryptionEnabled != rhs.encryptionEnabled {return false}
if lhs.jsonEnabled != rhs.jsonEnabled {return false}
if lhs.tlsEnabled != rhs.tlsEnabled {return false}
if lhs.root != rhs.root {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}

View file

@ -135,6 +135,10 @@ enum PortNum: SwiftProtobuf.Enum {
/// a certain destination would take on the mesh.
case tracerouteApp // = 70
///
/// Aggregates edge info for the network by sending out a list of each node's neighbors
case neighborinfoApp // = 71
///
/// Private applications should use portnums >= 256.
/// To simplify initial development and testing you can use "PRIVATE_APP"
@ -175,6 +179,7 @@ enum PortNum: SwiftProtobuf.Enum {
case 68: self = .zpsApp
case 69: self = .simulatorApp
case 70: self = .tracerouteApp
case 71: self = .neighborinfoApp
case 256: self = .privateApp
case 257: self = .atakForwarder
case 511: self = .max
@ -203,6 +208,7 @@ enum PortNum: SwiftProtobuf.Enum {
case .zpsApp: return 68
case .simulatorApp: return 69
case .tracerouteApp: return 70
case .neighborinfoApp: return 71
case .privateApp: return 256
case .atakForwarder: return 257
case .max: return 511
@ -236,6 +242,7 @@ extension PortNum: CaseIterable {
.zpsApp,
.simulatorApp,
.tracerouteApp,
.neighborinfoApp,
.privateApp,
.atakForwarder,
.max,
@ -271,6 +278,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
68: .same(proto: "ZPS_APP"),
69: .same(proto: "SIMULATOR_APP"),
70: .same(proto: "TRACEROUTE_APP"),
71: .same(proto: "NEIGHBORINFO_APP"),
256: .same(proto: "PRIVATE_APP"),
257: .same(proto: "ATAK_FORWARDER"),
511: .same(proto: "MAX"),

View file

@ -315,7 +315,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
subtitle.numberOfLines = 0
annotationView.detailCalloutAccessoryView = subtitle
let detailsIcon = UIButton(type: .detailDisclosure)
detailsIcon.setImage(UIImage(systemName: "info.square"), for: .normal)
detailsIcon.setImage(UIImage(systemName: "trash"), for: .normal)
annotationView.rightCalloutAccessoryView = detailsIcon
return annotationView
case let waypointAnnotation as WaypointEntity:
@ -365,9 +365,18 @@ struct MapViewSwiftUI: UIViewRepresentable {
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
// Only Allow Edit for waypoint annotations with a id
if view.tag > 0 {
parent.onWaypointEdit(view.tag)
switch view.annotation {
case let positionAnnotation as PositionEntity:
print(positionAnnotation)
case let waypointAnnotation as WaypointEntity:
// Only Allow Edit for waypoint annotations with a id
if view.tag > 0 {
parent.onWaypointEdit(view.tag)
}
print(waypointAnnotation)
default: break
}
}

View file

@ -309,7 +309,7 @@ struct DeviceConfig: View {
self.buttonGPIO = Int(node?.deviceConfig?.buttonGpio ?? 0)
self.buzzerGPIO = Int(node?.deviceConfig?.buzzerGpio ?? 0)
self.rebroadcastMode = Int(node?.deviceConfig?.rebroadcastMode ?? 0)
self.doubleTapAsButtonPress = node!.deviceConfig?.doubleTapAsButtonPress ?? false
self.doubleTapAsButtonPress = node?.deviceConfig?.doubleTapAsButtonPress ?? false
self.hasChanges = false
}
}

View file

@ -113,6 +113,7 @@
"interval.twenty.seconds"="Zwanzig Sekunden";
"interval.twentyfive.seconds"="Fünfundzwanzig Sekunden";
"interval.thirty.seconds"="Dreißig Sekunden";
"interval.fortyfive.seconds"="Forty Five Seconds";
"interval.one.minute"="Eine Minute";
"interval.two.minutes"="Zwei Minutes";
"interval.five.minutes"="Fünf Minutes";

View file

@ -113,6 +113,7 @@
"interval.twenty.seconds"="Twenty Seconds";
"interval.twentyfive.seconds"="Twenty Five Seconds";
"interval.thirty.seconds"="Thirty Seconds";
"interval.fortyfive.seconds"="Forty Five Seconds";
"interval.one.minute"="One Minute";
"interval.two.minutes"="Two Minutes";
"interval.five.minutes"="Five Minutes";

View file

@ -113,6 +113,7 @@
"interval.twenty.seconds"="二十秒";
"interval.twentyfive.seconds"="二十五秒";
"interval.thirty.seconds"="三十秒";
"interval.fortyfive.seconds"="Forty Five Seconds";
"interval.one.minute"="一分钟";
"interval.two.minutes"="两分钟";
"interval.five.minutes"="五分钟";