SwiftLint Whitespace fixes

This commit is contained in:
Garth Vander Houwen 2023-03-06 10:33:18 -08:00
parent c3cbe9fb57
commit fdade220de
104 changed files with 1644 additions and 1832 deletions

View file

@ -867,7 +867,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */

View file

@ -36,10 +36,10 @@ enum KeyboardType: Int, CaseIterable, Identifiable {
}
enum CenteringMode: Int, CaseIterable, Identifiable {
case allAnnotations = 0
case allPositions = 1
var id: Int { self.rawValue }
var description: String {
get {
@ -55,13 +55,12 @@ enum CenteringMode: Int, CaseIterable, Identifiable {
enum MeshMapType: String, CaseIterable, Identifiable {
case standard = "standard"
case standard = "standard"
case mutedStandard = "mutedStandard"
case hybrid = "hybrid"
case hybridFlyover = "hybridFlyover"
case satellite = "satellite"
case satelliteFlyover = "satelliteFlyover"
var id: String { self.rawValue }
@ -84,7 +83,7 @@ enum MeshMapType: String, CaseIterable, Identifiable {
}
}
func MKMapTypeValue() -> MKMapType {
switch self {
case .standard:
return MKMapType.standard
@ -123,7 +122,7 @@ enum UserTrackingModes: Int, CaseIterable, Identifiable {
}
}
func MKUserTrackingModeValue() -> MKUserTrackingMode {
switch self {
case .none:
return MKUserTrackingMode.none

View file

@ -26,9 +26,7 @@ enum BluetoothModes: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.BluetoothConfig.PairingMode {
switch self {
case .randomPin:
return Config.BluetoothConfig.PairingMode.randomPin
case .fixedPin:

View file

@ -7,17 +7,17 @@
import Foundation
// Default of 0 is unset
enum ConfigPresets : Int, CaseIterable, Identifiable {
enum ConfigPresets: Int, CaseIterable, Identifiable {
case unset = 0
case rakRotaryEncoder = 1
case cardKB = 2
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .unset:
return NSLocalizedString("canned.messages.preset.manual", comment: "Manual Configuration")
case .rakRotaryEncoder:
@ -45,7 +45,7 @@ enum InputEventChars: Int, CaseIterable, Identifiable {
var description: String {
get {
switch self {
case .none:
return NSLocalizedString("inputevent.none", comment: "None")
case .up:
@ -66,7 +66,7 @@ enum InputEventChars: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> ModuleConfig.CannedMessageConfig.InputEventChar {
switch self {
case .none:

View file

@ -17,7 +17,7 @@ enum ChannelRoles: Int, CaseIterable, Identifiable {
var description: String {
get {
switch self {
case .disabled:
return NSLocalizedString("channel.role.disabled", comment: "Disabled")
case .primary:
@ -28,9 +28,9 @@ enum ChannelRoles: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Channel.Role {
switch self {
case .disabled:
return Channel.Role.disabled
case .primary:

View file

@ -22,7 +22,7 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
var name: String {
get {
switch self {
case .client:
return "Client"
case .clientMute:
@ -43,7 +43,7 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
var description: String {
get {
switch self {
case .client:
return NSLocalizedString("device.role.client", comment: "Client (default) - App connected client.")
case .clientMute:
@ -62,9 +62,9 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.DeviceConfig.Role {
switch self {
case .client:
return Config.DeviceConfig.Role.client
case .clientMute:
@ -90,11 +90,11 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable {
case localOnly = 2
var id: Int { self.rawValue }
var name: String {
get {
switch self {
case .all:
return "All"
case .allSkipDecoding:
@ -117,7 +117,7 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.DeviceConfig.RebroadcastMode {
switch self {
case .all:
return Config.DeviceConfig.RebroadcastMode.all

View file

@ -8,10 +8,10 @@
import Foundation
enum ScreenUnits: Int, CaseIterable, Identifiable {
case metric = 0
case imperial = 1
var id: Int { self.rawValue }
var description: String {
get {
@ -24,7 +24,7 @@ enum ScreenUnits: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.DisplayConfig.DisplayUnits {
switch self {
case .metric:
return Config.DisplayConfig.DisplayUnits.metric
@ -128,7 +128,7 @@ enum OledTypes: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.DisplayConfig.OledType {
switch self {
case .auto:
return Config.DisplayConfig.OledType.oledAuto
@ -166,7 +166,7 @@ enum DisplayModes: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.DisplayConfig.DisplayMode {
switch self {
case .defaultMode:
return Config.DisplayConfig.DisplayMode.default

View file

@ -16,7 +16,7 @@ enum EthernetMode: Int, CaseIterable, Identifiable {
var description: String {
get {
switch self {
case .dhcp:
return "DHCP"
case .staticip:
@ -25,9 +25,9 @@ enum EthernetMode: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.NetworkConfig.AddressMode {
switch self {
case .dhcp:
return Config.NetworkConfig.AddressMode.dhcp
case .staticip:

View file

@ -8,7 +8,7 @@
import Foundation
enum OutputIntervals: Int, CaseIterable, Identifiable {
case unset = 0
case oneSecond = 1000
case twoSeconds = 2000
@ -19,12 +19,12 @@ enum OutputIntervals: Int, CaseIterable, Identifiable {
case fifteenSeconds = 15000
case thirtySeconds = 30000
case oneMinute = 60000
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .unset:
return NSLocalizedString("unset", comment: "Unset")
case .oneSecond:
@ -63,7 +63,6 @@ enum SenderIntervals: Int, CaseIterable, Identifiable {
case thirtyMinutes = 1800
case oneHour = 3600
var id: Int { self.rawValue }
var description: String {
get {
@ -118,7 +117,7 @@ enum UpdateIntervals: Int, CaseIterable, Identifiable {
var description: String {
get {
switch self {
case .tenSeconds:
return NSLocalizedString("interval.ten.seconds", comment: "Ten Seconds")
case .fifteenSeconds:

View file

@ -7,7 +7,7 @@
import Foundation
enum RegionCodes : Int, CaseIterable, Identifiable {
enum RegionCodes: Int, CaseIterable, Identifiable {
case unset = 0
case us = 1
@ -65,11 +65,11 @@ enum RegionCodes : Int, CaseIterable, Identifiable {
}
}
}
func protoEnumValue() -> Config.LoRaConfig.RegionCode {
switch self {
case .unset:
return Config.LoRaConfig.RegionCode.unset
case .us:
@ -106,96 +106,58 @@ enum RegionCodes : Int, CaseIterable, Identifiable {
}
}
enum ModemPresets : Int, CaseIterable, Identifiable {
case LongFast = 0
case LongSlow = 1
case LongModerate = 7
case VLongSlow = 2
case MedSlow = 3
case MedFast = 4
case ShortSlow = 5
case ShortFast = 6
enum ModemPresets: Int, CaseIterable, Identifiable {
case longFast = 0
case longSlow = 1
case longModerate = 7
case vLongSlow = 2
case medSlow = 3
case medFast = 4
case shortSlow = 5
case shortFast = 6
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .LongFast:
case .longFast:
return "Long Range - Fast"
case .LongSlow:
case .longSlow:
return "Long Range - Slow"
case .LongModerate:
case .longModerate:
return "Long Range - Moderate"
case .VLongSlow:
case .vLongSlow:
return "Very Long Range - Slow"
case .MedSlow:
case .medSlow:
return "Medium Range - Slow"
case .MedFast:
case .medFast:
return "Medium Range - Fast"
case .ShortSlow:
case .shortSlow:
return "Short Range - Slow"
case .ShortFast:
case .shortFast:
return "Short Range - Fast"
}
}
}
func protoEnumValue() -> Config.LoRaConfig.ModemPreset {
switch self {
case .LongFast:
return Config.LoRaConfig.ModemPreset.longFast
case .LongSlow:
return Config.LoRaConfig.ModemPreset.longSlow
case .LongModerate:
return Config.LoRaConfig.ModemPreset.longModerate
case .VLongSlow:
return Config.LoRaConfig.ModemPreset.veryLongSlow
case .MedSlow:
return Config.LoRaConfig.ModemPreset.mediumSlow
case .MedFast:
return Config.LoRaConfig.ModemPreset.mediumFast
case .ShortSlow:
return Config.LoRaConfig.ModemPreset.shortSlow
case .ShortFast:
return Config.LoRaConfig.ModemPreset.shortFast
}
}
}
enum HopValues : Int, CaseIterable, Identifiable {
case oneHop = 1
case twoHops = 2
case threeHops = 3
case fourHops = 4
case fiveHops = 5
case sixHops = 6
case sevenHops = 7
var id: Int { self.rawValue }
var description: String {
get {
switch self {
case .oneHop:
return "One Hop"
case .twoHops:
return "Two Hops"
case .threeHops:
return "Three Hops"
case .fourHops:
return "Four Hops"
case .fiveHops:
return "Five Hops"
case .sixHops:
return "Six Hops"
case .sevenHops:
return "Seven Hops"
}
case .longFast:
return Config.LoRaConfig.ModemPreset.longFast
case .longSlow:
return Config.LoRaConfig.ModemPreset.longSlow
case .longModerate:
return Config.LoRaConfig.ModemPreset.longModerate
case .vLongSlow:
return Config.LoRaConfig.ModemPreset.veryLongSlow
case .medSlow:
return Config.LoRaConfig.ModemPreset.mediumSlow
case .medFast:
return Config.LoRaConfig.ModemPreset.mediumFast
case .shortSlow:
return Config.LoRaConfig.ModemPreset.shortSlow
case .shortFast:
return Config.LoRaConfig.ModemPreset.shortFast
}
}
}

View file

@ -36,9 +36,9 @@ enum GpsFormats: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Config.DisplayConfig.GpsCoordinateFormat {
switch self {
case .gpsFormatDec:
return Config.DisplayConfig.GpsCoordinateFormat.dec
case .gpsFormatDms:
@ -55,7 +55,6 @@ enum GpsFormats: Int, CaseIterable, Identifiable {
}
}
enum GpsUpdateIntervals: Int, CaseIterable, Identifiable {
case fiveSeconds = 5
@ -80,7 +79,7 @@ enum GpsUpdateIntervals: Int, CaseIterable, Identifiable {
var description: String {
get {
switch self {
case .fiveSeconds:
return NSLocalizedString("interval.five.seconds", comment: "Five Seconds")
case .tenSeconds:

View file

@ -25,7 +25,7 @@ enum RoutingError: Int, CaseIterable, Identifiable {
var display: String {
get {
switch self {
case .none:
return NSLocalizedString("routing.acknowledged", comment: "Acknowledged")
case .noRoute:
@ -54,9 +54,9 @@ enum RoutingError: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> Routing.Error {
switch self {
case .none:
return Routing.Error.none
case .noRoute:
@ -81,7 +81,7 @@ enum RoutingError: Int, CaseIterable, Identifiable {
return Routing.Error.badRequest
case .notAuthorized:
return Routing.Error.notAuthorized
}
}
}

View file

@ -65,11 +65,11 @@ enum SerialBaudRates: Int, CaseIterable, Identifiable {
}
}
}
func protoEnumValue() -> ModuleConfig.SerialConfig.Serial_Baud {
switch self {
case .baudDefault:
return ModuleConfig.SerialConfig.Serial_Baud.baudDefault
case .baud110:
@ -113,7 +113,7 @@ enum SerialModeTypes: Int, CaseIterable, Identifiable {
case proto = 2
case txtmsg = 3
case nmea = 4
var id: Int { self.rawValue }
var description: String {
get {
@ -132,9 +132,9 @@ enum SerialModeTypes: Int, CaseIterable, Identifiable {
}
}
func protoEnumValue() -> ModuleConfig.SerialConfig.Serial_Mode {
switch self {
case .default:
return ModuleConfig.SerialConfig.Serial_Mode.default
case .simple:

View file

@ -19,7 +19,7 @@ enum WeatherConditions: Int, CaseIterable, Identifiable {
var symbolName: String {
get {
switch self {
case .clear:
return "sparkle"
case .cloudy:

View file

@ -13,24 +13,24 @@ struct CsvDocument: FileDocument {
static var readableContentTypes = [UTType.commaSeparatedText]
@State var csvData: String
init(emptyCsv: String = "" ) {
csvData = emptyCsv
}
init(configuration: ReadConfiguration) throws {
if let data = configuration.file.regularFileContents {
csvData = String(decoding: data, as: UTF8.self)
} else {
throw CocoaError(.fileReadCorruptFile)
}
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let data = Data(csvData.utf8)
return FileWrapper(regularFileWithContents: data)

View file

@ -7,14 +7,14 @@
import SwiftUI
func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> String {
func telemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> String {
var csvString: String = ""
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")
if metricsType == 0 {
// Create Device Metrics Header
csvString = "\(NSLocalizedString("battery.level", comment: "")), \(NSLocalizedString("voltage", comment: "")), \(NSLocalizedString("channel.utilization", comment: "")), \(NSLocalizedString("airtime", comment: "")), \(NSLocalizedString("timestamp", comment: ""))"
for dm in telemetry{
for dm in telemetry {
if dm.metricsType == 0 {
csvString += "\n"
csvString += String(dm.batteryLevel)
@ -31,7 +31,7 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin
} else if metricsType == 1 {
// Create Environment Telemetry Header
csvString = "Temperature, Relative Humidity, Barometric Pressure, Gas Resistance, \(NSLocalizedString("voltage", comment: "")), \(NSLocalizedString("current", comment: "")), \(NSLocalizedString("timestamp", comment: ""))"
for dm in telemetry{
for dm in telemetry {
if dm.metricsType == 1 {
csvString += "\n"
csvString += String(dm.temperature.localeTemperature())
@ -53,7 +53,7 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin
return csvString
}
func PositionToCsvFile(positions: [PositionEntity]) -> String {
func positionToCsvFile(positions: [PositionEntity]) -> String {
var csvString: String = ""
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")

File diff suppressed because it is too large Load diff

View file

@ -7,19 +7,19 @@
import SwiftUI
class SwiftUIEmojiTextField: UITextField {
override func awakeFromNib() {
super.awakeFromNib()
}
func setEmoji() {
_ = self.textInputMode
}
override var textInputContextIdentifier: String? {
return ""
}
override var textInputMode: UITextInputMode? {
for mode in UITextInputMode.activeInputModes {
if mode.primaryLanguage == "emoji" {
@ -34,7 +34,7 @@ class SwiftUIEmojiTextField: UITextField {
struct EmojiOnlyTextField: UIViewRepresentable {
@Binding var text: String
var placeholder: String = ""
func makeUIView(context: Context) -> SwiftUIEmojiTextField {
let emojiTextField = SwiftUIEmojiTextField()
emojiTextField.placeholder = placeholder
@ -42,15 +42,15 @@ struct EmojiOnlyTextField: UIViewRepresentable {
emojiTextField.delegate = context.coordinator
return emojiTextField
}
func updateUIView(_ uiView: SwiftUIEmojiTextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: EmojiOnlyTextField
init(parent: EmojiOnlyTextField) {
@ -63,12 +63,3 @@ struct EmojiOnlyTextField: UIViewRepresentable {
}
}
}
//struct EmojiContentView: View {
//
// @State private var text: String = ""
//
// var body: some View {
// EmojiTextField(text: $text, placeholder: "Enter emoji")
// }
//}

View file

@ -27,7 +27,7 @@ extension Data {
}
var hexDescription: String {
return reduce("") {$0 + String(format: "%02x", $1)}
}
}
}
extension Date {
@ -53,7 +53,7 @@ extension Float {
let locale = NSLocale.current as NSLocale
let localeUnit = locale.object(forKey: NSLocale.Key(rawValue: "kCFLocaleTemperatureUnitKey"))
var format: UnitTemperature = .celsius
if localeUnit! as! String == "Fahrenheit" {
format = .fahrenheit
}
@ -90,7 +90,7 @@ extension UIImage {
}
extension String {
func base64urlToBase64() -> String {
var base64 = self
.replacingOccurrences(of: "-", with: "+")
@ -100,7 +100,7 @@ extension String {
}
return base64
}
func base64ToBase64url() -> String {
let base64url = self
.replacingOccurrences(of: "+", with: "-")
@ -108,13 +108,12 @@ extension String {
.replacingOccurrences(of: "=", with: "")
return base64url
}
func onlyEmojis() -> Bool {
return count > 0 && !contains { !$0.isEmoji }
}
func image(fontSize:CGFloat = 40, bgColor:UIColor = UIColor.clear, imageSize:CGSize? = nil) -> UIImage?
{
func image(fontSize: CGFloat = 40, bgColor: UIColor = UIColor.clear, imageSize: CGSize? = nil) -> UIImage? {
let font = UIFont.systemFont(ofSize: fontSize)
let attributes = [NSAttributedString.Key.font: font]
let imageSize = imageSize ?? self.size(withAttributes: attributes)
@ -127,7 +126,7 @@ extension String {
UIGraphicsEndImageContext()
return image
}
func camelCaseToWords() -> String {
return unicodeScalars.dropFirst().reduce(String(prefix(1))) {
return CharacterSet.uppercaseLetters.contains($1)

View file

@ -25,7 +25,7 @@ class LocationHelper: NSObject, ObservableObject {
}
return altitude
}
static var currentSpeed: CLLocationSpeed {
guard let speed = shared.locationManager.location?.speed else {
@ -33,7 +33,7 @@ class LocationHelper: NSObject, ObservableObject {
}
return speed
}
static var currentHeading: CLLocationDirection {
guard let heading = shared.locationManager.location?.course else {
@ -41,7 +41,7 @@ class LocationHelper: NSObject, ObservableObject {
}
return heading
}
static var currentTimestamp: Date {
guard let timestamp = shared.locationManager.location?.timestamp else {
@ -49,21 +49,21 @@ class LocationHelper: NSObject, ObservableObject {
}
return timestamp
}
static var satsInView: Int {
// If we have a position we have a sat
var sats = 1
if shared.locationManager.location?.verticalAccuracy ?? 0 > 0 {
sats = 4
if 0...5 ~= shared.locationManager.location?.horizontalAccuracy ?? 0{
if 0...5 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
sats = 12
} else if 6...15 ~= shared.locationManager.location?.horizontalAccuracy ?? 0{
} else if 6...15 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
sats = 10
} else if 16...30 ~= shared.locationManager.location?.horizontalAccuracy ?? 0{
} else if 16...30 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
sats = 9
} else if 31...45 ~= shared.locationManager.location?.horizontalAccuracy ?? 0{
} else if 31...45 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
sats = 7
} else if 46...60 ~= shared.locationManager.location?.horizontalAccuracy ?? 0{
} else if 46...60 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
sats = 5
}
} else if shared.locationManager.location?.verticalAccuracy ?? 0 < 0 && 60...300 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {

View file

@ -14,7 +14,7 @@ class MeshLogger {
}
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmmssSSa", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mm:ss.SS a")
let formatter = DateFormatter()
formatter.dateFormat = dateFormatString
let timestamp = formatter.string(from: Date())

View file

@ -13,13 +13,13 @@ import ActivityKit
#endif
func generateMessageMarkdown (message: String) -> String {
let types: NSTextCheckingResult.CheckingType = [.address, .link, .phoneNumber]
let detector = try! NSDataDetector(types: types.rawValue)
let matches = detector.matches(in: message, options: [], range: NSRange(location: 0, length: message.utf16.count))
var messageWithMarkdown = message
if matches.count > 0 {
for match in matches {
guard let range = Range(match.range, in: message) else { continue }
if match.resultType == .address {
@ -39,8 +39,8 @@ func generateMessageMarkdown (message: String) -> String {
return messageWithMarkdown
}
func localConfig (config: Config, context:NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) {
func localConfig (config: Config, context: NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) {
// We don't care about any of the Power settings, config is available for everything else
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: nodeNum, context: context)
@ -57,8 +57,8 @@ func localConfig (config: Config, context:NSManagedObjectContext, nodeNum: Int64
}
}
func moduleConfig (config: ModuleConfig, context:NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) {
func moduleConfig (config: ModuleConfig, context: NSManagedObjectContext, nodeNum: Int64, nodeLongName: String) {
if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.cannedMessage(config.cannedMessage) {
upsertCannedMessagesModuleConfigPacket(config: config.cannedMessage, nodeNum: nodeNum, context: context)
} else if config.payloadVariant == ModuleConfig.OneOf_PayloadVariant.externalNotification(config.externalNotification) {
@ -75,18 +75,18 @@ func moduleConfig (config: ModuleConfig, context:NSManagedObjectContext, nodeNum
}
func myInfoPacket (myInfo: MyNodeInfo, peripheralId: String, context: NSManagedObjectContext) -> MyInfoEntity? {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.myinfo %@", comment: "MyInfo received: %@"), String(myInfo.myNodeNum))
MeshLogger.log(" \(logString)")
let fetchMyInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(myInfo.myNodeNum))
do {
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) as! [MyInfoEntity]
// Not Found Insert
if fetchedMyInfo.isEmpty {
let myInfoEntity = MyInfoEntity(context: context)
myInfoEntity.peripheralId = peripheralId
myInfoEntity.myNodeNum = Int64(myInfo.myNodeNum)
@ -111,19 +111,19 @@ func myInfoPacket (myInfo: MyNodeInfo, peripheralId: String, context: NSManagedO
print("💥 Error Inserting New Core Data MyInfoEntity: \(nsError)")
}
} else {
fetchedMyInfo[0].peripheralId = peripheralId
fetchedMyInfo[0].myNodeNum = Int64(myInfo.myNodeNum)
fetchedMyInfo[0].hasGps = myInfo.hasGps_p
fetchedMyInfo[0].bitrate = myInfo.bitrate
let lastDotIndex = myInfo.firmwareVersion.lastIndex(of: ".")//.lastIndex(of: ".", offsetBy: -1)
var version = myInfo.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset:6, in: myInfo.firmwareVersion))]
let lastDotIndex = myInfo.firmwareVersion.lastIndex(of: ".")// .lastIndex(of: ".", offsetBy: -1)
var version = myInfo.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset: 6, in: myInfo.firmwareVersion))]
version = version.dropLast()
fetchedMyInfo[0].firmwareVersion = String(version)
fetchedMyInfo[0].messageTimeoutMsec = Int32(bitPattern: myInfo.messageTimeoutMsec)
fetchedMyInfo[0].minAppVersion = Int32(bitPattern: myInfo.minAppVersion)
fetchedMyInfo[0].maxChannels = Int32(bitPattern: myInfo.maxChannels)
do {
try context.save()
print("💾 Updated myInfo for node number: \(String(myInfo.myNodeNum))")
@ -141,17 +141,17 @@ func myInfoPacket (myInfo: MyNodeInfo, peripheralId: String, context: NSManagedO
}
func channelPacket (channel: Channel, fromNum: Int64, context: NSManagedObjectContext) {
if channel.isInitialized && channel.hasSettings && channel.role != Channel.Role.disabled {
if channel.isInitialized && channel.hasSettings && channel.role != Channel.Role.disabled {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.channel.received %d %@", comment: "Channel %d received from: %@"), channel.index, String(fromNum))
MeshLogger.log("🎛️ \(logString)")
let fetchedMyInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
fetchedMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", fromNum)
do {
let fetchedMyInfo = try context.fetch(fetchedMyInfoRequest) as! [MyInfoEntity]
if fetchedMyInfo.count == 1 {
let newChannel = ChannelEntity(context: context)
@ -190,16 +190,16 @@ func channelPacket (channel: Channel, fromNum: Int64, context: NSManagedObjectCo
}
func deviceMetadataPacket (metadata: DeviceMetadata, fromNum: Int64, context: NSManagedObjectContext) {
if metadata.isInitialized {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.device.metadata.received %@", comment: "Device Metadata admin message received from: %@"), String(fromNum))
MeshLogger.log("🏷️ \(logString)")
let fetchedNodeRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchedNodeRequest.predicate = NSPredicate(format: "num == %lld", fromNum)
do {
let fetchedNode = try context.fetch(fetchedNodeRequest) as! [NodeInfoEntity]
if fetchedNode.count > 0 {
let newMetadata = DeviceMetadataEntity(context: context)
@ -229,26 +229,26 @@ func deviceMetadataPacket (metadata: DeviceMetadata, fromNum: Int64, context: NS
}
func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObjectContext) -> NodeInfoEntity? {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.nodeinfo.received %@", comment: "Node info received for: %@"), String(nodeInfo.num))
MeshLogger.log("📟 \(logString)")
guard (nodeInfo.num > 0) else { return nil }
guard nodeInfo.num > 0 else { return nil }
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeInfo.num))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Not Found Insert
if fetchedNode.isEmpty && nodeInfo.hasUser {
let newNode = NodeInfoEntity(context: context)
newNode.id = Int64(nodeInfo.num)
newNode.num = Int64(nodeInfo.num)
newNode.channel = Int32(channel)
if nodeInfo.hasDeviceMetrics {
let telemetry = TelemetryEntity(context: context)
telemetry.batteryLevel = Int32(nodeInfo.deviceMetrics.batteryLevel)
@ -259,7 +259,7 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
newTelemetries.append(telemetry)
newNode.telemetries? = NSOrderedSet(array: newTelemetries)
}
newNode.lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(nodeInfo.lastHeard)))
newNode.snr = nodeInfo.snr
if nodeInfo.hasUser {
@ -272,9 +272,8 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
newUser.hwModel = String(describing: nodeInfo.user.hwModel).uppercased()
newNode.user = newUser
}
if nodeInfo.position.longitudeI > 0 || nodeInfo.position.latitudeI > 0 && (nodeInfo.position.latitudeI != 373346000 && nodeInfo.position.longitudeI != -1220090000)
{
if nodeInfo.position.longitudeI > 0 || nodeInfo.position.latitudeI > 0 && (nodeInfo.position.latitudeI != 373346000 && nodeInfo.position.longitudeI != -1220090000) {
let position = PositionEntity(context: context)
position.seqNo = Int32(nodeInfo.position.seqNumber)
position.latitudeI = nodeInfo.position.latitudeI
@ -288,13 +287,13 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
newPostions.append(position)
newNode.positions? = NSOrderedSet(array: newPostions)
}
// Look for a MyInfo
let fetchMyInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(nodeInfo.num))
do {
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) as! [MyInfoEntity]
if fetchedMyInfo.count > 0 {
newNode.myInfo = fetchedMyInfo[0]
@ -311,15 +310,15 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
print("💥 Fetch MyInfo Error")
}
} else if nodeInfo.hasUser && nodeInfo.num > 0 {
fetchedNode[0].id = Int64(nodeInfo.num)
fetchedNode[0].num = Int64(nodeInfo.num)
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(nodeInfo.lastHeard)))
fetchedNode[0].snr = nodeInfo.snr
fetchedNode[0].channel = Int32(channel)
if nodeInfo.hasUser {
fetchedNode[0].user!.userId = nodeInfo.user.id
fetchedNode[0].user!.num = Int64(nodeInfo.num)
fetchedNode[0].user!.longName = nodeInfo.user.longName
@ -327,9 +326,9 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
fetchedNode[0].user!.macaddr = nodeInfo.user.macaddr
fetchedNode[0].user!.hwModel = String(describing: nodeInfo.user.hwModel).uppercased()
}
if nodeInfo.hasDeviceMetrics {
let newTelemetry = TelemetryEntity(context: context)
newTelemetry.batteryLevel = Int32(nodeInfo.deviceMetrics.batteryLevel)
newTelemetry.voltage = nodeInfo.deviceMetrics.voltage
@ -338,12 +337,11 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
let mutableTelemetries = fetchedNode[0].telemetries!.mutableCopy() as! NSMutableOrderedSet
fetchedNode[0].telemetries = mutableTelemetries.copy() as? NSOrderedSet
}
if nodeInfo.hasPosition {
if nodeInfo.position.longitudeI > 0 || nodeInfo.position.latitudeI > 0 && (nodeInfo.position.latitudeI != 373346000 && nodeInfo.position.longitudeI != -1220090000) {
let position = PositionEntity(context: context)
position.latitudeI = nodeInfo.position.latitudeI
position.longitudeI = nodeInfo.position.longitudeI
@ -353,13 +351,13 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableOrderedSet
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
}
}
// Look for a MyInfo
let fetchMyInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(nodeInfo.num))
do {
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) as! [MyInfoEntity]
if fetchedMyInfo.count > 0 {
@ -385,26 +383,26 @@ func nodeInfoPacket (nodeInfo: NodeInfo, channel: UInt32, context: NSManagedObje
}
func nodeInfoAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.nodeinfo.received %@", comment: "Node info received for: %@"), String(packet.from))
MeshLogger.log("📟 \(logString)")
guard (packet.from > 0) else { return }
guard packet.from > 0 else { return }
let fetchNodeInfoAppRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoAppRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
do {
let fetchedNode = try context.fetch(fetchNodeInfoAppRequest) as? [NodeInfoEntity] ?? []
if fetchedNode.count == 1 {
fetchedNode[0].id = Int64(packet.from)
fetchedNode[0].num = Int64(packet.from)
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
fetchedNode[0].snr = packet.rxSnr
fetchedNode[0].channel = Int32(packet.channel)
if let nodeInfoMessage = try? NodeInfo(serializedData: packet.decoded.payload) {
if nodeInfoMessage.hasDeviceMetrics {
let telemetry = TelemetryEntity(context: context)
@ -442,21 +440,21 @@ func nodeInfoAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
}
func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
if let adminMessage = try? AdminMessage(serializedData: packet.decoded.payload) {
if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getCannedMessageModuleMessagesResponse(adminMessage.getCannedMessageModuleMessagesResponse) {
if let cmmc = try? CannedMessageModuleConfig(serializedData: packet.decoded.payload) {
if !cmmc.messages.isEmpty {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.cannedmessages.messages.received %@", comment: "Canned Messages Messages Received For: %@"), String(packet.from))
MeshLogger.log("🥫 \(logString)")
let fetchNodeRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
do {
let fetchedNode = try context.fetch(fetchNodeRequest) as! [NodeInfoEntity]
if fetchedNode.count == 1 {
@ -481,65 +479,65 @@ func adminAppPacket (packet: MeshPacket, context: NSManagedObjectContext) {
}
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getChannelResponse(adminMessage.getChannelResponse) {
channelPacket(channel: adminMessage.getChannelResponse, fromNum: Int64(packet.from), context: context)
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getDeviceMetadataResponse(adminMessage.getDeviceMetadataResponse) {
deviceMetadataPacket(metadata: adminMessage.getDeviceMetadataResponse, fromNum: Int64(packet.from), context: context)
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getConfigResponse(adminMessage.getConfigResponse) {
let config = adminMessage.getConfigResponse
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
upsertBluetoothConfigPacket(config: config.bluetooth, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.device(config.device) {
upsertDeviceConfigPacket(config: config.device, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.lora(config.lora) {
upsertLoRaConfigPacket(config: config.lora, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.network(config.network) {
upsertNetworkConfigPacket(config: config.network, nodeNum: Int64(packet.from), context: context)
} else if config.payloadVariant == Config.OneOf_PayloadVariant.position(config.position) {
upsertPositionConfigPacket(config: config.position, nodeNum: Int64(packet.from), context: context)
}
} else if adminMessage.payloadVariant == AdminMessage.OneOf_PayloadVariant.getModuleConfigResponse(adminMessage.getModuleConfigResponse) {
let moduleConfig = adminMessage.getModuleConfigResponse
if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.cannedMessage(moduleConfig.cannedMessage) {
upsertCannedMessagesModuleConfigPacket(config: moduleConfig.cannedMessage, nodeNum: Int64(packet.from), context: context)
} else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.externalNotification(moduleConfig.externalNotification) {
upsertExternalNotificationModuleConfigPacket(config: moduleConfig.externalNotification, nodeNum: Int64(packet.from), context: context)
} else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.mqtt(moduleConfig.mqtt) {
upsertMqttModuleConfigPacket(config: moduleConfig.mqtt, nodeNum: Int64(packet.from), context: context)
} else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.rangeTest(moduleConfig.rangeTest) {
upsertRangeTestModuleConfigPacket(config: moduleConfig.rangeTest, nodeNum: Int64(packet.from), context: context)
} else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.serial(moduleConfig.serial) {
upsertSerialModuleConfigPacket(config: moduleConfig.serial, nodeNum: Int64(packet.from), context: context)
} else if moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.telemetry(moduleConfig.telemetry) {
upsertTelemetryModuleConfigPacket(config: moduleConfig.telemetry, nodeNum: Int64(packet.from), context: context)
}
} else {
MeshLogger.log("🕸️ MESH PACKET received for Admin App \(try! packet.decoded.jsonString())")
}
// Save an ack for the admin message log for each admin message response received as we stopped sending acks if there is also a response to reduce airtime.
adminResponseAck(packet: packet, context: context)
}
}
func adminResponseAck (packet: MeshPacket, context: NSManagedObjectContext) {
let fetchedAdminMessageRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MessageEntity")
fetchedAdminMessageRequest.predicate = NSPredicate(format: "messageId == %lld", packet.decoded.requestID)
do {
@ -565,22 +563,22 @@ func adminResponseAck (packet: MeshPacket, context: NSManagedObjectContext) {
}
func routingPacket (packet: MeshPacket, connectedNodeNum: Int64, context: NSManagedObjectContext) {
if let routingMessage = try? Routing(serializedData: packet.decoded.payload) {
let routingError = RoutingError(rawValue: routingMessage.errorReason.rawValue)
let routingErrorString = routingError?.display ?? NSLocalizedString("unknown", comment: "")
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.routing.message %@ %@", comment: "Routing received for RequestID: %@ Ack Status: %@"), String(packet.decoded.requestID), routingErrorString)
MeshLogger.log("🕸️ \(logString)")
let fetchMessageRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MessageEntity")
fetchMessageRequest.predicate = NSPredicate(format: "messageId == %lld", Int64(packet.decoded.requestID))
do {
let fetchedMessage = try context.fetch(fetchMessageRequest) as? [MessageEntity]
if fetchedMessage?.count ?? 0 > 0 {
if fetchedMessage![0].toUser != nil {
// Real ACK from DM Recipient
if packet.to != packet.from {
@ -588,14 +586,14 @@ func routingPacket (packet: MeshPacket, connectedNodeNum: Int64, context: NSMana
}
}
fetchedMessage![0].ackError = Int32(routingMessage.errorReason.rawValue)
if routingMessage.errorReason == Routing.Error.none {
fetchedMessage![0].receivedACK = true
}
fetchedMessage![0].ackSNR = packet.rxSnr
fetchedMessage![0].ackTimestamp = Int32(packet.rxTime)
if fetchedMessage![0].toUser != nil {
fetchedMessage![0].toUser?.objectWillChange.send()
} else {
@ -604,19 +602,19 @@ func routingPacket (packet: MeshPacket, connectedNodeNum: Int64, context: NSMana
do {
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) as? [MyInfoEntity]
if fetchedMyInfo?.count ?? 0 > 0 {
for ch in fetchedMyInfo![0].channels!.array as! [ChannelEntity] {
if ch.index == packet.channel {
ch.objectWillChange.send()
}
}
}
} catch {
}
}
} else {
return
}
@ -631,25 +629,25 @@ func routingPacket (packet: MeshPacket, connectedNodeNum: Int64, context: NSMana
}
func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManagedObjectContext) {
if let telemetryMessage = try? Telemetry(serializedData: packet.decoded.payload) {
// Only log telemetry from the mesh not the connected device
if connectedNode != Int64(packet.from) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.telemetry.received %@", comment: "Telemetry received for: %@"), String(packet.from))
MeshLogger.log("📈 \(logString)")
} else {
// If it is the connected node
}
let telemetry = TelemetryEntity(context: context)
let fetchNodeTelemetryRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeTelemetryRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
do {
let fetchedNode = try context.fetch(fetchNodeTelemetryRequest) as! [NodeInfoEntity]
if fetchedNode.count == 1 {
if telemetryMessage.variant == Telemetry.OneOf_Variant.deviceMetrics(telemetryMessage.deviceMetrics) {
@ -690,7 +688,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
content.body = "Time to charge your radio, there is \(telemetry.batteryLevel)% battery remaining."
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request) { (error) in
if error != nil {
@ -710,12 +708,12 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
let updatedMeshStatus = MeshActivityAttributes.MeshActivityStatus(timerRange: date, connected: true, channelUtilization: telemetry.channelUtilization, airtime: telemetry.airUtilTx, batteryLevel: UInt32(telemetry.batteryLevel))
let alertConfiguration = AlertConfiguration(title: "Mesh activity update", body: "Updated Device Metrics Data.", sound: .default)
let updatedContent = ActivityContent(state: updatedMeshStatus, staleDate: nil)
let meshActivity = Activity<MeshActivityAttributes>.activities.first(where: { $0.attributes.nodeNum == connectedNode })
if meshActivity != nil {
Task {
await meshActivity?.update(updatedContent, alertConfiguration: alertConfiguration)
//await meshActivity?.update(updatedContent)
// await meshActivity?.update(updatedContent)
print("Updated live activity.")
}
}
@ -733,16 +731,16 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
}
func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSManagedObjectContext) {
if let messageText = String(bytes: packet.decoded.payload, encoding: .utf8) {
MeshLogger.log("💬 \(NSLocalizedString("mesh.log.textmessage.received", comment: "Message received from the text message app"))")
let messageUsers: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserEntity")
messageUsers.predicate = NSPredicate(format: "num IN %@", [packet.to, packet.from])
do {
let fetchedUsers = try context.fetch(messageUsers) as! [UserEntity]
let newMessage = MessageEntity(context: context)
newMessage.messageId = Int64(packet.id)
@ -751,11 +749,11 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM
newMessage.snr = packet.rxSnr
newMessage.isEmoji = packet.decoded.emoji == 1
newMessage.channel = Int32(packet.channel)
if packet.decoded.replyID > 0 {
newMessage.replyID = Int64(packet.decoded.replyID)
}
if fetchedUsers.first(where: { $0.num == packet.to }) != nil && packet.to != 4294967295 {
newMessage.toUser = fetchedUsers.first(where: { $0.num == packet.to })
}
@ -764,20 +762,20 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM
}
newMessage.messagePayload = messageText
newMessage.messagePayloadMarkdown = generateMessageMarkdown(message: messageText)
newMessage.fromUser?.objectWillChange.send()
newMessage.toUser?.objectWillChange.send()
var messageSaved = false
do {
try context.save()
print("💾 Saved a new message for \(newMessage.messageId)")
messageSaved = true
if messageSaved {
if newMessage.fromUser != nil && newMessage.toUser != nil && !(newMessage.fromUser?.mute ?? false) {
// Create an iOS Notification for the received DM message and schedule it immediately
let manager = LocalNotificationManager()
@ -791,17 +789,17 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM
manager.schedule()
print("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? NSLocalizedString("unknown", comment: "Unknown"))")
} else if newMessage.fromUser != nil && newMessage.toUser == nil {
let fetchMyInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MyInfoEntity")
fetchMyInfoRequest.predicate = NSPredicate(format: "myNodeNum == %lld", Int64(connectedNode))
do {
let fetchedMyInfo = try context.fetch(fetchMyInfoRequest) as! [MyInfoEntity]
for channel in (fetchedMyInfo[0].channels?.array ?? []) as? [ChannelEntity] ?? [] {
if channel.index == newMessage.channel {
context.refresh(channel, mergeChanges: true)
}
if channel.index == newMessage.channel && !channel.mute {
// Create an iOS Notification for the received private channel message and schedule it immediately
let manager = LocalNotificationManager()
@ -817,7 +815,7 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM
}
}
} catch {
}
}
}
@ -833,21 +831,21 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, context: NSM
}
func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.waypoint.received %@", comment: "Waypoint Packet received from node: %@"), String(packet.from))
MeshLogger.log("📍 \(logString)")
let fetchWaypointRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "WaypointEntity")
fetchWaypointRequest.predicate = NSPredicate(format: "id == %lld", Int64(packet.id))
do {
if let waypointMessage = try? Waypoint(serializedData: packet.decoded.payload) {
let fetchedWaypoint = try context.fetch(fetchWaypointRequest) as! [WaypointEntity]
if fetchedWaypoint.isEmpty {
let waypoint = WaypointEntity(context: context)
waypoint.id = Int64(packet.id)
waypoint.name = waypointMessage.name
waypoint.longDescription = waypointMessage.description_p
@ -857,7 +855,7 @@ func waypointPacket (packet: MeshPacket, context: NSManagedObjectContext) {
waypoint.locked = Int64(waypointMessage.lockedTo)
if waypointMessage.expire > 0 {
waypoint.expire = Date(timeIntervalSince1970: TimeInterval(Int64(waypointMessage.expire)))
}else {
} else {
waypoint.expire = nil
}
waypoint.created = Date()

View file

@ -5,7 +5,7 @@ import CoreData
@main
struct MeshtasticAppleApp: App {
let persistenceController = PersistenceController.shared
@ObservedObject private var bleManager: BLEManager = BLEManager()
@ObservedObject private var userSettings: UserSettings = UserSettings()
@ -30,9 +30,9 @@ struct MeshtasticAppleApp: App {
print("URL received \(userActivity)")
self.incomingUrl = userActivity.webpageURL
if ((self.incomingUrl?.absoluteString.lowercased().contains("meshtastic.org/e/#")) != nil) {
if (self.incomingUrl?.absoluteString.lowercased().contains("meshtastic.org/e/#")) != nil {
if let components = self.incomingUrl?.absoluteString.components(separatedBy: "#") {
self.channelSettings = components.last!
}
@ -44,10 +44,10 @@ struct MeshtasticAppleApp: App {
}
}
.onOpenURL(perform: { (url) in
print("Some sort of URL was received \(url)")
self.incomingUrl = url
if url.absoluteString.lowercased().contains("meshtastic.org/e/#") {
if let components = self.incomingUrl?.absoluteString.components(separatedBy: "#") {
self.channelSettings = components.last!
@ -59,37 +59,37 @@ struct MeshtasticAppleApp: App {
print("User wants to import a MBTILES offline map file: \(self.incomingUrl?.absoluteString ?? "No Tiles link")")
}
//we are expecting a .mbtiles map file that contains raster data
//save it to the documents directory, and name it offline_map.mbtiles
// we are expecting a .mbtiles map file that contains raster data
// save it to the documents directory, and name it offline_map.mbtiles
let fileManager = FileManager.default
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let destination = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false)
if !self.saveChannels {
//tell the system we want the file please
// tell the system we want the file please
guard url.startAccessingSecurityScopedResource() else {
return
}
//do we need to delete an old one?
if (fileManager.fileExists(atPath: destination.path)) {
// do we need to delete an old one?
if fileManager.fileExists(atPath: destination.path) {
print(" Found an old map file. Deleting it")
try? fileManager.removeItem(atPath: destination.path)
}
do {
try fileManager.copyItem(at: url, to: destination)
} catch {
print("Copy MB Tile file failed. Error: \(error)")
}
if (fileManager.fileExists(atPath: destination.path)) {
if fileManager.fileExists(atPath: destination.path) {
print(" Saved the map file")
//need to tell the map view that it needs to update and try loading the new overlay
// need to tell the map view that it needs to update and try loading the new overlay
UserDefaults.standard.set(Date().timeIntervalSince1970, forKey: "lastUpdatedLocalMapFile")
} else {
print("💥 Didn't save the map file")
}

View file

@ -23,15 +23,13 @@ struct Peripheral: Identifiable {
self.lastUpdate = lastUpdate
self.peripheral = peripheral
}
func getSignalStrength() -> SignalStrength {
if (NSNumber(value: rssi).compare(NSNumber(-65)) == ComparisonResult.orderedDescending) {
if NSNumber(value: rssi).compare(NSNumber(-65)) == ComparisonResult.orderedDescending {
return SignalStrength.strong
}
else if (NSNumber(value: rssi).compare(NSNumber(-85)) == ComparisonResult.orderedDescending) {
} else if NSNumber(value: rssi).compare(NSNumber(-85)) == ComparisonResult.orderedDescending {
return SignalStrength.normal
}
else {
} else {
return SignalStrength.weak
}
}

View file

@ -62,7 +62,7 @@ class UserSettings: ObservableObject {
UserDefaults.standard.synchronize()
}
}
init() {
self.meshtasticUsername = UserDefaults.standard.object(forKey: "meshtasticusername") as? String ?? ""

View file

@ -7,9 +7,9 @@
import Foundation
extension ChannelEntity {
var allPrivateMessages: [MessageEntity] {
self.value(forKey: "allPrivateMessages") as? [MessageEntity] ?? [MessageEntity]()
}
}

View file

@ -32,19 +32,19 @@ class PersistenceController {
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "Meshtastic")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (_, error) in
// Merge policy that favors in memory data over data in the db
self.container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
self.container.viewContext.automaticallyMergesChangesFromParent = true
if let error = error as NSError? {
print("💥 CoreData Error: \(error.localizedDescription). Now attempting to truncate CoreData database. All app data will be lost.")
@ -52,18 +52,18 @@ class PersistenceController {
}
})
}
public func clearDatabase() {
guard let url = self.container.persistentStoreDescriptions.first?.url else { return }
let persistentStoreCoordinator = self.container.persistentStoreCoordinator
do {
try persistentStoreCoordinator.destroyPersistentStore(at:url, ofType: NSSQLiteStoreType, options: nil)
try persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: NSSQLiteStoreType, options: nil)
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
print("💥 CoreData database truncated. All app data has been erased.")
} catch let error {
print("💣 Failed to destroy CoreData database, delete the app and re-install to clear data. Attempted to clear persistent store: " + error.localizedDescription)
}
@ -71,17 +71,17 @@ class PersistenceController {
}
extension NSManagedObjectContext {
/// Executes the given `NSBatchDeleteRequest` and directly merges the changes to bring the given managed object context up to date.
///
/// - Parameter batchDeleteRequest: The `NSBatchDeleteRequest` to execute.
/// - Throws: An error if anything went wrong executing the batch deletion.
public func executeAndMergeChanges(using batchDeleteRequest: NSBatchDeleteRequest) throws {
batchDeleteRequest.resultType = .resultTypeObjectIDs
let result = try execute(batchDeleteRequest) as? NSBatchDeleteResult
let changes: [AnyHashable: Any] = [NSDeletedObjectsKey: result?.result as? [NSManagedObjectID] ?? []]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [self])
}
}

View file

@ -31,7 +31,7 @@ extension PositionEntity {
return nil
}
}
var nodeLocation: CLLocation? {
if latitudeI != 0 && longitudeI != 0 {
let location = CLLocation(latitude: latitude!, longitude: longitude!)
@ -40,7 +40,7 @@ extension PositionEntity {
return nil
}
}
var annotaton: MKPointAnnotation {
let pointAnn = MKPointAnnotation()
if nodeCoordinate != nil {

View file

@ -8,10 +8,10 @@
import CoreData
public func getNodeInfo(id: Int64, context: NSManagedObjectContext) -> NodeInfoEntity? {
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(id))
do {
let fetchNodeInfo = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
if fetchNodeInfo.count == 1 {
@ -24,10 +24,10 @@ public func getNodeInfo(id: Int64, context: NSManagedObjectContext) -> NodeInfoE
}
public func getUser(id: Int64, context: NSManagedObjectContext) -> UserEntity {
let fetchUserRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserEntity")
fetchUserRequest.predicate = NSPredicate(format: "num == %lld", Int64(id))
do {
let fetchedUser = try context.fetch(fetchUserRequest) as! [UserEntity]
if fetchedUser.count == 1 {
@ -40,10 +40,10 @@ public func getUser(id: Int64, context: NSManagedObjectContext) -> UserEntity {
}
public func getWaypoint(id: Int64, context: NSManagedObjectContext) -> WaypointEntity {
let fetchWaypointRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "WaypointEntity")
fetchWaypointRequest.predicate = NSPredicate(format: "id == %lld", Int64(id))
do {
let fetchedWaypoint = try context.fetch(fetchWaypointRequest) as! [WaypointEntity]
if fetchedWaypoint.count == 1 {

View file

@ -7,26 +7,26 @@
import CoreData
public func clearPositions(destNum: Int64, context: NSManagedObjectContext) -> Bool {
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(destNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
let newPostions = [PositionEntity]()
fetchedNode[0].positions? = NSOrderedSet(array: newPostions)
do {
try context.save()
return true
} catch {
context.rollback()
return false
}
} catch {
print("💥 Fetch NodeInfoEntity Error")
return false
@ -34,26 +34,26 @@ public func clearPositions(destNum: Int64, context: NSManagedObjectContext) -> B
}
public func clearTelemetry(destNum: Int64, metricsType: Int32, context: NSManagedObjectContext) -> Bool {
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(destNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
let emptyTelemetry = [TelemetryEntity]()
fetchedNode[0].telemetries? = NSOrderedSet(array: emptyTelemetry)
do {
try context.save()
return true
} catch {
context.rollback()
return false
}
} catch {
print("💥 Fetch NodeInfoEntity Error")
return false
@ -73,7 +73,7 @@ public func deleteChannelMessages(channel: ChannelEntity, context: NSManagedObje
}
public func deleteUserMessages(user: UserEntity, context: NSManagedObjectContext) {
do {
let objects = user.messageList
for object in objects {
@ -86,13 +86,13 @@ public func deleteUserMessages(user: UserEntity, context: NSManagedObjectContext
}
public func clearCoreDataDatabase(context: NSManagedObjectContext) {
let persistenceController = PersistenceController.shared.container
for i in 0...persistenceController.managedObjectModel.entities.count-1 {
let entity = persistenceController.managedObjectModel.entities[i]
let query = NSFetchRequest<NSFetchRequestResult>(entityName: entity.name!)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: query)
do {
try context.executeAndMergeChanges(using: deleteRequest)
} catch let error as NSError {
@ -102,23 +102,22 @@ public func clearCoreDataDatabase(context: NSManagedObjectContext) {
}
func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.position.received %@", comment: "Position Packet received from node: %@"), String(packet.from))
MeshLogger.log("📍 \(logString)")
let fetchNodePositionRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodePositionRequest.predicate = NSPredicate(format: "num == %lld", Int64(packet.from))
do {
if let positionMessage = try? Position(serializedData: packet.decoded.payload) {
// Don't save empty position packets
if positionMessage.longitudeI > 0 || positionMessage.latitudeI > 0 && (positionMessage.latitudeI != 373346000 && positionMessage.longitudeI != -1220090000)
{
if positionMessage.longitudeI > 0 || positionMessage.latitudeI > 0 && (positionMessage.latitudeI != 373346000 && positionMessage.longitudeI != -1220090000) {
let fetchedNode = try context.fetch(fetchNodePositionRequest) as! [NodeInfoEntity]
if fetchedNode.count == 1 {
// Unset the current latest position for this node
let fetchCurrentLatestPositionsRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "PositionEntity")
fetchCurrentLatestPositionsRequest.predicate = NSPredicate(format: "nodePosition.num == %lld && latest = true", Int64(packet.from))
@ -128,7 +127,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
position.latest = false
}
}
let position = PositionEntity(context: context)
position.latest = true
position.snr = packet.rxSnr
@ -145,14 +144,14 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
position.time = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
}
let mutablePositions = fetchedNode[0].positions!.mutableCopy() as! NSMutableOrderedSet
mutablePositions.add(position)
fetchedNode[0].id = Int64(packet.from)
fetchedNode[0].num = Int64(packet.from)
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
fetchedNode[0].snr = packet.rxSnr
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
do {
try context.save()
print("💾 Updated Node Position Coordinates, SNR and Time from Position App Packet For: \(fetchedNode[0].num)")
@ -173,15 +172,15 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
}
func upsertBluetoothConfigPacket(config: Meshtastic.Config.BluetoothConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.bluetooth.config %@", comment: "Bluetooth config received: %@"), String(nodeNum))
MeshLogger.log("📶 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
@ -214,14 +213,14 @@ func upsertBluetoothConfigPacket(config: Meshtastic.Config.BluetoothConfig, node
}
func upsertDeviceConfigPacket(config: Meshtastic.Config.DeviceConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.device.config %@", comment: "Device config received: %@"), String(nodeNum))
MeshLogger.log("📟 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
@ -260,22 +259,22 @@ func upsertDeviceConfigPacket(config: Meshtastic.Config.DeviceConfig, nodeNum: I
}
func upsertDisplayConfigPacket(config: Meshtastic.Config.DisplayConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.display.config %@", comment: "Display config received: %@"), String(nodeNum))
MeshLogger.log("🖥️ \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
if fetchedNode[0].displayConfig == nil {
let newDisplayConfig = DisplayConfigEntity(context: context)
newDisplayConfig.gpsFormat = Int32(config.gpsFormat.rawValue)
newDisplayConfig.screenOnSeconds = Int32(config.screenOnSecs)
@ -286,10 +285,9 @@ func upsertDisplayConfigPacket(config: Meshtastic.Config.DisplayConfig, nodeNum:
newDisplayConfig.displayMode = Int32(config.displaymode.rawValue)
newDisplayConfig.headingBold = config.headingBold
fetchedNode[0].displayConfig = newDisplayConfig
} else {
fetchedNode[0].displayConfig?.gpsFormat = Int32(config.gpsFormat.rawValue)
fetchedNode[0].displayConfig?.screenOnSeconds = Int32(config.screenOnSecs)
fetchedNode[0].displayConfig?.screenCarouselInterval = Int32(config.autoScreenCarouselSecs)
@ -299,41 +297,39 @@ func upsertDisplayConfigPacket(config: Meshtastic.Config.DisplayConfig, nodeNum:
fetchedNode[0].displayConfig?.displayMode = Int32(config.displaymode.rawValue)
fetchedNode[0].displayConfig?.headingBold = config.headingBold
}
do {
try context.save()
print("💾 Updated Display Config for node number: \(String(nodeNum))")
} catch {
context.rollback()
let nsError = error as NSError
print("💥 Error Updating Core Data DisplayConfigEntity: \(nsError)")
}
} else {
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Display Config")
}
} catch {
let nsError = error as NSError
print("💥 Fetching node for core data DisplayConfigEntity failed: \(nsError)")
}
}
func upsertLoRaConfigPacket(config: Meshtastic.Config.LoRaConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.lora.config %@", comment: "LoRa config received: %@"), String(nodeNum))
MeshLogger.log("📻 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", nodeNum)
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save LoRa Config
if fetchedNode.count > 0 {
@ -388,15 +384,15 @@ func upsertLoRaConfigPacket(config: Meshtastic.Config.LoRaConfig, nodeNum: Int64
}
func upsertNetworkConfigPacket(config: Meshtastic.Config.NetworkConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.network.config %@", comment: "Network config received: %@"), String(nodeNum))
MeshLogger.log("🌐 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save WiFi Config
if !fetchedNode.isEmpty {
@ -413,11 +409,11 @@ func upsertNetworkConfigPacket(config: Meshtastic.Config.NetworkConfig, nodeNum:
fetchedNode[0].networkConfig?.wifiSsid = config.wifiSsid
fetchedNode[0].networkConfig?.wifiPsk = config.wifiPsk
}
do {
try context.save()
print("💾 Updated Network Config for node number: \(String(nodeNum))")
} catch {
context.rollback()
let nsError = error as NSError
@ -433,15 +429,15 @@ func upsertNetworkConfigPacket(config: Meshtastic.Config.NetworkConfig, nodeNum:
}
func upsertPositionConfigPacket(config: Meshtastic.Config.PositionConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.position.config %@", comment: "Positon config received: %@"), String(nodeNum))
MeshLogger.log("🗺️ \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save LoRa Config
if !fetchedNode.isEmpty {
@ -482,24 +478,24 @@ func upsertPositionConfigPacket(config: Meshtastic.Config.PositionConfig, nodeNu
}
func upsertCannedMessagesModuleConfigPacket(config: Meshtastic.ModuleConfig.CannedMessageConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.cannedmessage.config %@", comment: "Canned Message module config received: %@"), String(nodeNum))
MeshLogger.log("🥫 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Canned Message Config
if !fetchedNode.isEmpty {
if fetchedNode[0].cannedMessageConfig == nil {
let newCannedMessageConfig = CannedMessageConfigEntity(context: context)
newCannedMessageConfig.enabled = config.enabled
newCannedMessageConfig.sendBell = config.sendBell
newCannedMessageConfig.rotary1Enabled = config.rotary1Enabled
@ -510,11 +506,11 @@ func upsertCannedMessagesModuleConfigPacket(config: Meshtastic.ModuleConfig.Cann
newCannedMessageConfig.inputbrokerEventCw = Int32(config.inputbrokerEventCw.rawValue)
newCannedMessageConfig.inputbrokerEventCcw = Int32(config.inputbrokerEventCcw.rawValue)
newCannedMessageConfig.inputbrokerEventPress = Int32(config.inputbrokerEventPress.rawValue)
fetchedNode[0].cannedMessageConfig = newCannedMessageConfig
} else {
fetchedNode[0].cannedMessageConfig?.enabled = config.enabled
fetchedNode[0].cannedMessageConfig?.sendBell = config.sendBell
fetchedNode[0].cannedMessageConfig?.rotary1Enabled = config.rotary1Enabled
@ -526,7 +522,7 @@ func upsertCannedMessagesModuleConfigPacket(config: Meshtastic.ModuleConfig.Cann
fetchedNode[0].cannedMessageConfig?.inputbrokerEventCcw = Int32(config.inputbrokerEventCcw.rawValue)
fetchedNode[0].cannedMessageConfig?.inputbrokerEventPress = Int32(config.inputbrokerEventPress.rawValue)
}
do {
try context.save()
print("💾 Updated Canned Message Module Config for node number: \(String(nodeNum))")
@ -545,19 +541,19 @@ func upsertCannedMessagesModuleConfigPacket(config: Meshtastic.ModuleConfig.Cann
}
func upsertExternalNotificationModuleConfigPacket(config: Meshtastic.ModuleConfig.ExternalNotificationConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.externalnotification.config %@", comment: "External Notifiation module config received: %@"), String(nodeNum))
MeshLogger.log("📣 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save External Notificaitone Config
if !fetchedNode.isEmpty {
if fetchedNode[0].externalNotificationConfig == nil {
let newExternalNotificationConfig = ExternalNotificationConfigEntity(context: context)
newExternalNotificationConfig.enabled = config.enabled
@ -575,7 +571,7 @@ func upsertExternalNotificationModuleConfigPacket(config: Meshtastic.ModuleConfi
newExternalNotificationConfig.outputMilliseconds = Int32(config.outputMs)
newExternalNotificationConfig.nagTimeout = Int32(config.nagTimeout)
fetchedNode[0].externalNotificationConfig = newExternalNotificationConfig
} else {
fetchedNode[0].externalNotificationConfig?.enabled = config.enabled
fetchedNode[0].externalNotificationConfig?.usePWM = config.usePwm
@ -592,7 +588,7 @@ func upsertExternalNotificationModuleConfigPacket(config: Meshtastic.ModuleConfi
fetchedNode[0].externalNotificationConfig?.outputMilliseconds = Int32(config.outputMs)
fetchedNode[0].externalNotificationConfig?.nagTimeout = Int32(config.nagTimeout)
}
do {
try context.save()
print("💾 Updated External Notification Module Config for node number: \(String(nodeNum))")
@ -611,19 +607,19 @@ func upsertExternalNotificationModuleConfigPacket(config: Meshtastic.ModuleConfi
}
func upsertMqttModuleConfigPacket(config: Meshtastic.ModuleConfig.MQTTConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.mqtt.config %@", comment: "MQTT module config received: %@"), String(nodeNum))
MeshLogger.log("🌉 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save MQTT Config
if !fetchedNode.isEmpty {
if fetchedNode[0].mqttConfig == nil {
let newMQTTConfig = MQTTConfigEntity(context: context)
newMQTTConfig.enabled = config.enabled
@ -659,15 +655,15 @@ func upsertMqttModuleConfigPacket(config: Meshtastic.ModuleConfig.MQTTConfig, no
}
func upsertRangeTestModuleConfigPacket(config: Meshtastic.ModuleConfig.RangeTestConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.rangetest.config %@", comment: "Range Test module config received: %@"), String(nodeNum))
MeshLogger.log("⛰️ \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
@ -700,22 +696,22 @@ func upsertRangeTestModuleConfigPacket(config: Meshtastic.ModuleConfig.RangeTest
}
func upsertSerialModuleConfigPacket(config: Meshtastic.ModuleConfig.SerialConfig, nodeNum: Int64, context: NSManagedObjectContext) {
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.serial.config %@", comment: "Serial module config received: %@"), String(nodeNum))
MeshLogger.log("🤖 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Device Config
if !fetchedNode.isEmpty {
if fetchedNode[0].serialConfig == nil {
let newSerialConfig = SerialConfigEntity(context: context)
newSerialConfig.enabled = config.enabled
newSerialConfig.echo = config.echo
@ -725,7 +721,7 @@ func upsertSerialModuleConfigPacket(config: Meshtastic.ModuleConfig.SerialConfig
newSerialConfig.timeout = Int32(config.timeout)
newSerialConfig.mode = Int32(config.mode.rawValue)
fetchedNode[0].serialConfig = newSerialConfig
} else {
fetchedNode[0].serialConfig?.enabled = config.enabled
fetchedNode[0].serialConfig?.echo = config.echo
@ -735,26 +731,26 @@ func upsertSerialModuleConfigPacket(config: Meshtastic.ModuleConfig.SerialConfig
fetchedNode[0].serialConfig?.timeout = Int32(config.timeout)
fetchedNode[0].serialConfig?.mode = Int32(config.mode.rawValue)
}
do {
try context.save()
print("💾 Updated Serial Module Config for node number: \(String(nodeNum))")
} catch {
context.rollback()
let nsError = error as NSError
print("💥 Error Updating Core Data SerialConfigEntity: \(nsError)")
}
} else {
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Serial Module Config")
}
} catch {
let nsError = error as NSError
print("💥 Fetching node for core data SerialConfigEntity failed: \(nsError)")
}
@ -764,51 +760,51 @@ func upsertTelemetryModuleConfigPacket(config: Meshtastic.ModuleConfig.Telemetry
let logString = String.localizedStringWithFormat(NSLocalizedString("mesh.log.telemetry.config %@", comment: "Telemetry module config received: %@"), String(nodeNum))
MeshLogger.log("📈 \(logString)")
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, save Telemetry Config
if !fetchedNode.isEmpty {
if fetchedNode[0].telemetryConfig == nil {
let newTelemetryConfig = TelemetryConfigEntity(context: context)
newTelemetryConfig.deviceUpdateInterval = Int32(config.deviceUpdateInterval)
newTelemetryConfig.environmentUpdateInterval = Int32(config.environmentUpdateInterval)
newTelemetryConfig.environmentMeasurementEnabled = config.environmentMeasurementEnabled
newTelemetryConfig.environmentScreenEnabled = config.environmentScreenEnabled
newTelemetryConfig.environmentDisplayFahrenheit = config.environmentDisplayFahrenheit
fetchedNode[0].telemetryConfig = newTelemetryConfig
} else {
fetchedNode[0].telemetryConfig?.deviceUpdateInterval = Int32(config.deviceUpdateInterval)
fetchedNode[0].telemetryConfig?.environmentUpdateInterval = Int32(config.environmentUpdateInterval)
fetchedNode[0].telemetryConfig?.environmentMeasurementEnabled = config.environmentMeasurementEnabled
fetchedNode[0].telemetryConfig?.environmentScreenEnabled = config.environmentScreenEnabled
fetchedNode[0].telemetryConfig?.environmentDisplayFahrenheit = config.environmentDisplayFahrenheit
}
do {
try context.save()
print("💾 Updated Telemetry Module Config for node number: \(String(nodeNum))")
} catch {
context.rollback()
let nsError = error as NSError
print("💥 Error Updating Core Data TelemetryConfigEntity: \(nsError)")
}
} else {
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Telemetry Module Config")
}
} catch {
let nsError = error as NSError
print("💥 Fetching node for core data TelemetryConfigEntity failed: \(nsError)")

View file

@ -8,14 +8,14 @@
import Foundation
extension UserEntity {
var messageList: [MessageEntity] {
self.value(forKey: "allMessages") as? [MessageEntity] ?? [MessageEntity]()
}
var adminMessageList: [MessageEntity] {
self.value(forKey: "adminMessages") as? [MessageEntity] ?? [MessageEntity]()
}
}

View file

@ -37,7 +37,7 @@ extension WaypointEntity {
return nil
}
}
var annotaton: MKPointAnnotation {
let pointAnn = MKPointAnnotation()
if waypointCoordinate != nil {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -31,7 +31,7 @@ struct AdminMessage {
///
/// TODO: REPLACE
var payloadVariant: AdminMessage.OneOf_PayloadVariant? = nil
var payloadVariant: AdminMessage.OneOf_PayloadVariant?
///
/// Send the specified channel in the response to this message
@ -752,7 +752,7 @@ extension AdminMessage.ConfigType: CaseIterable {
.networkConfig,
.displayConfig,
.loraConfig,
.bluetoothConfig,
.bluetoothConfig
]
}
@ -767,7 +767,7 @@ extension AdminMessage.ModuleConfigType: CaseIterable {
.telemetryConfig,
.cannedmsgConfig,
.audioConfig,
.remotehardwareConfig,
.remotehardwareConfig
]
}
@ -813,7 +813,7 @@ extension HamParameters: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".AdminMessage"
@ -848,7 +848,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
97: .standard(proto: "reboot_seconds"),
98: .standard(proto: "shutdown_seconds"),
99: .standard(proto: "factory_reset"),
100: .standard(proto: "nodedb_reset"),
100: .standard(proto: "nodedb_reset")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1315,7 +1315,7 @@ extension AdminMessage.ConfigType: SwiftProtobuf._ProtoNameProviding {
3: .same(proto: "NETWORK_CONFIG"),
4: .same(proto: "DISPLAY_CONFIG"),
5: .same(proto: "LORA_CONFIG"),
6: .same(proto: "BLUETOOTH_CONFIG"),
6: .same(proto: "BLUETOOTH_CONFIG")
]
}
@ -1329,7 +1329,7 @@ extension AdminMessage.ModuleConfigType: SwiftProtobuf._ProtoNameProviding {
5: .same(proto: "TELEMETRY_CONFIG"),
6: .same(proto: "CANNEDMSG_CONFIG"),
7: .same(proto: "AUDIO_CONFIG"),
8: .same(proto: "REMOTEHARDWARE_CONFIG"),
8: .same(proto: "REMOTEHARDWARE_CONFIG")
]
}
@ -1339,7 +1339,7 @@ extension HamParameters: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa
1: .standard(proto: "call_sign"),
2: .standard(proto: "tx_power"),
3: .same(proto: "frequency"),
4: .standard(proto: "short_name"),
4: .standard(proto: "short_name")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -50,7 +50,7 @@ struct ChannelSet {
init() {}
fileprivate var _loraConfig: Config.LoRaConfig? = nil
fileprivate var _loraConfig: Config.LoRaConfig?
}
#if swift(>=5.5) && canImport(_Concurrency)
@ -59,13 +59,13 @@ extension ChannelSet: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension ChannelSet: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".ChannelSet"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "settings"),
2: .standard(proto: "lora_config"),
2: .standard(proto: "lora_config")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -42,12 +42,12 @@ extension CannedMessageModuleConfig: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension CannedMessageModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".CannedMessageModuleConfig"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "messages"),
1: .same(proto: "messages")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -183,7 +183,7 @@ struct Channel {
init() {}
fileprivate var _settings: ChannelSettings? = nil
fileprivate var _settings: ChannelSettings?
}
#if swift(>=4.2)
@ -193,7 +193,7 @@ extension Channel.Role: CaseIterable {
static var allCases: [Channel.Role] = [
.disabled,
.primary,
.secondary,
.secondary
]
}
@ -207,7 +207,7 @@ extension Channel.Role: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension ChannelSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".ChannelSettings"
@ -217,7 +217,7 @@ extension ChannelSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplemen
3: .same(proto: "name"),
4: .same(proto: "id"),
5: .standard(proto: "uplink_enabled"),
6: .standard(proto: "downlink_enabled"),
6: .standard(proto: "downlink_enabled")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -276,7 +276,7 @@ extension Channel: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "index"),
2: .same(proto: "settings"),
3: .same(proto: "role"),
3: .same(proto: "role")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -323,6 +323,6 @@ extension Channel.Role: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "DISABLED"),
1: .same(proto: "PRIMARY"),
2: .same(proto: "SECONDARY"),
2: .same(proto: "SECONDARY")
]
}

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -27,7 +27,7 @@ struct Config {
///
/// Payload Variant
var payloadVariant: Config.OneOf_PayloadVariant? = nil
var payloadVariant: Config.OneOf_PayloadVariant?
var device: Config.DeviceConfig {
get {
@ -632,7 +632,7 @@ struct Config {
init() {}
fileprivate var _ipv4Config: Config.NetworkConfig.IpV4Config? = nil
fileprivate var _ipv4Config: Config.NetworkConfig.IpV4Config?
}
///
@ -1252,7 +1252,7 @@ extension Config.DeviceConfig.Role: CaseIterable {
.routerClient,
.repeater,
.tracker,
.sensor,
.sensor
]
}
@ -1261,7 +1261,7 @@ extension Config.DeviceConfig.RebroadcastMode: CaseIterable {
static var allCases: [Config.DeviceConfig.RebroadcastMode] = [
.all,
.allSkipDecoding,
.localOnly,
.localOnly
]
}
@ -1278,7 +1278,7 @@ extension Config.PositionConfig.PositionFlags: CaseIterable {
.seqNo,
.timestamp,
.heading,
.speed,
.speed
]
}
@ -1286,7 +1286,7 @@ extension Config.NetworkConfig.AddressMode: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
static var allCases: [Config.NetworkConfig.AddressMode] = [
.dhcp,
.static,
.static
]
}
@ -1298,7 +1298,7 @@ extension Config.DisplayConfig.GpsCoordinateFormat: CaseIterable {
.utm,
.mgrs,
.olc,
.osgr,
.osgr
]
}
@ -1306,7 +1306,7 @@ extension Config.DisplayConfig.DisplayUnits: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
static var allCases: [Config.DisplayConfig.DisplayUnits] = [
.metric,
.imperial,
.imperial
]
}
@ -1316,7 +1316,7 @@ extension Config.DisplayConfig.OledType: CaseIterable {
.oledAuto,
.oledSsd1306,
.oledSh1106,
.oledSh1107,
.oledSh1107
]
}
@ -1326,7 +1326,7 @@ extension Config.DisplayConfig.DisplayMode: CaseIterable {
.default,
.twocolor,
.inverted,
.color,
.color
]
}
@ -1348,7 +1348,7 @@ extension Config.LoRaConfig.RegionCode: CaseIterable {
.th,
.lora24,
.ua433,
.ua868,
.ua868
]
}
@ -1362,7 +1362,7 @@ extension Config.LoRaConfig.ModemPreset: CaseIterable {
.mediumFast,
.shortSlow,
.shortFast,
.longModerate,
.longModerate
]
}
@ -1371,7 +1371,7 @@ extension Config.BluetoothConfig.PairingMode: CaseIterable {
static var allCases: [Config.BluetoothConfig.PairingMode] = [
.randomPin,
.fixedPin,
.noPin,
.noPin
]
}
@ -1403,7 +1403,7 @@ extension Config.BluetoothConfig.PairingMode: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".Config"
@ -1414,7 +1414,7 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas
4: .same(proto: "network"),
5: .same(proto: "display"),
6: .same(proto: "lora"),
7: .same(proto: "bluetooth"),
7: .same(proto: "bluetooth")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1574,7 +1574,7 @@ extension Config.DeviceConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImpl
4: .standard(proto: "button_gpio"),
5: .standard(proto: "buzzer_gpio"),
6: .standard(proto: "rebroadcast_mode"),
7: .standard(proto: "node_info_broadcast_secs"),
7: .standard(proto: "node_info_broadcast_secs")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1641,7 +1641,7 @@ extension Config.DeviceConfig.Role: SwiftProtobuf._ProtoNameProviding {
3: .same(proto: "ROUTER_CLIENT"),
4: .same(proto: "REPEATER"),
5: .same(proto: "TRACKER"),
6: .same(proto: "SENSOR"),
6: .same(proto: "SENSOR")
]
}
@ -1649,7 +1649,7 @@ extension Config.DeviceConfig.RebroadcastMode: SwiftProtobuf._ProtoNameProviding
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "ALL"),
1: .same(proto: "ALL_SKIP_DECODING"),
2: .same(proto: "LOCAL_ONLY"),
2: .same(proto: "LOCAL_ONLY")
]
}
@ -1664,7 +1664,7 @@ extension Config.PositionConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
6: .standard(proto: "gps_attempt_time"),
7: .standard(proto: "position_flags"),
8: .standard(proto: "rx_gpio"),
9: .standard(proto: "tx_gpio"),
9: .standard(proto: "tx_gpio")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1745,7 +1745,7 @@ extension Config.PositionConfig.PositionFlags: SwiftProtobuf._ProtoNameProviding
64: .same(proto: "SEQ_NO"),
128: .same(proto: "TIMESTAMP"),
256: .same(proto: "HEADING"),
512: .same(proto: "SPEED"),
512: .same(proto: "SPEED")
]
}
@ -1759,7 +1759,7 @@ extension Config.PowerConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
5: .standard(proto: "mesh_sds_timeout_secs"),
6: .standard(proto: "sds_secs"),
7: .standard(proto: "ls_secs"),
8: .standard(proto: "min_wake_secs"),
8: .standard(proto: "min_wake_secs")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1833,7 +1833,7 @@ extension Config.NetworkConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
6: .standard(proto: "eth_enabled"),
7: .standard(proto: "address_mode"),
8: .standard(proto: "ipv4_config"),
9: .standard(proto: "rsyslog_server"),
9: .standard(proto: "rsyslog_server")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1904,7 +1904,7 @@ extension Config.NetworkConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
extension Config.NetworkConfig.AddressMode: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "DHCP"),
1: .same(proto: "STATIC"),
1: .same(proto: "STATIC")
]
}
@ -1914,7 +1914,7 @@ extension Config.NetworkConfig.IpV4Config: SwiftProtobuf.Message, SwiftProtobuf.
1: .same(proto: "ip"),
2: .same(proto: "gateway"),
3: .same(proto: "subnet"),
4: .same(proto: "dns"),
4: .same(proto: "dns")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1969,7 +1969,7 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
6: .same(proto: "units"),
7: .same(proto: "oled"),
8: .same(proto: "displaymode"),
9: .standard(proto: "heading_bold"),
9: .standard(proto: "heading_bold")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2045,14 +2045,14 @@ extension Config.DisplayConfig.GpsCoordinateFormat: SwiftProtobuf._ProtoNameProv
2: .same(proto: "UTM"),
3: .same(proto: "MGRS"),
4: .same(proto: "OLC"),
5: .same(proto: "OSGR"),
5: .same(proto: "OSGR")
]
}
extension Config.DisplayConfig.DisplayUnits: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "METRIC"),
1: .same(proto: "IMPERIAL"),
1: .same(proto: "IMPERIAL")
]
}
@ -2061,7 +2061,7 @@ extension Config.DisplayConfig.OledType: SwiftProtobuf._ProtoNameProviding {
0: .same(proto: "OLED_AUTO"),
1: .same(proto: "OLED_SSD1306"),
2: .same(proto: "OLED_SH1106"),
3: .same(proto: "OLED_SH1107"),
3: .same(proto: "OLED_SH1107")
]
}
@ -2070,7 +2070,7 @@ extension Config.DisplayConfig.DisplayMode: SwiftProtobuf._ProtoNameProviding {
0: .same(proto: "DEFAULT"),
1: .same(proto: "TWOCOLOR"),
2: .same(proto: "INVERTED"),
3: .same(proto: "COLOR"),
3: .same(proto: "COLOR")
]
}
@ -2091,7 +2091,7 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
12: .standard(proto: "override_duty_cycle"),
13: .standard(proto: "sx126x_rx_boosted_gain"),
14: .standard(proto: "override_frequency"),
103: .standard(proto: "ignore_incoming"),
103: .standard(proto: "ignore_incoming")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2207,7 +2207,7 @@ extension Config.LoRaConfig.RegionCode: SwiftProtobuf._ProtoNameProviding {
12: .same(proto: "TH"),
13: .same(proto: "LORA_24"),
14: .same(proto: "UA_433"),
15: .same(proto: "UA_868"),
15: .same(proto: "UA_868")
]
}
@ -2220,7 +2220,7 @@ extension Config.LoRaConfig.ModemPreset: SwiftProtobuf._ProtoNameProviding {
4: .same(proto: "MEDIUM_FAST"),
5: .same(proto: "SHORT_SLOW"),
6: .same(proto: "SHORT_FAST"),
7: .same(proto: "LONG_MODERATE"),
7: .same(proto: "LONG_MODERATE")
]
}
@ -2229,7 +2229,7 @@ extension Config.BluetoothConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageI
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "enabled"),
2: .same(proto: "mode"),
3: .standard(proto: "fixed_pin"),
3: .standard(proto: "fixed_pin")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2272,6 +2272,6 @@ extension Config.BluetoothConfig.PairingMode: SwiftProtobuf._ProtoNameProviding
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "RANDOM_PIN"),
1: .same(proto: "FIXED_PIN"),
2: .same(proto: "NO_PIN"),
2: .same(proto: "NO_PIN")
]
}

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -73,10 +73,10 @@ struct DeviceConnectionStatus {
init() {}
fileprivate var _wifi: WifiConnectionStatus? = nil
fileprivate var _ethernet: EthernetConnectionStatus? = nil
fileprivate var _bluetooth: BluetoothConnectionStatus? = nil
fileprivate var _serial: SerialConnectionStatus? = nil
fileprivate var _wifi: WifiConnectionStatus?
fileprivate var _ethernet: EthernetConnectionStatus?
fileprivate var _bluetooth: BluetoothConnectionStatus?
fileprivate var _serial: SerialConnectionStatus?
}
///
@ -109,7 +109,7 @@ struct WifiConnectionStatus {
init() {}
fileprivate var _status: NetworkConnectionStatus? = nil
fileprivate var _status: NetworkConnectionStatus?
}
///
@ -134,7 +134,7 @@ struct EthernetConnectionStatus {
init() {}
fileprivate var _status: NetworkConnectionStatus? = nil
fileprivate var _status: NetworkConnectionStatus?
}
///
@ -220,7 +220,7 @@ extension SerialConnectionStatus: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension DeviceConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".DeviceConnectionStatus"
@ -228,7 +228,7 @@ extension DeviceConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageI
1: .same(proto: "wifi"),
2: .same(proto: "ethernet"),
3: .same(proto: "bluetooth"),
4: .same(proto: "serial"),
4: .same(proto: "serial")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -281,7 +281,7 @@ extension WifiConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "status"),
2: .same(proto: "ssid"),
3: .same(proto: "rssi"),
3: .same(proto: "rssi")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -327,7 +327,7 @@ extension WifiConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
extension EthernetConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".EthernetConnectionStatus"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "status"),
1: .same(proto: "status")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -366,7 +366,7 @@ extension NetworkConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._Message
1: .standard(proto: "ip_address"),
2: .standard(proto: "is_connected"),
3: .standard(proto: "is_mqtt_connected"),
4: .standard(proto: "is_syslog_connected"),
4: .standard(proto: "is_syslog_connected")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -415,7 +415,7 @@ extension BluetoothConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._Messa
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "pin"),
2: .same(proto: "rssi"),
3: .standard(proto: "is_connected"),
3: .standard(proto: "is_connected")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -458,7 +458,7 @@ extension SerialConnectionStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageI
static let protoMessageName: String = _protobuf_package + ".SerialConnectionStatus"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "baud"),
2: .standard(proto: "is_connected"),
2: .standard(proto: "is_connected")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -69,7 +69,7 @@ extension ScreenFonts: CaseIterable {
static var allCases: [ScreenFonts] = [
.fontSmall,
.fontMedium,
.fontLarge,
.fontLarge
]
}
@ -246,8 +246,8 @@ struct OEMStore {
init() {}
fileprivate var _oemLocalConfig: LocalConfig? = nil
fileprivate var _oemLocalModuleConfig: LocalModuleConfig? = nil
fileprivate var _oemLocalConfig: LocalConfig?
fileprivate var _oemLocalModuleConfig: LocalModuleConfig?
}
#if swift(>=5.5) && canImport(_Concurrency)
@ -259,13 +259,13 @@ extension OEMStore: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension ScreenFonts: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "FONT_SMALL"),
1: .same(proto: "FONT_MEDIUM"),
2: .same(proto: "FONT_LARGE"),
2: .same(proto: "FONT_LARGE")
]
}
@ -279,16 +279,16 @@ extension DeviceState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
8: .same(proto: "version"),
7: .standard(proto: "rx_text_message"),
9: .standard(proto: "no_save"),
11: .standard(proto: "did_gps_reset"),
11: .standard(proto: "did_gps_reset")
]
fileprivate class _StorageClass {
var _myNode: MyNodeInfo? = nil
var _owner: User? = nil
var _myNode: MyNodeInfo?
var _owner: User?
var _nodeDb: [NodeInfo] = []
var _receiveQueue: [MeshPacket] = []
var _version: UInt32 = 0
var _rxTextMessage: MeshPacket? = nil
var _rxTextMessage: MeshPacket?
var _noSave: Bool = false
var _didGpsReset: Bool = false
@ -397,7 +397,7 @@ extension ChannelFile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
static let protoMessageName: String = _protobuf_package + ".ChannelFile"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "channels"),
2: .same(proto: "version"),
2: .same(proto: "version")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -441,7 +441,7 @@ extension OEMStore: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
5: .standard(proto: "oem_text"),
6: .standard(proto: "oem_aes_key"),
7: .standard(proto: "oem_local_config"),
8: .standard(proto: "oem_local_module_config"),
8: .standard(proto: "oem_local_module_config")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -245,7 +245,7 @@ extension LocalModuleConfig: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".LocalConfig"
@ -257,17 +257,17 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
5: .same(proto: "display"),
6: .same(proto: "lora"),
7: .same(proto: "bluetooth"),
8: .same(proto: "version"),
8: .same(proto: "version")
]
fileprivate class _StorageClass {
var _device: Config.DeviceConfig? = nil
var _position: Config.PositionConfig? = nil
var _power: Config.PowerConfig? = nil
var _network: Config.NetworkConfig? = nil
var _display: Config.DisplayConfig? = nil
var _lora: Config.LoRaConfig? = nil
var _bluetooth: Config.BluetoothConfig? = nil
var _device: Config.DeviceConfig?
var _position: Config.PositionConfig?
var _power: Config.PowerConfig?
var _network: Config.NetworkConfig?
var _display: Config.DisplayConfig?
var _lora: Config.LoRaConfig?
var _bluetooth: Config.BluetoothConfig?
var _version: UInt32 = 0
static let defaultInstance = _StorageClass()
@ -383,19 +383,19 @@ extension LocalModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
7: .standard(proto: "canned_message"),
9: .same(proto: "audio"),
10: .standard(proto: "remote_hardware"),
8: .same(proto: "version"),
8: .same(proto: "version")
]
fileprivate class _StorageClass {
var _mqtt: ModuleConfig.MQTTConfig? = nil
var _serial: ModuleConfig.SerialConfig? = nil
var _externalNotification: ModuleConfig.ExternalNotificationConfig? = nil
var _storeForward: ModuleConfig.StoreForwardConfig? = nil
var _rangeTest: ModuleConfig.RangeTestConfig? = nil
var _telemetry: ModuleConfig.TelemetryConfig? = nil
var _cannedMessage: ModuleConfig.CannedMessageConfig? = nil
var _audio: ModuleConfig.AudioConfig? = nil
var _remoteHardware: ModuleConfig.RemoteHardwareConfig? = nil
var _mqtt: ModuleConfig.MQTTConfig?
var _serial: ModuleConfig.SerialConfig?
var _externalNotification: ModuleConfig.ExternalNotificationConfig?
var _storeForward: ModuleConfig.StoreForwardConfig?
var _rangeTest: ModuleConfig.RangeTestConfig?
var _telemetry: ModuleConfig.TelemetryConfig?
var _cannedMessage: ModuleConfig.CannedMessageConfig?
var _audio: ModuleConfig.AudioConfig?
var _remoteHardware: ModuleConfig.RemoteHardwareConfig?
var _version: UInt32 = 0
static let defaultInstance = _StorageClass()

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -302,7 +302,7 @@ extension HardwareModel: CaseIterable {
.heltecWslV3,
.betafpv2400Tx,
.betafpv900NanoTx,
.privateHw,
.privateHw
]
}
@ -353,7 +353,7 @@ extension Constants: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
static var allCases: [Constants] = [
.zero,
.dataPayloadLen,
.dataPayloadLen
]
}
@ -476,7 +476,7 @@ extension CriticalErrorCode: CaseIterable {
.transmitFailed,
.brownout,
.sx1262Failure,
.radioSpiBug,
.radioSpiBug
]
}
@ -781,7 +781,7 @@ extension Position.LocSource: CaseIterable {
.locUnset,
.locManual,
.locInternal,
.locExternal,
.locExternal
]
}
@ -792,7 +792,7 @@ extension Position.AltSource: CaseIterable {
.altManual,
.altInternal,
.altExternal,
.altBarometric,
.altBarometric
]
}
@ -886,7 +886,7 @@ struct Routing {
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var variant: Routing.OneOf_Variant? = nil
var variant: Routing.OneOf_Variant?
///
/// A route request going from the requester
@ -1075,7 +1075,7 @@ extension Routing.Error: CaseIterable {
.noResponse,
.dutyCycleLimit,
.badRequest,
.notAuthorized,
.notAuthorized
]
}
@ -1503,7 +1503,7 @@ extension MeshPacket.Priority: CaseIterable {
.default,
.reliable,
.ack,
.max,
.max
]
}
@ -1512,7 +1512,7 @@ extension MeshPacket.Delayed: CaseIterable {
static var allCases: [MeshPacket.Delayed] = [
.noDelay,
.broadcast,
.direct,
.direct
]
}
@ -1591,9 +1591,9 @@ struct NodeInfo {
init() {}
fileprivate var _user: User? = nil
fileprivate var _position: Position? = nil
fileprivate var _deviceMetrics: DeviceMetrics? = nil
fileprivate var _user: User?
fileprivate var _position: Position?
fileprivate var _deviceMetrics: DeviceMetrics?
}
///
@ -1796,7 +1796,7 @@ extension LogRecord.Level: CaseIterable {
.warning,
.info,
.debug,
.trace,
.trace
]
}
@ -2102,7 +2102,7 @@ struct ToRadio {
///
/// Log levels, chosen to match python logging conventions.
var payloadVariant: ToRadio.OneOf_PayloadVariant? = nil
var payloadVariant: ToRadio.OneOf_PayloadVariant?
///
/// Send this packet on the mesh
@ -2308,7 +2308,7 @@ extension DeviceMetadata: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension HardwareModel: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
@ -2346,14 +2346,14 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding {
44: .same(proto: "HELTEC_WSL_V3"),
45: .same(proto: "BETAFPV_2400_TX"),
46: .same(proto: "BETAFPV_900_NANO_TX"),
255: .same(proto: "PRIVATE_HW"),
255: .same(proto: "PRIVATE_HW")
]
}
extension Constants: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "ZERO"),
237: .same(proto: "DATA_PAYLOAD_LEN"),
237: .same(proto: "DATA_PAYLOAD_LEN")
]
}
@ -2370,7 +2370,7 @@ extension CriticalErrorCode: SwiftProtobuf._ProtoNameProviding {
8: .same(proto: "TRANSMIT_FAILED"),
9: .same(proto: "BROWNOUT"),
10: .same(proto: "SX1262_FAILURE"),
11: .same(proto: "RADIO_SPI_BUG"),
11: .same(proto: "RADIO_SPI_BUG")
]
}
@ -2398,7 +2398,7 @@ extension Position: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
19: .standard(proto: "sats_in_view"),
20: .standard(proto: "sensor_id"),
21: .standard(proto: "next_update"),
22: .standard(proto: "seq_number"),
22: .standard(proto: "seq_number")
]
fileprivate class _StorageClass {
@ -2611,7 +2611,7 @@ extension Position.LocSource: SwiftProtobuf._ProtoNameProviding {
0: .same(proto: "LOC_UNSET"),
1: .same(proto: "LOC_MANUAL"),
2: .same(proto: "LOC_INTERNAL"),
3: .same(proto: "LOC_EXTERNAL"),
3: .same(proto: "LOC_EXTERNAL")
]
}
@ -2621,7 +2621,7 @@ extension Position.AltSource: SwiftProtobuf._ProtoNameProviding {
1: .same(proto: "ALT_MANUAL"),
2: .same(proto: "ALT_INTERNAL"),
3: .same(proto: "ALT_EXTERNAL"),
4: .same(proto: "ALT_BAROMETRIC"),
4: .same(proto: "ALT_BAROMETRIC")
]
}
@ -2633,7 +2633,7 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase,
3: .standard(proto: "short_name"),
4: .same(proto: "macaddr"),
5: .standard(proto: "hw_model"),
6: .standard(proto: "is_licensed"),
6: .standard(proto: "is_licensed")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2690,7 +2690,7 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase,
extension RouteDiscovery: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".RouteDiscovery"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "route"),
1: .same(proto: "route")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2724,7 +2724,7 @@ extension Routing: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "route_request"),
2: .standard(proto: "route_reply"),
3: .standard(proto: "error_reason"),
3: .standard(proto: "error_reason")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2815,7 +2815,7 @@ extension Routing.Error: SwiftProtobuf._ProtoNameProviding {
8: .same(proto: "NO_RESPONSE"),
9: .same(proto: "DUTY_CYCLE_LIMIT"),
32: .same(proto: "BAD_REQUEST"),
33: .same(proto: "NOT_AUTHORIZED"),
33: .same(proto: "NOT_AUTHORIZED")
]
}
@ -2829,7 +2829,7 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
5: .same(proto: "source"),
6: .standard(proto: "request_id"),
7: .standard(proto: "reply_id"),
8: .same(proto: "emoji"),
8: .same(proto: "emoji")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2903,7 +2903,7 @@ extension Waypoint: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
5: .standard(proto: "locked_to"),
6: .same(proto: "name"),
7: .same(proto: "description"),
8: .same(proto: "icon"),
8: .same(proto: "icon")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -2982,7 +2982,7 @@ extension MeshPacket: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
10: .standard(proto: "want_ack"),
11: .same(proto: "priority"),
12: .standard(proto: "rx_rssi"),
13: .same(proto: "delayed"),
13: .same(proto: "delayed")
]
fileprivate class _StorageClass {
@ -3160,7 +3160,7 @@ extension MeshPacket.Priority: SwiftProtobuf._ProtoNameProviding {
64: .same(proto: "DEFAULT"),
70: .same(proto: "RELIABLE"),
120: .same(proto: "ACK"),
127: .same(proto: "MAX"),
127: .same(proto: "MAX")
]
}
@ -3168,7 +3168,7 @@ extension MeshPacket.Delayed: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "NO_DELAY"),
1: .same(proto: "DELAYED_BROADCAST"),
2: .same(proto: "DELAYED_DIRECT"),
2: .same(proto: "DELAYED_DIRECT")
]
}
@ -3180,7 +3180,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
3: .same(proto: "position"),
4: .same(proto: "snr"),
5: .standard(proto: "last_heard"),
6: .standard(proto: "device_metrics"),
6: .standard(proto: "device_metrics")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3256,7 +3256,7 @@ extension MyNodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
13: .standard(proto: "air_period_rx"),
14: .standard(proto: "has_wifi"),
15: .standard(proto: "channel_utilization"),
16: .standard(proto: "air_util_tx"),
16: .standard(proto: "air_util_tx")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3366,7 +3366,7 @@ extension LogRecord: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
1: .same(proto: "message"),
2: .same(proto: "time"),
3: .same(proto: "source"),
4: .same(proto: "level"),
4: .same(proto: "level")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3418,7 +3418,7 @@ extension LogRecord.Level: SwiftProtobuf._ProtoNameProviding {
20: .same(proto: "INFO"),
30: .same(proto: "WARNING"),
40: .same(proto: "ERROR"),
50: .same(proto: "CRITICAL"),
50: .same(proto: "CRITICAL")
]
}
@ -3428,7 +3428,7 @@ extension QueueStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
1: .same(proto: "res"),
2: .same(proto: "free"),
3: .same(proto: "maxlen"),
4: .standard(proto: "mesh_packet_id"),
4: .standard(proto: "mesh_packet_id")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3487,7 +3487,7 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
10: .same(proto: "channel"),
11: .same(proto: "queueStatus"),
12: .same(proto: "xmodemPacket"),
13: .same(proto: "metadata"),
13: .same(proto: "metadata")
]
fileprivate class _StorageClass {
@ -3758,7 +3758,7 @@ extension ToRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
1: .same(proto: "packet"),
3: .standard(proto: "want_config_id"),
4: .same(proto: "disconnect"),
5: .same(proto: "xmodemPacket"),
5: .same(proto: "xmodemPacket")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3852,7 +3852,7 @@ extension Compressed: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
static let protoMessageName: String = _protobuf_package + ".Compressed"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "portnum"),
2: .same(proto: "data"),
2: .same(proto: "data")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3897,7 +3897,7 @@ extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
6: .same(proto: "hasEthernet"),
7: .same(proto: "role"),
8: .standard(proto: "position_flags"),
9: .standard(proto: "hw_model"),
9: .standard(proto: "hw_model")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -29,7 +29,7 @@ struct ModuleConfig {
///
/// TODO: REPLACE
var payloadVariant: ModuleConfig.OneOf_PayloadVariant? = nil
var payloadVariant: ModuleConfig.OneOf_PayloadVariant?
///
/// TODO: REPLACE
@ -829,7 +829,7 @@ extension ModuleConfig.AudioConfig.Audio_Baud: CaseIterable {
.codec21300,
.codec21200,
.codec2700,
.codec2700B,
.codec2700B
]
}
@ -851,7 +851,7 @@ extension ModuleConfig.SerialConfig.Serial_Baud: CaseIterable {
.baud230400,
.baud460800,
.baud576000,
.baud921600,
.baud921600
]
}
@ -862,7 +862,7 @@ extension ModuleConfig.SerialConfig.Serial_Mode: CaseIterable {
.simple,
.proto,
.textmsg,
.nmea,
.nmea
]
}
@ -876,7 +876,7 @@ extension ModuleConfig.CannedMessageConfig.InputEventChar: CaseIterable {
.right,
.select,
.back,
.cancel,
.cancel
]
}
@ -902,7 +902,7 @@ extension ModuleConfig.CannedMessageConfig.InputEventChar: @unchecked Sendable {
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension ModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".ModuleConfig"
@ -915,7 +915,7 @@ extension ModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
6: .same(proto: "telemetry"),
7: .standard(proto: "canned_message"),
8: .same(proto: "audio"),
9: .standard(proto: "remote_hardware"),
9: .standard(proto: "remote_hardware")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1108,7 +1108,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
3: .same(proto: "username"),
4: .same(proto: "password"),
5: .standard(proto: "encryption_enabled"),
6: .standard(proto: "json_enabled"),
6: .standard(proto: "json_enabled")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1165,7 +1165,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
extension ModuleConfig.RemoteHardwareConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = ModuleConfig.protoMessageName + ".RemoteHardwareConfig"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "enabled"),
1: .same(proto: "enabled")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1203,7 +1203,7 @@ extension ModuleConfig.AudioConfig: SwiftProtobuf.Message, SwiftProtobuf._Messag
4: .standard(proto: "i2s_ws"),
5: .standard(proto: "i2s_sd"),
6: .standard(proto: "i2s_din"),
7: .standard(proto: "i2s_sck"),
7: .standard(proto: "i2s_sck")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1272,7 +1272,7 @@ extension ModuleConfig.AudioConfig.Audio_Baud: SwiftProtobuf._ProtoNameProviding
5: .same(proto: "CODEC2_1300"),
6: .same(proto: "CODEC2_1200"),
7: .same(proto: "CODEC2_700"),
8: .same(proto: "CODEC2_700B"),
8: .same(proto: "CODEC2_700B")
]
}
@ -1285,7 +1285,7 @@ extension ModuleConfig.SerialConfig: SwiftProtobuf.Message, SwiftProtobuf._Messa
4: .same(proto: "txd"),
5: .same(proto: "baud"),
6: .same(proto: "timeout"),
7: .same(proto: "mode"),
7: .same(proto: "mode")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1361,7 +1361,7 @@ extension ModuleConfig.SerialConfig.Serial_Baud: SwiftProtobuf._ProtoNameProvidi
12: .same(proto: "BAUD_230400"),
13: .same(proto: "BAUD_460800"),
14: .same(proto: "BAUD_576000"),
15: .same(proto: "BAUD_921600"),
15: .same(proto: "BAUD_921600")
]
}
@ -1371,7 +1371,7 @@ extension ModuleConfig.SerialConfig.Serial_Mode: SwiftProtobuf._ProtoNameProvidi
1: .same(proto: "SIMPLE"),
2: .same(proto: "PROTO"),
3: .same(proto: "TEXTMSG"),
4: .same(proto: "NMEA"),
4: .same(proto: "NMEA")
]
}
@ -1391,7 +1391,7 @@ extension ModuleConfig.ExternalNotificationConfig: SwiftProtobuf.Message, SwiftP
12: .standard(proto: "alert_bell_vibra"),
13: .standard(proto: "alert_bell_buzzer"),
7: .standard(proto: "use_pwm"),
14: .standard(proto: "nag_timeout"),
14: .standard(proto: "nag_timeout")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1492,7 +1492,7 @@ extension ModuleConfig.StoreForwardConfig: SwiftProtobuf.Message, SwiftProtobuf.
2: .same(proto: "heartbeat"),
3: .same(proto: "records"),
4: .standard(proto: "history_return_max"),
5: .standard(proto: "history_return_window"),
5: .standard(proto: "history_return_window")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1546,7 +1546,7 @@ extension ModuleConfig.RangeTestConfig: SwiftProtobuf.Message, SwiftProtobuf._Me
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "enabled"),
2: .same(proto: "sender"),
3: .same(proto: "save"),
3: .same(proto: "save")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1594,7 +1594,7 @@ extension ModuleConfig.TelemetryConfig: SwiftProtobuf.Message, SwiftProtobuf._Me
4: .standard(proto: "environment_screen_enabled"),
5: .standard(proto: "environment_display_fahrenheit"),
6: .standard(proto: "air_quality_enabled"),
7: .standard(proto: "air_quality_interval"),
7: .standard(proto: "air_quality_interval")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1666,7 +1666,7 @@ extension ModuleConfig.CannedMessageConfig: SwiftProtobuf.Message, SwiftProtobuf
8: .standard(proto: "updown1_enabled"),
9: .same(proto: "enabled"),
10: .standard(proto: "allow_input_source"),
11: .standard(proto: "send_bell"),
11: .standard(proto: "send_bell")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1754,6 +1754,6 @@ extension ModuleConfig.CannedMessageConfig.InputEventChar: SwiftProtobuf._ProtoN
19: .same(proto: "LEFT"),
20: .same(proto: "RIGHT"),
24: .same(proto: "CANCEL"),
27: .same(proto: "BACK"),
27: .same(proto: "BACK")
]
}

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -52,7 +52,7 @@ struct ServiceEnvelope {
init() {}
fileprivate var _packet: MeshPacket? = nil
fileprivate var _packet: MeshPacket?
}
#if swift(>=5.5) && canImport(_Concurrency)
@ -61,14 +61,14 @@ extension ServiceEnvelope: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension ServiceEnvelope: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".ServiceEnvelope"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "packet"),
2: .standard(proto: "channel_id"),
3: .standard(proto: "gateway_id"),
3: .standard(proto: "gateway_id")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -238,7 +238,7 @@ extension PortNum: CaseIterable {
.tracerouteApp,
.privateApp,
.atakForwarder,
.max,
.max
]
}
@ -273,6 +273,6 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
70: .same(proto: "TRACEROUTE_APP"),
256: .same(proto: "PRIVATE_APP"),
257: .same(proto: "ATAK_FORWARDER"),
511: .same(proto: "MAX"),
511: .same(proto: "MAX")
]
}

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -125,7 +125,7 @@ extension HardwareMessage.TypeEnum: CaseIterable {
.watchGpios,
.gpiosChanged,
.readGpios,
.readGpiosReply,
.readGpiosReply
]
}
@ -138,14 +138,14 @@ extension HardwareMessage.TypeEnum: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension HardwareMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".HardwareMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "type"),
2: .standard(proto: "gpio_mask"),
3: .standard(proto: "gpio_value"),
3: .standard(proto: "gpio_value")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -191,6 +191,6 @@ extension HardwareMessage.TypeEnum: SwiftProtobuf._ProtoNameProviding {
2: .same(proto: "WATCH_GPIOS"),
3: .same(proto: "GPIOS_CHANGED"),
4: .same(proto: "READ_GPIOS"),
5: .same(proto: "READ_GPIOS_REPLY"),
5: .same(proto: "READ_GPIOS_REPLY")
]
}

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -42,12 +42,12 @@ extension RTTTLConfig: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension RTTTLConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".RTTTLConfig"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "ringtone"),
1: .same(proto: "ringtone")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -33,7 +33,7 @@ struct StoreAndForward {
///
/// TODO: REPLACE
var variant: StoreAndForward.OneOf_Variant? = nil
var variant: StoreAndForward.OneOf_Variant?
///
/// TODO: REPLACE
@ -345,7 +345,7 @@ extension StoreAndForward.RequestResponse: CaseIterable {
.clientStats,
.clientPing,
.clientPong,
.clientAbort,
.clientAbort
]
}
@ -362,7 +362,7 @@ extension StoreAndForward.Heartbeat: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension StoreAndForward: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".StoreAndForward"
@ -371,7 +371,7 @@ extension StoreAndForward: SwiftProtobuf.Message, SwiftProtobuf._MessageImplemen
2: .same(proto: "stats"),
3: .same(proto: "history"),
4: .same(proto: "heartbeat"),
5: .same(proto: "empty"),
5: .same(proto: "empty")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -486,7 +486,7 @@ extension StoreAndForward.RequestResponse: SwiftProtobuf._ProtoNameProviding {
66: .same(proto: "CLIENT_STATS"),
67: .same(proto: "CLIENT_PING"),
68: .same(proto: "CLIENT_PONG"),
106: .same(proto: "CLIENT_ABORT"),
106: .same(proto: "CLIENT_ABORT")
]
}
@ -501,7 +501,7 @@ extension StoreAndForward.Statistics: SwiftProtobuf.Message, SwiftProtobuf._Mess
6: .standard(proto: "requests_history"),
7: .same(proto: "heartbeat"),
8: .standard(proto: "return_max"),
9: .standard(proto: "return_window"),
9: .standard(proto: "return_window")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -575,7 +575,7 @@ extension StoreAndForward.History: SwiftProtobuf.Message, SwiftProtobuf._Message
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "history_messages"),
2: .same(proto: "window"),
3: .standard(proto: "last_request"),
3: .standard(proto: "last_request")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -618,7 +618,7 @@ extension StoreAndForward.Heartbeat: SwiftProtobuf.Message, SwiftProtobuf._Messa
static let protoMessageName: String = StoreAndForward.protoMessageName + ".Heartbeat"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "period"),
2: .same(proto: "secondary"),
2: .same(proto: "secondary")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -146,7 +146,7 @@ extension TelemetrySensorType: CaseIterable {
.qmi8658,
.qmc5883L,
.sht31,
.pmsa003I,
.pmsa003I
]
}
@ -291,7 +291,7 @@ struct Telemetry {
/// seconds since 1970
var time: UInt32 = 0
var variant: Telemetry.OneOf_Variant? = nil
var variant: Telemetry.OneOf_Variant?
///
/// Key native device metrics such as battery level
@ -374,7 +374,7 @@ extension Telemetry.OneOf_Variant: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
@ -391,7 +391,7 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding {
10: .same(proto: "QMI8658"),
11: .same(proto: "QMC5883L"),
12: .same(proto: "SHT31"),
13: .same(proto: "PMSA003I"),
13: .same(proto: "PMSA003I")
]
}
@ -401,7 +401,7 @@ extension DeviceMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa
1: .standard(proto: "battery_level"),
2: .same(proto: "voltage"),
3: .standard(proto: "channel_utilization"),
4: .standard(proto: "air_util_tx"),
4: .standard(proto: "air_util_tx")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -453,7 +453,7 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
3: .standard(proto: "barometric_pressure"),
4: .standard(proto: "gas_resistance"),
5: .same(proto: "voltage"),
6: .same(proto: "current"),
6: .same(proto: "current")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -521,7 +521,7 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
9: .standard(proto: "particles_10um"),
10: .standard(proto: "particles_25um"),
11: .standard(proto: "particles_50um"),
12: .standard(proto: "particles_100um"),
12: .standard(proto: "particles_100um")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -611,7 +611,7 @@ extension Telemetry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
1: .same(proto: "time"),
2: .standard(proto: "device_metrics"),
3: .standard(proto: "environment_metrics"),
4: .standard(proto: "air_quality_metrics"),
4: .standard(proto: "air_quality_metrics")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {

View file

@ -15,7 +15,7 @@ import SwiftProtobuf
// 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 {
private struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
@ -96,7 +96,7 @@ extension XModem.Control: CaseIterable {
.ack,
.nak,
.can,
.ctrlz,
.ctrlz
]
}
@ -109,7 +109,7 @@ extension XModem.Control: @unchecked Sendable {}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "meshtastic"
private let _protobuf_package = "meshtastic"
extension XModem: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".XModem"
@ -117,7 +117,7 @@ extension XModem: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas
1: .same(proto: "control"),
2: .same(proto: "seq"),
3: .same(proto: "crc16"),
4: .same(proto: "buffer"),
4: .same(proto: "buffer")
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -170,6 +170,6 @@ extension XModem.Control: SwiftProtobuf._ProtoNameProviding {
6: .same(proto: "ACK"),
21: .same(proto: "NAK"),
24: .same(proto: "CAN"),
26: .same(proto: "CTRLZ"),
26: .same(proto: "CTRLZ")
]
}

View file

@ -15,19 +15,19 @@ import ActivityKit
#endif
struct Connect: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
@State var node: NodeInfoEntity? = nil
@State var node: NodeInfoEntity?
@State var isUnsetRegion = false
@State var invalidFirmwareVersion = false
@State var liveActivityStarted = false
@State var presentingSwitchPreferredPeripheral = false
@State var selectedPeripherialId = ""
var body: some View {
NavigationStack {
VStack {
List {
@ -63,7 +63,7 @@ struct Connect: View {
.font(.caption).foregroundColor(Color.gray)
.padding([.top, .bottom])
.swipeActions {
Button(role: .destructive) {
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected {
bleManager.disconnectPeripheral(reconnect: false)
@ -72,8 +72,8 @@ struct Connect: View {
Label("disconnect", systemImage: "antenna.radiowaves.left.and.right.slash")
}
}
.contextMenu{
.contextMenu {
if node != nil {
#if !targetEnvironment(macCatalyst)
if #available(iOS 16.2, *) {
@ -114,7 +114,7 @@ struct Connect: View {
}
}
} else {
if bleManager.isConnecting {
HStack {
Image(systemName: "antenna.radiowaves.left.and.right")
@ -129,7 +129,7 @@ struct Connect: View {
.foregroundColor(.orange)
} else {
VStack {
Text("Connection Attempt \(bleManager.timeoutTimerCount) of 10")
.font(.callout)
.foregroundColor(.orange)
@ -137,9 +137,9 @@ struct Connect: View {
}
}
.padding()
} else {
if bleManager.lastConnectionError.count > 0 {
Text(bleManager.lastConnectionError).font(.callout).foregroundColor(.red)
}
@ -157,7 +157,7 @@ struct Connect: View {
}
}
.textCase(nil)
if !self.bleManager.isConnected {
Section(header: Text("available.radios").font(.title)) {
ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name > $1.name })) { peripheral in
@ -183,7 +183,7 @@ struct Connect: View {
}
}
.confirmationDialog("Connecting to a new radio will clear all local app data on the phone.", isPresented: $presentingSwitchPreferredPeripheral, titleVisibility: .visible) {
Button("Connect to new radio?", role: .destructive) {
bleManager.stopScanning()
bleManager.connectedPeripheral = nil
@ -191,9 +191,9 @@ struct Connect: View {
if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == CBPeripheralState.connected {
bleManager.disconnectPeripheral()
}
clearCoreDataDatabase(context: context)
let radio = bleManager.peripherals.first(where: { $0.peripheral.identifier.uuidString == selectedPeripherialId} )
let radio = bleManager.peripherals.first(where: { $0.peripheral.identifier.uuidString == selectedPeripherialId})
bleManager.connectTo(peripheral: radio!.peripheral)
presentingSwitchPreferredPeripheral = false
selectedPeripherialId = ""
@ -201,14 +201,14 @@ struct Connect: View {
}
.textCase(nil)
}
} else {
Text("bluetooth.off")
.foregroundColor(.red)
.font(.title)
}
}
HStack(alignment: .center) {
Spacer()
#if targetEnvironment(macCatalyst)
@ -236,23 +236,23 @@ struct Connect: View {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
}
.sheet(isPresented: $invalidFirmwareVersion, onDismiss: didDismissSheet) {
.sheet(isPresented: $invalidFirmwareVersion, onDismiss: didDismissSheet) {
InvalidVersion(minimumVersion: self.bleManager.minimumVersion, version: self.bleManager.connectedVersion)
.presentationDetents([.large])
.presentationDragIndicator(.automatic)
}
.onChange(of: (self.bleManager.invalidVersion)) { cv in
.onChange(of: (self.bleManager.invalidVersion)) { _ in
invalidFirmwareVersion = self.bleManager.invalidVersion
}
.onChange(of: (self.bleManager.isSubscribed)) { sub in
if userSettings.preferredPeripheralId.count > 0 && sub {
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(bleManager.connectedPeripheral?.num ?? -1))
do {
let fetchedNode = try context.fetch(fetchNodeInfoRequest) as! [NodeInfoEntity]
// Found a node, check it for a region
if !fetchedNode.isEmpty {
@ -264,14 +264,14 @@ struct Connect: View {
}
}
} catch {
}
}
}
.onAppear(perform: {
self.bleManager.context = context
self.bleManager.userSettings = userSettings
// Ask for notification permission
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success {
@ -287,17 +287,17 @@ struct Connect: View {
if #available(iOS 16.2, *) {
liveActivityStarted = true
let timerSeconds = 60
let mostRecent = node?.telemetries?.lastObject as! TelemetryEntity
let activityAttributes = MeshActivityAttributes(nodeNum: Int(node?.num ?? 0), name: node?.user?.longName ?? "unknown")
let future = Date(timeIntervalSinceNow: Double(timerSeconds))
let initialContentState = MeshActivityAttributes.ContentState(timerRange: Date.now...future, connected: true, channelUtilization: mostRecent.channelUtilization, airtime: mostRecent.airUtilTx, batteryLevel: UInt32(mostRecent.batteryLevel))
let activityContent = ActivityContent(state: initialContentState, staleDate: Calendar.current.date(byAdding: .minute, value: 2, to: Date())!)
do {
let myActivity = try Activity<MeshActivityAttributes>.request(attributes: activityAttributes, content: activityContent,
pushType: nil)
@ -307,7 +307,7 @@ struct Connect: View {
}
}
}
func endActivity() {
liveActivityStarted = false
Task {
@ -322,7 +322,7 @@ struct Connect: View {
}
}
#endif
#if os(iOS)
func postNotification() {
let timerSeconds = 60
@ -344,7 +344,7 @@ struct Connect: View {
}
}
#endif
func didDismissSheet() {
bleManager.disconnectPeripheral(reconnect: false)
}

View file

@ -7,20 +7,20 @@
import SwiftUI
struct InvalidVersion: View {
@Environment(\.dismiss) private var dismiss
@State var minimumVersion = ""
@State var version = ""
var body: some View {
VStack {
Text("update.firmware")
.font(.largeTitle)
.foregroundColor(.orange)
Divider()
VStack {
Text("The Meshtastic Apple apps support firmware version \(minimumVersion) and above.")
@ -36,7 +36,7 @@ struct InvalidVersion: View {
.padding()
Divider()
.padding(.top)
VStack{
VStack {
Text("🦕 End of life Version 🦖 ☄️")
.font(.title3)
.foregroundColor(.orange)
@ -46,20 +46,20 @@ struct InvalidVersion: View {
.padding([.leading, .trailing, .bottom])
Link("Version 1.2 End of life (EOL) Info", destination: URL(string: "https://meshtastic.org/docs/1.2-End-of-life/")!)
.font(.callout)
#if targetEnvironment(macCatalyst)
Button {
dismiss()
} label: {
Label("close", systemImage: "xmark")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
#endif
}.padding()
}
}

View file

@ -5,11 +5,11 @@
import SwiftUI
struct ContentView: View {
@EnvironmentObject var userSettings: UserSettings
@State private var selection: Tab = .ble
enum Tab {
case contacts
case messages
@ -18,11 +18,11 @@ struct ContentView: View {
case nodes
case settings
}
var body: some View {
TabView(selection: $selection) {
Contacts()
.tabItem {
Label("messages", systemImage: "message")

View file

@ -9,9 +9,7 @@ import SwiftUI
import Charts
struct BatteryGauge: View {
@State var batteryLevel = 0.0
private let minValue = 1.0
private let maxValue = 100.00
@ -24,7 +22,6 @@ struct BatteryGauge: View {
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
} else {
let gradient = Gradient(colors: [.red, .orange, .green])
Gauge(value: batteryLevel, in: minValue...maxValue) {
if batteryLevel > 1.0 && batteryLevel < 10 {
@ -52,7 +49,6 @@ struct BatteryGauge: View {
struct BatteryGauge_Previews: PreviewProvider {
static var previews: some View {
VStack {
BatteryGauge(batteryLevel: 0.0)
BatteryGauge(batteryLevel: 9.0)

View file

@ -13,9 +13,9 @@ struct CircleText: View {
var brightness: Double? = 0
var body: some View {
let font = Font.system(size: fontSize!)
ZStack {
Circle()
.fill(color)

View file

@ -14,16 +14,16 @@ import SwiftUI
//
struct DateTimeText: View {
var dateTime: Date?
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
var body: some View {
if (dateTime != nil && dateTime! >= sixMonthsAgo!){
if dateTime != nil && dateTime! >= sixMonthsAgo! {
Text("\(dateTime!, style: .date) \(dateTime!, style: .time)")
} else {
Text("unknown.age")
}
}

View file

@ -10,18 +10,18 @@ import CoreLocation
import MapKit
struct DistanceText: View {
var meters: CLLocationDistance
var body: some View {
let distanceFormatter = MKDistanceFormatter()
Text("distance")+Text(": \(distanceFormatter.string(fromDistance: Double(meters)))")
}
}
struct DistanceText_Previews: PreviewProvider {
static var previews: some View {
VStack {
DistanceText(meters: 100)
DistanceText(meters: 1000)

View file

@ -9,7 +9,7 @@ struct LastHeardText: View {
var lastHeard: Date?
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
var body: some View {
if (lastHeard != nil && lastHeard! >= sixMonthsAgo!){
if lastHeard != nil && lastHeard! >= sixMonthsAgo! {
Text("heard")+Text(": \(lastHeard!, style: .relative) ")+Text("ago")
} else {
Text("unknown.age")

View file

@ -7,11 +7,11 @@
import SwiftUI
struct MeshtasticLogo: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
#if targetEnvironment(macCatalyst)
VStack {
Image("logo-white")

View file

@ -7,16 +7,16 @@
import SwiftUI
struct MessageTemplate: View {
var user: UserEntity
var message: MessageEntity
var messageReply: MessageEntity?
var body: some View {
// Display the message being replied to and the arrow
if message.replyID > 0 {
HStack {
Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.blue).font(.caption2)
@ -31,8 +31,8 @@ struct MessageTemplate: View {
.padding(.trailing)
}
}
// Message
}
}

View file

@ -3,13 +3,13 @@ import SwiftUI
struct NodeAnnotation: View {
let time: Date
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
var body: some View {
if (time >= sixMonthsAgo!) {
if time >= sixMonthsAgo! {
VStack(spacing: 0) {
Text(time, style: .offset)
.font(.caption2).foregroundColor(.accentColor)
@ -17,9 +17,9 @@ struct NodeAnnotation: View {
.background(Color(.white))
.cornerRadius(10)
}
} else {
VStack(spacing: 0) {
Text("unknown.age")
.font(.caption2).foregroundColor(.accentColor)

View file

@ -33,7 +33,7 @@ import SwiftUI
struct SignalStrengthIndicator: View {
let signalStrength: SignalStrength
var body: some View {
HStack {
ForEach(0..<3) { bar in
@ -44,7 +44,7 @@ struct SignalStrengthIndicator: View {
}
}
}
private func getColor() -> Color {
switch signalStrength {
case .weak:
@ -71,7 +71,7 @@ extension Shape {
}
}
enum SignalStrength : Int {
enum SignalStrength: Int {
case weak = 0
case normal = 1
case strong = 2

View file

@ -10,14 +10,13 @@ struct AirQualityIndexCompact: View {
var aqi: Int
var body: some View {
HStack (spacing: 0.5) {
HStack(spacing: 0.5) {
Text("AQI \(aqi)")
.foregroundColor(.gray)
.padding(.trailing, 0)
.font(.caption)
if aqi > 0 && aqi < 51 {
// Good
Circle()
@ -38,7 +37,7 @@ struct AirQualityIndexCompact: View {
Circle()
.fill(.orange)
.frame(width: 10, height: 10)
} else if aqi > 300 && aqi < 401 {
// Very Poor
Circle()
@ -55,7 +54,7 @@ struct AirQualityIndexCompact: View {
}
struct AQICircleDisplay_Previews: PreviewProvider {
static var previews: some View {
VStack {
AirQualityIndexCompact(aqi: 5)
AirQualityIndexCompact(aqi: 51)

View file

@ -19,7 +19,7 @@ struct CurrentConditionsCompact: View {
}
struct CurrentConditionsCompact_Previews: PreviewProvider {
static var previews: some View {
VStack {
CurrentConditionsCompact(temp: 22, condition: WeatherConditions.clear)
CurrentConditionsCompact(temp: 17, condition: WeatherConditions.cloudy)

View file

@ -12,15 +12,15 @@ import WeatherKit
struct NodeWeatherForecastView: View {
var location: CLLocation
@State private var forecast: NodeWeatherForecast = placeholderForecast
var body: some View {
VStack {
chart
.frame(width: 400)
}
//.frame(width: 350, height: 200)
// .frame(width: 350, height: 200)
.padding(10)
.background()
.task {
@ -38,12 +38,12 @@ struct NodeWeatherForecastView: View {
}
}
}
var chart: some View {
Chart {
areaMarks(seriesKey: "Temperature", value: 0)
.foregroundStyle(.linearGradient(colors: [.teal, .yellow], startPoint: .bottom, endPoint: .top))
ForEach(forecast.nightTimeRanges, id: \.lowerBound) { range in
RectangleMark(
xStart: .value("Hour", range.lowerBound),
@ -53,7 +53,7 @@ struct NodeWeatherForecastView: View {
.mask {
areaMarks(seriesKey: "Mask", value: range.lowerBound.timeIntervalSince1970)
}
if range.lowerBound != forecast.entries.first!.date {
let date = range.lowerBound
RectangleMark(
@ -71,7 +71,7 @@ struct NodeWeatherForecastView: View {
.foregroundStyle(.white, .indigo)
}
}
if range.upperBound != forecast.entries.last!.date {
let date = range.upperBound
RectangleMark(
@ -107,7 +107,7 @@ struct NodeWeatherForecastView: View {
}
}
}
@ChartContentBuilder
func areaMarks(seriesKey: String, value: Double) -> some ChartContent {
ForEach(forecast.entries) { entry in
@ -120,14 +120,14 @@ struct NodeWeatherForecastView: View {
.interpolationMethod(.catmullRom)
}
}
static var placeholderForecast: NodeWeatherForecast {
func entry(hourOffset: Int, degrees: Double, isDaylight: Bool) -> NodeWeatherForecast.WeatherEntry {
let startDate = Calendar.current.date(from: DateComponents(year: 2022, month: 5, day: 6, hour: 9))!
let date = Calendar.current.date(byAdding: DateComponents(hour: hourOffset), to: startDate)!
return NodeWeatherForecast.WeatherEntry(date: date, degrees: degrees, isDaylight: isDaylight)
}
return NodeWeatherForecast(entries: [
entry(hourOffset: 0, degrees: 63, isDaylight: true),
entry(hourOffset: 1, degrees: 68, isDaylight: true),
@ -165,17 +165,17 @@ struct NodeWeatherForecast {
var degrees: Double
var isDaylight: Bool
}
var entries: [WeatherEntry]
var low: Double {
return entries.map(\.degrees).min()! - 2
}
var hottestEntry: WeatherEntry {
return entries.sorted { $0.degrees > $1.degrees }.first!
}
var nightTimeRanges: [Range<Date>] {
var currentLowerBound: Date?
var results: [Range<Date>] = []
@ -192,7 +192,7 @@ struct NodeWeatherForecast {
}
return results
}
var binRange: ClosedRange<Date> {
let startDate: Date = entries.map(\.date).first(where: {
Calendar.current.component(.hour, from: $0).isMultiple(of: 3)
@ -202,7 +202,7 @@ struct NodeWeatherForecast {
})!
return startDate ... endDate
}
func temperature(at date: Date) -> Double {
entries.first(where: { $0.date == date })!.degrees
}

View file

@ -25,10 +25,10 @@ extension MKMapRect {
left = min(left, coordinate.longitude)
right = max(right, coordinate.longitude)
}
let topLeft = MKMapPoint(CLLocationCoordinate2D(latitude:top, longitude:left))
let bottomRight = MKMapPoint(CLLocationCoordinate2D(latitude:bottom, longitude:right))
self = MKMapRect(x:topLeft.x, y:topLeft.y,
width:bottomRight.x - topLeft.x, height:bottomRight.y - topLeft.y)
let topLeft = MKMapPoint(CLLocationCoordinate2D(latitude: top, longitude: left))
let bottomRight = MKMapPoint(CLLocationCoordinate2D(latitude: bottom, longitude: right))
self = MKMapRect(x: topLeft.x, y: topLeft.y,
width: bottomRight.x - topLeft.x, height: bottomRight.y - topLeft.y)
}
}
}
@ -48,32 +48,32 @@ class LocalMBTileOverlay: MKTileOverlay {
return _boundingMapRect
}
}
init?(mbTilePath path: String) {
super.init(urlTemplate: nil)
self.path = path
do {
self.mb = try Connection(self.path, readonly: true)
let metadata = Table("metadata")
let name = Expression<String>("name")
let value = Expression<String>("value")
//make sure it's raster
// make sure it's raster
let formatQuery = try mb.pluck(metadata.select(value).filter(name == "format"))
if formatQuery?[value] == nil || (formatQuery![value] != "jpg" && formatQuery![value] != "png") {
throw MapTileError.invalidFormat
}
let minZQuery = try mb.pluck(metadata.select(value).filter(name == "minzoom"))
self.minimumZ = Int(minZQuery![value])!
let maxZQuery = try mb.pluck(metadata.select(value).filter(name == "maxzoom"))
self.maximumZ = Int(maxZQuery![value])!
self.isGeometryFlipped = true
let boundingBoxString = try mb.pluck(metadata.select(value).filter(name == "bounds"))
let boundCoords = boundingBoxString![value].split(separator: ",")
let coords = [
@ -83,15 +83,15 @@ class LocalMBTileOverlay: MKTileOverlay {
longitude: Double(boundCoords[2]) ?? 0)
]
self._boundingMapRect = MKMapRect(coordinates: coords)
} catch {
print("💥 Map tile error: \(error)")
return nil
}
}
override func loadTile(at path: MKTileOverlayPath, result: @escaping (Data?, Error?) -> Void) {
let tileX = Int64(path.x)
let tileY = Int64(path.y)
let tileZ = Int64(path.z)
@ -99,9 +99,9 @@ class LocalMBTileOverlay: MKTileOverlay {
let zoomLevel = Expression<Int64>("zoom_level")
let tileColumn = Expression<Int64>("tile_column")
let tileRow = Expression<Int64>("tile_row")
if let dataQuery = try? self.mb.pluck(Table("tiles").select(tileData).filter(zoomLevel == tileZ).filter(tileColumn == tileX).filter(tileRow == tileY)) {
let data = Data(bytes: dataQuery[tileData].bytes, count: dataQuery[tileData].bytes.count)//dataQuery![tileData].bytes
let data = Data(bytes: dataQuery[tileData].bytes, count: dataQuery[tileData].bytes.count)// dataQuery![tileData].bytes
result(data, nil)
} else {
print("💥 No tile here: x:\(tileX) y:\(tileY) z:\(tileZ)")

View file

@ -8,7 +8,7 @@
import MapKit
extension MKMapView {
func fitAllAnnotations(with padding: UIEdgeInsets = UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100)) {
var zoomRect: MKMapRect = .null
annotations.forEach({
@ -16,10 +16,10 @@ extension MKMapView {
let pointRect = MKMapRect(x: annotationPoint.x, y: annotationPoint.y, width: 0.01, height: 0.01)
zoomRect = zoomRect.union(pointRect)
})
setVisibleMapRect(zoomRect, edgePadding: padding, animated: true)
}
func fit(annotations: [MKAnnotation], andShow show: Bool, with padding: UIEdgeInsets = UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100)) {
var zoomRect: MKMapRect = .null
annotations.forEach({
@ -27,11 +27,11 @@ extension MKMapView {
let rect = MKMapRect(x: aPoint.x, y: aPoint.y, width: 0.1, height: 0.1)
zoomRect = zoomRect.isNull ? rect : zoomRect.union(rect)
})
if show {
addAnnotations(annotations)
}
setVisibleMapRect(zoomRect, edgePadding: padding, animated: true)
}
}

View file

@ -4,12 +4,12 @@
////
//// Created by Cem Yilmaz on 05.07.21.
////
//import SwiftUI
//import MapKit
//import CoreData
// import SwiftUI
// import MapKit
// import CoreData
//
//#if canImport(MapKit) && canImport(UIKit)
//public struct MapView: UIViewRepresentable {
// #if canImport(MapKit) && canImport(UIKit)
// public struct MapView: UIViewRepresentable {
//
// @Environment(\.managedObjectContext) var context
//
@ -463,7 +463,7 @@
// }
// }
//
//}
// }
//
//// MARK: End of implementation
//#endif
// MARK: End of implementation
// #endif

View file

@ -12,7 +12,7 @@ func degreesToRadians(_ number: Double) -> Double {
}
struct MapViewSwiftUI: UIViewRepresentable {
var onLongPress: (_ waypointCoordinate: CLLocationCoordinate2D) -> Void
var onWaypointEdit: (_ waypointId: Int ) -> Void
let mapView = MKMapView()
@ -21,19 +21,19 @@ struct MapViewSwiftUI: UIViewRepresentable {
let mapViewType: MKMapType
let userTrackingMode: MKUserTrackingMode
let centeringMode: CenteringMode
let centerOnPositionsOnly: Bool
@AppStorage("meshMapRecentering") private var recenter: Bool = false
// Offline Maps
//make this view dependent on the UserDefault that is updated when importing a new map file
// make this view dependent on the UserDefault that is updated when importing a new map file
@AppStorage("lastUpdatedLocalMapFile") private var lastUpdatedLocalMapFile = 0
@State private var loadedLastUpdatedLocalMapFile = 0
var customMapOverlay: CustomMapOverlay?
@State private var presentCustomMapOverlayHash: CustomMapOverlay?
var overlays: [Overlay] = []
let dynamicRegion: Bool = true
func makeUIView(context: Context) -> MKMapView {
// Map View Parameters
mapView.mapType = mapViewType
@ -63,7 +63,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
mapView.addAnnotations(positions)
}
}
// Other MKMapView Settings
mapView.preferredConfiguration.elevationStyle = .realistic// .flat
mapView.isPitchEnabled = true
@ -73,14 +73,14 @@ struct MapViewSwiftUI: UIViewRepresentable {
mapView.showsBuildings = true
mapView.showsScale = true
mapView.showsTraffic = true
#if targetEnvironment(macCatalyst)
// Show the default always visible compass and the mac only controls
mapView.showsCompass = true
mapView.showsZoomControls = true
mapView.showsPitchControl = true
#else
#if os(iOS)
// Hide the default compass that only appears when you are not going north and instead always show the compass in the bottom right corner of the map
mapView.showsCompass = false
@ -91,26 +91,26 @@ struct MapViewSwiftUI: UIViewRepresentable {
compassButton.trailingAnchor.constraint(equalTo: mapView.trailingAnchor, constant: -5).isActive = true
compassButton.bottomAnchor.constraint(equalTo: mapView.bottomAnchor, constant: -25).isActive = true
#endif
#endif
mapView.delegate = context.coordinator
return mapView
}
func updateUIView(_ mapView: MKMapView, context: Context) {
mapView.mapType = mapViewType
if self.customMapOverlay != self.presentCustomMapOverlayHash || self.loadedLastUpdatedLocalMapFile != self.lastUpdatedLocalMapFile {
mapView.removeOverlays(mapView.overlays)
if self.customMapOverlay != nil {
let fileManager = FileManager.default
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let tilePath = documentsDirectory.appendingPathComponent("offline_map.mbtiles", isDirectory: false).path
if fileManager.fileExists(atPath: tilePath) {
print("Loading local map file")
if let overlay = LocalMBTileOverlay(mbTilePath: tilePath) {
overlay.canReplaceMapContent = false//customMapOverlay.canReplaceMapContent
overlay.canReplaceMapContent = false// customMapOverlay.canReplaceMapContent
mapView.addOverlay(overlay)
}
} else {
@ -122,9 +122,9 @@ struct MapViewSwiftUI: UIViewRepresentable {
self.loadedLastUpdatedLocalMapFile = self.lastUpdatedLocalMapFile
}
}
DispatchQueue.main.async {
let annotationCount = waypoints.count + positions.count
if annotationCount != mapView.annotations.count {
mapView.removeAnnotations(mapView.annotations)
@ -151,17 +151,17 @@ struct MapViewSwiftUI: UIViewRepresentable {
}
}
}
func makeCoordinator() -> MapCoordinator {
return Coordinator(self)
}
final class MapCoordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate {
var parent: MapViewSwiftUI
var longPressRecognizer = UILongPressGestureRecognizer()
var overlays: [Overlay] = []
init(_ parent: MapViewSwiftUI) {
self.parent = parent
super.init()
@ -172,22 +172,21 @@ struct MapViewSwiftUI: UIViewRepresentable {
self.parent.mapView.addGestureRecognizer(longPressRecognizer)
self.overlays = []
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
switch annotation {
case let positionAnnotation as PositionEntity:
let reuseID = String(positionAnnotation.nodePosition?.num ?? 0) + "-" + String(positionAnnotation.time?.timeIntervalSince1970 ?? 0)
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "node") as? MKMarkerAnnotationView ?? MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseID )
annotationView.tag = -1
annotationView.canShowCallout = true
if positionAnnotation.latest {
annotationView.markerTintColor = .systemRed
annotationView.displayPriority = .required
annotationView.titleVisibility = .visible
}
else {
} else {
annotationView.markerTintColor = UIColor(.indigo)
annotationView.displayPriority = .defaultHigh
annotationView.titleVisibility = .adaptive
@ -205,10 +204,10 @@ struct MapViewSwiftUI: UIViewRepresentable {
let distanceFormatter = MKDistanceFormatter()
subtitle.text! += "Altitude: \(distanceFormatter.string(fromDistance: Double(positionAnnotation.altitude))) \n"
if positionAnnotation.nodePosition?.metadata != nil {
if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.client ||
DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.clientMute ||
DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.routerClient{
DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.routerClient {
annotationView.glyphImage = UIImage(systemName: "flipphone")
} else if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.repeater {
annotationView.glyphImage = UIImage(systemName: "repeat")
@ -219,7 +218,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
} else if DeviceRoles(rawValue: Int(positionAnnotation.nodePosition!.metadata?.role ?? 0)) == DeviceRoles.sensor {
annotationView.glyphImage = UIImage(systemName: "sensor")
}
let pf = PositionFlags(rawValue: Int(positionAnnotation.nodePosition?.metadata?.positionFlags ?? 3))
if pf.contains(.Satsinview) {
subtitle.text! += "Sats in view: \(String(positionAnnotation.satsInView)) \n"
@ -227,8 +226,8 @@ struct MapViewSwiftUI: UIViewRepresentable {
if pf.contains(.SeqNo) {
subtitle.text! += "Sequence: \(String(positionAnnotation.seqNo)) \n"
}
if pf.contains(.Heading){
if pf.contains(.Heading) {
if parent.userTrackingMode != MKUserTrackingMode.followWithHeading {
annotationView.glyphImage = UIImage(systemName: "location.north.fill")?.rotate(radians: Float(degreesToRadians(Double(positionAnnotation.heading))))
subtitle.text! += "Heading: \(String(positionAnnotation.heading)) \n"
@ -244,7 +243,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
}
subtitle.text! += "Speed: \(formatter.string(from: Measurement(value: Double(positionAnnotation.speed), unit: UnitSpeed.kilometersPerHour))) \n"
}
} else {
// node metadata is nil
annotationView.glyphImage = UIImage(systemName: "flipphone")
@ -279,8 +278,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
let subtitle = UILabel()
if waypointAnnotation.longDescription?.count ?? 0 > 0 {
subtitle.text = (waypointAnnotation.longDescription ?? "") + "\n"
}
else {
} else {
subtitle.text = ""
}
if LocationHelper.currentLocation.distance(from: LocationHelper.DefaultLocation) > 0.0 {
@ -306,23 +304,23 @@ struct MapViewSwiftUI: UIViewRepresentable {
default: return nil
}
}
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)
}
}
@objc func longPressHandler(_ gesture: UILongPressGestureRecognizer) {
if gesture.state != UIGestureRecognizer.State.ended {
return
} else if gesture.state != UIGestureRecognizer.State.began {
// Screen Position - CGPoint
let location = longPressRecognizer.location(in: self.parent.mapView)
// Map Coordinate - CLLocationCoordinate2D
let coordinate = self.parent.mapView.convert(location, toCoordinateFrom: self.parent.mapView)
let annotation = MKPointAnnotation()
@ -333,11 +331,11 @@ struct MapViewSwiftUI: UIViewRepresentable {
parent.onLongPress(coordinate)
}
}
public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let index = self.overlays.firstIndex(where: { overlay_ in overlay_.shape.hash == overlay.hash }) {
let unwrappedOverlay = self.overlays[index]
if let circleOverlay = unwrappedOverlay.shape as? MKCircle {
let renderer = MKCircleRenderer(circle: circleOverlay)
@ -379,18 +377,18 @@ struct MapViewSwiftUI: UIViewRepresentable {
}
}
}
/// is supposed to be located in the folder with the map name
public struct DefaultTile: Hashable {
let tileName: String
let tileType: String
public init(tileName: String, tileType: String) {
self.tileName = tileName
self.tileType = tileType
}
}
public struct CustomMapOverlay: Equatable, Hashable {
let mapName: String
let tileType: String
@ -398,7 +396,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
var minimumZoomLevel: Int?
var maximumZoomLevel: Int?
let defaultTile: DefaultTile?
public init(
mapName: String,
tileType: String,
@ -414,7 +412,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
self.maximumZoomLevel = maximumZoomLevel
self.defaultTile = defaultTile
}
public init?(
mapName: String?,
tileType: String,
@ -423,7 +421,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
maximumZoomLevel: Int? = nil,
defaultTile: DefaultTile? = nil
) {
if (mapName == nil || mapName! == "") {
if mapName == nil || mapName! == "" {
return nil
}
self.mapName = mapName!
@ -434,15 +432,15 @@ struct MapViewSwiftUI: UIViewRepresentable {
self.defaultTile = defaultTile
}
}
public class CustomMapOverlaySource: MKTileOverlay {
// requires folder: tiles/{mapName}/z/y/y,{tileType}
private var parent: MapViewSwiftUI
private let mapName: String
private let tileType: String
private let defaultTile: DefaultTile?
public init(
parent: MapViewSwiftUI,
mapName: String,
@ -455,7 +453,7 @@ struct MapViewSwiftUI: UIViewRepresentable {
self.defaultTile = defaultTile
super.init(urlTemplate: "")
}
public override func url(forTilePath path: MKTileOverlayPath) -> URL {
if let tileUrl = Bundle.main.url(
forResource: "\(path.y)",
@ -477,21 +475,21 @@ struct MapViewSwiftUI: UIViewRepresentable {
}
}
}
public struct Overlay {
public static func == (lhs: MapViewSwiftUI.Overlay, rhs: MapViewSwiftUI.Overlay) -> Bool {
// maybe to use in the future for comparison of full array
lhs.shape.coordinate.latitude == rhs.shape.coordinate.latitude &&
lhs.shape.coordinate.longitude == rhs.shape.coordinate.longitude &&
lhs.fillColor == rhs.fillColor
}
var shape: MKOverlay
var fillColor: UIColor?
var strokeColor: UIColor?
var lineWidth: CGFloat
public init(
shape: MKOverlay,
fillColor: UIColor? = nil,

View file

@ -5,12 +5,12 @@
//// Created by Joshua Pirihi on 24/12/21.
////
//
//import UIKit
//import MapKit
//import SwiftUI
// import UIKit
// import MapKit
// import SwiftUI
//
//// a simple circle annotation, with a string in it
//class PositionAnnotation: NSObject, MKAnnotation {
// class PositionAnnotation: NSObject, MKAnnotation {
//
// // This property must be key-value observable, which the `@objc dynamic` attributes provide.
// @objc dynamic var coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
@ -22,9 +22,9 @@
// // the text to appear inside the little circle
// var shortName: String?
//
//}
// }
//
//class PositionAnnotationView: MKAnnotationView {
// class PositionAnnotationView: MKAnnotationView {
//
// private let annotationFrame = CGRect(x: 0, y: 0, width: 40, height: 40)
// private let label: UILabel
@ -57,4 +57,4 @@
// context.setFillColor(Color.accentColor.cgColor ?? CGColor(red: 0, green: 0.5, blue: 1.0, alpha: 1.0))
// context.fillEllipse(in: circleRect)
// }
//}
// }

View file

@ -9,14 +9,14 @@ import SwiftUI
import CoreLocation
struct WaypointFormView: View {
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var dismiss
@State var coordinate: CLLocationCoordinate2D
@State var waypointId : Int = 0
@State var waypointId: Int = 0
@FocusState private var iconIsFocused: Bool
@State private var name: String = ""
@State private var description: String = ""
@State private var icon: String = "📍"
@ -26,9 +26,9 @@ struct WaypointFormView: View {
@State private var expire: Date = Date() // = Date.now.addingTimeInterval(60 * 120) // 1 minute * 120 = 2 Hours
@State private var locked: Bool = false
@State private var lockedTo: Int64 = 0
var body: some View {
Form {
let distance = CLLocation(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude).distance(from: CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude))
Section(header: Text((waypointId > 0) ? "Editing Waypoint" : "Create Waypoint")) {
@ -52,7 +52,7 @@ struct WaypointFormView: View {
axis: .vertical
)
.foregroundColor(Color.gray)
.onChange(of: name, perform: { value in
.onChange(of: name, perform: { _ in
let totalBytes = name.utf8.count
// Only mess with the value if it is too big
if totalBytes > 30 {
@ -73,7 +73,7 @@ struct WaypointFormView: View {
axis: .vertical
)
.foregroundColor(Color.gray)
.onChange(of: description, perform: { value in
.onChange(of: description, perform: { _ in
let totalBytes = description.utf8.count
// Only mess with the value if it is too big
if totalBytes > 100 {
@ -92,14 +92,14 @@ struct WaypointFormView: View {
.font(.title)
.focused($iconIsFocused)
.onChange(of: icon) { value in
// If you have anything other than emojis in your string make it empty
if !value.onlyEmojis() {
icon = ""
}
// If a second emoji is entered delete the first one
if value.count >= 1 {
if value.count > 1 {
let index = value.index(value.startIndex, offsetBy: 1)
icon = String(value[index])
@ -107,7 +107,7 @@ struct WaypointFormView: View {
iconIsFocused = false
}
}
}
Toggle(isOn: $expires) {
Label("Expires", systemImage: "clock.badge.xmark")
@ -126,9 +126,9 @@ struct WaypointFormView: View {
}
HStack {
Button {
var newWaypoint = Waypoint()
if waypointId > 0 {
newWaypoint.id = UInt32(waypointId)
} else {
@ -144,7 +144,7 @@ struct WaypointFormView: View {
let unicode = unicodeScalers[unicodeScalers.startIndex].value
newWaypoint.icon = unicode
if locked {
if lockedTo == 0 {
newWaypoint.lockedTo = UInt32(bleManager.connectedPeripheral!.num)
} else {
@ -172,8 +172,8 @@ struct WaypointFormView: View {
.controlSize(.large)
.disabled(bleManager.connectedPeripheral == nil)
.padding(.bottom)
Button(role:.cancel) {
Button(role: .cancel) {
dismiss()
} label: {
Label("cancel", systemImage: "x.circle")
@ -184,7 +184,7 @@ struct WaypointFormView: View {
.padding(.bottom)
if waypointId > 0 {
Menu {
Button("For me", action: {
let waypoint = getWaypoint(id: Int64(waypointId), context: bleManager.context!)
@ -197,10 +197,10 @@ struct WaypointFormView: View {
dismiss() })
Button("For everyone", action: {
var newWaypoint = Waypoint()
if waypointId > 0 {
newWaypoint.id = UInt32(waypointId)
}
}
newWaypoint.name = name.count > 0 ? name : "Dropped Pin"
newWaypoint.description_p = description
newWaypoint.latitudeI = Int32(coordinate.latitude * 1e7)
@ -211,7 +211,7 @@ struct WaypointFormView: View {
let unicode = unicodeScalers[unicodeScalers.startIndex].value
newWaypoint.icon = unicode
if locked {
if lockedTo == 0 {
newWaypoint.lockedTo = UInt32(bleManager.connectedPeripheral!.num)
} else {
@ -241,7 +241,7 @@ struct WaypointFormView: View {
}
.onChange(of: waypointId) { newId in
print(newId)
}
.onAppear {
if waypointId > 0 {

View file

@ -9,27 +9,27 @@ import SwiftUI
import CoreData
struct ChannelMessageList: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
enum Field: Hashable {
case messageText
}
// Keyboard State
@State var typingMessage: String = ""
@State private var totalBytes = 0
var maxbytes = 228
@FocusState var focusedField: Field?
@ObservedObject var channel: ChannelEntity
@State var showDeleteMessageAlert = false
@State private var deleteMessageId: Int64 = 0
@State private var replyMessageId: Int64 = 0
@State private var sendPositionWithMessage: Bool = false
var body: some View {
NavigationStack {
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmmssa", options: 0, locale: Locale.current)
@ -54,8 +54,8 @@ struct ChannelMessageList: View {
.padding(.trailing)
}
}
HStack (alignment: .top) {
if currentUser { Spacer(minLength:50) }
HStack(alignment: .top) {
if currentUser { Spacer(minLength: 50) }
if !currentUser {
CircleText(text: message.fromUser?.shortName ?? "????", color: currentUser ? .accentColor : Color(.gray), circleSize: 44, fontSize: 14)
.padding(.all, 5)
@ -71,7 +71,7 @@ struct ChannelMessageList: View {
.background(currentUser ? .accentColor : Color(.gray))
.cornerRadius(15)
.contextMenu {
VStack{
VStack {
Text("channel")+Text(": \(message.channel)")
}
Menu("tapback") {
@ -81,7 +81,7 @@ struct ChannelMessageList: View {
print("Sent \(tb.emojiString) Tapback")
self.context.refresh(channel, mergeChanges: true)
} else { print("\(tb.emojiString) Tapback Failed") }
}) {
Text(tb.description)
let image = tb.emojiString.image()
@ -152,11 +152,11 @@ struct ChannelMessageList: View {
Image(systemName: "trash")
}
}
let tapbacks = message.value(forKey: "tapbacks") as! [MessageEntity]
if tapbacks.count > 0 {
VStack (alignment: .trailing) {
HStack {
VStack(alignment: .trailing) {
HStack {
ForEach( tapbacks ) { (tapback: MessageEntity) in
VStack {
let image = tapback.messagePayload!.image(fontSize: 20)
@ -193,7 +193,7 @@ struct ChannelMessageList: View {
.padding(.bottom)
.id(channel.allPrivateMessages.firstIndex(of: message))
if !currentUser {
Spacer(minLength:50)
Spacer(minLength: 50)
}
}
.padding([.leading, .trailing])
@ -225,7 +225,7 @@ struct ChannelMessageList: View {
scrollView.scrollTo(channel.allPrivateMessages.last!.messageId)
}
})
.onChange(of: channel.allPrivateMessages, perform: { messages in
.onChange(of: channel.allPrivateMessages, perform: { _ in
if channel.allPrivateMessages.count > 0 {
scrollView.scrollTo(channel.allPrivateMessages.last!.messageId)
}
@ -238,14 +238,14 @@ struct ChannelMessageList: View {
let userLongName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown"
sendPositionWithMessage = true
if userSettings.meshtasticUsername.count > 0 {
typingMessage = "📍 " + userSettings.meshtasticUsername + " has shared their position with you from node " + userLongName
} else {
typingMessage = "📍 " + userLongName + " has shared their position with you."
}
} label: {
Text("share.position")
Image(systemName: "mappin.and.ellipse")
@ -261,7 +261,7 @@ struct ChannelMessageList: View {
}
#endif
HStack(alignment: .top) {
ZStack {
let kbType = UIKeyboardType(rawValue: UserDefaults.standard.object(forKey: "keyboardType") as? Int ?? 0)
TextField("message", text: $typingMessage, axis: .vertical)
@ -290,20 +290,20 @@ struct ChannelMessageList: View {
let userLongName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown"
sendPositionWithMessage = true
if userSettings.meshtasticUsername.count > 0 {
typingMessage = "📍 " + userSettings.meshtasticUsername + " has shared their position with you from node " + userLongName
} else {
typingMessage = "📍 " + userLongName + " has shared their position with you."
}
} label: {
Image(systemName: "mappin.and.ellipse")
.symbolRenderingMode(.hierarchical)
.imageScale(.large).foregroundColor(.accentColor)
}
ProgressView("\(NSLocalizedString("bytes", comment: "")): \(totalBytes) / \(maxbytes)", value: Double(totalBytes), total: Double(maxbytes))
.frame(width: 130)
.padding(5)

View file

@ -13,15 +13,15 @@ struct Contacts: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@ObservedObject private var userSettings: UserSettings = UserSettings()
@FetchRequest(
sortDescriptors: [NSSortDescriptor(key: "longName", ascending: true)],
animation: .default)
private var users: FetchedResults<UserEntity>
@State var node: NodeInfoEntity? = nil
@State private var userSelection: UserEntity? = nil // Nothing selected by default.
@State private var channelSelection: ChannelEntity? = nil // Nothing selected by default.
@State var node: NodeInfoEntity?
@State private var userSelection: UserEntity? // Nothing selected by default.
@State private var channelSelection: ChannelEntity? // Nothing selected by default.
@State private var isPresentingDeleteChannelMessagesConfirm: Bool = false
@State private var isPresentingDeleteUserMessagesConfirm: Bool = false
@State private var isPresentingTraceRouteSentAlert = false
@ -38,7 +38,7 @@ struct Contacts: View {
ForEach(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in
if channel.name?.lowercased() ?? "" != "admin" && channel.name?.lowercased() ?? "" != "gpio" && channel.name?.lowercased() ?? "" != "serial" {
NavigationLink(destination: ChannelMessageList(channel: channel)) {
let mostRecent = channel.allPrivateMessages.last(where: { $0.channel == channel.index })
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 ))))
let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0
@ -60,7 +60,7 @@ struct Contacts: View {
}
Spacer()
if channel.allPrivateMessages.count > 0 {
VStack (alignment: .trailing) {
VStack(alignment: .trailing) {
if lastMessageDay == currentDay {
Text(lastMessageTime, style: .time )
.font(.subheadline)
@ -102,7 +102,7 @@ struct Contacts: View {
// Would rather not do this but the merge changes on
// A single object is only working on mac GVH
context.refreshAllObjects()
//context.refresh(channel, mergeChanges: true)
// context.refresh(channel, mergeChanges: true)
} catch {
context.rollback()
print("💥 Save Channel Mute Error")
@ -136,7 +136,7 @@ struct Contacts: View {
}
}
.padding([.top, .bottom])
}
}
Section(header: Text("direct.messages")) {
@ -157,7 +157,7 @@ struct Contacts: View {
Text(user.longName ?? NSLocalizedString("unknown", comment: "Unknown")).font(.headline)
Spacer()
if user.messageList.count > 0 {
VStack (alignment: .trailing) {
VStack(alignment: .trailing) {
if lastMessageDay == currentDay {
Text(lastMessageTime, style: .time )
.font(.subheadline)
@ -218,8 +218,7 @@ struct Contacts: View {
.alert(
"Trace Route Sent",
isPresented: $isPresentingTraceRouteSentAlert
)
{
) {
Button("OK", role: .cancel) { }
}
message: {
@ -264,15 +263,15 @@ struct Contacts: View {
node = fetchedNode[0]
}
} catch {
}
}
}
}
detail: {
if let user = userSelection {
UserMessageList(user:user)
UserMessageList(user: user)
} else {
Text("select.contact")
}

View file

@ -9,11 +9,11 @@ import SwiftUI
import CoreData
struct UserMessageList: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
enum Field: Hashable {
case messageText
}
@ -28,7 +28,7 @@ struct UserMessageList: View {
@State private var deleteMessageId: Int64 = 0
@State private var replyMessageId: Int64 = 0
@State private var sendPositionWithMessage: Bool = false
var body: some View {
NavigationStack {
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmmss", options: 0, locale: Locale.current)
@ -39,7 +39,7 @@ struct UserMessageList: View {
ForEach( user.messageList ) { (message: MessageEntity) in
if user.num != bleManager.connectedPeripheral?.num ?? -1 {
let currentUser: Bool = (bleManager.connectedPeripheral?.num ?? 0 == message.fromUser?.num ?? -1 ? true : false)
if message.replyID > 0 {
let messageReply = user.messageList.first(where: { $0.messageId == message.replyID })
HStack {
@ -55,8 +55,8 @@ struct UserMessageList: View {
.padding(.trailing)
}
}
HStack (alignment: .top) {
if currentUser { Spacer(minLength:50) }
HStack(alignment: .top) {
if currentUser { Spacer(minLength: 50) }
if !currentUser {
CircleText(text: message.fromUser?.shortName ?? "????", color: currentUser ? .accentColor : Color(.gray), circleSize: 44, fontSize: 14)
.padding(.all, 5)
@ -64,7 +64,7 @@ struct UserMessageList: View {
}
VStack(alignment: currentUser ? .trailing : .leading) {
let markdownText: LocalizedStringKey = LocalizedStringKey.init(message.messagePayloadMarkdown ?? (message.messagePayload ?? "EMPTY MESSAGE"))
let linkBlue = Color(red: 0.4627, green: 0.8392, blue: 1) /* #76d6ff */
Text(markdownText)
.tint(linkBlue)
@ -73,7 +73,7 @@ struct UserMessageList: View {
.background(currentUser ? .accentColor : Color(.gray))
.cornerRadius(15)
.contextMenu {
VStack{
VStack {
Text("channel")+Text(": \(message.channel)")
}
Menu("tapback") {
@ -83,7 +83,7 @@ struct UserMessageList: View {
print("Sent \(tb.emojiString) Tapback")
self.context.refresh(user, mergeChanges: true)
} else { print("\(tb.emojiString) Tapback Failed") }
}) {
Text(tb.description)
let image = tb.emojiString.image()
@ -157,11 +157,11 @@ struct UserMessageList: View {
Image(systemName: "trash")
}
}
let tapbacks = message.value(forKey: "tapbacks") as! [MessageEntity]
if tapbacks.count > 0 {
VStack (alignment: .trailing) {
HStack {
VStack(alignment: .trailing) {
HStack {
ForEach( tapbacks ) { (tapback: MessageEntity) in
VStack {
let image = tapback.messagePayload!.image(fontSize: 20)
@ -198,7 +198,7 @@ struct UserMessageList: View {
.padding(.bottom)
.id(user.messageList.firstIndex(of: message))
if !currentUser {
Spacer(minLength:50)
Spacer(minLength: 50)
}
}
.padding([.leading, .trailing])
@ -231,7 +231,7 @@ struct UserMessageList: View {
scrollView.scrollTo(user.messageList.last!.messageId)
}
})
.onChange(of: user.messageList, perform: { messages in
.onChange(of: user.messageList, perform: { _ in
if user.messageList.count > 0 {
scrollView.scrollTo(user.messageList.last!.messageId)
}
@ -243,13 +243,13 @@ struct UserMessageList: View {
Button {
let userLongName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown"
sendPositionWithMessage = true
if userSettings.meshtasticUsername.count > 0 {
typingMessage = "📍 " + userSettings.meshtasticUsername + " has shared their position with you from node " + userLongName + " and requested a response with your position."
} else {
typingMessage = "📍 " + userLongName + " has shared their position and requested a response with your position."
}
} label: {
Text("share.position")
Image(systemName: "mappin.and.ellipse")
@ -264,7 +264,7 @@ struct UserMessageList: View {
.padding(.trailing)
}
#endif
HStack(alignment: .top) {
ZStack {
let kbType = UIKeyboardType(rawValue: UserDefaults.standard.object(forKey: "keyboardType") as? Int ?? 0)
@ -293,13 +293,13 @@ struct UserMessageList: View {
Button {
let userLongName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown"
sendPositionWithMessage = true
if userSettings.meshtasticUsername.count > 0 {
typingMessage = "📍 " + userSettings.meshtasticUsername + " has shared their position with you from node " + userLongName + " and requested a response with your position."
} else {
typingMessage = "📍 " + userLongName + " has shared their position and requested a response with your position."
}
} label: {
Image(systemName: "mappin.and.ellipse")
.symbolRenderingMode(.hierarchical)

View file

@ -8,21 +8,21 @@ import SwiftUI
import Charts
struct DeviceMetricsLog: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State private var isPresentingClearLogConfirm: Bool = false
@State var isExporting = false
@State var exportString = ""
var node: NodeInfoEntity
var body: some View {
NavigationStack {
let oneDayAgo = Calendar.current.date(byAdding: .day, value: -3, to: Date())
let data = node.telemetries?.filtered(using: NSPredicate(format: "metricsType == 0 && time !=nil && time >= %@", oneDayAgo! as CVarArg)) ?? []
if data.count > 0 {
GroupBox(label: Label("battery.level.trend", systemImage: "battery.100")) {
GroupBox(label: Label("battery.level.trend", systemImage: "battery.100")) {
Chart(data.array as! [TelemetryEntity], id: \.self) {
LineMark(
x: .value("Hour", $0.time!.formattedDate(format: "ha")),
@ -39,15 +39,15 @@ struct DeviceMetricsLog: View {
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
//Add a table for mac and ipad
// Add a table for mac and ipad
Table(node.telemetries!.reversed() as! [TelemetryEntity]) {
TableColumn("battery.level") { dm in
if dm.metricsType == 0 {
if dm.batteryLevel == 0 {
Text("Powered")
} else {
Text("\(String(dm.batteryLevel))%")
}
}
@ -73,10 +73,10 @@ struct DeviceMetricsLog: View {
}
}
}
} else {
ScrollView {
let columns = [
GridItem(.flexible(minimum: 30, maximum: 60), spacing: 0.1),
GridItem(.flexible(minimum: 30, maximum: 60), spacing: 0.1),
@ -118,7 +118,7 @@ struct DeviceMetricsLog: View {
.font(.caption)
Text("\(String(format: "%.2f", dm.airUtilTx))%")
.font(.caption)
Text(dm.time?.formattedDate(format: dateFormatString) ?? "Unknown time")
.font(.caption2)
}
@ -154,7 +154,7 @@ struct DeviceMetricsLog: View {
}
}
Button {
exportString = TelemetryToCsvFile(telemetry: node.telemetries!.array as! [TelemetryEntity], metricsType: 0)
exportString = telemetryToCsvFile(telemetry: node.telemetries!.array as! [TelemetryEntity], metricsType: 0)
isExporting = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
@ -182,7 +182,7 @@ struct DeviceMetricsLog: View {
if case .success = result {
print("Device metrics log download succeeded.")
self.isExporting = false
} else {
print("Device metrics log download failed: \(result).")
}

View file

@ -7,24 +7,24 @@
import SwiftUI
struct EnvironmentMetricsLog: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State private var isPresentingClearLogConfirm: Bool = false
@State var isExporting = false
@State var exportString = ""
var node: NodeInfoEntity
var body: some View {
NavigationStack {
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
//Add a table for mac and ipad
// Add a table for mac and ipad
Table(node.telemetries!.reversed() as! [TelemetryEntity]) {
TableColumn("Temperature") { em in
if em.metricsType == 1 {
@ -72,7 +72,7 @@ struct EnvironmentMetricsLog: View {
GridItem(spacing: 0)
]
LazyVGrid(columns: columns, alignment: .leading, spacing: 1) {
GridRow {
Text("Temp")
.font(.caption)
@ -91,11 +91,11 @@ struct EnvironmentMetricsLog: View {
.fontWeight(.bold)
}
ForEach(node.telemetries!.reversed() as! [TelemetryEntity], id: \.self) { (em: TelemetryEntity) in
if em.metricsType == 1 {
GridRow {
Text(em.temperature.formattedTemperature())
.font(.caption)
Text("\(String(format: "%.2f", em.relativeHumidity))")
@ -116,7 +116,7 @@ struct EnvironmentMetricsLog: View {
}
}
HStack {
Button(role: .destructive) {
isPresentingClearLogConfirm = true
} label: {
@ -134,11 +134,11 @@ struct EnvironmentMetricsLog: View {
Button("Delete all environment metrics?", role: .destructive) {
if clearTelemetry(destNum: node.num, metricsType: 1, context: context) {
print("Clear Environment Metrics Log Failed")
}
}
}
}
Button {
exportString = TelemetryToCsvFile(telemetry: node.telemetries!.array as! [TelemetryEntity], metricsType: 1)
exportString = telemetryToCsvFile(telemetry: node.telemetries!.array as! [TelemetryEntity], metricsType: 1)
isExporting = true
} label: {
Label("save", systemImage: "square.and.arrow.down")

View file

@ -9,7 +9,7 @@ import MapKit
import CoreLocation
struct NodeDetail: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.colorScheme) var colorScheme: ColorScheme
@ -29,28 +29,28 @@ struct NodeDetail: View {
tileType: "png",
canReplaceMapContent: true
)
var node: NodeInfoEntity
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: false)],
predicate: NSPredicate(
format: "expire == nil || expire >= %@", Date() as NSDate
), animation: .none)
private var waypoints: FetchedResults<WaypointEntity>
/// The current weather condition for the city.
@State private var condition: WeatherCondition?
@State private var temperature: Measurement<UnitTemperature>?
@State private var humidity: Int?
@State private var symbolName: String = "cloud.fill"
@State private var attributionLink: URL?
@State private var attributionLogo: URL?
var body: some View {
let hwModelString = node.user?.hwModel ?? "UNSET"
NavigationStack {
GeometryReader { bounds in
VStack {
@ -75,12 +75,12 @@ struct NodeDetail: View {
centerOnPositionsOnly: true,
customMapOverlay: self.customMapOverlay,
overlays: self.overlays
)
VStack (alignment: .leading) {
VStack(alignment: .leading) {
Spacer()
HStack (alignment: .bottom, spacing: 1) {
HStack(alignment: .bottom, spacing: 1) {
Picker("Map Type", selection: $mapType) {
ForEach(MeshMapType.allCases) { map in
Text(map.description).tag(map.MKMapTypeValue())
@ -92,8 +92,7 @@ struct NodeDetail: View {
VStack {
Label(temperature?.formatted(.measurement(width: .narrow)) ?? "??", systemImage: symbolName)
.font(.caption)
Label("\(humidity ?? 0)%", systemImage: "humidity")
.font(.caption2)
}
@ -122,7 +121,7 @@ struct NodeDetail: View {
#endif
.gesture(
LongPressGesture(minimumDuration: 0.5)
.onEnded { value in
.onEnded { _ in
showingForecast = true
}
)
@ -137,7 +136,7 @@ struct NodeDetail: View {
}
.padding([.top], 20)
}
ScrollView {
Divider()
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
@ -153,17 +152,17 @@ struct NodeDetail: View {
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
.cornerRadius(5)
Text(String(hwModelString))
.foregroundColor(.gray)
.font(.largeTitle).fixedSize()
}
}
if node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title)
.foregroundColor(.accentColor)
@ -176,15 +175,15 @@ struct NodeDetail: View {
.fixedSize()
}
}
if node.telemetries?.count ?? 0 >= 1 {
let mostRecent = node.telemetries?.lastObject as! TelemetryEntity
Divider()
VStack(alignment: .center) {
BatteryGauge(batteryLevel: Double(mostRecent.batteryLevel))
if mostRecent.voltage > 0 {
Text(String(format: "%.2f", mostRecent.voltage) + " V")
.font(.title)
.foregroundColor(.gray)
@ -195,10 +194,10 @@ struct NodeDetail: View {
}
}
.padding()
Divider()
HStack(alignment: .center) {
VStack {
HStack {
Image(systemName: "person")
@ -207,7 +206,7 @@ struct NodeDetail: View {
.symbolRenderingMode(.hierarchical)
Text("user").font(.title)+Text(":").font(.title)
}
Text("!\(String(format:"%02x", node.num))")
Text("!\(String(format: "%02x", node.num))")
.font(.title).foregroundColor(.gray)
}
Divider()
@ -222,28 +221,28 @@ struct NodeDetail: View {
Text(String(node.num)).font(.title).foregroundColor(.gray)
}
Divider()
VStack{
VStack {
HStack {
Image(systemName: "globe")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("MAC Address: ").font(.title)
}
Text(String(node.user?.macaddr?.macAddressString ?? "not a valid mac address"))
.font(.title)
.foregroundColor(.gray)
}
Divider()
VStack{
VStack {
HStack {
Image(systemName: "clock.badge.checkmark.fill")
.font(.title)
.foregroundColor(.accentColor)
.symbolRenderingMode(.hierarchical)
Text("heard.last").font(.title)+Text(":").font(.title)
}
DateTimeText(dateTime: node.lastHeard)
.font(.title3)
@ -251,11 +250,11 @@ struct NodeDetail: View {
}
}
Divider()
} else {
HStack {
VStack(alignment: .center) {
CircleText(text: node.user?.shortName ?? "???", color: .accentColor)
}
@ -270,11 +269,11 @@ struct NodeDetail: View {
.font(.callout).fixedSize()
}
}
if node.snr > 0 {
Divider()
VStack(alignment: .center) {
Image(systemName: "waveform.path")
.font(.title)
.foregroundColor(.accentColor)
@ -286,14 +285,14 @@ struct NodeDetail: View {
.fixedSize()
}
}
if node.telemetries?.count ?? 0 >= 1 {
let mostRecent = node.telemetries?.lastObject as! TelemetryEntity
Divider()
VStack(alignment: .center) {
BatteryGauge(batteryLevel: Double(mostRecent.batteryLevel))
if mostRecent.voltage > 0 {
Text(String(format: "%.2f", mostRecent.voltage) + " V")
.font(.callout)
.foregroundColor(.gray)
@ -338,36 +337,36 @@ struct NodeDetail: View {
.padding([.bottom], 10)
Divider()
}
VStack {
if (node.positions?.count ?? 0) > 0 {
NavigationLink {
PositionLog(node: node)
} label: {
Image(systemName: "building.columns")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Position Log")
.font(.title3)
}
.fixedSize(horizontal: false, vertical: true)
Divider()
}
if (node.telemetries?.count ?? 0) > 0 {
NavigationLink {
DeviceMetricsLog(node: node)
} label: {
Image(systemName: "flipphone")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Device Metrics Log")
.font(.title3)
}
@ -375,28 +374,28 @@ struct NodeDetail: View {
NavigationLink {
EnvironmentMetricsLog(node: node)
} label: {
Image(systemName: "chart.xyaxis.line")
.symbolRenderingMode(.hierarchical)
.font(.title)
Text("Environment Metrics Log")
.font(.title3)
}
Divider()
}
}
if (self.bleManager.connectedPeripheral != nil && node.metadata != nil) {
if self.bleManager.connectedPeripheral != nil && node.metadata != nil {
HStack {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? -1, context: context)
if node.metadata?.canShutdown ?? false || hwModelString == "RAK4631" {//node.metadata?.hwModel ?? "UNSET" == "RAK4631" {
if node.metadata?.canShutdown ?? false || hwModelString == "RAK4631" {// node.metadata?.hwModel ?? "UNSET" == "RAK4631" {
Button(action: {
showingShutdownConfirm = true
}) {
Label("Power Off", systemImage: "power")
}
.buttonStyle(.bordered)
@ -414,7 +413,7 @@ struct NodeDetail: View {
}
}
}
Button(action: {
showingRebootConfirm = true
}) {
@ -448,7 +447,7 @@ struct NodeDetail: View {
.controlSize(.mini)
}
.frame(height: 15)
Link("Other data sources", destination: attributionLink ?? URL(string: "https://weather-data.apple.com/legal-attribution.html")!)
}
.font(.footnote)
@ -456,7 +455,7 @@ struct NodeDetail: View {
}
}
.edgesIgnoringSafeArea([.leading, .trailing])
.sheet(isPresented: $presentingWaypointForm ) {//, onDismiss: didDismissSheet) {
.sheet(isPresented: $presentingWaypointForm ) {// , onDismiss: didDismissSheet) {
WaypointFormView(coordinate: waypointCoordinate ?? LocationHelper.DefaultLocation, waypointId: editingWaypoint)
.presentationDetents([.medium, .large])
.presentationDragIndicator(.automatic)
@ -496,17 +495,17 @@ struct NodeDetail: View {
}
.task(id: node.num) {
do {
if node.positions?.count ?? 0 > 0 {
let mostRecent = node.positions?.lastObject as! PositionEntity
let weather = try await WeatherService.shared.weather(for: mostRecent.nodeLocation!)
condition = weather.currentWeather.condition
temperature = weather.currentWeather.temperature
humidity = Int(weather.currentWeather.humidity * 100)
symbolName = weather.currentWeather.symbolName
let attribution = try await WeatherService.shared.attribution
attributionLink = attribution.legalPageURL
attributionLogo = colorScheme == .light ? attribution.combinedMarkLightURL : attribution.combinedMarkDarkURL

View file

@ -23,12 +23,12 @@ struct NodeList: View {
private var nodes: FetchedResults<NodeInfoEntity>
@State private var selection: NodeInfoEntity? = nil // Nothing selected by default.
@State private var selection: NodeInfoEntity? // Nothing selected by default.
var body: some View {
NavigationSplitView {
List (nodes, id: \.self, selection: $selection) { node in
List(nodes, id: \.self, selection: $selection) { node in
if nodes.count == 0 {
Text("no.nodes").font(.title)
} else {
@ -53,13 +53,13 @@ struct NodeList: View {
HStack(alignment: .bottom) {
let lastPostion = node.positions!.reversed()[0] as! PositionEntity
let myCoord = CLLocation(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
if lastPostion.nodeCoordinate != nil && myCoord.coordinate.longitude != LocationHelper.DefaultLocation.longitude && myCoord.coordinate.latitude != LocationHelper.DefaultLocation.latitude {
if lastPostion.nodeCoordinate != nil && myCoord.coordinate.longitude != LocationHelper.DefaultLocation.longitude && myCoord.coordinate.latitude != LocationHelper.DefaultLocation.latitude {
let nodeCoord = CLLocation(latitude: lastPostion.nodeCoordinate!.latitude, longitude: lastPostion.nodeCoordinate!.longitude)
let metersAway = nodeCoord.distance(from: myCoord)
Image(systemName: "lines.measurement.horizontal")
.font(.title3)
.symbolRenderingMode(.hierarchical)
DistanceText(meters: metersAway).font(.subheadline)
}
}
@ -89,7 +89,7 @@ struct NodeList: View {
}
} detail: {
if let node = selection {
NodeDetail(node:node)
NodeDetail(node: node)
} else {
Text("select.node")
}

View file

@ -15,7 +15,7 @@ struct NodeMap: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
@AppStorage("meshMapCustomTileServer") var customTileServer: String = "" {
didSet {
if customTileServer == "" {
@ -32,18 +32,18 @@ struct NodeMap: View {
@AppStorage("meshMapType") private var meshMapType = "hybridFlyover"
@AppStorage("meshMapUserTrackingMode") private var meshMapUserTrackingMode = 0
@AppStorage("meshMapCenteringMode") private var meshMapCenteringMode = 0
//&& nodePosition != nil
// && nodePosition != nil
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "time", ascending: true)],
predicate: NSPredicate(format: "time >= %@ && nodePosition != nil", Calendar.current.startOfDay(for: Date()) as NSDate), animation: .none)
private var positions: FetchedResults<PositionEntity>
@FetchRequest(sortDescriptors: [NSSortDescriptor(key: "name", ascending: false)],
predicate: NSPredicate(
format: "expire == nil || expire >= %@", Date() as NSDate
), animation: .none)
private var waypoints: FetchedResults<WaypointEntity>
@State private var mapType: MKMapType = .standard
@State private var userTrackingMode: MKUserTrackingMode = .none
@State private var mapCenteringMode: CenteringMode = .allAnnotations
@ -56,12 +56,12 @@ struct NodeMap: View {
canReplaceMapContent: true
)
@State private var overlays: [MapViewSwiftUI.Overlay] = []
var body: some View {
NavigationStack {
ZStack {
MapViewSwiftUI(onLongPress: { coord in
waypointCoordinate = coord
editingWaypoint = 0
@ -98,11 +98,11 @@ struct NodeMap: View {
}
.ignoresSafeArea(.all, edges: [.top, .leading, .trailing])
.frame(maxHeight: .infinity)
.sheet(isPresented: $presentingWaypointForm ) {//, onDismiss: didDismissSheet) {
.sheet(isPresented: $presentingWaypointForm ) {// , onDismiss: didDismissSheet) {
WaypointFormView(coordinate: waypointCoordinate, waypointId: editingWaypoint)
.presentationDetents([.medium, .large])
.presentationDragIndicator(.automatic)
}
}
.navigationBarItems(leading:
@ -143,7 +143,7 @@ struct NodeMap: View {
mapType = .hybridFlyover
}
})
.onDisappear (perform: {
.onDisappear(perform: {
UIApplication.shared.isIdleTimerDisabled = false
})
}

View file

@ -7,25 +7,25 @@
import SwiftUI
struct PositionLog: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@State var isExporting = false
@State var exportString = ""
var node: NodeInfoEntity
@State private var isPresentingClearLogConfirm = false
var body: some View {
NavigationStack {
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmma", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mma").replacingOccurrences(of: ",", with: "")
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
//Add a table for mac and ipad
// Add a table for mac and ipad
Table(node.positions!.reversed() as! [PositionEntity]) {
TableColumn("SeqNo") { position in
Text(String(position.seqNo))
@ -55,9 +55,9 @@ struct PositionLog: View {
Text(position.time?.formattedDate(format: dateFormatString) ?? NSLocalizedString("unknown.age", comment: ""))
}
}
} else {
ScrollView {
// Use a grid on iOS as a table only shows a single column
let columns = [
@ -68,9 +68,9 @@ struct PositionLog: View {
GridItem(spacing: 0)
]
LazyVGrid(columns: columns, alignment: .leading, spacing: 1) {
GridRow {
Text("Latitude")
.font(.caption2)
.fontWeight(.bold)
@ -125,20 +125,20 @@ struct PositionLog: View {
Button("Delete all positions?", role: .destructive) {
if clearPositions(destNum: node.num, context: context) {
print("Successfully Cleared Position Log")
} else {
print("Clear Position Log Failed")
}
}
}
Button {
exportString = PositionToCsvFile(positions: node.positions!.array as! [PositionEntity])
exportString = positionToCsvFile(positions: node.positions!.array as! [PositionEntity])
isExporting = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
.buttonStyle(.bordered)
@ -154,12 +154,12 @@ struct PositionLog: View {
onCompletion: { result in
if case .success = result {
print("Position log download succeeded.")
self.isExporting = false
} else {
print("Position log download failed: \(result).")
}
}

View file

@ -8,18 +8,18 @@ import SwiftUI
import StoreKit
struct AboutMeshtastic: View {
let locale = Locale.current
var body: some View {
VStack{
VStack {
List {
Section(header: Text("What is Meshtastic?")) {
Text("An open source, off-grid, decentralized, mesh network built to run on affordable, low-power devices.")
.font(.title3)
}
Section(header: Text("Apple Apps")) {
Button("Review the app") {

View file

@ -14,38 +14,38 @@ import MapKit
import CoreLocation
struct AdminMessageList: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
var user: UserEntity?
var body: some View {
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMddjmmssa", options: 0, locale: Locale.current)
let dateFormatString = (localeDateFormat ?? "MM/dd/YY j:mm:ss a")
List {
if user != nil {
ForEach ( user!.adminMessageList.reversed() ) { am in
VStack (alignment: .leading) {
ForEach( user!.adminMessageList.reversed() ) { am in
VStack(alignment: .leading) {
Text("\(am.adminDescription ?? NSLocalizedString("unknown", comment: "Unknown"))")
.font(.caption)
Text("Sent \(Date(timeIntervalSince1970: TimeInterval(am.messageTimestamp)).formattedDate(format: dateFormatString))")
.foregroundColor(.gray)
.font(.caption2)
HStack (spacing: 0) {
HStack(spacing: 0) {
let ackErrorVal = RoutingError(rawValue: Int(am.ackError))
if am.ackTimestamp > 0 {
Text(ackErrorVal?.display ?? "Empty Ack Error")
.foregroundColor(am.receivedACK ? .gray : .red)
.font(.caption2)
}
if am.receivedACK && am.ackTimestamp > 0 {
Text(" \(Date(timeIntervalSince1970: TimeInterval(am.ackTimestamp)).formattedDate(format: "h:mm:ss a"))")
.foregroundColor(.gray)

View file

@ -9,7 +9,7 @@ struct AppSettings: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
@State private var isPresentingCoreDataResetConfirm = false
@State private var preferredDeviceConnected = false
@ -28,32 +28,32 @@ struct AppSettings: View {
.listRowSeparator(.visible)
}
Section(header: Text("options")) {
Picker("keyboard.type", selection: $userSettings.keyboardType) {
ForEach(KeyboardType.allCases) { kb in
Text(kb.description)
}
}
.pickerStyle(DefaultPickerStyle())
}
Section(header: Text("phone.gps")) {
Toggle(isOn: $userSettings.provideLocation) {
Label("provide.location", systemImage: "location.circle.fill")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if userSettings.provideLocation {
Picker("update.interval", selection: $userSettings.provideLocationInterval) {
ForEach(LocationUpdateInterval.allCases) { lu in
Text(lu.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("phone.gps.interval.description")
.font(.caption)
.foregroundColor(.gray)
@ -68,27 +68,27 @@ struct AppSettings: View {
.font(.caption)
.foregroundColor(.gray)
}
Section(header: Text("map options")) {
Picker("map.type", selection: $userSettings.meshMapType) {
ForEach(MeshMapType.allCases) { map in
Text(map.description)
}
}
.pickerStyle(DefaultPickerStyle())
if userSettings.meshMapUserTrackingMode == 0 {
Picker("map.centering", selection: $userSettings.meshMapCenteringMode) {
ForEach(CenteringMode.allCases) { cm in
Text(cm.description)
}
}
.pickerStyle(DefaultPickerStyle())
Toggle(isOn: $userSettings.meshMapRecentering) {
Label("map.recentering", systemImage: "camera.metering.center.weighted")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
@ -126,8 +126,8 @@ struct AppSettings: View {
.onAppear {
self.bleManager.context = context
}
.onChange(of: userSettings.provideLocation) { newProvideLocation in
.onChange(of: userSettings.provideLocation) { _ in
if bleManager.connectedPeripheral != nil {
self.bleManager.sendWantConfig()
}

View file

@ -16,15 +16,14 @@ func generateChannelKey(size: Int) -> String {
}
struct Channels: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
@Environment(\.sizeCategory) var sizeCategory
var node: NodeInfoEntity?
@State var hasChanges = false
@State private var isPresentingEditView = false
@State private var isPresentingSaveConfirm: Bool = false
@ -35,14 +34,14 @@ struct Channels: View {
@State private var channelRole = 0
@State private var uplink = false
@State private var downlink = false
var body: some View {
NavigationStack {
List {
if node != nil && node?.myInfo != nil {
ForEach(node!.myInfo!.channels?.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in
Button(action: {
Button(action: {
channelIndex = channel.index
channelRole = Int(channel.role)
channelKey = channel.psk?.base64EncodedString() ?? ""
@ -87,7 +86,7 @@ struct Channels: View {
}
}
if node?.myInfo?.channels?.array.count ?? 0 < 8 && node != nil {
Button {
let key = generateChannelKey(size: 32)
channelName = ""
@ -98,7 +97,7 @@ struct Channels: View {
downlink = false
hasChanges = false
isPresentingEditView = true
} label: {
Label("Add Channel", systemImage: "plus.square")
}
@ -107,7 +106,7 @@ struct Channels: View {
.controlSize(.large)
.padding()
.sheet(isPresented: $isPresentingEditView) {
#if targetEnvironment(macCatalyst)
Text("channel")
.font(.largeTitle)
@ -125,7 +124,7 @@ struct Channels: View {
.keyboardType(.alphabet)
.foregroundColor(Color.gray)
.disabled(channelRole == 1 && channelName.count > 0)
.onChange(of: channelName, perform: { value in
.onChange(of: channelName, perform: { _ in
channelName = channelName.replacing(" ", with: "")
let totalBytes = channelName.utf8.count
// Only mess with the value if it is too big
@ -165,23 +164,23 @@ struct Channels: View {
.buttonBorderShape(.capsule)
.controlSize(.small)
}
HStack (alignment: .top) {
HStack(alignment: .top) {
Text("Key")
Spacer()
TextField (
TextField(
"",
text: $channelKey,
axis: .vertical
)
.foregroundColor(Color.gray)
.disabled(true)
}
.textSelection(.enabled)
Picker("Channel Role", selection: $channelRole) {
if channelRole == 1 {
Text("Primary").tag(1)
} else{
} else {
Text("Disabled").tag(0)
Text("Secondary").tag(2)
}
@ -193,13 +192,13 @@ struct Channels: View {
Toggle("Downlink Enabled", isOn: $downlink)
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
//.onSubmit {
//validate(name: channelName)
//}
.onChange(of: channelName) { newName in
// .onSubmit {
// validate(name: channelName)
// }
.onChange(of: channelName) { _ in
hasChanges = true
}
.onChange(of: channelKeySize) { newKeySize in
.onChange(of: channelKeySize) { _ in
if channelKeySize == -1 {
channelKey = "AQ=="
} else {
@ -208,16 +207,16 @@ struct Channels: View {
}
hasChanges = true
}
.onChange(of: channelKey) { newKey in
.onChange(of: channelKey) { _ in
hasChanges = true
}
.onChange(of: channelRole) { newRole in
.onChange(of: channelRole) { _ in
hasChanges = true
}
.onChange(of: uplink) { newUplink in
.onChange(of: uplink) { _ in
hasChanges = true
}
.onChange(of: downlink) { newDownlink in
.onChange(of: downlink) { _ in
hasChanges = true
}
HStack {
@ -231,7 +230,7 @@ struct Channels: View {
channel.settings.psk = Data(base64Encoded: channelKey) ?? Data()
channel.settings.uplinkEnabled = uplink
channel.settings.downlinkEnabled = downlink
} else {
if channelIndex <= node!.myInfo!.channels?.count ?? 0 {
let channelEntity = node!.myInfo!.channels?[Int(channelIndex)] as! ChannelEntity
@ -246,9 +245,9 @@ struct Channels: View {
}
}
}
let adminMessageId = bleManager.saveChannel(channel: channel, fromUser: node!.user!, toUser: node!.user!)
if adminMessageId > 0 {
self.isPresentingEditView = false
channelName = ""

View file

@ -8,13 +8,10 @@
import SwiftUI
struct BluetoothConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var enabled = true
@ -22,43 +19,35 @@ struct BluetoothConfig: View {
@State var fixedPin = "123456"
@State var shortPin = false
var pinLength: Int = 6
let numberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .none
return formatter
}()
var body: some View {
Form {
Section(header: Text("options")) {
Toggle(isOn: $enabled) {
Label("enabled", systemImage: "antenna.radiowaves.left.and.right")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Picker("bluetooth.pairingmode", selection: $mode ) {
ForEach(BluetoothModes.allCases) { bm in
Text(bm.description)
}
}
.pickerStyle(DefaultPickerStyle())
if mode == 1 {
HStack {
Label("bluetooth.mode.fixedpin", systemImage: "wallet.pass")
TextField("bluetooth.mode.fixedpin", text: $fixedPin)
.foregroundColor(.gray)
.onChange(of: fixedPin, perform: { value in
.onChange(of: fixedPin, perform: { _ in
// Don't let the first character be 0 because it will get stripped when saving a UInt32
if fixedPin.first == "0" {
fixedPin = fixedPin.replacing("0", with: "")
}
//Require that pin is no more than 6 numbers and no less than 6 numbers
// Require that pin is no more than 6 numbers and no less than 6 numbers
if fixedPin.utf8.count == pinLength {
shortPin = false
} else if fixedPin.utf8.count > pinLength {
@ -80,7 +69,6 @@ struct BluetoothConfig: View {
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.bluetoothConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
@ -128,7 +116,6 @@ struct BluetoothConfig: View {
self.mode = Int(node?.bluetoothConfig?.mode ?? 0)
self.fixedPin = String(node?.bluetoothConfig?.fixedPin ?? 123456)
self.hasChanges = false
// Need to request a BluetoothConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.bluetoothConfig == nil {
print("empty bluetooth config")

View file

@ -7,33 +7,33 @@
import SwiftUI
struct DeviceConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingNodeDBResetConfirm = false
@State private var isPresentingFactoryResetConfirm = false
@State private var isPresentingSaveConfirm = false
@State var hasChanges = false
@State var deviceRole = 0
@State var buzzerGPIO = 0
@State var buttonGPIO = 0
@State var serialEnabled = true
@State var debugLogEnabled = false
@State var rebroadcastMode = 0
var body: some View {
VStack {
Form {
Section(header: Text("options")) {
Picker("Device Role", selection: $deviceRole ) {
ForEach(DeviceRoles.allCases) { dr in
Text(dr.name)
@ -44,7 +44,7 @@ struct DeviceConfig: View {
Text(DeviceRoles(rawValue: deviceRole)?.description ?? "")
.foregroundColor(.gray)
.font(.caption)
Picker("Rebroadcast Mode", selection: $rebroadcastMode ) {
ForEach(RebroadcastModes.allCases) { rm in
Text(rm.name)
@ -56,24 +56,24 @@ struct DeviceConfig: View {
.foregroundColor(.gray)
.font(.caption)
}
Section(header: Text("Debug")) {
Toggle(isOn: $serialEnabled) {
Label("Serial Console", systemImage: "terminal")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $debugLogEnabled) {
Label("Debug Log", systemImage: "ant.fill")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
Section(header: Text("GPIO")) {
Picker("Button GPIO", selection: $buttonGPIO) {
ForEach(0..<40) {
if $0 == 0 {
@ -95,14 +95,14 @@ struct DeviceConfig: View {
}
.pickerStyle(DefaultPickerStyle())
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.deviceConfig == nil)
// Only show these buttons for the BLE connected node
if bleManager.connectedPeripheral != nil && node?.num ?? -1 == bleManager.connectedPeripheral.num {
HStack {
Button("Reset NodeDB", role: .destructive) {
isPresentingNodeDBResetConfirm = true
}
@ -117,7 +117,7 @@ struct DeviceConfig: View {
titleVisibility: .visible
) {
Button("Erase all device and app data?", role: .destructive) {
if bleManager.sendNodeDBReset(fromUser: node!.user!, toUser: node!.user!) {
bleManager.disconnectPeripheral()
clearCoreDataDatabase(context: context)
@ -140,23 +140,23 @@ struct DeviceConfig: View {
titleVisibility: .visible
) {
Button("Factory reset your device and app? ", role: .destructive) {
if bleManager.sendFactoryReset(fromUser: node!.user!, toUser: node!.user!) {
bleManager.disconnectPeripheral()
clearCoreDataDatabase(context: context)
} else {
print("Factory Reset Failed")
}
}
}
}
}
HStack {
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
@ -166,7 +166,7 @@ struct DeviceConfig: View {
.controlSize(.large)
.padding()
.confirmationDialog(
"are.you.sure",
isPresented: $isPresentingSaveConfirm,
titleVisibility: .visible
@ -182,7 +182,7 @@ struct DeviceConfig: View {
dc.debugLogEnabled = debugLogEnabled
dc.buttonGpio = UInt32(buttonGPIO)
dc.buzzerGpio = UInt32(buzzerGPIO)
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
@ -212,7 +212,7 @@ struct DeviceConfig: View {
self.buttonGPIO = Int(node?.deviceConfig?.buttonGpio ?? 0)
self.buzzerGPIO = Int(node?.deviceConfig?.buzzerGpio ?? 0)
self.hasChanges = false
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.deviceConfig == nil {
print("empty device config")
@ -223,37 +223,37 @@ struct DeviceConfig: View {
}
}
.onChange(of: deviceRole) { newRole in
if node != nil && node!.deviceConfig != nil {
if newRole != node!.deviceConfig!.role { hasChanges = true }
}
}
.onChange(of: serialEnabled) { newSerial in
if node != nil && node!.deviceConfig != nil {
if newSerial != node!.deviceConfig!.serialEnabled { hasChanges = true }
}
}
.onChange(of: debugLogEnabled) { newDebugLog in
if node != nil && node!.deviceConfig != nil {
if newDebugLog != node!.deviceConfig!.debugLogEnabled { hasChanges = true }
}
}
.onChange(of: buttonGPIO) { newButtonGPIO in
if node != nil && node!.deviceConfig != nil {
if newButtonGPIO != node!.deviceConfig!.buttonGpio { hasChanges = true }
}
}
.onChange(of: buzzerGPIO) { newBuzzerGPIO in
if node != nil && node!.deviceConfig != nil {
if newBuzzerGPIO != node!.deviceConfig!.buttonGpio { hasChanges = true }
}
}

View file

@ -8,13 +8,13 @@
import SwiftUI
struct DisplayConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@ -25,12 +25,12 @@ struct DisplayConfig: View {
@State var flipScreen = false
@State var oledType = 0
@State var displayMode = 0
var body: some View {
Form {
Section(header: Text("Device Screen")) {
Picker("Display Mode", selection: $displayMode ) {
ForEach(DisplayModes.allCases) { dm in
Text(dm.description)
@ -39,7 +39,7 @@ struct DisplayConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("Override automatic OLED screen detection.")
.font(.caption)
Toggle(isOn: $compassNorthTop) {
Label("Always point north", systemImage: "location.north.circle")
@ -47,7 +47,7 @@ struct DisplayConfig: View {
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Text("The compass heading on the screen outside of the circle will always point north.")
.font(.caption)
Toggle(isOn: $flipScreen) {
Label("Flip Screen", systemImage: "pip.swap")
@ -55,7 +55,7 @@ struct DisplayConfig: View {
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Text("Flip screen vertically")
.font(.caption)
Picker("OLED Type", selection: $oledType ) {
ForEach(OledTypes.allCases) { ot in
Text(ot.description)
@ -64,7 +64,7 @@ struct DisplayConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("Override automatic OLED screen detection.")
.font(.caption)
}
Section(header: Text("Timing & Format")) {
Picker("Screen on for", selection: $screenOnSeconds ) {
@ -75,7 +75,7 @@ struct DisplayConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("How long the screen remains on after the user button is pressed or messages are received.")
.font(.caption)
Picker("Carousel Interval", selection: $screenCarouselInterval ) {
ForEach(ScreenCarouselIntervals.allCases) { sci in
Text(sci.description)
@ -84,27 +84,27 @@ struct DisplayConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("Automatically toggles to the next page on the screen like a carousel, based the specified interval.")
.font(.caption)
Picker("GPS Format", selection: $gpsFormat ) {
ForEach(GpsFormats.allCases) { lu in
Text(lu.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("The format used to display GPS coordinates on the device screen.")
.font(.caption)
.listRowSeparator(.visible)
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.displayConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
@ -129,10 +129,10 @@ struct DisplayConfig: View {
dc.flipScreen = flipScreen
dc.oled = OledTypes(rawValue: oledType)!.protoEnumValue()
dc.displaymode = DisplayModes(rawValue: displayMode)!.protoEnumValue()
let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
@ -159,7 +159,7 @@ struct DisplayConfig: View {
self.oledType = Int(node?.displayConfig?.oledType ?? 0)
self.displayMode = Int(node?.displayConfig?.displayMode ?? 0)
self.hasChanges = false
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.displayConfig == nil {
print("empty display config")

View file

@ -9,7 +9,7 @@ import SwiftUI
import CoreData
struct LoRaConfig: View {
enum Field: Hashable {
case channelNum
}
@ -20,14 +20,14 @@ struct LoRaConfig: View {
formatter.groupingSeparator = ""
return formatter
}()
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
@FocusState var focusedField: Field?
var node: NodeInfoEntity?
@State var isPresentingSaveConfirm = false
@State var hasChanges = false
@State var region = 0
@ -40,9 +40,9 @@ struct LoRaConfig: View {
@State var bandwidth = 0
@State var spreadFactor = 0
@State var codingRate = 0
var body: some View {
VStack {
Form {
Section(header: Text("Options")) {
@ -54,15 +54,15 @@ struct LoRaConfig: View {
}
.pickerStyle(DefaultPickerStyle())
.fixedSize()
Text("The region where you will be using your radios.")
.font(.caption)
Toggle(isOn: $usePreset) {
Label("Use Preset", systemImage: "list.bullet.rectangle")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if usePreset {
Picker("Presets", selection: $modemPreset ) {
ForEach(ModemPresets.allCases) { m in
@ -76,12 +76,12 @@ struct LoRaConfig: View {
}
}
Section(header: Text("Advanced")) {
Toggle(isOn: $txEnabled) {
Label("Transmit Enabled", systemImage: "waveform.path")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if !usePreset {
HStack {
Picker("Bandwidth", selection: $spreadFactor) {
@ -124,7 +124,7 @@ struct LoRaConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("Sets the maximum number of hops, default is 3. Increasing hops also increases air time utilization and should be used carefully.")
.font(.caption)
HStack {
Text("LoRa Channel Number")
.fixedSize()
@ -147,8 +147,7 @@ struct LoRaConfig: View {
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.loRaConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
@ -198,7 +197,7 @@ struct LoRaConfig: View {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
self.bleManager.context = context
self.hopLimit = Int(node?.loRaConfig?.hopLimit ?? 3)
self.region = Int(node?.loRaConfig?.regionCode ?? 0)
@ -211,14 +210,14 @@ struct LoRaConfig: View {
self.codingRate = Int(node?.loRaConfig?.codingRate ?? 0)
self.spreadFactor = Int(node?.loRaConfig?.spreadFactor ?? 0)
print("Spreadum: \(self.spreadFactor)")
self.hasChanges = false
// Need to request a LoRaConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.loRaConfig == nil {
print("empty lora config")
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if node != nil && connectedNode != nil{
if node != nil && connectedNode != nil {
_ = bleManager.requestLoRaConfig(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
}
}

View file

@ -7,18 +7,14 @@
import SwiftUI
struct CannedMessagesConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var hasMessagesChanges = false
@State var configPreset = 0
@State var enabled = false
/// CannedMessageModule will sends a bell character with the messages.
@State var sendBell: Bool = false
@ -38,29 +34,22 @@ struct CannedMessagesConfig: View {
@State var inputbrokerEventCcw = 0
/// Generate input event on Press of this kind.
@State var inputbrokerEventPress = 0
@State var messages = ""
var body: some View {
VStack {
Form {
Section(header: Text("options")) {
Toggle(isOn: $enabled) {
Label("enabled", systemImage: "list.bullet.rectangle.fill")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $sendBell) {
Label("Send Bell", systemImage: "bell")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Picker("Configuration Presets", selection: $configPreset ) {
ForEach(ConfigPresets.allCases) { cp in
Text(cp.description)
@ -69,26 +58,21 @@ struct CannedMessagesConfig: View {
.pickerStyle(DefaultPickerStyle())
.padding(.top, 10)
.padding(.bottom, 10)
}
HStack {
Label("Messages", systemImage: "message.fill")
TextField("Messages separate with |", text: $messages, axis: .vertical)
.foregroundColor(.gray)
.autocapitalization(.none)
.disableAutocorrection(true)
.onChange(of: messages, perform: { value in
.onChange(of: messages, perform: { _ in
let totalBytes = messages.utf8.count
// Only mess with the value if it is too big
if totalBytes > 198 {
let firstNBytes = Data(messages.utf8.prefix(198))
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
// Set the shortName back to the last place where it was the right size
messages = maxBytesString
}
@ -98,35 +82,27 @@ struct CannedMessagesConfig: View {
.foregroundColor(.gray)
}
.keyboardType(.default)
Section(header: Text("Control Type")) {
Toggle(isOn: $rotary1Enabled) {
Label("Rotary 1", systemImage: "dial.min")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
.disabled(updown1Enabled)
Toggle(isOn: $updown1Enabled) {
Label("Up Down 1", systemImage: "arrow.up.arrow.down")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
.disabled(rotary1Enabled)
}
.disabled(configPreset > 0)
Section(header: Text("Inputs")) {
Picker("Pin A", selection: $inputbrokerPinA) {
ForEach(0..<40) {
if $0 == 0 {
Text("unset")
} else {
Text("Pin \($0)")
}
}
@ -134,14 +110,11 @@ struct CannedMessagesConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("GPIO pin for rotary encoder A port.")
.font(.caption)
Picker("Pin B", selection: $inputbrokerPinB) {
ForEach(0..<40) {
if $0 == 0 {
Text("unset")
} else {
Text("Pin \($0)")
}
}
@ -149,14 +122,11 @@ struct CannedMessagesConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("GPIO pin for rotary encoder B port.")
.font(.caption)
Picker("Press Pin", selection: $inputbrokerPinPress) {
ForEach(0..<40) {
if $0 == 0 {
Text("unset")
} else {
Text("Pin \($0)")
}
}
@ -164,12 +134,9 @@ struct CannedMessagesConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("GPIO pin for rotary encoder Press port.")
.font(.caption)
}
.disabled(configPreset > 0)
Section(header: Text("Key Mapping")) {
Picker("Clockwise Rotary Event", selection: $inputbrokerEventCw ) {
ForEach(InputEventChars.allCases) { iec in
Text(iec.description)
@ -178,7 +145,6 @@ struct CannedMessagesConfig: View {
.pickerStyle(DefaultPickerStyle())
.padding(.top, 10)
.padding(.bottom, 10)
Picker("Counter Clockwise Rotary Event", selection: $inputbrokerEventCcw ) {
ForEach(InputEventChars.allCases) { iec in
Text(iec.description)
@ -187,7 +153,6 @@ struct CannedMessagesConfig: View {
.pickerStyle(DefaultPickerStyle())
.padding(.top, 10)
.padding(.bottom, 10)
Picker("Encoder Press Event", selection: $inputbrokerEventPress ) {
ForEach(InputEventChars.allCases) { iec in
Text(iec.description)
@ -201,10 +166,8 @@ struct CannedMessagesConfig: View {
}
.scrollDismissesKeyboard(.immediately)
.disabled(self.bleManager.connectedPeripheral == nil || node?.cannedMessageConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
@ -287,7 +250,7 @@ struct CannedMessagesConfig: View {
self.messages = node?.cannedMessageConfig?.messages ?? ""
self.hasChanges = false
self.hasMessagesChanges = false
// Need to request a CannedMessagesModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.cannedMessageConfig == nil {
print("empty canned messages module config")
@ -298,9 +261,9 @@ struct CannedMessagesConfig: View {
}
}
.onChange(of: configPreset) { newPreset in
if newPreset == 1 {
// RAK Rotary Encoder
updown1Enabled = true
rotary1Enabled = false
@ -310,9 +273,9 @@ struct CannedMessagesConfig: View {
inputbrokerEventCw = InputEventChars.down.rawValue
inputbrokerEventCcw = InputEventChars.up.rawValue
inputbrokerEventPress = InputEventChars.select.rawValue
} else if newPreset == 2 {
// CardKB / RAK Keypad
updown1Enabled = false
rotary1Enabled = false
@ -323,7 +286,7 @@ struct CannedMessagesConfig: View {
inputbrokerEventCcw = InputEventChars.none.rawValue
inputbrokerEventPress = InputEventChars.none.rawValue
}
hasChanges = true
}
.onChange(of: enabled) { newEnabled in

View file

@ -7,13 +7,13 @@
import SwiftUI
struct ExternalNotificationConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var enabled = false
@ -30,9 +30,9 @@ struct ExternalNotificationConfig: View {
@State var outputVibra = 0
@State var outputMilliseconds = 0
@State var nagTimeout = 0
var body: some View {
Form {
Section(header: Text("options")) {
Toggle(isOn: $enabled) {
@ -58,8 +58,7 @@ struct ExternalNotificationConfig: View {
Section(header: Text("Primary GPIO")
.font(.caption)
.foregroundColor(.gray)
.textCase(.uppercase))
{
.textCase(.uppercase)) {
Toggle(isOn: $active) {
Label("Active", systemImage: "togglepower")
}
@ -93,12 +92,11 @@ struct ExternalNotificationConfig: View {
Text("Specifies how long the monitored GPIO should output.")
.font(.caption)
}
Section(header: Text("Optional GPIO")
.font(.caption)
.foregroundColor(.gray)
.textCase(.uppercase))
{
.textCase(.uppercase)) {
Toggle(isOn: $alertBellBuzzer) {
Label("Alert GPIO buzzer when receiving a bell", systemImage: "bell")
}
@ -174,7 +172,7 @@ struct ExternalNotificationConfig: View {
enc.outputMs = UInt32(outputMilliseconds)
enc.usePwm = usePWM
let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0{
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
hasChanges = false
@ -208,7 +206,7 @@ struct ExternalNotificationConfig: View {
self.nagTimeout = Int(node?.externalNotificationConfig?.nagTimeout ?? 0)
self.usePWM = node?.externalNotificationConfig?.usePWM ?? false
self.hasChanges = false
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.externalNotificationConfig == nil {
print("empty external notification module config")

View file

@ -7,7 +7,7 @@
import SwiftUI
struct MQTTConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
@ -20,9 +20,9 @@ struct MQTTConfig: View {
@State var password = ""
@State var encryptionEnabled = false
@State var jsonEnabled = false
var body: some View {
Form {
Section(header: Text("options")) {
Toggle(isOn: $enabled) {
@ -30,7 +30,7 @@ struct MQTTConfig: View {
Label("enabled", systemImage: "dot.radiowaves.right")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $encryptionEnabled) {
Label("Encryption Enabled", systemImage: "lock.icloud")
@ -50,7 +50,7 @@ struct MQTTConfig: View {
.foregroundColor(.gray)
.autocapitalization(.none)
.disableAutocorrection(true)
.onChange(of: address, perform: { value in
.onChange(of: address, perform: { _ in
let totalBytes = address.utf8.count
// Only mess with the value if it is too big
if totalBytes > 30 {
@ -66,24 +66,24 @@ struct MQTTConfig: View {
.keyboardType(.default)
}
.autocorrectionDisabled()
HStack {
Label("mqtt.username", systemImage: "person.text.rectangle")
TextField("mqtt.username", text: $username)
.foregroundColor(.gray)
.autocapitalization(.none)
.disableAutocorrection(true)
.onChange(of: username, perform: { value in
.onChange(of: username, perform: { _ in
let totalBytes = username.utf8.count
// Only mess with the value if it is too big
if totalBytes > 62 {
let firstNBytes = Data(username.utf8.prefix(62))
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
// Set the shortName back to the last place where it was the right size
username = maxBytesString
}
@ -100,17 +100,17 @@ struct MQTTConfig: View {
.foregroundColor(.gray)
.autocapitalization(.none)
.disableAutocorrection(true)
.onChange(of: password, perform: { value in
.onChange(of: password, perform: { _ in
let totalBytes = password.utf8.count
// Only mess with the value if it is too big
if totalBytes > 62 {
let firstNBytes = Data(password.utf8.prefix(62))
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
// Set the shortName back to the last place where it was the right size
password = maxBytesString
}
@ -127,7 +127,7 @@ struct MQTTConfig: View {
}
.scrollDismissesKeyboard(.interactively)
.disabled(self.bleManager.connectedPeripheral == nil || node?.mqttConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
@ -182,7 +182,7 @@ struct MQTTConfig: View {
self.encryptionEnabled = (node?.mqttConfig?.encryptionEnabled ?? false)
self.jsonEnabled = (node?.mqttConfig?.jsonEnabled ?? false)
self.hasChanges = false
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil {
print("empty mqtt module config")

View file

@ -7,19 +7,19 @@
import SwiftUI
struct RangeTestConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var enabled = false
@State var sender = 0
@State var save = false
var body: some View {
VStack {
Form {
@ -65,7 +65,7 @@ struct RangeTestConfig: View {
let nodeName = node?.user?.longName ?? NSLocalizedString("unknown", comment: "Unknown")
let buttonText = String.localizedStringWithFormat(NSLocalizedString("save.config %@", comment: "Save Config for %@"), nodeName)
Button(buttonText) {
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode != nil {
var rtc = ModuleConfig.RangeTestConfig()
@ -96,7 +96,7 @@ struct RangeTestConfig: View {
self.save = node?.rangeTestConfig?.save ?? false
self.sender = Int(node?.rangeTestConfig?.sender ?? 0)
self.hasChanges = false
// Need to request a RangeTestModule Config from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.rangeTestConfig == nil {
print("empty range test module config")

View file

@ -7,16 +7,16 @@
import SwiftUI
struct SerialConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var enabled = false
@State var echo = false
@State var rxd = 0
@ -24,21 +24,21 @@ struct SerialConfig: View {
@State var baudRate = 0
@State var timeout = 0
@State var mode = 0
var body: some View {
VStack {
Form {
Section(header: Text("options")) {
Toggle(isOn: $enabled) {
Label("enabled", systemImage: "terminal")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $echo) {
Label("echo", systemImage: "repeat")
@ -46,14 +46,14 @@ struct SerialConfig: View {
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Text("If set, any packets you send will be echoed back to your device.")
.font(.caption)
Picker("Baud", selection: $baudRate ) {
ForEach(SerialBaudRates.allCases) { sbr in
Text(sbr.description)
}
}
.pickerStyle(DefaultPickerStyle())
Picker("timeout", selection: $timeout ) {
ForEach(SerialTimeoutIntervals.allCases) { sti in
Text(sti.description)
@ -62,7 +62,7 @@ struct SerialConfig: View {
.pickerStyle(DefaultPickerStyle())
Text("The amount of time to wait before we consider your packet as done.")
.font(.caption)
Picker("mode", selection: $mode ) {
ForEach(SerialModeTypes.allCases) { smt in
Text(smt.description)
@ -71,7 +71,7 @@ struct SerialConfig: View {
.pickerStyle(DefaultPickerStyle())
}
Section(header: Text("GPIO")) {
Picker("Receive data (rxd) GPIO pin", selection: $rxd) {
ForEach(0..<40) {
if $0 == 0 {
@ -98,13 +98,13 @@ struct SerialConfig: View {
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.serialConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
@ -113,7 +113,7 @@ struct SerialConfig: View {
.controlSize(.large)
.padding()
.confirmationDialog(
"are.you.sure",
isPresented: $isPresentingSaveConfirm,
titleVisibility: .visible
@ -131,9 +131,9 @@ struct SerialConfig: View {
sc.baud = SerialBaudRates(rawValue: baudRate)!.protoEnumValue()
sc.timeout = UInt32(timeout)
sc.mode = SerialModeTypes(rawValue: mode)!.protoEnumValue()
let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
@ -153,7 +153,7 @@ struct SerialConfig: View {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
self.bleManager.context = context
self.enabled = node?.serialConfig?.enabled ?? false
self.echo = node?.serialConfig?.echo ?? false
@ -163,7 +163,7 @@ struct SerialConfig: View {
self.timeout = Int(node?.serialConfig?.timeout ?? 0)
self.mode = Int(node?.serialConfig?.mode ?? 0)
self.hasChanges = false
// Need to request a SerialModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.serialConfig == nil {
print("empty serial module config")
@ -175,51 +175,51 @@ struct SerialConfig: View {
}
.onChange(of: enabled) { newEnabled in
if node != nil && node!.serialConfig != nil {
if newEnabled != node!.serialConfig!.enabled { hasChanges = true }
}
}
.onChange(of: echo) { newEcho in
if node != nil && node!.serialConfig != nil {
if newEcho != node!.serialConfig!.echo { hasChanges = true }
}
}
.onChange(of: rxd) { newRxd in
if node != nil && node!.serialConfig != nil {
if newRxd != node!.serialConfig!.rxd { hasChanges = true }
}
}
.onChange(of: txd) { newTxd in
if node != nil && node!.serialConfig != nil {
if newTxd != node!.serialConfig!.txd { hasChanges = true }
}
}
.onChange(of: baudRate) { newBaud in
if node != nil && node!.serialConfig != nil {
if newBaud != node!.serialConfig!.baudRate { hasChanges = true }
}
}
.onChange(of: timeout) { newTimeout in
if node != nil && node!.serialConfig != nil {
if newTimeout != node!.serialConfig!.timeout { hasChanges = true }
}
}
.onChange(of: mode) { newMode in
if node != nil && node!.serialConfig != nil {
if newMode != node!.serialConfig!.mode { hasChanges = true }
}
}

View file

@ -7,13 +7,13 @@
import SwiftUI
struct TelemetryConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var deviceUpdateInterval = 0
@ -21,9 +21,9 @@ struct TelemetryConfig: View {
@State var environmentMeasurementEnabled = false
@State var environmentScreenEnabled = false
@State var environmentDisplayFahrenheit = false
var body: some View {
VStack {
Form {
Section(header: Text("update.interval")) {
@ -88,7 +88,7 @@ struct TelemetryConfig: View {
tc.environmentMeasurementEnabled = environmentMeasurementEnabled
tc.environmentScreenEnabled = environmentScreenEnabled
tc.environmentDisplayFahrenheit = environmentDisplayFahrenheit
let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
// for now just disable the button after a successful save
@ -114,7 +114,7 @@ struct TelemetryConfig: View {
self.environmentScreenEnabled = node?.telemetryConfig?.environmentScreenEnabled ?? false
self.environmentDisplayFahrenheit = node?.telemetryConfig?.environmentDisplayFahrenheit ?? false
self.hasChanges = false
// Need to request a TelemetryModuleConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.telemetryConfig == nil {
print("empty telemetry module config")

View file

@ -8,13 +8,13 @@
import SwiftUI
struct NetworkConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges: Bool = false
@State var wifiEnabled = false
@ -24,13 +24,13 @@ struct NetworkConfig: View {
@State var ntpServer = ""
@State var ethEnabled = false
@State var ethMode = 0
var body: some View {
VStack {
Form {
Section(header: Text("WiFi Options (ESP32 Only)")) {
Toggle(isOn: $wifiEnabled) {
Label("enabled", systemImage: "wifi")
}
@ -41,7 +41,7 @@ struct NetworkConfig: View {
.foregroundColor(.gray)
.autocapitalization(.none)
.disableAutocorrection(true)
.onChange(of: wifiSsid, perform: { value in
.onChange(of: wifiSsid, perform: { _ in
let totalBytes = wifiSsid.utf8.count
// Only mess with the value if it is too big
if totalBytes > 32 {
@ -51,7 +51,7 @@ struct NetworkConfig: View {
wifiSsid = maxBytesString
}
}
hasChanges = true
hasChanges = true
})
.foregroundColor(.gray)
}
@ -62,7 +62,7 @@ struct NetworkConfig: View {
.foregroundColor(.gray)
.autocapitalization(.none)
.disableAutocorrection(true)
.onChange(of: wifiPsk, perform: { value in
.onChange(of: wifiPsk, perform: { _ in
let totalBytes = wifiPsk.utf8.count
// Only mess with the value if it is too big
if totalBytes > 63 {
@ -117,8 +117,8 @@ struct NetworkConfig: View {
network.wifiSsid = self.wifiSsid
network.wifiPsk = self.wifiPsk
network.ethEnabled = self.ethEnabled
//network.addressMode = Config.NetworkConfig.AddressMode.dhcp
// network.addressMode = Config.NetworkConfig.AddressMode.dhcp
let adminMessageId = bleManager.saveNetworkConfig(config: network, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: node?.myInfo?.adminIndex ?? 0)
if adminMessageId > 0 {
// Should show a saved successfully alert once I know that to be true
@ -145,7 +145,7 @@ struct NetworkConfig: View {
self.wifiMode = Int(node?.networkConfig?.wifiMode ?? 0)
self.ethEnabled = node?.networkConfig?.ethEnabled ?? false
self.hasChanges = false
// Need to request a NetworkConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.positionConfig == nil {
print("empty network config")

View file

@ -7,10 +7,9 @@
import SwiftUI
struct PositionFlags: OptionSet
{
struct PositionFlags: OptionSet {
let rawValue: Int
static let Altitude = PositionFlags(rawValue: 1)
static let AltitudeMsl = PositionFlags(rawValue: 2)
static let GeoidalSeparation = PositionFlags(rawValue: 4)
@ -24,17 +23,17 @@ struct PositionFlags: OptionSet
}
struct PositionConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@State var hasFlagChanges = false
@State var smartPositionEnabled = true
@State var deviceGpsEnabled = true
@State var fixedPosition = false
@ -42,7 +41,7 @@ struct PositionConfig: View {
@State var gpsAttemptTime = 0
@State var positionBroadcastSeconds = 0
@State var positionFlags = 3
/// Position Flags
/// Altitude value - 1
@State var includeAltitude = false
@ -68,9 +67,9 @@ struct PositionConfig: View {
/// Intended for use with vehicle not walking speeds
/// walking speeds are likely to be error prone like the compass
@State var includeHeading = false
var body: some View {
VStack {
Form {
Section(header: Text("Device GPS")) {
@ -103,36 +102,36 @@ struct PositionConfig: View {
.font(.caption)
}
}
Section(header: Text("Position Packet")) {
Toggle(isOn: $smartPositionEnabled) {
Label("Smart Position Broadcast", systemImage: "location.fill.viewfinder")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Picker("Position Broadcast Interval", selection: $positionBroadcastSeconds) {
ForEach(UpdateIntervals.allCases) { at in
Text(at.description)
}
}
.pickerStyle(DefaultPickerStyle())
Text("We should send our position this often (but only if it has changed significantly)")
.font(.caption)
}
Section(header: Text("Position Flags")) {
Text("Optional fields to include when assembling position messages. the more fields are included, the larger the message will be - leading to longer airtime and a higher risk of packet loss")
.font(.caption)
.listRowSeparator(.visible)
Toggle(isOn: $includeAltitude) {
Label("Altitude", systemImage: "arrow.up")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if includeAltitude {
Toggle(isOn: $includeAltitudeMsl) {
Label("Altitude is Mean Sea Level", systemImage: "arrow.up.to.line.compact")
@ -143,40 +142,40 @@ struct PositionConfig: View {
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
Toggle(isOn: $includeSatsinview) {
Label("Number of satellites", systemImage: "skew")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $includeSeqNo) { //64
Toggle(isOn: $includeSeqNo) { // 64
Label("Sequence number", systemImage: "number")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $includeTimestamp) { //128
Toggle(isOn: $includeTimestamp) { // 128
Label("timestamp", systemImage: "clock")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $includeHeading) { //128
Toggle(isOn: $includeHeading) { // 128
Label("Vehicle heading", systemImage: "location.circle")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
Toggle(isOn: $includeSpeed) { //128
Toggle(isOn: $includeSpeed) { // 128
Label("Vehicle speed", systemImage: "speedometer")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
Section(header: Text("Advanced Position Flags")) {
Toggle(isOn: $includeDop) {
Text("Dilution of precision (DOP) PDOP used by default")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if includeDop {
Toggle(isOn: $includeHvdop) {
Text("If DOP is set use, HDOP / VDOP values instead of PDOP")
@ -186,7 +185,7 @@ struct PositionConfig: View {
}
}
.disabled(self.bleManager.connectedPeripheral == nil || node?.positionConfig == nil)
Button {
isPresentingSaveConfirm = true
} label: {
@ -205,12 +204,12 @@ struct PositionConfig: View {
let nodeName = node?.user?.longName ?? NSLocalizedString("unknown", comment: "Unknown")
let buttonText = String.localizedStringWithFormat(NSLocalizedString("save.config %@", comment: "Save Config for %@"), nodeName)
Button(buttonText) {
if fixedPosition {
_ = bleManager.sendPosition(destNum: node!.num, wantResponse: true)
}
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context)
if connectedNode != nil {
var pc = Config.PositionConfig()
pc.positionBroadcastSmartEnabled = smartPositionEnabled
@ -219,7 +218,7 @@ struct PositionConfig: View {
pc.gpsUpdateInterval = UInt32(gpsUpdateInterval)
pc.gpsAttemptTime = UInt32(gpsAttemptTime)
pc.positionBroadcastSecs = UInt32(positionBroadcastSeconds)
var pf : PositionFlags = []
var pf: PositionFlags = []
if includeAltitude { pf.insert(.Altitude) }
if includeAltitudeMsl { pf.insert(.AltitudeMsl) }
if includeGeoidalSeparation { pf.insert(.GeoidalSeparation) }
@ -253,7 +252,7 @@ struct PositionConfig: View {
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
})
.onAppear {
self.bleManager.context = context
self.smartPositionEnabled = node?.positionConfig?.smartPositionEnabled ?? true
self.deviceGpsEnabled = node?.positionConfig?.deviceGpsEnabled ?? true
@ -262,9 +261,9 @@ struct PositionConfig: View {
self.gpsAttemptTime = Int(node?.positionConfig?.gpsAttemptTime ?? 30)
self.positionBroadcastSeconds = Int(node?.positionConfig?.positionBroadcastSeconds ?? 900)
self.positionFlags = Int(node?.positionConfig?.positionFlags ?? 3)
let pf = PositionFlags(rawValue: self.positionFlags)
if pf.contains(.Altitude) { self.includeAltitude = true } else { self.includeAltitude = false }
if pf.contains(.AltitudeMsl) { self.includeAltitudeMsl = true } else { self.includeAltitudeMsl = false }
if pf.contains(.GeoidalSeparation) { self.includeGeoidalSeparation = true } else { self.includeGeoidalSeparation = false }
@ -275,9 +274,9 @@ struct PositionConfig: View {
if pf.contains(.Timestamp) { self.includeTimestamp = true } else { self.includeTimestamp = false }
if pf.contains(.Speed) { self.includeSpeed = true } else { self.includeSpeed = false }
if pf.contains(.Heading) { self.includeHeading = true } else { self.includeHeading = false }
self.hasChanges = false
// Need to request a PositionConfig from the remote node before allowing changes
if bleManager.connectedPeripheral != nil && node?.positionConfig == nil {
print("empty position config")

View file

@ -10,7 +10,7 @@ struct MeshLog: View {
@State private var document: LogDocument = LogDocument(logFile: "MESHTASTIC MESH ACTIVITY LOG\n")
var body: some View {
List(logs, id: \.self, rowContent: Text.init)
.task {
do {
@ -55,7 +55,7 @@ struct MeshLog: View {
)
.textSelection(.enabled)
.font(.caption)
HStack(alignment: .center) {
Spacer()
Button(role: .destructive) {
@ -74,7 +74,7 @@ struct MeshLog: View {
.controlSize(.large)
.padding()
Spacer()
Button {
isExporting = true
} label: {

View file

@ -7,9 +7,9 @@
import SwiftUI
struct SaveChannelQRCode: View {
@Environment(\.dismiss) private var dismiss
var channelSetLink: String
var bleManager: BLEManager
@State var connectedToDevice = false
@ -22,15 +22,15 @@ struct SaveChannelQRCode: View {
.foregroundColor(.gray)
.font(.callout)
.padding()
HStack {
Button {
let success = bleManager.saveChannelSet(base64UrlString: channelSetLink)
if success {
dismiss()
}
} label: {
Label("save", systemImage: "square.and.arrow.down")
}
@ -39,13 +39,13 @@ struct SaveChannelQRCode: View {
.controlSize(.large)
.padding()
.disabled(!connectedToDevice)
#if targetEnvironment(macCatalyst)
Button {
dismiss()
} label: {
Label("cancel", systemImage: "xmark")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)

View file

@ -8,7 +8,7 @@
import SwiftUI
struct Settings: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@EnvironmentObject var userSettings: UserSettings
@ -17,9 +17,9 @@ struct Settings: View {
@State private var selectedNode: Int = 0
@State private var connectedNodeNum: Int = 0
@State private var initialLoad: Bool = true
@State private var selection: SettingsSidebar = .about
enum SettingsSidebar {
case appSettings
case shareChannels
@ -41,11 +41,11 @@ struct Settings: View {
case adminMessageLog
case about
}
var body: some View {
NavigationSplitView {
List {
NavigationLink() {
NavigationLink {
AppSettings()
} label: {
Image(systemName: "gearshape")
@ -80,10 +80,10 @@ struct Settings: View {
let node = nodes.first(where: { $0.num == newValue })
let connectedNode = nodes.first(where: { $0.num == connectedNodeNum })
connectedNodeNum = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral?.num ?? 0 : 0)
if node?.metadata == nil {
let adminMessageId = bleManager.requestDeviceMetadata(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex, context: context)
if adminMessageId > 0 {
print("Sent node metadata request from node details")
}
@ -92,9 +92,9 @@ struct Settings: View {
}
}
}
Section("radio.configuration") {
NavigationLink {
ShareChannels(node: nodes.first(where: { $0.num == connectedNodeNum }))
} label: {
@ -104,18 +104,18 @@ struct Settings: View {
}
.tag(SettingsSidebar.shareChannels)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink {
UserConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
Image(systemName: "person.crop.rectangle.fill")
.symbolRenderingMode(.hierarchical)
Text("user")
}
.tag(SettingsSidebar.userConfig)
NavigationLink() {
NavigationLink {
LoRaConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
Image(systemName: "dot.radiowaves.left.and.right")
@ -123,8 +123,8 @@ struct Settings: View {
Text("lora")
}
.tag(SettingsSidebar.loraConfig)
NavigationLink() {
NavigationLink {
Channels(node: nodes.first(where: { $0.num == connectedNodeNum }))
} label: {
Image(systemName: "fibrechannel")
@ -133,8 +133,8 @@ struct Settings: View {
}
.tag(SettingsSidebar.channelConfig)
.disabled(selectedNode > 0 && selectedNode != connectedNodeNum)
NavigationLink() {
NavigationLink {
BluetoothConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
Image(systemName: "antenna.radiowaves.left.and.right")
@ -142,7 +142,7 @@ struct Settings: View {
Text("bluetooth")
}
.tag(SettingsSidebar.bluetoothConfig)
NavigationLink {
DeviceConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -151,7 +151,7 @@ struct Settings: View {
Text("device")
}
.tag(SettingsSidebar.deviceConfig)
NavigationLink {
DisplayConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -160,30 +160,30 @@ struct Settings: View {
Text("display")
}
.tag(SettingsSidebar.displayConfig)
NavigationLink {
NetworkConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
Image(systemName: "network")
.symbolRenderingMode(.hierarchical)
Text("network")
}
.tag(SettingsSidebar.networkConfig)
NavigationLink {
PositionConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
Image(systemName: "location")
.symbolRenderingMode(.hierarchical)
Text("position")
}
.tag(SettingsSidebar.positionConfig)
}
Section("module.configuration") {
NavigationLink {
CannedMessagesConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -194,7 +194,7 @@ struct Settings: View {
Text("canned.messages")
}
.tag(SettingsSidebar.cannedMessagesConfig)
NavigationLink {
ExternalNotificationConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -203,7 +203,7 @@ struct Settings: View {
Text("external.notification")
}
.tag(SettingsSidebar.externalNotificationConfig)
NavigationLink {
MQTTConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -212,7 +212,7 @@ struct Settings: View {
Text("mqtt")
}
.tag(SettingsSidebar.mqttConfig)
NavigationLink {
RangeTestConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -221,7 +221,7 @@ struct Settings: View {
Text("range.test")
}
.tag(SettingsSidebar.rangeTestConfig)
NavigationLink {
SerialConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -230,7 +230,7 @@ struct Settings: View {
Text("serial")
}
.tag(SettingsSidebar.serialConfig)
NavigationLink {
TelemetryConfig(node: nodes.first(where: { $0.num == selectedNode }))
} label: {
@ -249,7 +249,7 @@ struct Settings: View {
Text("mesh.log")
}
.tag(SettingsSidebar.meshLog)
NavigationLink {
let connectedNode = nodes.first(where: { $0.num == connectedNodeNum })
AdminMessageList(user: connectedNode?.user)
@ -266,7 +266,7 @@ struct Settings: View {
} label: {
Image(systemName: "questionmark.app")
.symbolRenderingMode(.hierarchical)
Text("about.meshtastic")
}
.tag(SettingsSidebar.about)
@ -280,7 +280,7 @@ struct Settings: View {
selectedNode = Int(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral?.num ?? 0 : 0)
initialLoad = false
}
}
.listStyle(GroupedListStyle())
.navigationTitle("settings")

View file

@ -10,13 +10,13 @@ import CoreImage.CIFilterBuiltins
struct QrCodeImage {
let context = CIContext()
func generateQRCode(from text: String) -> UIImage {
var qrImage = UIImage(systemName: "xmark.circle") ?? UIImage()
let data = Data(text.utf8)
let filter = CIFilter.qrCodeGenerator()
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 20, y: 20)
if let outputImage = filter.outputImage?.transformed(by: transform) {
if let image = context.createCGImage(
@ -30,7 +30,7 @@ struct QrCodeImage {
}
struct ShareChannels: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var dismiss
@ -47,13 +47,13 @@ struct ShareChannels: View {
var node: NodeInfoEntity?
@State private var channelsUrl = "https://www.meshtastic.org/e/#"
var qrCodeImage = QrCodeImage()
var body: some View {
GeometryReader { bounds in
let smallest = min(bounds.size.width, bounds.size.height)
ScrollView {
if node != nil && node?.myInfo != nil {
Grid() {
Grid {
GridRow {
Spacer()
Text("include")
@ -195,7 +195,7 @@ struct ShareChannels: View {
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding(.bottom)
Image(uiImage: qrImage)
.resizable()
.scaledToFit()
@ -227,21 +227,21 @@ struct ShareChannels: View {
Text("Primary Channel").font(.title2)
Text("The first channel is the Primary channel and is where much of the mesh activity takes place. DM's are only available on the primary channel and it can not be disabled.")
.font(.callout)
.padding([.leading,.trailing,.bottom])
.padding([.leading, .trailing, .bottom])
Text("Admin Channel").font(.title2)
Text("A channel with the name 'admin' is the Admin channel and can be used to remotely administer nodes on your mesh, text messages can not be sent over the admin channel.")
.font(.callout)
.padding([.leading,.trailing,.bottom])
.padding([.leading, .trailing, .bottom])
Text("Private Channels").font(.title2)
Text("The other channels can be used for private group converations. Each of these groups has its own encryption key.")
.font(.callout)
.padding([.leading,.trailing,.bottom])
.padding([.leading, .trailing, .bottom])
Divider()
}
.padding()
.presentationDetents([.large])
.presentationDragIndicator(.automatic)
#if targetEnvironment(macCatalyst)
Button {
isPresentingHelp = false
@ -264,13 +264,13 @@ struct ShareChannels: View {
bleManager.context = context
GenerateChannelSet()
}
.onChange(of: includeChannel1) { includeCh1 in GenerateChannelSet() }
.onChange(of: includeChannel2) { includeCh2 in GenerateChannelSet() }
.onChange(of: includeChannel3) { includeCh3 in GenerateChannelSet() }
.onChange(of: includeChannel4) { includeCh4 in GenerateChannelSet() }
.onChange(of: includeChannel5) { includeCh5 in GenerateChannelSet() }
.onChange(of: includeChannel6) { includeCh6 in GenerateChannelSet() }
.onChange(of: includeChannel7) { includeCh7 in GenerateChannelSet() }
.onChange(of: includeChannel1) { _ in GenerateChannelSet() }
.onChange(of: includeChannel2) { _ in GenerateChannelSet() }
.onChange(of: includeChannel3) { _ in GenerateChannelSet() }
.onChange(of: includeChannel4) { _ in GenerateChannelSet() }
.onChange(of: includeChannel5) { _ in GenerateChannelSet() }
.onChange(of: includeChannel6) { _ in GenerateChannelSet() }
.onChange(of: includeChannel7) { _ in GenerateChannelSet() }
}
}
func GenerateChannelSet() {
@ -291,10 +291,10 @@ struct ShareChannels: View {
if node?.myInfo?.channels != nil && node?.myInfo?.channels?.count ?? 0 > 0 {
for ch in node!.myInfo!.channels!.array as! [ChannelEntity] {
if ch.role > 0 {
if ch.index == 0 && includeChannel0 || ch.index == 1 && includeChannel1 || ch.index == 2 && includeChannel2 || ch.index == 3 && includeChannel3 ||
ch.index == 4 && includeChannel4 || ch.index == 5 && includeChannel5 || ch.index == 6 && includeChannel6 || ch.index == 7 && includeChannel7 {
ch.index == 4 && includeChannel4 || ch.index == 5 && includeChannel5 || ch.index == 6 && includeChannel6 || ch.index == 7 && includeChannel7 {
var channelSettings = ChannelSettings()
channelSettings.name = ch.name!
channelSettings.psk = ch.psk!

View file

@ -8,17 +8,17 @@ import SwiftUI
import CoreData
struct UserConfig: View {
@Environment(\.managedObjectContext) var context
@EnvironmentObject var bleManager: BLEManager
@Environment(\.dismiss) private var goBack
var node: NodeInfoEntity?
enum Field: Hashable {
case frequencyOverride
}
@State private var isPresentingFactoryResetConfirm: Bool = false
@State private var isPresentingSaveConfirm: Bool = false
@State var hasChanges = false
@ -28,24 +28,24 @@ struct UserConfig: View {
@State var overrideDutyCycle = false
@State var overrideFrequency: Float = 0.0
@State var txPower = 0
@FocusState var focusedField: Field?
let floatFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
var body: some View {
VStack {
Form {
Section(header: Text("User Details")) {
HStack {
Label(isLicensed ? "Call Sign" : "Long Name", systemImage: "person.crop.rectangle.fill")
TextField("Long Name", text: $longName)
.onChange(of: longName, perform: { value in
.onChange(of: longName, perform: { _ in
let totalBytes = longName.utf8.count
// Only mess with the value if it is too big
if totalBytes > (isLicensed ? 8 : 36) {
@ -61,12 +61,12 @@ struct UserConfig: View {
.disableAutocorrection(true)
Text("\(String(isLicensed ? "Call Sign" : "Long Name")) can be up to \(isLicensed ? "8" : "36") bytes long.")
.font(.caption2)
HStack {
Label("Short Name", systemImage: "circlebadge.fill")
TextField("Short Name", text: $shortName)
.foregroundColor(.gray)
.onChange(of: shortName, perform: { value in
.onChange(of: shortName, perform: { _ in
let totalBytes = shortName.utf8.count
// Only mess with the value if it is too big
if totalBytes > 4 {
@ -83,20 +83,20 @@ struct UserConfig: View {
.disableAutocorrection(true)
Text("The last 4 of the device MAC address will be appended to the short name to set the device's BLE Name. Short name can be up to 4 bytes long.")
.font(.caption2)
// Only manage ham mode for the locally connected node
if node?.num ?? 0 > 0 && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
if node?.num ?? 0 > 0 && node?.num ?? 0 == bleManager.connectedPeripheral?.num ?? 0 {
Toggle(isOn: $isLicensed) {
Label("Licensed Operator", systemImage: "person.text.rectangle")
}
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
if isLicensed {
Text("Onboarding for licensed operators requires firmware 2.0.20 or greater. Make sure to refer to your local regulations and contact the local amateur frequency coordinators with questions.")
.font(.caption2)
Text("What licensed operator mode does:\n* Sets the node name to your call sign \n* Broadcasts node info every 10 minutes \n* Overrides frequency, dutycycle and tx power \n* Disables encryption")
.font(.caption2)
HStack {
Label("Frequency", systemImage: "waveform.path.ecg")
Spacer()
@ -141,11 +141,11 @@ struct UserConfig: View {
titleVisibility: .visible
) {
Button("Save User Config to \(node?.user?.longName ?? "Unknown")?") {
let connectedUser = getUser(id: bleManager.connectedPeripheral?.num ?? -1, context: context)
let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? -1, context: context)
if node != nil && connectedNode != nil {
if !isLicensed {
var u = User()
u.shortName = shortName
@ -157,7 +157,7 @@ struct UserConfig: View {
}
} else {
var ham = HamParameters()
//ham.shortName = shortName
// ham.shortName = shortName
ham.callSign = longName
ham.txPower = Int32(txPower)
ham.frequency = overrideFrequency
@ -204,11 +204,11 @@ struct UserConfig: View {
if newIsLicensed != node?.user!.isLicensed { hasChanges = true }
}
}
.onChange(of: overrideFrequency) { newOverrideFrequency in
//hasChanges = true
.onChange(of: overrideFrequency) { _ in
// hasChanges = true
}
.onChange(of: txPower) { newTxPower in
//hasChanges = true
.onChange(of: txPower) { _ in
// hasChanges = true
}
}
}

Some files were not shown because too many files have changed in this diff Show more