diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 0191e8c6..b0ebd248 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -97,7 +97,7 @@ DDB6ABD628AE742000384BA1 /* BluetoothConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABD528AE742000384BA1 /* BluetoothConfig.swift */; }; DDB6ABD928B0A4BA00384BA1 /* BluetoothModes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABD828B0A4BA00384BA1 /* BluetoothModes.swift */; }; DDB6ABDB28B0AC6000384BA1 /* DistanceText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABDA28B0AC6000384BA1 /* DistanceText.swift */; }; - DDB6ABE028B13AC700384BA1 /* DeviceRoles.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABDF28B13AC700384BA1 /* DeviceRoles.swift */; }; + DDB6ABE028B13AC700384BA1 /* DeviceEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABDF28B13AC700384BA1 /* DeviceEnums.swift */; }; DDB6ABE228B13FB500384BA1 /* PositionConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */; }; DDB6ABE428B13FFF00384BA1 /* DisplayEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE328B13FFF00384BA1 /* DisplayEnums.swift */; }; DDB6ABE628B1406100384BA1 /* LoraConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */; }; @@ -264,7 +264,7 @@ DDB6ABD528AE742000384BA1 /* BluetoothConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothConfig.swift; sourceTree = ""; }; DDB6ABD828B0A4BA00384BA1 /* BluetoothModes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothModes.swift; sourceTree = ""; }; DDB6ABDA28B0AC6000384BA1 /* DistanceText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistanceText.swift; sourceTree = ""; }; - DDB6ABDF28B13AC700384BA1 /* DeviceRoles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRoles.swift; sourceTree = ""; }; + DDB6ABDF28B13AC700384BA1 /* DeviceEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceEnums.swift; sourceTree = ""; }; DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionConfigEnums.swift; sourceTree = ""; }; DDB6ABE328B13FFF00384BA1 /* DisplayEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayEnums.swift; sourceTree = ""; }; DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoraConfigEnums.swift; sourceTree = ""; }; @@ -290,6 +290,7 @@ DDD3BBD4292D763200D609B3 /* MeshtasticTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeshtasticTests.swift; sourceTree = ""; }; DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeText.swift; sourceTree = ""; }; DDD9E4E3284B208E003777C5 /* UserEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserEntityExtension.swift; sourceTree = ""; }; + DDDD527729B5B83F0045BC3C /* MeshtasticDataModelV9.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV9.xcdatamodel; sourceTree = ""; }; DDDE59F429AF163D00490C6C /* WidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; DDDE59F829AF163D00490C6C /* WidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetsBundle.swift; sourceTree = ""; }; DDDE59FA29AF163D00490C6C /* WidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetsLiveActivity.swift; sourceTree = ""; }; @@ -478,7 +479,7 @@ DDB6ABD828B0A4BA00384BA1 /* BluetoothModes.swift */, DD1925B628CDA5A400720036 /* CannedMessagesConfigEnums.swift */, DDA1C48D28DB49D3009933EC /* ChannelRoles.swift */, - DDB6ABDF28B13AC700384BA1 /* DeviceRoles.swift */, + DDB6ABDF28B13AC700384BA1 /* DeviceEnums.swift */, DDB6ABE328B13FFF00384BA1 /* DisplayEnums.swift */, DD5D0A9B2931B9F200F7EA61 /* EthernetModes.swift */, DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */, @@ -937,7 +938,7 @@ C9A88B55278B503C00BD810A /* MapViewModule.swift in Sources */, DD2553592855B52700E55709 /* PositionConfig.swift in Sources */, DD97E96828EFE9A00056DDA4 /* About.swift in Sources */, - DDB6ABE028B13AC700384BA1 /* DeviceRoles.swift in Sources */, + DDB6ABE028B13AC700384BA1 /* DeviceEnums.swift in Sources */, DD86D40C287F401000BAEB7A /* SaveChannelQRCode.swift in Sources */, DDA1C48E28DB49D3009933EC /* ChannelRoles.swift in Sources */, DD8ED9C8289CE4B900B3B0AB /* RoutingError.swift in Sources */, @@ -1468,6 +1469,7 @@ DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + DDDD527729B5B83F0045BC3C /* MeshtasticDataModelV9.xcdatamodel */, DDBA45EC299ED78100DEEDDC /* MeshtasticDataModelV8.xcdatamodel */, DD5E51CC2986643400D21B61 /* MeshtasticDataModelV7.xcdatamodel */, DD964FC029724F6D007C176F /* MeshtasticDataModelV6.xcdatamodel */, @@ -1477,7 +1479,7 @@ DD5D0A9A2931AD6B00F7EA61 /* MeshtasticDataModelV2.xcdatamodel */, DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */, ); - currentVersion = DDBA45EC299ED78100DEEDDC /* MeshtasticDataModelV8.xcdatamodel */; + currentVersion = DDDD527729B5B83F0045BC3C /* MeshtasticDataModelV9.xcdatamodel */; name = Meshtastic.xcdatamodeld; path = Meshtastic/Meshtastic.xcdatamodeld; sourceTree = ""; diff --git a/Meshtastic/Enums/DeviceRoles.swift b/Meshtastic/Enums/DeviceEnums.swift similarity index 73% rename from Meshtastic/Enums/DeviceRoles.swift rename to Meshtastic/Enums/DeviceEnums.swift index 9691a52d..a9926b04 100644 --- a/Meshtastic/Enums/DeviceRoles.swift +++ b/Meshtastic/Enums/DeviceEnums.swift @@ -82,3 +82,49 @@ enum DeviceRoles: Int, CaseIterable, Identifiable { } } } + +enum RebroadcastModes: Int, CaseIterable, Identifiable { + + case all = 0 + case allSkipDecoding = 1 + case localOnly = 2 + + var id: Int { self.rawValue } + + var name: String { + get { + switch self { + + case .all: + return "All" + case .allSkipDecoding: + return "All Skip Decoding" + case .localOnly: + return "Local Only" + } + } + } + var description: String { + get { + switch self { + case .all: + return "Rebroadcast any observed message, if it was on our private channel or from another mesh with the same lora params." + case .allSkipDecoding: + return "Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior." + case .localOnly: + return "Inverted top bar for 2 Color display" + } + } + } + func protoEnumValue() -> Config.DeviceConfig.RebroadcastMode { + + switch self { + case .all: + return Config.DeviceConfig.RebroadcastMode.all + case .allSkipDecoding: + return Config.DeviceConfig.RebroadcastMode.allSkipDecoding + case .localOnly: + return Config.DeviceConfig.RebroadcastMode.localOnly + } + } +} diff --git a/Meshtastic/Enums/DisplayEnums.swift b/Meshtastic/Enums/DisplayEnums.swift index 52bde654..6774fd18 100644 --- a/Meshtastic/Enums/DisplayEnums.swift +++ b/Meshtastic/Enums/DisplayEnums.swift @@ -36,6 +36,8 @@ enum ScreenUnits: Int, CaseIterable, Identifiable { enum ScreenOnIntervals: Int, CaseIterable, Identifiable { + case fifteenSeconds = 15 + case thirtySeconds = 30 case oneMinute = 60 case fiveMinutes = 300 case tenMinutes = 600 @@ -48,6 +50,10 @@ enum ScreenOnIntervals: Int, CaseIterable, Identifiable { var description: String { get { switch self { + case .fifteenSeconds: + return NSLocalizedString("interval.fifteen.seconds", comment: "Fifteen Seconds") + case .thirtySeconds: + return NSLocalizedString("interval.thirty.seconds", comment: "Thirty Seconds") case .oneMinute: return NSLocalizedString("interval.one.minute", comment: "One Minute") case .fiveMinutes: diff --git a/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion b/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion index 25c323b3..6e12995e 100644 --- a/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion +++ b/Meshtastic/Meshtastic.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - MeshtasticDataModelV8.xcdatamodel + MeshtasticDataModelV9.xcdatamodel diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV9.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV9.xcdatamodel/contents new file mode 100644 index 00000000..13847836 --- /dev/null +++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV9.xcdatamodel/contents @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index e04170a6..4c98e4b1 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -232,6 +232,8 @@ func upsertDeviceConfigPacket(config: Meshtastic.Config.DeviceConfig, nodeNum: I newDeviceConfig.debugLogEnabled = config.debugLogEnabled newDeviceConfig.buttonGpio = Int32(config.buttonGpio) newDeviceConfig.buzzerGpio = Int32(config.buzzerGpio) + newDeviceConfig.rebroadcastMode = Int32(config.rebroadcastMode.rawValue) + newDeviceConfig.nodeInfoBroadcastSecs = Int32(config.nodeInfoBroadcastSecs) fetchedNode[0].deviceConfig = newDeviceConfig } else { fetchedNode[0].deviceConfig?.role = Int32(config.role.rawValue) @@ -239,6 +241,8 @@ func upsertDeviceConfigPacket(config: Meshtastic.Config.DeviceConfig, nodeNum: I fetchedNode[0].deviceConfig?.debugLogEnabled = config.debugLogEnabled fetchedNode[0].deviceConfig?.buttonGpio = Int32(config.buttonGpio) fetchedNode[0].deviceConfig?.buzzerGpio = Int32(config.buzzerGpio) + fetchedNode[0].deviceConfig?.rebroadcastMode = Int32(config.rebroadcastMode.rawValue) + fetchedNode[0].deviceConfig?.nodeInfoBroadcastSecs = Int32(config.nodeInfoBroadcastSecs) } do { try context.save() @@ -280,8 +284,10 @@ func upsertDisplayConfigPacket(config: Meshtastic.Config.DisplayConfig, nodeNum: newDisplayConfig.flipScreen = config.flipScreen newDisplayConfig.oledType = Int32(config.oled.rawValue) newDisplayConfig.displayMode = Int32(config.displaymode.rawValue) + newDisplayConfig.headingBold = config.headingBold fetchedNode[0].displayConfig = newDisplayConfig + } else { fetchedNode[0].displayConfig?.gpsFormat = Int32(config.gpsFormat.rawValue) @@ -291,6 +297,7 @@ func upsertDisplayConfigPacket(config: Meshtastic.Config.DisplayConfig, nodeNum: fetchedNode[0].displayConfig?.flipScreen = config.flipScreen fetchedNode[0].displayConfig?.oledType = Int32(config.oled.rawValue) fetchedNode[0].displayConfig?.displayMode = Int32(config.displaymode.rawValue) + fetchedNode[0].displayConfig?.headingBold = config.headingBold } do { diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 7a1f6bba..a0720a06 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -24,6 +24,7 @@ struct DeviceConfig: View { @State var buttonGPIO = 0 @State var serialEnabled = true @State var debugLogEnabled = false + @State var rebroadcastMode = 0 var body: some View { @@ -43,6 +44,17 @@ 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) + } + } + .pickerStyle(DefaultPickerStyle()) + .padding(.top, 10) + Text(RebroadcastModes(rawValue: rebroadcastMode)?.description ?? "") + .foregroundColor(.gray) + .font(.caption) } Section(header: Text("Debug")) { diff --git a/Meshtastic/Views/Settings/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index 7d9fc96e..ff44bb8e 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -13,11 +13,10 @@ struct LoRaConfig: View { enum Field: Hashable { case channelNum } - + let formatter: NumberFormatter = { let formatter = NumberFormatter() formatter.numberStyle = .decimal - formatter.maximumFractionDigits = 2 return formatter }() @@ -37,7 +36,7 @@ struct LoRaConfig: View { @State var txEnabled = true @State var usePreset = true @State var channelNum = 0 - @State var bandwidth = 0.0 + @State var bandwidth = 0 @State var spreadFactor = 0 @State var codingRate = 0 @@ -85,15 +84,15 @@ struct LoRaConfig: View { if !usePreset { HStack { Picker("Bandwidth", selection: $spreadFactor) { - Text("\(31)") + Text("\(31) kHz") .tag(31) - Text("\(62)") + Text("\(62) kHz") .tag(62) - Text("\(125)") + Text("\(125) kHz") .tag(125) - Text("\(250)") + Text("\(250) kHz") .tag(0) - Text("\(500)") + Text("\(500) kHz") .tag(500) } } @@ -125,6 +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() @@ -207,7 +207,7 @@ struct LoRaConfig: View { self.txEnabled = node?.loRaConfig?.txEnabled ?? true self.txPower = Int(node?.loRaConfig?.txPower ?? 0) self.channelNum = Int(node?.loRaConfig?.channelNum ?? 0) - self.bandwidth = Double(node?.loRaConfig?.bandwidth ?? 0) + self.bandwidth = Int(node?.loRaConfig?.bandwidth ?? 0) self.codingRate = Int(node?.loRaConfig?.codingRate ?? 0) self.spreadFactor = Int(node?.loRaConfig?.spreadFactor ?? 0) print("Spreadum: \(self.spreadFactor)") @@ -250,8 +250,7 @@ struct LoRaConfig: View { } .onChange(of: bandwidth) { newBandwidth in if node != nil && node!.loRaConfig != nil { - hasChanges = true - //if newBandwidth != node!.loRaConfig!.bandwidth { hasChanges = true } + if newBandwidth != node!.loRaConfig!.bandwidth { hasChanges = true } } } .onChange(of: codingRate) { newCodingRate in