mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge branch 'main' into debugging/channel-settings
This commit is contained in:
commit
e5825e8154
51 changed files with 3373 additions and 1480 deletions
|
|
@ -22,6 +22,7 @@
|
|||
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2E65252767A01F00E45FC5 /* NodeDetail.swift */; };
|
||||
DD3501892852FC3B000FC853 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3501882852FC3B000FC853 /* Settings.swift */; };
|
||||
DD35018B2852FC79000FC853 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD35018A2852FC79000FC853 /* UserSettings.swift */; };
|
||||
DD4033C228B286B70096A444 /* Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4033C128B286B70096A444 /* Onboarding.swift */; };
|
||||
DD41582628582E9B009B0E59 /* DeviceConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41582528582E9B009B0E59 /* DeviceConfig.swift */; };
|
||||
DD415828285859C4009B0E59 /* TelemetryConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD415827285859C4009B0E59 /* TelemetryConfig.swift */; };
|
||||
DD41582A28585C32009B0E59 /* RangeTestConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41582928585C32009B0E59 /* RangeTestConfig.swift */; };
|
||||
|
|
@ -51,6 +52,8 @@
|
|||
DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD86D4102881D16900BAEB7A /* WriteCsvFile.swift */; };
|
||||
DD882F5D2772E4640005BF05 /* Contacts.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD882F5C2772E4640005BF05 /* Contacts.swift */; };
|
||||
DD8EBF43285058FA00426DCA /* DisplayConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8EBF42285058FA00426DCA /* DisplayConfig.swift */; };
|
||||
DD8ED9C52898D51F00B3B0AB /* WiFiConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8ED9C42898D51F00B3B0AB /* WiFiConfig.swift */; };
|
||||
DD8ED9C8289CE4B900B3B0AB /* RoutingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8ED9C7289CE4B900B3B0AB /* RoutingError.swift */; };
|
||||
DD90860C26F684AF00DC5189 /* BatteryIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860B26F684AF00DC5189 /* BatteryIcon.swift */; };
|
||||
DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD90860D26F69BAE00DC5189 /* NodeMap.swift */; };
|
||||
DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */; };
|
||||
|
|
@ -67,6 +70,15 @@
|
|||
DDAF8C6926ED0D070058C060 /* deviceonly.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6826ED0D070058C060 /* deviceonly.pb.swift */; };
|
||||
DDAF8C6E26ED19040058C060 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAF8C6D26ED19040058C060 /* Extensions.swift */; };
|
||||
DDB2CC6E27F3EB47009C5FCC /* telemetry.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB2CC6D27F3EB47009C5FCC /* telemetry.pb.swift */; };
|
||||
DDB3107228A6224100F1DE3D /* device_metadata.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB3107128A6224100F1DE3D /* device_metadata.pb.swift */; };
|
||||
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 */; };
|
||||
DDB6ABE228B13FB500384BA1 /* PositionConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */; };
|
||||
DDB6ABE428B13FFF00384BA1 /* ScreenIntervals.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE328B13FFF00384BA1 /* ScreenIntervals.swift */; };
|
||||
DDB6ABE628B1406100384BA1 /* LoraConfigEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */; };
|
||||
DDB6ABE828B141AF00384BA1 /* WiFiModes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB6ABE728B141AF00384BA1 /* WiFiModes.swift */; };
|
||||
DDC2E15826CE248E0042C5E4 /* MeshtasticApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E15726CE248E0042C5E4 /* MeshtasticApp.swift */; };
|
||||
DDC2E15C26CE248F0042C5E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */; };
|
||||
DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */; };
|
||||
|
|
@ -115,6 +127,8 @@
|
|||
DD2E65252767A01F00E45FC5 /* NodeDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeDetail.swift; sourceTree = "<group>"; };
|
||||
DD3501882852FC3B000FC853 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
|
||||
DD35018A2852FC79000FC853 /* UserSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettings.swift; sourceTree = "<group>"; };
|
||||
DD4033C128B286B70096A444 /* Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Onboarding.swift; sourceTree = "<group>"; };
|
||||
DD4033C328B405A60096A444 /* MeshtasticDataModel v 8.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModel v 8.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD41582528582E9B009B0E59 /* DeviceConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceConfig.swift; sourceTree = "<group>"; };
|
||||
DD415827285859C4009B0E59 /* TelemetryConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryConfig.swift; sourceTree = "<group>"; };
|
||||
DD41582928585C32009B0E59 /* RangeTestConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RangeTestConfig.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -145,6 +159,10 @@
|
|||
DD86D4102881D16900BAEB7A /* WriteCsvFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteCsvFile.swift; sourceTree = "<group>"; };
|
||||
DD882F5C2772E4640005BF05 /* Contacts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contacts.swift; sourceTree = "<group>"; };
|
||||
DD8EBF42285058FA00426DCA /* DisplayConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayConfig.swift; sourceTree = "<group>"; };
|
||||
DD8ED9C328978D9D00B3B0AB /* MeshtasticDataModel v 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModel v 5.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD8ED9C42898D51F00B3B0AB /* WiFiConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WiFiConfig.swift; sourceTree = "<group>"; };
|
||||
DD8ED9C7289CE4B900B3B0AB /* RoutingError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoutingError.swift; sourceTree = "<group>"; };
|
||||
DD8ED9C9289EA77E00B3B0AB /* MeshtasticDataModel v 6.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModel v 6.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD90860A26F645B700DC5189 /* Meshtastic.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Meshtastic.entitlements; sourceTree = "<group>"; };
|
||||
DD90860B26F684AF00DC5189 /* BatteryIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryIcon.swift; sourceTree = "<group>"; };
|
||||
DD90860D26F69BAE00DC5189 /* NodeMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeMap.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -163,6 +181,16 @@
|
|||
DDAF8C6D26ED19040058C060 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
||||
DDB2CC6D27F3EB47009C5FCC /* telemetry.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = telemetry.pb.swift; sourceTree = "<group>"; };
|
||||
DDB2CC6F27F3F0AC009C5FCC /* MeshtasticDataModel v 3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModel v 3.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DDB3107128A6224100F1DE3D /* device_metadata.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = device_metadata.pb.swift; sourceTree = "<group>"; };
|
||||
DDB6ABD528AE742000384BA1 /* BluetoothConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothConfig.swift; sourceTree = "<group>"; };
|
||||
DDB6ABD728AE8F5D00384BA1 /* MeshtasticDataModel v 7.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModel v 7.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DDB6ABD828B0A4BA00384BA1 /* BluetoothModes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothModes.swift; sourceTree = "<group>"; };
|
||||
DDB6ABDA28B0AC6000384BA1 /* DistanceText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistanceText.swift; sourceTree = "<group>"; };
|
||||
DDB6ABDF28B13AC700384BA1 /* DeviceRoles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRoles.swift; sourceTree = "<group>"; };
|
||||
DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionConfigEnums.swift; sourceTree = "<group>"; };
|
||||
DDB6ABE328B13FFF00384BA1 /* ScreenIntervals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenIntervals.swift; sourceTree = "<group>"; };
|
||||
DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoraConfigEnums.swift; sourceTree = "<group>"; };
|
||||
DDB6ABE728B141AF00384BA1 /* WiFiModes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WiFiModes.swift; sourceTree = "<group>"; };
|
||||
DDC2E15426CE248E0042C5E4 /* Meshtastic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Meshtastic.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DDC2E15726CE248E0042C5E4 /* MeshtasticApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticApp.swift; sourceTree = "<group>"; };
|
||||
DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../Assets.xcassets; sourceTree = "<group>"; };
|
||||
|
|
@ -270,10 +298,12 @@
|
|||
DD61937A2863876A00E59241 /* Config */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDB6ABD528AE742000384BA1 /* BluetoothConfig.swift */,
|
||||
DD41582528582E9B009B0E59 /* DeviceConfig.swift */,
|
||||
DD8EBF42285058FA00426DCA /* DisplayConfig.swift */,
|
||||
DD2553562855B02500E55709 /* LoRaConfig.swift */,
|
||||
DD2553582855B52700E55709 /* PositionConfig.swift */,
|
||||
DD8ED9C42898D51F00B3B0AB /* WiFiConfig.swift */,
|
||||
DD61937B2863877A00E59241 /* Module */,
|
||||
);
|
||||
path = Config;
|
||||
|
|
@ -301,6 +331,20 @@
|
|||
path = Export;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DD8ED9C6289CE4A100B3B0AB /* Enums */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDB6ABD828B0A4BA00384BA1 /* BluetoothModes.swift */,
|
||||
DDB6ABDF28B13AC700384BA1 /* DeviceRoles.swift */,
|
||||
DDB6ABE528B1406100384BA1 /* LoraConfigEnums.swift */,
|
||||
DDB6ABE128B13FB500384BA1 /* PositionConfigEnums.swift */,
|
||||
DD8ED9C7289CE4B900B3B0AB /* RoutingError.swift */,
|
||||
DDB6ABE328B13FFF00384BA1 /* ScreenIntervals.swift */,
|
||||
DDB6ABE728B141AF00384BA1 /* WiFiModes.swift */,
|
||||
);
|
||||
path = Enums;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DD8EDE9226F97A2B00A5A10B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -311,6 +355,7 @@
|
|||
DDAF8C5626ED07740058C060 /* Protobufs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDB3107128A6224100F1DE3D /* device_metadata.pb.swift */,
|
||||
DDCFF600285453A7005FA625 /* localonly.pb.swift */,
|
||||
DD4DED8F27AD2975004BA27E /* cannedmessages.pb.swift */,
|
||||
DDAF8C6126ED0A230058C060 /* admin.pb.swift */,
|
||||
|
|
@ -355,6 +400,7 @@
|
|||
DDC2E15626CE248E0042C5E4 /* Meshtastic */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD8ED9C6289CE4A100B3B0AB /* Enums */,
|
||||
DD90860A26F645B700DC5189 /* Meshtastic.entitlements */,
|
||||
DDC4D5662754996200A4208E /* Persistence */,
|
||||
DDAF8C5626ED07740058C060 /* Protobufs */,
|
||||
|
|
@ -404,8 +450,9 @@
|
|||
DD47E3D726F2F21A00029299 /* Bluetooth */,
|
||||
DD47E3CA26F0E50300029299 /* Nodes */,
|
||||
DDC2E18B26CE25A70042C5E4 /* Messages */,
|
||||
DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */,
|
||||
DD4A911C2708C57100501B7E /* Settings */,
|
||||
DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */,
|
||||
DD4033C128B286B70096A444 /* Onboarding.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -447,6 +494,7 @@
|
|||
DDC3B273283F411B00AC321C /* LastHeardText.swift */,
|
||||
DDA6B2EA28420A7B003E8C16 /* NodeAnnotation.swift */,
|
||||
DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */,
|
||||
DDB6ABDA28B0AC6000384BA1 /* DistanceText.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -643,8 +691,10 @@
|
|||
DD5394FE276BA0EF00AD86B1 /* PositionEntityExtension.swift in Sources */,
|
||||
DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */,
|
||||
DD4C158C2824A91E0032668E /* module_config.pb.swift in Sources */,
|
||||
DDB6ABE828B141AF00384BA1 /* WiFiModes.swift in Sources */,
|
||||
DD4F23CD28779A3C001D37CB /* TelemetryLog.swift in Sources */,
|
||||
DD6B85A828009258000ACD6B /* ShareChannel.swift in Sources */,
|
||||
DDB6ABD628AE742000384BA1 /* BluetoothConfig.swift in Sources */,
|
||||
DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */,
|
||||
DDC4D568275499A500A4208E /* Persistence.swift in Sources */,
|
||||
DD90860E26F69BAE00DC5189 /* NodeMap.swift in Sources */,
|
||||
|
|
@ -661,8 +711,10 @@
|
|||
DD6193772862F90F00E59241 /* CannedMessagesConfig.swift in Sources */,
|
||||
DD41582628582E9B009B0E59 /* DeviceConfig.swift in Sources */,
|
||||
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */,
|
||||
DDB6ABE628B1406100384BA1 /* LoraConfigEnums.swift in Sources */,
|
||||
DDB2CC6E27F3EB47009C5FCC /* telemetry.pb.swift in Sources */,
|
||||
DD23A50F26FD1B4400D9B90C /* PeripheralModel.swift in Sources */,
|
||||
DDB6ABDB28B0AC6000384BA1 /* DistanceText.swift in Sources */,
|
||||
C9A7BC1027759A9600760B50 /* PositionAnnotationView.swift in Sources */,
|
||||
DD882F5D2772E4640005BF05 /* Contacts.swift in Sources */,
|
||||
DD47E3CE26F103C600029299 /* NodeList.swift in Sources */,
|
||||
|
|
@ -671,14 +723,19 @@
|
|||
DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */,
|
||||
DD17E5DE277D49D400010EC2 /* storeforward.pb.swift in Sources */,
|
||||
DD2553572855B02500E55709 /* LoRaConfig.swift in Sources */,
|
||||
DDB6ABD928B0A4BA00384BA1 /* BluetoothModes.swift in Sources */,
|
||||
DDD9E4E4284B208E003777C5 /* UserEntityExtension.swift in Sources */,
|
||||
C9A88B55278B503C00BD810A /* MapViewModule.swift in Sources */,
|
||||
DD2553592855B52700E55709 /* PositionConfig.swift in Sources */,
|
||||
DDB3107228A6224100F1DE3D /* device_metadata.pb.swift in Sources */,
|
||||
DDAF8C6326ED0A230058C060 /* admin.pb.swift in Sources */,
|
||||
DDB6ABE028B13AC700384BA1 /* DeviceRoles.swift in Sources */,
|
||||
DD86D40C287F401000BAEB7A /* SaveChannelQRCode.swift in Sources */,
|
||||
DD8ED9C8289CE4B900B3B0AB /* RoutingError.swift in Sources */,
|
||||
C9483F6D2773017500998F6B /* MapView.swift in Sources */,
|
||||
DDAF8C5826ED07FD0058C060 /* mesh.pb.swift in Sources */,
|
||||
DD8169FB271F1F3A00F4AB02 /* MeshLog.swift in Sources */,
|
||||
DD8ED9C52898D51F00B3B0AB /* WiFiConfig.swift in Sources */,
|
||||
DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */,
|
||||
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */,
|
||||
DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */,
|
||||
|
|
@ -686,11 +743,14 @@
|
|||
DDA6B2E928419CF2003E8C16 /* MeshPackets.swift in Sources */,
|
||||
DDCE4E2C2869F92900BE9F8F /* UserConfig.swift in Sources */,
|
||||
DD6193752862F6E600E59241 /* ExternalNotificationConfig.swift in Sources */,
|
||||
DD4033C228B286B70096A444 /* Onboarding.swift in Sources */,
|
||||
DDB6ABE428B13FFF00384BA1 /* ScreenIntervals.swift in Sources */,
|
||||
DD86D40A287F04F100BAEB7A /* InvalidVersion.swift in Sources */,
|
||||
DDD94A502845C8F5004A87A0 /* DateTimeText.swift in Sources */,
|
||||
C9A88B57278B559900BD810A /* apponly.pb.swift in Sources */,
|
||||
DD4C158E2824AA7E0032668E /* config.pb.swift in Sources */,
|
||||
DD47E3D926F3093800029299 /* MessageBubble.swift in Sources */,
|
||||
DDB6ABE228B13FB500384BA1 /* PositionConfigEnums.swift in Sources */,
|
||||
DD415828285859C4009B0E59 /* TelemetryConfig.swift in Sources */,
|
||||
DD73FD1128750779000852D6 /* LocationHistory.swift in Sources */,
|
||||
C9697F9D279336B700250207 /* LocalMBTileOverlay.swift in Sources */,
|
||||
|
|
@ -875,7 +935,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.27;
|
||||
MARKETING_VERSION = 1.3.39;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -907,7 +967,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.3.27;
|
||||
MARKETING_VERSION = 1.3.39;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1080,12 +1140,16 @@
|
|||
DD9D8F2D2764403B00080993 /* Meshtastic.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
DD4033C328B405A60096A444 /* MeshtasticDataModel v 8.xcdatamodel */,
|
||||
DDB6ABD728AE8F5D00384BA1 /* MeshtasticDataModel v 7.xcdatamodel */,
|
||||
DD8ED9C9289EA77E00B3B0AB /* MeshtasticDataModel v 6.xcdatamodel */,
|
||||
DD8ED9C328978D9D00B3B0AB /* MeshtasticDataModel v 5.xcdatamodel */,
|
||||
DD619373285CC7D600E59241 /* MeshtasticDataModel v 4.xcdatamodel */,
|
||||
DDB2CC6F27F3F0AC009C5FCC /* MeshtasticDataModel v 3.xcdatamodel */,
|
||||
DD45C77427BD4EF80011784F /* MeshtasticDataModel v2.xcdatamodel */,
|
||||
DD9D8F2E2764403B00080993 /* CoreDataSample.xcdatamodel */,
|
||||
);
|
||||
currentVersion = DD619373285CC7D600E59241 /* MeshtasticDataModel v 4.xcdatamodel */;
|
||||
currentVersion = DD4033C328B405A60096A444 /* MeshtasticDataModel v 8.xcdatamodel */;
|
||||
name = Meshtastic.xcdatamodeld;
|
||||
path = Meshtastic/Meshtastic.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
|||
39
Meshtastic/Enums/BluetoothModes.swift
Normal file
39
Meshtastic/Enums/BluetoothModes.swift
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// BluetoothModes.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/19/22.
|
||||
//
|
||||
|
||||
enum BluetoothModes: Int, CaseIterable, Identifiable {
|
||||
|
||||
case randomPin = 0
|
||||
case fixedPin = 1
|
||||
case noPin = 2
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .randomPin:
|
||||
return "Random PIN"
|
||||
case .fixedPin:
|
||||
return "Fixed PIN"
|
||||
case .noPin:
|
||||
return "No PIN (Just Works)"
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.BluetoothConfig.PairingMode {
|
||||
|
||||
switch self {
|
||||
|
||||
case .randomPin:
|
||||
return Config.BluetoothConfig.PairingMode.randomPin
|
||||
case .fixedPin:
|
||||
return Config.BluetoothConfig.PairingMode.fixedPin
|
||||
case .noPin:
|
||||
return Config.BluetoothConfig.PairingMode.noPin
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Meshtastic/Enums/DeviceRoles.swift
Normal file
48
Meshtastic/Enums/DeviceRoles.swift
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// DeviceRoles.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/20/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// Default of 0 is Client
|
||||
enum DeviceRoles: Int, CaseIterable, Identifiable {
|
||||
|
||||
case client = 0
|
||||
case clientMute = 1
|
||||
case router = 2
|
||||
case routerClient = 3
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .client:
|
||||
return "Client (default) - App connected client."
|
||||
case .clientMute:
|
||||
return "Client Mute - Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh."
|
||||
case .router:
|
||||
return "Router - Mesh packets will prefer to be routed over this node. This node will not be used by client apps. The wifi/ble radios and the oled screen will be put to sleep."
|
||||
case .routerClient:
|
||||
return "Router Client - Mesh packets will prefer to be routed over this node. The Router Client can be used as both a Router and an app connected Client."
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.DeviceConfig.Role {
|
||||
|
||||
switch self {
|
||||
|
||||
case .client:
|
||||
return Config.DeviceConfig.Role.client
|
||||
case .clientMute:
|
||||
return Config.DeviceConfig.Role.clientMute
|
||||
case .router:
|
||||
return Config.DeviceConfig.Role.router
|
||||
case .routerClient:
|
||||
return Config.DeviceConfig.Role.routerClient
|
||||
}
|
||||
}
|
||||
}
|
||||
181
Meshtastic/Enums/LoraConfigEnums.swift
Normal file
181
Meshtastic/Enums/LoraConfigEnums.swift
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
//
|
||||
// LoraConfig.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/20/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum RegionCodes : Int, CaseIterable, Identifiable {
|
||||
|
||||
case unset = 0
|
||||
case us = 1
|
||||
case eu433 = 2
|
||||
case eu868 = 3
|
||||
case cn = 4
|
||||
case jp = 5
|
||||
case anz = 6
|
||||
case kr = 7
|
||||
case tw = 8
|
||||
case ru = 9
|
||||
case `in` = 10
|
||||
case nz865 = 11
|
||||
case th = 12
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .unset:
|
||||
return "Please set a region"
|
||||
case .us:
|
||||
return "United States"
|
||||
case .eu433:
|
||||
return "European Union 433mhz"
|
||||
case .eu868:
|
||||
return "European Union 868mhz"
|
||||
case .cn:
|
||||
return "China"
|
||||
case .jp:
|
||||
return "Japan"
|
||||
case .anz:
|
||||
return "Australia / New Zealand"
|
||||
case .kr:
|
||||
return "Korea"
|
||||
case .tw:
|
||||
return "Taiwan"
|
||||
case .ru:
|
||||
return "Russia"
|
||||
case .in:
|
||||
return "India"
|
||||
case .nz865:
|
||||
return "New Zealand 865mhz"
|
||||
case .th:
|
||||
return "Thailand"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func protoEnumValue() -> Config.LoRaConfig.RegionCode {
|
||||
|
||||
switch self {
|
||||
|
||||
case .unset:
|
||||
return Config.LoRaConfig.RegionCode.unset
|
||||
case .us:
|
||||
return Config.LoRaConfig.RegionCode.us
|
||||
case .eu433:
|
||||
return Config.LoRaConfig.RegionCode.eu433
|
||||
case .eu868:
|
||||
return Config.LoRaConfig.RegionCode.eu868
|
||||
case .cn:
|
||||
return Config.LoRaConfig.RegionCode.cn
|
||||
case .jp:
|
||||
return Config.LoRaConfig.RegionCode.jp
|
||||
case .anz:
|
||||
return Config.LoRaConfig.RegionCode.anz
|
||||
case .kr:
|
||||
return Config.LoRaConfig.RegionCode.kr
|
||||
case .tw:
|
||||
return Config.LoRaConfig.RegionCode.tw
|
||||
case .ru:
|
||||
return Config.LoRaConfig.RegionCode.ru
|
||||
case .in:
|
||||
return Config.LoRaConfig.RegionCode.in
|
||||
case .nz865:
|
||||
return Config.LoRaConfig.RegionCode.nz865
|
||||
case .th:
|
||||
return Config.LoRaConfig.RegionCode.th
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ModemPresets : Int, CaseIterable, Identifiable {
|
||||
|
||||
case LongFast = 0
|
||||
case LongSlow = 1
|
||||
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:
|
||||
return "Long Range - Fast"
|
||||
case .LongSlow:
|
||||
return "Long Range - Slow"
|
||||
case .VLongSlow:
|
||||
return "Very Long Range - Slow"
|
||||
case .MedSlow:
|
||||
return "Medium Range - Slow"
|
||||
case .MedFast:
|
||||
return "Medium Range - Fast"
|
||||
case .ShortSlow:
|
||||
return "Short Range - Slow"
|
||||
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 .VLongSlow:
|
||||
return Config.LoRaConfig.ModemPreset.vlongSlow
|
||||
case .MedSlow:
|
||||
return Config.LoRaConfig.ModemPreset.medSlow
|
||||
case .MedFast:
|
||||
return Config.LoRaConfig.ModemPreset.medFast
|
||||
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 = 0
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
132
Meshtastic/Enums/PositionConfigEnums.swift
Normal file
132
Meshtastic/Enums/PositionConfigEnums.swift
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
//
|
||||
// GpsFormats.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/20/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum GpsFormats: Int, CaseIterable, Identifiable {
|
||||
|
||||
case gpsFormatDec = 0
|
||||
case gpsFormatDms = 1
|
||||
case gpsFormatUtm = 2
|
||||
case gpsFormatMgrs = 3
|
||||
case gpsFormatOlc = 4
|
||||
case gpsFormatOsgr = 5
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .gpsFormatDec:
|
||||
return "Decimal Degrees Format"
|
||||
case .gpsFormatDms:
|
||||
return "Degrees Minutes Seconds"
|
||||
case .gpsFormatUtm:
|
||||
return "Universal Transverse Mercator"
|
||||
case .gpsFormatMgrs:
|
||||
return "Military Grid Reference System"
|
||||
case .gpsFormatOlc:
|
||||
return "Open Location Code (aka Plus Codes)"
|
||||
case .gpsFormatOsgr:
|
||||
return "Ordnance Survey Grid Reference"
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.DisplayConfig.GpsCoordinateFormat {
|
||||
|
||||
switch self {
|
||||
|
||||
case .gpsFormatDec:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatDec
|
||||
case .gpsFormatDms:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatDms
|
||||
case .gpsFormatUtm:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatUtm
|
||||
case .gpsFormatMgrs:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatMgrs
|
||||
case .gpsFormatOlc:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatOlc
|
||||
case .gpsFormatOsgr:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatOsgr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum GpsUpdateIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case fiveSeconds = 5
|
||||
case tenSeconds = 10
|
||||
case fifteenSeconds = 15
|
||||
case thirtySeconds = 0
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 600
|
||||
case fifteenMinutes = 900
|
||||
case thirtyMinutes = 1800
|
||||
case oneHour = 3600
|
||||
case maxInt32 = 2147483647
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
|
||||
case .fiveSeconds:
|
||||
return "Five Seconds"
|
||||
case .tenSeconds:
|
||||
return "Ten Seconds"
|
||||
case .fifteenSeconds:
|
||||
return "fifteenSeconds"
|
||||
case .thirtySeconds:
|
||||
return "Thirty Seconds"
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
case .thirtyMinutes:
|
||||
return "Thirty Minutes"
|
||||
case .oneHour:
|
||||
return "One Hour"
|
||||
case .maxInt32:
|
||||
return "On Boot Only"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum GpsAttemptTimes: Int, CaseIterable, Identifiable {
|
||||
|
||||
case thirtySeconds = 0
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 600
|
||||
case fifteenMinutes = 900
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .thirtySeconds:
|
||||
return "Thirty Seconds"
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Meshtastic/Enums/RoutingError.swift
Normal file
109
Meshtastic/Enums/RoutingError.swift
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// RoutingError.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/4/22.
|
||||
//
|
||||
|
||||
enum RoutingError: Int, CaseIterable, Identifiable {
|
||||
|
||||
case none = 0
|
||||
case noRoute = 1
|
||||
case gotNak = 2
|
||||
case timeout = 3
|
||||
case noInterface = 4
|
||||
case maxRetransmit = 5
|
||||
case noChannel = 6
|
||||
case tooLarge = 7
|
||||
case noResponse = 8
|
||||
case badRequest = 32
|
||||
case notAuthorized = 33
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var display: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .none:
|
||||
return "No Error."
|
||||
case .noRoute:
|
||||
return "No Route"
|
||||
case .gotNak:
|
||||
return "Received a nak"
|
||||
case .timeout:
|
||||
return "Timeout"
|
||||
case .noInterface:
|
||||
return "No Interface"
|
||||
case .maxRetransmit:
|
||||
return "Max Retransmission Reached"
|
||||
case .noChannel:
|
||||
return "No Channel"
|
||||
case .tooLarge:
|
||||
return "The packet is too large"
|
||||
case .noResponse:
|
||||
return "No Response"
|
||||
case .badRequest:
|
||||
return "Bad Request"
|
||||
case .notAuthorized:
|
||||
return "Not Authorized"
|
||||
}
|
||||
}
|
||||
}
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .none:
|
||||
return "This message is not a failure."
|
||||
case .noRoute:
|
||||
return "Our node doesn't have a route to the requested destination anymore."
|
||||
case .gotNak:
|
||||
return "We received a nak while trying to forward on your behalf."
|
||||
case .timeout:
|
||||
return "We timed out while attempting to route this packet."
|
||||
case .noInterface:
|
||||
return "No suitable interface could be found for delivering this packet."
|
||||
case .maxRetransmit:
|
||||
return "We reached the max retransmission count (Hop Limit) and have received no responses."
|
||||
case .noChannel:
|
||||
return "No suitable channel was found for sending this packet (i.e. was requested channel index disabled?)."
|
||||
case .tooLarge:
|
||||
return "The packet was too big for sending (exceeds interface MTU after encoding)."
|
||||
case .noResponse:
|
||||
return "The request had want_response set, the request reached the destination node, but no service on that node wants to send a response (possibly due to bad channel permissions)."
|
||||
case .badRequest:
|
||||
return "The application layer service on the remote node received your request, but considered your request somehow invalid."
|
||||
case .notAuthorized:
|
||||
return "The application layer service on the remote node received your request, but considered your request not authorized (i.e you did not send the request on the required bound channel)."
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Routing.Error {
|
||||
|
||||
switch self {
|
||||
|
||||
case .none:
|
||||
return Routing.Error.none
|
||||
case .noRoute:
|
||||
return Routing.Error.noRoute
|
||||
case .gotNak:
|
||||
return Routing.Error.gotNak
|
||||
case .timeout:
|
||||
return Routing.Error.timeout
|
||||
case .noInterface:
|
||||
return Routing.Error.noInterface
|
||||
case .maxRetransmit:
|
||||
return Routing.Error.maxRetransmit
|
||||
case .noChannel:
|
||||
return Routing.Error.noChannel
|
||||
case .tooLarge:
|
||||
return Routing.Error.tooLarge
|
||||
case .noResponse:
|
||||
return Routing.Error.noResponse
|
||||
case .badRequest:
|
||||
return Routing.Error.badRequest
|
||||
case .notAuthorized:
|
||||
return Routing.Error.notAuthorized
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Meshtastic/Enums/ScreenIntervals.swift
Normal file
73
Meshtastic/Enums/ScreenIntervals.swift
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// ScreenIntervals.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/20/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// Default of 0 is One Minute
|
||||
enum ScreenOnIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 0
|
||||
case fifteenMinutes = 900
|
||||
case thirtyMinutes = 1800
|
||||
case oneHour = 3600
|
||||
case max = 31536000 // One Year
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
case .thirtyMinutes:
|
||||
return "Thirty Minutes"
|
||||
case .oneHour:
|
||||
return "One Hour"
|
||||
case .max:
|
||||
return "Always On"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default of 0 is off
|
||||
enum ScreenCarouselIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case off = 0
|
||||
case thirtySeconds = 30
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 600
|
||||
case fifteenMinutes = 900
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .off:
|
||||
return "Off"
|
||||
case .thirtySeconds:
|
||||
return "Thirty Seconds"
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Meshtastic/Enums/WiFiModes.swift
Normal file
42
Meshtastic/Enums/WiFiModes.swift
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// WiFiModes.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/20/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum WiFiModes: Int, CaseIterable, Identifiable {
|
||||
|
||||
case client = 0
|
||||
case accessPoint = 1
|
||||
case accessPointHidden = 2
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .client:
|
||||
return "Client"
|
||||
case .accessPoint:
|
||||
return "Software Access Point"
|
||||
case .accessPointHidden:
|
||||
return "Software Access Point (Hidden)"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.WiFiConfig.WiFiMode {
|
||||
|
||||
switch self {
|
||||
|
||||
case .client:
|
||||
return Config.WiFiConfig.WiFiMode.client
|
||||
case .accessPoint:
|
||||
return Config.WiFiConfig.WiFiMode.accessPoint
|
||||
case .accessPointHidden:
|
||||
return Config.WiFiConfig.WiFiMode.accessPointHidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,8 +35,30 @@ func TelemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin
|
|||
}
|
||||
|
||||
} else {
|
||||
// Create Device Telemetry Header
|
||||
csvString = "Battery Level, Voltage, Channel Utilization, Airtime, Timestamp"
|
||||
|
||||
// Create Environment Telemetry Header
|
||||
csvString = "Temperature, Relative Humidity, Barometric Pressure, Gas Resistance, Voltage, Current"
|
||||
|
||||
for dm in telemetry{
|
||||
|
||||
if dm.metricsType == 0 {
|
||||
|
||||
csvString += "\n"
|
||||
csvString += String("\(dm.temperature)°")
|
||||
csvString += ", "
|
||||
csvString += String(dm.relativeHumidity)
|
||||
csvString += ", "
|
||||
csvString += String(dm.barometricPressure)
|
||||
csvString += ", "
|
||||
csvString += String(dm.gasResistance)
|
||||
csvString += ", "
|
||||
csvString += String(dm.voltage)
|
||||
csvString += ", "
|
||||
csvString += String(dm.current)
|
||||
csvString += ", "
|
||||
csvString += dm.time?.formattedDate(format: "yyyy-MM-dd HH:mm:ss") ?? "Unknown Age"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return csvString
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
@Published var connectedPeripheral: Peripheral!
|
||||
@Published var lastConnectionError: String
|
||||
@Published var lastConnnectionVersion: String
|
||||
@Published var connectedVersion: String
|
||||
|
||||
@Published var isSwitchedOn: Bool = false
|
||||
@Published var isScanning: Bool = false
|
||||
|
|
@ -77,7 +77,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
//self.meshLoggingEnabled = UserDefaults.standard.object(forKey: "meshActivityLog") as? Bool ?? false
|
||||
self.lastConnectionError = ""
|
||||
self.lastConnnectionVersion = "0.0.0"
|
||||
self.connectedVersion = "0.0.0"
|
||||
super.init()
|
||||
// let bleQueue: DispatchQueue = DispatchQueue(label: "CentralManager")
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
|
|
@ -131,7 +131,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
self.timeoutTimerCount += 1
|
||||
|
||||
if timeoutTimerCount == 5 {
|
||||
if timeoutTimerCount == 10 {
|
||||
|
||||
if connectedPeripheral != nil {
|
||||
|
||||
|
|
@ -145,7 +145,10 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if meshLoggingEnabled { MeshLogger.log(self.lastConnectionError + " This can occur when a device has been taken out of BLE range, or if a device is already connected to another phone, tablet or computer.") }
|
||||
|
||||
self.timeoutTimerCount = 0
|
||||
self.timeoutTimer?.invalidate()
|
||||
if self.timeoutTimer != nil {
|
||||
|
||||
self.timeoutTimer!.invalidate()
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -159,19 +162,27 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if meshLoggingEnabled { MeshLogger.log("✅ BLE Connecting: \(peripheral.name ?? "Unknown")") }
|
||||
|
||||
stopScanning()
|
||||
|
||||
|
||||
if self.connectedPeripheral != nil {
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ BLE Disconnecting from: \(self.connectedPeripheral.name) to connect to \(peripheral.name ?? "Unknown")") }
|
||||
self.disconnectPeripheral()
|
||||
}
|
||||
|
||||
|
||||
self.connectedVersion = "0.0.0"
|
||||
self.centralManager?.connect(peripheral)
|
||||
|
||||
// Invalidate any existing timer
|
||||
if self.timeoutTimer != nil {
|
||||
|
||||
self.timeoutTimer!.invalidate()
|
||||
}
|
||||
|
||||
// Use a timer to keep track of connecting peripherals, context to pass the radio name with the timer and the RunLoop to prevent
|
||||
// the timer from running on the main UI thread
|
||||
let context = ["name": "@\(peripheral.name ?? "Unknown")"]
|
||||
self.timeoutTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(timeoutTimerFired), userInfo: context, repeats: true)
|
||||
self.timeoutTimer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(timeoutTimerFired), userInfo: context, repeats: true)
|
||||
RunLoop.current.add(self.timeoutTimer!, forMode: .common)
|
||||
}
|
||||
|
||||
|
|
@ -223,8 +234,11 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
// Invalidate and reset connection timer count, remove any connection errors
|
||||
self.lastConnectionError = ""
|
||||
self.timeoutTimer!.invalidate()
|
||||
self.timeoutTimerCount = 0
|
||||
if self.timeoutTimer != nil {
|
||||
|
||||
self.timeoutTimer!.invalidate()
|
||||
}
|
||||
|
||||
// Map the peripheral to the connectedNode and connectedPeripheral ObservedObjects
|
||||
connectedPeripheral = peripherals.filter({ $0.peripheral.identifier == peripheral.identifier }).first
|
||||
|
|
@ -259,7 +273,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
// Happens when device is manually reset / powered off
|
||||
// We will try and re-connect to this device
|
||||
lastConnectionError = "🚨 \(e.localizedDescription) The app will automatically reconnect to the preferred radio if it reappears within 10 seconds."
|
||||
lastConnectionError = "🚨 \(e.localizedDescription) The app will automatically reconnect to the preferred radio if it reappears within one minute."
|
||||
if peripheral.identifier.uuidString == UserDefaults.standard.object(forKey: "preferredPeripheralId") as? String ?? "" {
|
||||
if meshLoggingEnabled { MeshLogger.log("ℹ️ BLE Reconnecting: \(peripheral.name ?? "Unknown")") }
|
||||
self.connectTo(peripheral: peripheral)
|
||||
|
|
@ -460,15 +474,20 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
// MyInfo
|
||||
if decodedInfo.myInfo.isInitialized && decodedInfo.myInfo.myNodeNum > 0 {
|
||||
|
||||
let lastDotIndex = decodedInfo.myInfo.firmwareVersion.lastIndex(of: ".")
|
||||
let version = decodedInfo.myInfo.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset: 6, in: decodedInfo.myInfo.firmwareVersion))]
|
||||
|
||||
nowKnown = true
|
||||
connectedVersion = String(version)
|
||||
|
||||
let myInfo = myInfoPacket(myInfo: decodedInfo.myInfo, meshLogging: meshLoggingEnabled, context: context!)
|
||||
|
||||
if myInfo != nil {
|
||||
|
||||
self.connectedPeripheral.bitrate = myInfo!.bitrate
|
||||
self.connectedPeripheral.num = myInfo!.myNodeNum
|
||||
lastConnnectionVersion = myInfo?.firmwareVersion ?? myInfo!.firmwareVersion ?? "Unknown"
|
||||
|
||||
self.connectedPeripheral.firmwareVersion = myInfo!.firmwareVersion ?? "Unknown"
|
||||
self.connectedPeripheral.name = myInfo!.bleName ?? "Unknown"
|
||||
self.connectedPeripheral.longName = myInfo!.bleName ?? "Unknown"
|
||||
|
|
@ -584,6 +603,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
if userSettings?.provideLocation ?? false {
|
||||
|
||||
if self.positionTimer != nil {
|
||||
|
||||
self.positionTimer!.invalidate()
|
||||
}
|
||||
let context = ["name": "@\(peripheral.name ?? "Unknown")"]
|
||||
|
|
@ -734,7 +754,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return success
|
||||
}
|
||||
|
||||
public func sendPosition(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
public func sendLocation(destNum: Int64, wantAck: Bool) -> Bool {
|
||||
|
||||
var success = false
|
||||
|
||||
|
|
@ -744,58 +764,91 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
var waypointPacket = Waypoint()
|
||||
waypointPacket.latitudeI = Int32(LocationHelper.currentLocation.latitude * 1e7)
|
||||
waypointPacket.longitudeI = Int32(LocationHelper.currentLocation.longitude * 1e7)
|
||||
|
||||
let fetchNode: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
fetchNode.predicate = NSPredicate(format: "num == %lld", fromNodeNum)
|
||||
let oneWeekFromNow = Calendar.current.date(byAdding: .day, value: 7, to: Date())
|
||||
waypointPacket.expire = UInt32(oneWeekFromNow!.timeIntervalSince1970)
|
||||
waypointPacket.name = "Test Waypoint"
|
||||
|
||||
|
||||
var meshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(destNum)
|
||||
meshPacket.from = 0 // Send 0 as from from phone to device to avoid warning about client trying to set node num
|
||||
meshPacket.wantAck = true//wantAck
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! waypointPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.waypointApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
do {
|
||||
|
||||
let fetchedNode = try context?.fetch(fetchNode) as! [NodeInfoEntity]
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("📍 Sent a Location Packet from the Apple device GPS to node: \(fromNodeNum)") }
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
success = true
|
||||
|
||||
if fetchedNode.count == 1 {
|
||||
|
||||
var positionPacket = Position()
|
||||
positionPacket.latitudeI = Int32(LocationHelper.currentLocation.latitude * 1e7)
|
||||
positionPacket.longitudeI = Int32(LocationHelper.currentLocation.longitude * 1e7)
|
||||
positionPacket.time = UInt32(LocationHelper.currentTimestamp.timeIntervalSince1970)
|
||||
positionPacket.altitude = Int32(LocationHelper.currentAltitude)
|
||||
|
||||
// Get Errors without some speed
|
||||
if LocationHelper.currentSpeed >= 5 {
|
||||
|
||||
positionPacket.groundSpeed = UInt32(LocationHelper.currentSpeed)
|
||||
positionPacket.groundTrack = UInt32(LocationHelper.currentHeading)
|
||||
}
|
||||
|
||||
var meshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(destNum)
|
||||
meshPacket.from = 0 // Send 0 as from from phone to device to avoid warning about client trying to set node num
|
||||
meshPacket.wantAck = wantResponse
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! positionPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.positionApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("📍 Sent a Position Packet from the Apple device GPS to node: \(fromNodeNum)") }
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
success = true
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success
|
||||
}
|
||||
|
||||
public func sendPosition(destNum: Int64, wantAck: Bool) -> Bool {
|
||||
|
||||
var success = false
|
||||
|
||||
let fromNodeNum = connectedPeripheral.num
|
||||
|
||||
if fromNodeNum <= 0 || (LocationHelper.currentLocation.latitude == LocationHelper.DefaultLocation.latitude && LocationHelper.currentLocation.longitude == LocationHelper.DefaultLocation.longitude) {
|
||||
|
||||
} catch {
|
||||
success = false
|
||||
return false
|
||||
}
|
||||
|
||||
var positionPacket = Position()
|
||||
positionPacket.latitudeI = Int32(LocationHelper.currentLocation.latitude * 1e7)
|
||||
positionPacket.longitudeI = Int32(LocationHelper.currentLocation.longitude * 1e7)
|
||||
positionPacket.time = UInt32(LocationHelper.currentTimestamp.timeIntervalSince1970)
|
||||
positionPacket.altitude = Int32(LocationHelper.currentAltitude)
|
||||
|
||||
// Get Errors without some speed
|
||||
if LocationHelper.currentSpeed >= 5 {
|
||||
|
||||
positionPacket.groundSpeed = UInt32(LocationHelper.currentSpeed)
|
||||
positionPacket.groundTrack = UInt32(LocationHelper.currentHeading)
|
||||
}
|
||||
|
||||
var meshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(destNum)
|
||||
meshPacket.from = 0 // Send 0 as from from phone to device to avoid warning about client trying to set node num
|
||||
meshPacket.wantAck = wantAck
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! positionPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.positionApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
let binaryData: Data = try! toRadio.serializedData()
|
||||
|
||||
if meshLoggingEnabled { MeshLogger.log("📍 Sent a Position Packet from the Apple device GPS to node: \(fromNodeNum)") }
|
||||
|
||||
if connectedPeripheral!.peripheral.state == CBPeripheralState.connected {
|
||||
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
success = true
|
||||
|
||||
}
|
||||
|
||||
return success
|
||||
|
|
@ -809,7 +862,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
// Send a position out to the mesh if "share location with the mesh" is enabled in settings
|
||||
if userSettings!.provideLocation {
|
||||
|
||||
let success = sendPosition(destNum: connectedPeripheral.num, wantResponse: false)
|
||||
let success = sendPosition(destNum: connectedPeripheral.num, wantAck: false)
|
||||
if !success {
|
||||
|
||||
print("Failed to send positon to device")
|
||||
|
|
@ -819,7 +872,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
}
|
||||
}
|
||||
|
||||
public func sendShutdown(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
public func sendShutdown(destNum: Int64) -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.shutdownSeconds = 10
|
||||
|
|
@ -829,7 +882,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
|
|
@ -867,7 +920,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return false
|
||||
}
|
||||
|
||||
public func sendReboot(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
public func sendReboot(destNum: Int64) -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.rebootSeconds = 10
|
||||
|
|
@ -877,7 +930,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -916,7 +969,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return false
|
||||
}
|
||||
|
||||
public func sendFactoryReset(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
public func sendFactoryReset(destNum: Int64) -> Bool {
|
||||
|
||||
var deviceConfig = Config.DeviceConfig()
|
||||
deviceConfig.factoryReset = true
|
||||
|
|
@ -929,7 +982,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
|
|
@ -966,7 +1019,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return false
|
||||
}
|
||||
|
||||
public func saveUser(config: User, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveUser(config: User, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setOwner = config
|
||||
|
|
@ -976,16 +1029,16 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
let messageDescription = "Saved Position Config for \(toUser.longName ?? "Unknown")"
|
||||
let messageDescription = "Saved User Config for \(toUser.longName ?? "Unknown")"
|
||||
|
||||
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
|
||||
|
||||
|
|
@ -995,7 +1048,36 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveDeviceConfig(config: Config.DeviceConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveBluetoothConfig(config: Config.BluetoothConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.bluetooth = config
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
let messageDescription = "Saved Bluetooth Config for \(toUser.longName ?? "Unknown")"
|
||||
|
||||
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
|
||||
|
||||
return Int64(meshPacket.id)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
public func saveDeviceConfig(config: Config.DeviceConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.device = config
|
||||
|
|
@ -1005,7 +1087,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -1024,7 +1106,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveDisplayConfig(config: Config.DisplayConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveDisplayConfig(config: Config.DisplayConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.display = config
|
||||
|
|
@ -1034,7 +1116,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -1053,7 +1135,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveLoRaConfig(config: Config.LoRaConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveLoRaConfig(config: Config.LoRaConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.lora = config
|
||||
|
|
@ -1064,7 +1146,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -1083,7 +1165,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func savePositionConfig(config: Config.PositionConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func savePositionConfig(config: Config.PositionConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.position = config
|
||||
|
|
@ -1093,7 +1175,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -1112,7 +1194,36 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveCannedMessageModuleConfig(config: ModuleConfig.CannedMessageConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveWiFiConfig(config: Config.WiFiConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.wifi = config
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
let messageDescription = "Saved WiFi Config for \(toUser.longName ?? "Unknown")"
|
||||
|
||||
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription, fromUser: fromUser, toUser: toUser) {
|
||||
|
||||
return Int64(meshPacket.id)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
public func saveCannedMessageModuleConfig(config: ModuleConfig.CannedMessageConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setModuleConfig.cannedMessage = config
|
||||
|
|
@ -1122,7 +1233,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
|
|
@ -1143,19 +1254,19 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
public func saveCannedMessageModuleMessages(messages: String, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
|
||||
adminPacket.setCannedMessageModulePart1 = messages
|
||||
adminPacket.setCannedMessageModuleMessages = messages
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(toUser.num)
|
||||
meshPacket.from = 0 //UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
dataMessage.wantResponse = wantResponse
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
|
|
@ -1221,20 +1332,20 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
public func getCannedMessageModuleMessages(destNum: Int64, wantResponse: Bool) -> Bool {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.getCannedMessageModulePart1Request = true
|
||||
|
||||
//adminPacket.getOwnerRequest = true
|
||||
adminPacket.getCannedMessageModuleMessagesRequest = true
|
||||
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedPeripheral.num)
|
||||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.decoded.wantResponse = wantResponse
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
dataMessage.wantResponse = wantResponse
|
||||
|
||||
meshPacket.decoded = dataMessage
|
||||
|
||||
|
|
@ -1267,7 +1378,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return false
|
||||
}
|
||||
|
||||
public func saveExternalNotificationModuleConfig(config: ModuleConfig.ExternalNotificationConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveExternalNotificationModuleConfig(config: ModuleConfig.ExternalNotificationConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setModuleConfig.externalNotification = config
|
||||
|
|
@ -1277,7 +1388,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
|
|
@ -1295,7 +1406,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveRangeTestModuleConfig(config: ModuleConfig.RangeTestConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveRangeTestModuleConfig(config: ModuleConfig.RangeTestConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setModuleConfig.rangeTest = config
|
||||
|
|
@ -1305,7 +1416,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
|
|
@ -1323,7 +1434,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveSerialModuleConfig(config: ModuleConfig.SerialConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveSerialModuleConfig(config: ModuleConfig.SerialConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setModuleConfig.serial = config
|
||||
|
|
@ -1333,7 +1444,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(connectedPeripheral.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
meshPacket.hopLimit = 0
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
|
|
@ -1352,7 +1463,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
return 0
|
||||
}
|
||||
|
||||
public func saveTelemetryModuleConfig(config: ModuleConfig.TelemetryConfig, fromUser: UserEntity, toUser: UserEntity, wantResponse: Bool) -> Int64 {
|
||||
public func saveTelemetryModuleConfig(config: ModuleConfig.TelemetryConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setModuleConfig.telemetry = config
|
||||
|
|
@ -1362,7 +1473,7 @@ class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeriph
|
|||
meshPacket.from = 0 //UInt32(fromUser.num)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = wantResponse
|
||||
meshPacket.wantAck = true
|
||||
|
||||
var dataMessage = DataMessage()
|
||||
dataMessage.payload = try! adminPacket.serializedData()
|
||||
|
|
|
|||
|
|
@ -23,6 +23,17 @@ extension Date {
|
|||
}
|
||||
}
|
||||
|
||||
extension Int {
|
||||
|
||||
func numberOfDigits() -> Int {
|
||||
if abs(self) < 10 {
|
||||
return 1
|
||||
} else {
|
||||
return 1 + (self/10).numberOfDigits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
|
||||
/// Create `Data` from hexadecimal string representation
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
|
||||
isDefault = true
|
||||
print("📟 Default Device config")
|
||||
|
||||
} else {
|
||||
|
||||
print("📟 Custom Device config")
|
||||
}
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
|
|
@ -88,6 +92,91 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
}
|
||||
}
|
||||
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.bluetooth(config.bluetooth) {
|
||||
|
||||
var isDefault = false
|
||||
|
||||
if (try! config.bluetooth.jsonString()) == "{}" {
|
||||
|
||||
isDefault = true
|
||||
print("📶 Default Bluetooth config")
|
||||
if meshlogging { MeshLogger.log("🖥️ Default Bluetooth config \(String(nodeNum))") }
|
||||
|
||||
} else {
|
||||
|
||||
if meshlogging { MeshLogger.log("🖥️ Custom Bluetooth config \(String(nodeNum))") }
|
||||
print("📶 Custom Bluetooth config")
|
||||
}
|
||||
|
||||
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].bluetoothConfig == nil {
|
||||
|
||||
let newBluetoothConfig = BluetoothConfigEntity(context: context)
|
||||
|
||||
if isDefault {
|
||||
|
||||
newBluetoothConfig.enabled = true
|
||||
newBluetoothConfig.mode = Int32(config.bluetooth.mode.rawValue)
|
||||
newBluetoothConfig.fixedPin = Int32("123456") ?? 123456
|
||||
|
||||
} else {
|
||||
|
||||
newBluetoothConfig.enabled = config.bluetooth.enabled
|
||||
newBluetoothConfig.mode = Int32(config.bluetooth.mode.rawValue)
|
||||
newBluetoothConfig.fixedPin = Int32(config.bluetooth.fixedPin)
|
||||
|
||||
}
|
||||
fetchedNode[0].bluetoothConfig = newBluetoothConfig
|
||||
|
||||
} else {
|
||||
|
||||
if isDefault {
|
||||
|
||||
fetchedNode[0].bluetoothConfig?.enabled = true
|
||||
fetchedNode[0].bluetoothConfig?.mode = Int32(config.bluetooth.mode.rawValue)
|
||||
fetchedNode[0].bluetoothConfig?.fixedPin = Int32("123456") ?? 123456
|
||||
|
||||
} else {
|
||||
|
||||
fetchedNode[0].bluetoothConfig?.enabled = config.bluetooth.enabled
|
||||
fetchedNode[0].bluetoothConfig?.mode = Int32(config.bluetooth.mode.rawValue)
|
||||
fetchedNode[0].bluetoothConfig?.fixedPin = Int32(config.bluetooth.fixedPin)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
try context.save()
|
||||
if meshlogging { MeshLogger.log("💾 Updated Bluetooth Config for node number: \(String(nodeNum))") }
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data BluetoothConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Bluetooth Config")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data BluetoothConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.display(config.display) {
|
||||
|
||||
var isDefault = false
|
||||
|
|
@ -95,7 +184,12 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
if (try! config.display.jsonString()) == "{}" {
|
||||
|
||||
isDefault = true
|
||||
print("🖥️ Default Display config")
|
||||
|
||||
if meshlogging { MeshLogger.log("🖥️ Default Display config \(String(nodeNum))") }
|
||||
|
||||
} else {
|
||||
|
||||
if meshlogging { MeshLogger.log("🖥️ Custom Display config \(String(nodeNum))") }
|
||||
}
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
|
|
@ -116,12 +210,14 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
newDisplayConfig.screenOnSeconds = 0
|
||||
newDisplayConfig.screenCarouselInterval = 0
|
||||
newDisplayConfig.gpsFormat = 0
|
||||
newDisplayConfig.compassNorthTop = false
|
||||
|
||||
} else {
|
||||
|
||||
newDisplayConfig.gpsFormat = Int32(config.display.gpsFormat.rawValue)
|
||||
newDisplayConfig.screenOnSeconds = Int32(config.display.screenOnSecs)
|
||||
newDisplayConfig.screenCarouselInterval = Int32(config.display.autoScreenCarouselSecs)
|
||||
newDisplayConfig.compassNorthTop = config.display.compassNorthTop
|
||||
}
|
||||
fetchedNode[0].displayConfig = newDisplayConfig
|
||||
|
||||
|
|
@ -132,12 +228,14 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
fetchedNode[0].displayConfig?.screenOnSeconds = 0
|
||||
fetchedNode[0].displayConfig?.screenCarouselInterval = 0
|
||||
fetchedNode[0].displayConfig?.gpsFormat = 0
|
||||
fetchedNode[0].displayConfig?.compassNorthTop = false
|
||||
|
||||
} else {
|
||||
|
||||
fetchedNode[0].displayConfig?.gpsFormat = Int32(config.display.gpsFormat.rawValue)
|
||||
fetchedNode[0].displayConfig?.screenOnSeconds = Int32(config.display.screenOnSecs)
|
||||
fetchedNode[0].displayConfig?.screenCarouselInterval = Int32(config.display.autoScreenCarouselSecs)
|
||||
fetchedNode[0].displayConfig?.compassNorthTop = config.display.compassNorthTop
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,10 +251,15 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
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)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -243,10 +346,16 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data LoRaConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Lora Config")
|
||||
}
|
||||
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data LoRaConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -257,6 +366,11 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
if (try! config.position.jsonString()) == "{}" {
|
||||
|
||||
isDefault = true
|
||||
if meshlogging { MeshLogger.log("🗺️ Default Position config received \(String(nodeNum))") }
|
||||
|
||||
} else {
|
||||
|
||||
if meshlogging { MeshLogger.log("🗺️ Custom Position config received \(String(nodeNum))") }
|
||||
}
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
|
|
@ -328,10 +442,97 @@ func localConfig (config: Config, meshlogging: Bool, context:NSManagedObjectCont
|
|||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data PositionConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Position Config")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data PositionConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
if config.payloadVariant == Config.OneOf_PayloadVariant.wifi(config.wifi) {
|
||||
|
||||
var isDefault = false
|
||||
|
||||
if (try! config.wifi.jsonString()) == "{}" {
|
||||
|
||||
isDefault = true
|
||||
if meshlogging { MeshLogger.log("📶 Default WiFi config received \(String(nodeNum))") }
|
||||
|
||||
} else {
|
||||
|
||||
if meshlogging { MeshLogger.log("📶 Custom WiFi config received \(String(nodeNum))") }
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
if fetchedNode[0].wiFiConfig == nil {
|
||||
|
||||
let newWiFiConfig = WiFiConfigEntity(context: context)
|
||||
|
||||
if isDefault {
|
||||
|
||||
newWiFiConfig.ssid = ""
|
||||
newWiFiConfig.password = ""
|
||||
newWiFiConfig.mode = 0
|
||||
|
||||
} else {
|
||||
|
||||
newWiFiConfig.ssid = config.wifi.ssid
|
||||
newWiFiConfig.password = config.wifi.psk
|
||||
newWiFiConfig.mode = Int32(config.wifi.mode.rawValue)
|
||||
}
|
||||
newWiFiConfig.num = fetchedNode[0].num
|
||||
fetchedNode[0].wiFiConfig = newWiFiConfig
|
||||
|
||||
} else {
|
||||
|
||||
if isDefault {
|
||||
|
||||
fetchedNode[0].wiFiConfig?.ssid = ""
|
||||
fetchedNode[0].wiFiConfig?.password = ""
|
||||
fetchedNode[0].wiFiConfig?.mode = 0
|
||||
|
||||
} else {
|
||||
|
||||
fetchedNode[0].wiFiConfig?.ssid = config.wifi.ssid
|
||||
fetchedNode[0].wiFiConfig?.password = config.wifi.psk
|
||||
fetchedNode[0].wiFiConfig?.mode = Int32(config.wifi.mode.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
try context.save()
|
||||
if meshlogging { MeshLogger.log("💾 Updated WiFi Config for node number: \(String(nodeNum))") }
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data WiFiConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save WiFi Config")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data WiFiConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -347,6 +548,9 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
|
||||
isDefault = true
|
||||
print("🥫 Default Canned Message Module config")
|
||||
} else {
|
||||
|
||||
print("🥫 Custom Canned Message Module config")
|
||||
}
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
|
|
@ -388,7 +592,8 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
newCannedMessageConfig.inputbrokerEventCcw = Int32(config.cannedMessage.inputbrokerEventCcw.rawValue)
|
||||
newCannedMessageConfig.inputbrokerEventPress = Int32(config.cannedMessage.inputbrokerEventPress.rawValue)
|
||||
}
|
||||
|
||||
|
||||
newCannedMessageConfig.num = nodeNum
|
||||
fetchedNode[0].cannedMessageConfig = newCannedMessageConfig
|
||||
|
||||
} else {
|
||||
|
|
@ -419,13 +624,14 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
fetchedNode[0].cannedMessageConfig?.inputbrokerEventCcw = Int32(config.cannedMessage.inputbrokerEventCcw.rawValue)
|
||||
fetchedNode[0].cannedMessageConfig?.inputbrokerEventPress = Int32(config.cannedMessage.inputbrokerEventPress.rawValue)
|
||||
}
|
||||
fetchedNode[0].cannedMessageConfig?.num = nodeNum
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
try context.save()
|
||||
if meshlogging { MeshLogger.log("💾 Updated Canned Message Module Config for node number: \(String(nodeNum))") }
|
||||
print(try config.cannedMessage.jsonString())
|
||||
|
||||
|
||||
} catch {
|
||||
|
||||
|
|
@ -434,10 +640,15 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data CannedMessageConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Canned Message Module Config")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data CannedMessageConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -449,6 +660,10 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
|
||||
isDefault = true
|
||||
print("🚨 Default External Notifiation Module config")
|
||||
|
||||
} else {
|
||||
|
||||
print("🚨 Custom External Notifiation Module config")
|
||||
}
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "NodeInfoEntity")
|
||||
|
|
@ -485,6 +700,7 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
newExternalNotificationConfig.outputMilliseconds = Int32(config.externalNotification.outputMs)
|
||||
}
|
||||
|
||||
newExternalNotificationConfig.num = nodeNum
|
||||
fetchedNode[0].externalNotificationConfig = newExternalNotificationConfig
|
||||
|
||||
} else {
|
||||
|
|
@ -507,6 +723,7 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
fetchedNode[0].externalNotificationConfig?.output = Int32(config.externalNotification.output)
|
||||
fetchedNode[0].externalNotificationConfig?.outputMilliseconds = Int32(config.externalNotification.outputMs)
|
||||
}
|
||||
fetchedNode[0].externalNotificationConfig?.num = nodeNum
|
||||
}
|
||||
|
||||
do {
|
||||
|
|
@ -521,10 +738,15 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data ExternalNotificationConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save External Notifiation Module Config")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data ExternalNotificationConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -563,7 +785,7 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
newRangeTestConfig.enabled = config.rangeTest.enabled
|
||||
newRangeTestConfig.save = config.rangeTest.save
|
||||
}
|
||||
|
||||
newRangeTestConfig.num = nodeNum
|
||||
fetchedNode[0].rangeTestConfig = newRangeTestConfig
|
||||
|
||||
} else {
|
||||
|
|
@ -594,10 +816,15 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
let nsError = error as NSError
|
||||
print("💥 Error Updating Core Data RangeTestConfigEntity: \(nsError)")
|
||||
}
|
||||
} else {
|
||||
|
||||
print("💥 No Nodes found in local database matching node number \(nodeNum) unable to save Range Test Module Config")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Fetching node for core data RangeTestConfigEntity failed: \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -688,10 +915,15 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
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)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -723,25 +955,17 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
newTelemetryConfig.deviceUpdateInterval = 0
|
||||
newTelemetryConfig.environmentUpdateInterval = 0
|
||||
newTelemetryConfig.environmentMeasurementEnabled = false
|
||||
newTelemetryConfig.environmentSensorType = 0
|
||||
newTelemetryConfig.environmentScreenEnabled = false
|
||||
newTelemetryConfig.environmentDisplayFahrenheit = false
|
||||
newTelemetryConfig.environmentRecoveryInterval = 0
|
||||
newTelemetryConfig.environmentReadErrorCountThreshold = 0
|
||||
|
||||
} else {
|
||||
|
||||
newTelemetryConfig.deviceUpdateInterval = Int32(config.telemetry.deviceUpdateInterval)
|
||||
newTelemetryConfig.environmentUpdateInterval = Int32(config.telemetry.environmentUpdateInterval)
|
||||
newTelemetryConfig.environmentMeasurementEnabled = config.telemetry.environmentMeasurementEnabled
|
||||
newTelemetryConfig.environmentSensorType = Int32(config.telemetry.environmentSensorType.rawValue)
|
||||
newTelemetryConfig.environmentScreenEnabled = config.telemetry.environmentScreenEnabled
|
||||
newTelemetryConfig.environmentDisplayFahrenheit = config.telemetry.environmentDisplayFahrenheit
|
||||
newTelemetryConfig.environmentRecoveryInterval = Int32(config.telemetry.environmentRecoveryInterval)
|
||||
newTelemetryConfig.environmentReadErrorCountThreshold = Int32(config.telemetry.environmentReadErrorCountThreshold)
|
||||
|
||||
}
|
||||
|
||||
fetchedNode[0].telemetryConfig = newTelemetryConfig
|
||||
|
||||
} else {
|
||||
|
|
@ -751,23 +975,16 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
fetchedNode[0].telemetryConfig?.deviceUpdateInterval = 0
|
||||
fetchedNode[0].telemetryConfig?.environmentUpdateInterval = 0
|
||||
fetchedNode[0].telemetryConfig?.environmentMeasurementEnabled = false
|
||||
fetchedNode[0].telemetryConfig?.environmentSensorType = 0
|
||||
fetchedNode[0].telemetryConfig?.environmentScreenEnabled = false
|
||||
fetchedNode[0].telemetryConfig?.environmentDisplayFahrenheit = false
|
||||
fetchedNode[0].telemetryConfig?.environmentRecoveryInterval = 0
|
||||
fetchedNode[0].telemetryConfig?.environmentReadErrorCountThreshold = 0
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
fetchedNode[0].telemetryConfig?.deviceUpdateInterval = Int32(config.telemetry.deviceUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.environmentUpdateInterval = Int32(config.telemetry.environmentUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.environmentMeasurementEnabled = config.telemetry.environmentMeasurementEnabled
|
||||
fetchedNode[0].telemetryConfig?.environmentSensorType = Int32(config.telemetry.environmentSensorType.rawValue)
|
||||
fetchedNode[0].telemetryConfig?.environmentScreenEnabled = config.telemetry.environmentScreenEnabled
|
||||
fetchedNode[0].telemetryConfig?.environmentDisplayFahrenheit = config.telemetry.environmentDisplayFahrenheit
|
||||
fetchedNode[0].telemetryConfig?.environmentRecoveryInterval = Int32(config.telemetry.environmentRecoveryInterval)
|
||||
fetchedNode[0].telemetryConfig?.environmentReadErrorCountThreshold = Int32(config.telemetry.environmentReadErrorCountThreshold)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -783,10 +1000,15 @@ func moduleConfig (config: ModuleConfig, meshlogging: Bool, context:NSManagedObj
|
|||
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)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1138,6 +1360,7 @@ func adminAppPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedOb
|
|||
print("channel settings:", channel.settings)
|
||||
}
|
||||
|
||||
|
||||
if meshLogging { MeshLogger.log("ℹ️ MESH PACKET received for Admin App UNHANDLED \(try! packet.jsonString())") }
|
||||
|
||||
//PowerConfig
|
||||
|
|
@ -1175,7 +1398,7 @@ func positionPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedOb
|
|||
|
||||
fetchedNode[0].id = Int64(packet.from)
|
||||
fetchedNode[0].num = Int64(packet.from)
|
||||
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
|
||||
fetchedNode[0].lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
|
||||
fetchedNode[0].snr = packet.rxSnr
|
||||
fetchedNode[0].positions = mutablePositions.copy() as? NSOrderedSet
|
||||
|
||||
|
|
@ -1195,6 +1418,7 @@ func positionPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedOb
|
|||
print("💥 Error Saving NodeInfoEntity from POSITION_APP \(nsError)")
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
print("💥 Empty POSITION_APP Packet")
|
||||
|
|
@ -1245,43 +1469,47 @@ func routingPacket (packet: MeshPacket, meshLogging: Bool, context: NSManagedObj
|
|||
|
||||
if meshLogging { MeshLogger.log("🕸️ ROUTING PACKET received for RequestID: \(packet.decoded.requestID) Error: \(errorExplanation)") }
|
||||
|
||||
if routingMessage.errorReason == Routing.Error.none {
|
||||
|
||||
let fetchMessageRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MessageEntity")
|
||||
fetchMessageRequest.predicate = NSPredicate(format: "messageId == %lld", Int64(packet.decoded.requestID))
|
||||
let fetchMessageRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "MessageEntity")
|
||||
fetchMessageRequest.predicate = NSPredicate(format: "messageId == %lld", Int64(packet.decoded.requestID))
|
||||
|
||||
do {
|
||||
do {
|
||||
|
||||
let fetchedMessage = try context.fetch(fetchMessageRequest) as? [MessageEntity]
|
||||
let fetchedMessage = try context.fetch(fetchMessageRequest) as? [MessageEntity]
|
||||
|
||||
if fetchedMessage?.count ?? 0 > 0 {
|
||||
|
||||
if fetchedMessage?.count ?? 0 > 0 {
|
||||
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)
|
||||
fetchedMessage![0].objectWillChange.send()
|
||||
fetchedMessage![0].fromUser?.objectWillChange.send()
|
||||
fetchedMessage![0].toUser?.objectWillChange.send()
|
||||
|
||||
} else {
|
||||
|
||||
return
|
||||
}
|
||||
fetchedMessage![0].ackSNR = packet.rxSnr
|
||||
fetchedMessage![0].ackTimestamp = Int32(packet.rxTime)
|
||||
fetchedMessage![0].objectWillChange.send()
|
||||
fetchedMessage![0].fromUser?.objectWillChange.send()
|
||||
fetchedMessage![0].toUser?.objectWillChange.send()
|
||||
|
||||
try context.save()
|
||||
|
||||
if meshLogging {
|
||||
MeshLogger.log("💾 ACK Received and saved for MessageID \(packet.decoded.requestID)")
|
||||
}
|
||||
} else {
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving ACK for message MessageID \(packet.id) Error: \(nsError)")
|
||||
return
|
||||
}
|
||||
|
||||
try context.save()
|
||||
|
||||
if meshLogging {
|
||||
MeshLogger.log("💾 ACK Received and saved for MessageID \(packet.decoded.requestID)")
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
||||
let nsError = error as NSError
|
||||
print("💥 Error Saving ACK for message MessageID \(packet.id) Error: \(nsError)")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1355,7 +1583,7 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, meshLogging:
|
|||
|
||||
if let messageText = String(bytes: packet.decoded.payload, encoding: .utf8) {
|
||||
|
||||
if meshLogging { MeshLogger.log("💬 Message received for text message app \(messageText)") }
|
||||
if meshLogging { MeshLogger.log("💬 Message received for text message app") }
|
||||
|
||||
let messageUsers: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserEntity")
|
||||
messageUsers.predicate = NSPredicate(format: "num IN %@", [packet.to, packet.from])
|
||||
|
|
@ -1406,6 +1634,28 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, meshLogging:
|
|||
|
||||
messageSaved = true
|
||||
|
||||
if messageSaved { //&& (newMessage.toUser != nil && newMessage.toUser!.num == broadcastNodeNum || connectedNode == newMessage.toUser!.num) {
|
||||
|
||||
|
||||
if newMessage.fromUser != nil {
|
||||
|
||||
// Create an iOS Notification for the received message and schedule it immediately
|
||||
let manager = LocalNotificationManager()
|
||||
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: ("notification.id.\(newMessage.messageId)"),
|
||||
title: "\(newMessage.fromUser?.longName ?? "Unknown")",
|
||||
subtitle: "AKA \(newMessage.fromUser?.shortName ?? "???")",
|
||||
content: messageText)
|
||||
]
|
||||
|
||||
manager.schedule()
|
||||
|
||||
if meshLogging { MeshLogger.log("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown")") }
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
context.rollback()
|
||||
|
|
@ -1413,28 +1663,6 @@ func textMessageAppPacket(packet: MeshPacket, connectedNode: Int64, meshLogging:
|
|||
let nsError = error as NSError
|
||||
print("💥 Failed to save new MessageEntity \(nsError)")
|
||||
}
|
||||
do {
|
||||
|
||||
if messageSaved && (newMessage.toUser != nil && newMessage.toUser!.num == broadcastNodeNum || connectedNode == newMessage.toUser!.num) {
|
||||
|
||||
// Create an iOS Notification for the received message and schedule it immediately
|
||||
let manager = LocalNotificationManager()
|
||||
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: ("notification.id.\(newMessage.messageId)"),
|
||||
title: "\(newMessage.fromUser?.longName ?? "Unknown")",
|
||||
subtitle: "AKA \(newMessage.fromUser?.shortName ?? "???")",
|
||||
content: messageText)
|
||||
]
|
||||
|
||||
manager.schedule()
|
||||
if meshLogging { MeshLogger.log("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "Unknown") \(messageText)") }
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
}
|
||||
|
||||
} catch {
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<dict>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:meshtastic.org/*</string>
|
||||
<string>applinks:meshtastic.org/e/*</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>MeshtasticDataModel v 4.xcdatamodel</string>
|
||||
<string>MeshtasticDataModel v 8.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,222 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="20086" systemVersion="21G72" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="CannedMessageConfigEntity" representedClassName="CannedMessageConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCcw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventPress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinB" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinPress" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rotary1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="updown1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessageConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DeviceConfigEntity" representedClassName="DeviceConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="debugLogEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="role" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="serialEnabled" optional="YES" attributeType="Boolean" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="deviceConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="deviceConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DisplayConfigEntity" representedClassName="DisplayConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="gpsFormat" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenCarouselInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenOnSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="displayConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="displayConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="ExternalNotificationConfigEntity" representedClassName="ExternalNotificationConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="active" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessage" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="output" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputMilliseconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="externalNotificationConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="externalNotificationConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="LoRaConfigEntity" representedClassName="LoRaConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hopLimit" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="modemPreset" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="regionCode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txPower" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="loRaConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="loRaConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ackError" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackSNR" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="admin" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="adminDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="isEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="messageId" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messagePayload" optional="YES" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="messageTimestamp" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="receivedACK" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="replyID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="fromUser" maxCount="1" deletionRule="Nullify" ordered="YES" destinationEntity="UserEntity" inverseName="sentMessages" inverseEntity="UserEntity"/>
|
||||
<relationship name="toUser" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="receivedMessages" inverseEntity="UserEntity"/>
|
||||
<fetchedProperty name="tapbacks" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="replyID == $FETCH_SOURCE.messageId AND isEmoji == true"/>
|
||||
</fetchedProperty>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="messageId"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="MyInfoEntity" representedClassName="MyInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bitrate" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="errorCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="firmwareVersion" attributeType="String"/>
|
||||
<attribute name="hasGps" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hasWifi" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="maxChannels" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messageTimeoutMsec" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="minAppVersion" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="myNodeNum" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rebootCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="myInfoNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="myInfo" inverseEntity="NodeInfoEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="myNodeNum"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="NodeInfoEntity" representedClassName="NodeInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="lastHeard" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessageConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CannedMessageConfigEntity" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfigEntity"/>
|
||||
<relationship name="deviceConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DeviceConfigEntity" inverseName="deviceConfigNode" inverseEntity="DeviceConfigEntity"/>
|
||||
<relationship name="displayConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DisplayConfigEntity" inverseName="displayConfigNode" inverseEntity="DisplayConfigEntity"/>
|
||||
<relationship name="externalNotificationConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ExternalNotificationConfigEntity" inverseName="externalNotificationConfigNode" inverseEntity="ExternalNotificationConfigEntity"/>
|
||||
<relationship name="loRaConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="LoRaConfigEntity" inverseName="loRaConfigNode" inverseEntity="LoRaConfigEntity"/>
|
||||
<relationship name="myInfo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MyInfoEntity" inverseName="myInfoNode" inverseEntity="MyInfoEntity"/>
|
||||
<relationship name="positionConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PositionConfigEntity" inverseName="positionConfigNode" inverseEntity="PositionConfigEntity"/>
|
||||
<relationship name="positions" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PositionEntity" inverseName="nodePosition" inverseEntity="PositionEntity"/>
|
||||
<relationship name="rangeTestConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RangeTestConfigEntity" inverseName="rangeTestConfigNode" inverseEntity="RangeTestConfigEntity"/>
|
||||
<relationship name="serialConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SerialConfigEntity" inverseName="serialConfigNode" inverseEntity="SerialConfigEntity"/>
|
||||
<relationship name="telemetries" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TelemetryEntity" inverseName="nodeTelemetry" inverseEntity="TelemetryEntity"/>
|
||||
<relationship name="telemetryConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TelemetryConfigEntity" inverseName="telemetryConfigNode" inverseEntity="TelemetryConfigEntity"/>
|
||||
<relationship name="user" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="userNode" inverseEntity="UserEntity"/>
|
||||
<relationship name="wiFiConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="WiFiConfigEntity" inverseName="wiFiConfigNode" inverseEntity="WiFiConfigEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="num"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PositionConfigEntity" representedClassName="PositionConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceGpsEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPosition" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsAttemptTime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="positionBroadcastSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="smartPositionEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="positionConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positionConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PositionEntity" representedClassName="PositionEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="satsInView" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="nodePosition" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positions" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="RangeTestConfigEntity" representedClassName="RangeTestConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="save" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sender" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<relationship name="rangeTestConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rangeTestConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="SerialConfigEntity" representedClassName="SerialConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="baudRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="serialConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="serialConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryConfigEntity" representedClassName="TelemetryConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentDisplayFahrenheit" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentMeasurementEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentScreenEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="telemetryConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetryConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryEntity" representedClassName="TelemetryEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="batteryLevel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelUtilization" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="gasResistance" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="metricsType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="relativeHumidity" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="temperature" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="voltage" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="nodeTelemetry" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetries" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="UserEntity" representedClassName="UserEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hwModel" attributeType="String"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="longName" attributeType="String"/>
|
||||
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="team" optional="YES" attributeType="String"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="userNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="user" inverseEntity="NodeInfoEntity"/>
|
||||
<fetchedProperty name="adminMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="(toUser.num == $FETCH_SOURCE.num) AND isEmoji == false AND admin = true"/>
|
||||
</fetchedProperty>
|
||||
<fetchedProperty name="allMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="((toUser.num == $FETCH_SOURCE.num) OR (fromUser.num == $FETCH_SOURCE.num)) AND isEmoji == false AND admin = false"/>
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<entity name="WiFiConfigEntity" representedClassName="WiFiConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="apHidden" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="apMode" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="password" optional="YES" attributeType="String" minValueString="0" maxValueString="60"/>
|
||||
<attribute name="ssid" optional="YES" attributeType="String" minValueString="0" maxValueString="30"/>
|
||||
<relationship name="wiFiConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="wiFiConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="CannedMessageConfigEntity" positionX="45" positionY="144" width="128" height="209"/>
|
||||
<element name="DeviceConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
|
||||
<element name="DisplayConfigEntity" positionX="54" positionY="153" width="128" height="104"/>
|
||||
<element name="ExternalNotificationConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
<element name="MessageEntity" positionX="-36" positionY="63" width="128" height="245"/>
|
||||
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="209"/>
|
||||
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="314"/>
|
||||
<element name="PositionConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
|
||||
<element name="RangeTestConfigEntity" positionX="72" positionY="171" width="128" height="104"/>
|
||||
<element name="SerialConfigEntity" positionX="54" positionY="153" width="128" height="164"/>
|
||||
<element name="TelemetryConfigEntity" positionX="72" positionY="171" width="128" height="134"/>
|
||||
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="209"/>
|
||||
<element name="UserEntity" positionX="0" positionY="144" width="128" height="230"/>
|
||||
<element name="WiFiConfigEntity" positionX="45" positionY="144" width="128" height="134"/>
|
||||
</elements>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21G83" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="CannedMessageConfigEntity" representedClassName="CannedMessageConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCcw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventPress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinB" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinPress" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rotary1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="updown1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessageConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DeviceConfigEntity" representedClassName="DeviceConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="debugLogEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="role" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="serialEnabled" optional="YES" attributeType="Boolean" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="deviceConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="deviceConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DisplayConfigEntity" representedClassName="DisplayConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="compassNorthTop" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsFormat" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenCarouselInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenOnSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="displayConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="displayConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="ExternalNotificationConfigEntity" representedClassName="ExternalNotificationConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="active" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessage" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="output" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputMilliseconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="externalNotificationConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="externalNotificationConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="LoRaConfigEntity" representedClassName="LoRaConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hopLimit" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="modemPreset" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="regionCode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txPower" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="loRaConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="loRaConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ackError" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackSNR" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="admin" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="adminDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="isEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="messageId" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messagePayload" optional="YES" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="messageTimestamp" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="receivedACK" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="replyID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="fromUser" maxCount="1" deletionRule="Nullify" ordered="YES" destinationEntity="UserEntity" inverseName="sentMessages" inverseEntity="UserEntity"/>
|
||||
<relationship name="toUser" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="receivedMessages" inverseEntity="UserEntity"/>
|
||||
<fetchedProperty name="tapbacks" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="replyID == $FETCH_SOURCE.messageId AND isEmoji == true"/>
|
||||
</fetchedProperty>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="messageId"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="MyInfoEntity" representedClassName="MyInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bitrate" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="errorCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="firmwareVersion" attributeType="String"/>
|
||||
<attribute name="hasGps" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hasWifi" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="maxChannels" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messageTimeoutMsec" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="minAppVersion" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="myNodeNum" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rebootCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="myInfoNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="myInfo" inverseEntity="NodeInfoEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="myNodeNum"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="NodeInfoEntity" representedClassName="NodeInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="lastHeard" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessageConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CannedMessageConfigEntity" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfigEntity"/>
|
||||
<relationship name="deviceConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DeviceConfigEntity" inverseName="deviceConfigNode" inverseEntity="DeviceConfigEntity"/>
|
||||
<relationship name="displayConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DisplayConfigEntity" inverseName="displayConfigNode" inverseEntity="DisplayConfigEntity"/>
|
||||
<relationship name="externalNotificationConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ExternalNotificationConfigEntity" inverseName="externalNotificationConfigNode" inverseEntity="ExternalNotificationConfigEntity"/>
|
||||
<relationship name="loRaConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="LoRaConfigEntity" inverseName="loRaConfigNode" inverseEntity="LoRaConfigEntity"/>
|
||||
<relationship name="myInfo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MyInfoEntity" inverseName="myInfoNode" inverseEntity="MyInfoEntity"/>
|
||||
<relationship name="positionConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PositionConfigEntity" inverseName="positionConfigNode" inverseEntity="PositionConfigEntity"/>
|
||||
<relationship name="positions" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PositionEntity" inverseName="nodePosition" inverseEntity="PositionEntity"/>
|
||||
<relationship name="rangeTestConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RangeTestConfigEntity" inverseName="rangeTestConfigNode" inverseEntity="RangeTestConfigEntity"/>
|
||||
<relationship name="serialConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SerialConfigEntity" inverseName="serialConfigNode" inverseEntity="SerialConfigEntity"/>
|
||||
<relationship name="telemetries" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TelemetryEntity" inverseName="nodeTelemetry" inverseEntity="TelemetryEntity"/>
|
||||
<relationship name="telemetryConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TelemetryConfigEntity" inverseName="telemetryConfigNode" inverseEntity="TelemetryConfigEntity"/>
|
||||
<relationship name="user" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="userNode" inverseEntity="UserEntity"/>
|
||||
<relationship name="wiFiConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="WiFiConfigEntity" inverseName="wiFiConfigNode" inverseEntity="WiFiConfigEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="num"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PositionConfigEntity" representedClassName="PositionConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceGpsEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPosition" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsAttemptTime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="positionBroadcastSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="smartPositionEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="positionConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positionConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PositionEntity" representedClassName="PositionEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="satsInView" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="nodePosition" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positions" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="RangeTestConfigEntity" representedClassName="RangeTestConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="save" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sender" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<relationship name="rangeTestConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rangeTestConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="SerialConfigEntity" representedClassName="SerialConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="baudRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="serialConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="serialConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryConfigEntity" representedClassName="TelemetryConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentDisplayFahrenheit" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentMeasurementEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentScreenEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="telemetryConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetryConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryEntity" representedClassName="TelemetryEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="batteryLevel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelUtilization" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="gasResistance" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="metricsType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="relativeHumidity" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="temperature" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="voltage" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="nodeTelemetry" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetries" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="UserEntity" representedClassName="UserEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hwModel" attributeType="String"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="longName" attributeType="String"/>
|
||||
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="team" optional="YES" attributeType="String"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="userNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="user" inverseEntity="NodeInfoEntity"/>
|
||||
<fetchedProperty name="adminMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="(toUser.num == $FETCH_SOURCE.num) AND isEmoji == false AND admin = true"/>
|
||||
</fetchedProperty>
|
||||
<fetchedProperty name="allMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="((toUser.num == $FETCH_SOURCE.num) OR (fromUser.num == $FETCH_SOURCE.num)) AND isEmoji == false AND admin = false"/>
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<entity name="WiFiConfigEntity" representedClassName="WiFiConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="password" optional="YES" attributeType="String" minValueString="0" maxValueString="60"/>
|
||||
<attribute name="ssid" optional="YES" attributeType="String" minValueString="0" maxValueString="30"/>
|
||||
<relationship name="wiFiConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="wiFiConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="CannedMessageConfigEntity" positionX="45" positionY="144" width="128" height="209"/>
|
||||
<element name="DeviceConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
|
||||
<element name="DisplayConfigEntity" positionX="54" positionY="153" width="128" height="119"/>
|
||||
<element name="ExternalNotificationConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
<element name="MessageEntity" positionX="-36" positionY="63" width="128" height="245"/>
|
||||
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="209"/>
|
||||
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="314"/>
|
||||
<element name="PositionConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
|
||||
<element name="RangeTestConfigEntity" positionX="72" positionY="171" width="128" height="104"/>
|
||||
<element name="SerialConfigEntity" positionX="54" positionY="153" width="128" height="164"/>
|
||||
<element name="TelemetryConfigEntity" positionX="72" positionY="171" width="128" height="134"/>
|
||||
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="209"/>
|
||||
<element name="UserEntity" positionX="0" positionY="144" width="128" height="230"/>
|
||||
<element name="WiFiConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
</elements>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21G83" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="BluetoothConfigEntity" representedClassName="BluetoothConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPin" optional="YES" attributeType="Integer 32" defaultValueString="123456" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="bluetoothConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="bluetoothConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="CannedMessageConfigEntity" representedClassName="CannedMessageConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCcw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventPress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinB" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinPress" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rotary1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="updown1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessageConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DeviceConfigEntity" representedClassName="DeviceConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="debugLogEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="role" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="serialEnabled" optional="YES" attributeType="Boolean" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="deviceConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="deviceConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DisplayConfigEntity" representedClassName="DisplayConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="compassNorthTop" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsFormat" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenCarouselInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenOnSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="displayConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="displayConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="ExternalNotificationConfigEntity" representedClassName="ExternalNotificationConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="active" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessage" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="output" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputMilliseconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="externalNotificationConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="externalNotificationConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="LoRaConfigEntity" representedClassName="LoRaConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hopLimit" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="modemPreset" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="regionCode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txPower" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="loRaConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="loRaConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ackError" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackSNR" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="admin" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="adminDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="isEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="messageId" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messagePayload" optional="YES" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="messageTimestamp" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="receivedACK" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="replyID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="fromUser" maxCount="1" deletionRule="Nullify" ordered="YES" destinationEntity="UserEntity" inverseName="sentMessages" inverseEntity="UserEntity"/>
|
||||
<relationship name="toUser" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="receivedMessages" inverseEntity="UserEntity"/>
|
||||
<fetchedProperty name="tapbacks" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="replyID == $FETCH_SOURCE.messageId AND isEmoji == true"/>
|
||||
</fetchedProperty>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="messageId"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="MyInfoEntity" representedClassName="MyInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bitrate" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="errorCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="firmwareVersion" attributeType="String"/>
|
||||
<attribute name="hasGps" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hasWifi" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="maxChannels" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messageTimeoutMsec" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="minAppVersion" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="myNodeNum" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rebootCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="myInfoNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="myInfo" inverseEntity="NodeInfoEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="myNodeNum"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="NodeInfoEntity" representedClassName="NodeInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="lastHeard" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="bluetoothConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="BluetoothConfigEntity" inverseName="bluetoothConfigNode" inverseEntity="BluetoothConfigEntity"/>
|
||||
<relationship name="cannedMessageConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CannedMessageConfigEntity" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfigEntity"/>
|
||||
<relationship name="deviceConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DeviceConfigEntity" inverseName="deviceConfigNode" inverseEntity="DeviceConfigEntity"/>
|
||||
<relationship name="displayConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DisplayConfigEntity" inverseName="displayConfigNode" inverseEntity="DisplayConfigEntity"/>
|
||||
<relationship name="externalNotificationConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ExternalNotificationConfigEntity" inverseName="externalNotificationConfigNode" inverseEntity="ExternalNotificationConfigEntity"/>
|
||||
<relationship name="loRaConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="LoRaConfigEntity" inverseName="loRaConfigNode" inverseEntity="LoRaConfigEntity"/>
|
||||
<relationship name="myInfo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MyInfoEntity" inverseName="myInfoNode" inverseEntity="MyInfoEntity"/>
|
||||
<relationship name="positionConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PositionConfigEntity" inverseName="positionConfigNode" inverseEntity="PositionConfigEntity"/>
|
||||
<relationship name="positions" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PositionEntity" inverseName="nodePosition" inverseEntity="PositionEntity"/>
|
||||
<relationship name="rangeTestConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RangeTestConfigEntity" inverseName="rangeTestConfigNode" inverseEntity="RangeTestConfigEntity"/>
|
||||
<relationship name="serialConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SerialConfigEntity" inverseName="serialConfigNode" inverseEntity="SerialConfigEntity"/>
|
||||
<relationship name="telemetries" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TelemetryEntity" inverseName="nodeTelemetry" inverseEntity="TelemetryEntity"/>
|
||||
<relationship name="telemetryConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TelemetryConfigEntity" inverseName="telemetryConfigNode" inverseEntity="TelemetryConfigEntity"/>
|
||||
<relationship name="user" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="userNode" inverseEntity="UserEntity"/>
|
||||
<relationship name="wiFiConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="WiFiConfigEntity" inverseName="wiFiConfigNode" inverseEntity="WiFiConfigEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="num"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PositionConfigEntity" representedClassName="PositionConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceGpsEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPosition" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsAttemptTime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="positionBroadcastSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="smartPositionEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="positionConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positionConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PositionEntity" representedClassName="PositionEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="satsInView" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="nodePosition" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positions" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="RangeTestConfigEntity" representedClassName="RangeTestConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="save" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sender" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<relationship name="rangeTestConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rangeTestConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="SerialConfigEntity" representedClassName="SerialConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="baudRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="serialConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="serialConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryConfigEntity" representedClassName="TelemetryConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentDisplayFahrenheit" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentMeasurementEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentScreenEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="telemetryConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetryConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryEntity" representedClassName="TelemetryEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="batteryLevel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelUtilization" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="gasResistance" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="metricsType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="relativeHumidity" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="temperature" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="voltage" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="nodeTelemetry" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetries" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="UserEntity" representedClassName="UserEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hwModel" attributeType="String"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="longName" attributeType="String"/>
|
||||
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="team" optional="YES" attributeType="String"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="userNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="user" inverseEntity="NodeInfoEntity"/>
|
||||
<fetchedProperty name="adminMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="(toUser.num == $FETCH_SOURCE.num) AND isEmoji == false AND admin = true"/>
|
||||
</fetchedProperty>
|
||||
<fetchedProperty name="allMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="((toUser.num == $FETCH_SOURCE.num) OR (fromUser.num == $FETCH_SOURCE.num)) AND isEmoji == false AND admin = false"/>
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<entity name="WiFiConfigEntity" representedClassName="WiFiConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="password" optional="YES" attributeType="String" minValueString="0" maxValueString="60"/>
|
||||
<attribute name="ssid" optional="YES" attributeType="String" minValueString="0" maxValueString="30"/>
|
||||
<relationship name="wiFiConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="wiFiConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="CannedMessageConfigEntity" positionX="45" positionY="144" width="128" height="209"/>
|
||||
<element name="DeviceConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
|
||||
<element name="DisplayConfigEntity" positionX="54" positionY="153" width="128" height="119"/>
|
||||
<element name="ExternalNotificationConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
<element name="MessageEntity" positionX="-36" positionY="63" width="128" height="245"/>
|
||||
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="209"/>
|
||||
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="329"/>
|
||||
<element name="PositionConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
|
||||
<element name="RangeTestConfigEntity" positionX="72" positionY="171" width="128" height="104"/>
|
||||
<element name="SerialConfigEntity" positionX="54" positionY="153" width="128" height="164"/>
|
||||
<element name="TelemetryConfigEntity" positionX="72" positionY="171" width="128" height="134"/>
|
||||
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="209"/>
|
||||
<element name="UserEntity" positionX="0" positionY="144" width="128" height="230"/>
|
||||
<element name="WiFiConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
<element name="BluetoothConfigEntity" positionX="54" positionY="153" width="128" height="104"/>
|
||||
</elements>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21G83" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="BluetoothConfigEntity" representedClassName="BluetoothConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPin" optional="YES" attributeType="Integer 32" defaultValueString="123456" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="bluetoothConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="bluetoothConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="CannedMessageConfigEntity" representedClassName="CannedMessageConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCcw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventPress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinB" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinPress" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rotary1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="updown1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessageConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DeviceConfigEntity" representedClassName="DeviceConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="debugLogEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="role" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="serialEnabled" optional="YES" attributeType="Boolean" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="deviceConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="deviceConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DisplayConfigEntity" representedClassName="DisplayConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="compassNorthTop" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsFormat" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenCarouselInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenOnSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="displayConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="displayConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="ExternalNotificationConfigEntity" representedClassName="ExternalNotificationConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="active" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessage" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="output" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputMilliseconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="externalNotificationConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="externalNotificationConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="LoRaConfigEntity" representedClassName="LoRaConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hopLimit" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="modemPreset" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="regionCode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txPower" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="loRaConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="loRaConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ackError" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackSNR" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="admin" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="adminDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="isEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="messageId" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messagePayload" optional="YES" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="messageTimestamp" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="receivedACK" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="replyID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="fromUser" maxCount="1" deletionRule="Nullify" ordered="YES" destinationEntity="UserEntity" inverseName="sentMessages" inverseEntity="UserEntity"/>
|
||||
<relationship name="toUser" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="receivedMessages" inverseEntity="UserEntity"/>
|
||||
<fetchedProperty name="tapbacks" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="replyID == $FETCH_SOURCE.messageId AND isEmoji == true"/>
|
||||
</fetchedProperty>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="messageId"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="MyInfoEntity" representedClassName="MyInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bitrate" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="errorCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="firmwareVersion" attributeType="String"/>
|
||||
<attribute name="hasGps" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hasWifi" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="maxChannels" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messageTimeoutMsec" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="minAppVersion" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="myNodeNum" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rebootCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="myInfoNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="myInfo" inverseEntity="NodeInfoEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="myNodeNum"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="NodeInfoEntity" representedClassName="NodeInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="lastHeard" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="bluetoothConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="BluetoothConfigEntity" inverseName="bluetoothConfigNode" inverseEntity="BluetoothConfigEntity"/>
|
||||
<relationship name="cannedMessageConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CannedMessageConfigEntity" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfigEntity"/>
|
||||
<relationship name="deviceConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DeviceConfigEntity" inverseName="deviceConfigNode" inverseEntity="DeviceConfigEntity"/>
|
||||
<relationship name="displayConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DisplayConfigEntity" inverseName="displayConfigNode" inverseEntity="DisplayConfigEntity"/>
|
||||
<relationship name="externalNotificationConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ExternalNotificationConfigEntity" inverseName="externalNotificationConfigNode" inverseEntity="ExternalNotificationConfigEntity"/>
|
||||
<relationship name="loRaConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="LoRaConfigEntity" inverseName="loRaConfigNode" inverseEntity="LoRaConfigEntity"/>
|
||||
<relationship name="myInfo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MyInfoEntity" inverseName="myInfoNode" inverseEntity="MyInfoEntity"/>
|
||||
<relationship name="positionConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PositionConfigEntity" inverseName="positionConfigNode" inverseEntity="PositionConfigEntity"/>
|
||||
<relationship name="positions" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PositionEntity" inverseName="nodePosition" inverseEntity="PositionEntity"/>
|
||||
<relationship name="rangeTestConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RangeTestConfigEntity" inverseName="rangeTestConfigNode" inverseEntity="RangeTestConfigEntity"/>
|
||||
<relationship name="serialConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SerialConfigEntity" inverseName="serialConfigNode" inverseEntity="SerialConfigEntity"/>
|
||||
<relationship name="telemetries" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TelemetryEntity" inverseName="nodeTelemetry" inverseEntity="TelemetryEntity"/>
|
||||
<relationship name="telemetryConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TelemetryConfigEntity" inverseName="telemetryConfigNode" inverseEntity="TelemetryConfigEntity"/>
|
||||
<relationship name="user" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="userNode" inverseEntity="UserEntity"/>
|
||||
<relationship name="wiFiConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="WiFiConfigEntity" inverseName="wiFiConfigNode" inverseEntity="WiFiConfigEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="num"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PositionConfigEntity" representedClassName="PositionConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceGpsEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPosition" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsAttemptTime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="positionBroadcastSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="smartPositionEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="positionConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positionConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PositionEntity" representedClassName="PositionEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="satsInView" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="nodePosition" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positions" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="RangeTestConfigEntity" representedClassName="RangeTestConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="save" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sender" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<relationship name="rangeTestConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rangeTestConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="SerialConfigEntity" representedClassName="SerialConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="baudRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="serialConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="serialConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryConfigEntity" representedClassName="TelemetryConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentDisplayFahrenheit" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentMeasurementEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentScreenEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="telemetryConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetryConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryEntity" representedClassName="TelemetryEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="batteryLevel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelUtilization" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="gasResistance" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="metricsType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="relativeHumidity" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="temperature" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="voltage" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="nodeTelemetry" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetries" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="UserEntity" representedClassName="UserEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hwModel" attributeType="String"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="longName" attributeType="String"/>
|
||||
<attribute name="macaddr" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="team" optional="YES" attributeType="String"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="userNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="user" inverseEntity="NodeInfoEntity"/>
|
||||
<fetchedProperty name="adminMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="(toUser.num == $FETCH_SOURCE.num) AND isEmoji == false AND admin = true"/>
|
||||
</fetchedProperty>
|
||||
<fetchedProperty name="allMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="((toUser.num == $FETCH_SOURCE.num) OR (fromUser.num == $FETCH_SOURCE.num)) AND isEmoji == false AND admin = false"/>
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<entity name="WiFiConfigEntity" representedClassName="WiFiConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="password" optional="YES" attributeType="String" minValueString="0" maxValueString="60"/>
|
||||
<attribute name="ssid" optional="YES" attributeType="String" minValueString="0" maxValueString="30"/>
|
||||
<relationship name="wiFiConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="wiFiConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="BluetoothConfigEntity" positionX="54" positionY="153" width="128" height="104"/>
|
||||
<element name="CannedMessageConfigEntity" positionX="45" positionY="144" width="128" height="209"/>
|
||||
<element name="DeviceConfigEntity" positionX="45" positionY="144" width="128" height="104"/>
|
||||
<element name="DisplayConfigEntity" positionX="54" positionY="153" width="128" height="119"/>
|
||||
<element name="ExternalNotificationConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="LoRaConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
<element name="MessageEntity" positionX="-36" positionY="63" width="128" height="245"/>
|
||||
<element name="MyInfoEntity" positionX="-18" positionY="81" width="128" height="209"/>
|
||||
<element name="NodeInfoEntity" positionX="-63" positionY="-18" width="128" height="329"/>
|
||||
<element name="PositionConfigEntity" positionX="63" positionY="162" width="128" height="149"/>
|
||||
<element name="PositionEntity" positionX="-54" positionY="54" width="128" height="119"/>
|
||||
<element name="RangeTestConfigEntity" positionX="72" positionY="171" width="128" height="104"/>
|
||||
<element name="SerialConfigEntity" positionX="54" positionY="153" width="128" height="164"/>
|
||||
<element name="TelemetryConfigEntity" positionX="72" positionY="171" width="128" height="134"/>
|
||||
<element name="TelemetryEntity" positionX="160" positionY="192" width="128" height="209"/>
|
||||
<element name="UserEntity" positionX="0" positionY="144" width="128" height="230"/>
|
||||
<element name="WiFiConfigEntity" positionX="45" positionY="144" width="128" height="119"/>
|
||||
</elements>
|
||||
</model>
|
||||
|
|
@ -178,6 +178,16 @@ struct AdminMessage {
|
|||
set {variant = .confirmSetModuleConfig(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Send all channels in the response to this message
|
||||
var getAllChannelRequest: Bool {
|
||||
get {
|
||||
if case .getAllChannelRequest(let v)? = variant {return v}
|
||||
return false
|
||||
}
|
||||
set {variant = .getAllChannelRequest(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again.
|
||||
/// Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes.
|
||||
|
|
@ -223,123 +233,33 @@ struct AdminMessage {
|
|||
}
|
||||
|
||||
///
|
||||
/// Get the Canned Message Module message part1 in the response to this message.
|
||||
var getCannedMessageModulePart1Request: Bool {
|
||||
/// Get the Canned Message Module messages in the response to this message.
|
||||
var getCannedMessageModuleMessagesRequest: Bool {
|
||||
get {
|
||||
if case .getCannedMessageModulePart1Request(let v)? = variant {return v}
|
||||
if case .getCannedMessageModuleMessagesRequest(let v)? = variant {return v}
|
||||
return false
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart1Request(newValue)}
|
||||
set {variant = .getCannedMessageModuleMessagesRequest(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var getCannedMessageModulePart1Response: String {
|
||||
/// Get the Canned Message Module messages in the response to this message.
|
||||
var getCannedMessageModuleMessagesResponse: String {
|
||||
get {
|
||||
if case .getCannedMessageModulePart1Response(let v)? = variant {return v}
|
||||
if case .getCannedMessageModuleMessagesResponse(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart1Response(newValue)}
|
||||
set {variant = .getCannedMessageModuleMessagesResponse(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Get the Canned Message Module message part2 in the response to this message.
|
||||
var getCannedMessageModulePart2Request: Bool {
|
||||
/// Set the Canned Message Module messages text.
|
||||
var setCannedMessageModuleMessages: String {
|
||||
get {
|
||||
if case .getCannedMessageModulePart2Request(let v)? = variant {return v}
|
||||
return false
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart2Request(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var getCannedMessageModulePart2Response: String {
|
||||
get {
|
||||
if case .getCannedMessageModulePart2Response(let v)? = variant {return v}
|
||||
if case .setCannedMessageModuleMessages(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart2Response(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Get the Canned Message Module message part3 in the response to this message.
|
||||
var getCannedMessageModulePart3Request: Bool {
|
||||
get {
|
||||
if case .getCannedMessageModulePart3Request(let v)? = variant {return v}
|
||||
return false
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart3Request(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var getCannedMessageModulePart3Response: String {
|
||||
get {
|
||||
if case .getCannedMessageModulePart3Response(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart3Response(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Get the Canned Message Module message part4 in the response to this message.
|
||||
var getCannedMessageModulePart4Request: Bool {
|
||||
get {
|
||||
if case .getCannedMessageModulePart4Request(let v)? = variant {return v}
|
||||
return false
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart4Request(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var getCannedMessageModulePart4Response: String {
|
||||
get {
|
||||
if case .getCannedMessageModulePart4Response(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .getCannedMessageModulePart4Response(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the canned message module part 1 text.
|
||||
var setCannedMessageModulePart1: String {
|
||||
get {
|
||||
if case .setCannedMessageModulePart1(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .setCannedMessageModulePart1(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the canned message module part 2 text.
|
||||
var setCannedMessageModulePart2: String {
|
||||
get {
|
||||
if case .setCannedMessageModulePart2(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .setCannedMessageModulePart2(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the canned message module part 3 text.
|
||||
var setCannedMessageModulePart3: String {
|
||||
get {
|
||||
if case .setCannedMessageModulePart3(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .setCannedMessageModulePart3(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the canned message module part 4 text.
|
||||
var setCannedMessageModulePart4: String {
|
||||
get {
|
||||
if case .setCannedMessageModulePart4(let v)? = variant {return v}
|
||||
return String()
|
||||
}
|
||||
set {variant = .setCannedMessageModulePart4(newValue)}
|
||||
set {variant = .setCannedMessageModuleMessages(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -352,6 +272,26 @@ struct AdminMessage {
|
|||
set {variant = .shutdownSeconds(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Request the node to send device metadata (firmware, protobuf version, etc)
|
||||
var getDeviceMetadataRequest: UInt32 {
|
||||
get {
|
||||
if case .getDeviceMetadataRequest(let v)? = variant {return v}
|
||||
return 0
|
||||
}
|
||||
set {variant = .getDeviceMetadataRequest(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Device metadata response
|
||||
var getDeviceMetadataResponse: DeviceMetadata {
|
||||
get {
|
||||
if case .getDeviceMetadataResponse(let v)? = variant {return v}
|
||||
return DeviceMetadata()
|
||||
}
|
||||
set {variant = .getDeviceMetadataResponse(newValue)}
|
||||
}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
///
|
||||
|
|
@ -405,6 +345,9 @@ struct AdminMessage {
|
|||
/// Sent immediatly after a config change has been sent to ensure comms, if this is not recieved, the config will be reverted after 10 mins
|
||||
case confirmSetModuleConfig(Bool)
|
||||
///
|
||||
/// Send all channels in the response to this message
|
||||
case getAllChannelRequest(Bool)
|
||||
///
|
||||
/// Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again.
|
||||
/// Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes.
|
||||
/// If you fail to do so, the radio will assume loss of comms and revert your changes.
|
||||
|
|
@ -421,44 +364,23 @@ struct AdminMessage {
|
|||
/// Tell the node to reboot in this many seconds (or <0 to cancel reboot)
|
||||
case rebootSeconds(Int32)
|
||||
///
|
||||
/// Get the Canned Message Module message part1 in the response to this message.
|
||||
case getCannedMessageModulePart1Request(Bool)
|
||||
/// Get the Canned Message Module messages in the response to this message.
|
||||
case getCannedMessageModuleMessagesRequest(Bool)
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case getCannedMessageModulePart1Response(String)
|
||||
/// Get the Canned Message Module messages in the response to this message.
|
||||
case getCannedMessageModuleMessagesResponse(String)
|
||||
///
|
||||
/// Get the Canned Message Module message part2 in the response to this message.
|
||||
case getCannedMessageModulePart2Request(Bool)
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case getCannedMessageModulePart2Response(String)
|
||||
///
|
||||
/// Get the Canned Message Module message part3 in the response to this message.
|
||||
case getCannedMessageModulePart3Request(Bool)
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case getCannedMessageModulePart3Response(String)
|
||||
///
|
||||
/// Get the Canned Message Module message part4 in the response to this message.
|
||||
case getCannedMessageModulePart4Request(Bool)
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case getCannedMessageModulePart4Response(String)
|
||||
///
|
||||
/// Set the canned message module part 1 text.
|
||||
case setCannedMessageModulePart1(String)
|
||||
///
|
||||
/// Set the canned message module part 2 text.
|
||||
case setCannedMessageModulePart2(String)
|
||||
///
|
||||
/// Set the canned message module part 3 text.
|
||||
case setCannedMessageModulePart3(String)
|
||||
///
|
||||
/// Set the canned message module part 4 text.
|
||||
case setCannedMessageModulePart4(String)
|
||||
/// Set the Canned Message Module messages text.
|
||||
case setCannedMessageModuleMessages(String)
|
||||
///
|
||||
/// Tell the node to shutdown in this many seconds (or <0 to cancel shutdown)
|
||||
case shutdownSeconds(Int32)
|
||||
///
|
||||
/// Request the node to send device metadata (firmware, protobuf version, etc)
|
||||
case getDeviceMetadataRequest(UInt32)
|
||||
///
|
||||
/// Device metadata response
|
||||
case getDeviceMetadataResponse(DeviceMetadata)
|
||||
|
||||
#if !swift(>=4.1)
|
||||
static func ==(lhs: AdminMessage.OneOf_Variant, rhs: AdminMessage.OneOf_Variant) -> Bool {
|
||||
|
|
@ -522,6 +444,10 @@ struct AdminMessage {
|
|||
guard case .confirmSetModuleConfig(let l) = lhs, case .confirmSetModuleConfig(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getAllChannelRequest, .getAllChannelRequest): return {
|
||||
guard case .getAllChannelRequest(let l) = lhs, case .getAllChannelRequest(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.confirmSetChannel, .confirmSetChannel): return {
|
||||
guard case .confirmSetChannel(let l) = lhs, case .confirmSetChannel(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
|
|
@ -538,58 +464,30 @@ struct AdminMessage {
|
|||
guard case .rebootSeconds(let l) = lhs, case .rebootSeconds(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart1Request, .getCannedMessageModulePart1Request): return {
|
||||
guard case .getCannedMessageModulePart1Request(let l) = lhs, case .getCannedMessageModulePart1Request(let r) = rhs else { preconditionFailure() }
|
||||
case (.getCannedMessageModuleMessagesRequest, .getCannedMessageModuleMessagesRequest): return {
|
||||
guard case .getCannedMessageModuleMessagesRequest(let l) = lhs, case .getCannedMessageModuleMessagesRequest(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart1Response, .getCannedMessageModulePart1Response): return {
|
||||
guard case .getCannedMessageModulePart1Response(let l) = lhs, case .getCannedMessageModulePart1Response(let r) = rhs else { preconditionFailure() }
|
||||
case (.getCannedMessageModuleMessagesResponse, .getCannedMessageModuleMessagesResponse): return {
|
||||
guard case .getCannedMessageModuleMessagesResponse(let l) = lhs, case .getCannedMessageModuleMessagesResponse(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart2Request, .getCannedMessageModulePart2Request): return {
|
||||
guard case .getCannedMessageModulePart2Request(let l) = lhs, case .getCannedMessageModulePart2Request(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart2Response, .getCannedMessageModulePart2Response): return {
|
||||
guard case .getCannedMessageModulePart2Response(let l) = lhs, case .getCannedMessageModulePart2Response(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart3Request, .getCannedMessageModulePart3Request): return {
|
||||
guard case .getCannedMessageModulePart3Request(let l) = lhs, case .getCannedMessageModulePart3Request(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart3Response, .getCannedMessageModulePart3Response): return {
|
||||
guard case .getCannedMessageModulePart3Response(let l) = lhs, case .getCannedMessageModulePart3Response(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart4Request, .getCannedMessageModulePart4Request): return {
|
||||
guard case .getCannedMessageModulePart4Request(let l) = lhs, case .getCannedMessageModulePart4Request(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getCannedMessageModulePart4Response, .getCannedMessageModulePart4Response): return {
|
||||
guard case .getCannedMessageModulePart4Response(let l) = lhs, case .getCannedMessageModulePart4Response(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.setCannedMessageModulePart1, .setCannedMessageModulePart1): return {
|
||||
guard case .setCannedMessageModulePart1(let l) = lhs, case .setCannedMessageModulePart1(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.setCannedMessageModulePart2, .setCannedMessageModulePart2): return {
|
||||
guard case .setCannedMessageModulePart2(let l) = lhs, case .setCannedMessageModulePart2(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.setCannedMessageModulePart3, .setCannedMessageModulePart3): return {
|
||||
guard case .setCannedMessageModulePart3(let l) = lhs, case .setCannedMessageModulePart3(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.setCannedMessageModulePart4, .setCannedMessageModulePart4): return {
|
||||
guard case .setCannedMessageModulePart4(let l) = lhs, case .setCannedMessageModulePart4(let r) = rhs else { preconditionFailure() }
|
||||
case (.setCannedMessageModuleMessages, .setCannedMessageModuleMessages): return {
|
||||
guard case .setCannedMessageModuleMessages(let l) = lhs, case .setCannedMessageModuleMessages(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.shutdownSeconds, .shutdownSeconds): return {
|
||||
guard case .shutdownSeconds(let l) = lhs, case .shutdownSeconds(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getDeviceMetadataRequest, .getDeviceMetadataRequest): return {
|
||||
guard case .getDeviceMetadataRequest(let l) = lhs, case .getDeviceMetadataRequest(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.getDeviceMetadataResponse, .getDeviceMetadataResponse): return {
|
||||
guard case .getDeviceMetadataResponse(let l) = lhs, case .getDeviceMetadataResponse(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
|
@ -624,6 +522,10 @@ struct AdminMessage {
|
|||
///
|
||||
/// TODO: REPLACE
|
||||
case loraConfig // = 5
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
case bluetoothConfig // = 6
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
init() {
|
||||
|
|
@ -638,6 +540,7 @@ struct AdminMessage {
|
|||
case 3: self = .wifiConfig
|
||||
case 4: self = .displayConfig
|
||||
case 5: self = .loraConfig
|
||||
case 6: self = .bluetoothConfig
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -650,6 +553,7 @@ struct AdminMessage {
|
|||
case .wifiConfig: return 3
|
||||
case .displayConfig: return 4
|
||||
case .loraConfig: return 5
|
||||
case .bluetoothConfig: return 6
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -736,6 +640,7 @@ extension AdminMessage.ConfigType: CaseIterable {
|
|||
.wifiConfig,
|
||||
.displayConfig,
|
||||
.loraConfig,
|
||||
.bluetoothConfig,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -780,23 +685,17 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
15: .standard(proto: "get_module_config_response"),
|
||||
16: .standard(proto: "set_module_config"),
|
||||
17: .standard(proto: "confirm_set_module_config"),
|
||||
18: .standard(proto: "get_all_channel_request"),
|
||||
32: .standard(proto: "confirm_set_channel"),
|
||||
33: .standard(proto: "confirm_set_radio"),
|
||||
34: .standard(proto: "exit_simulator"),
|
||||
35: .standard(proto: "reboot_seconds"),
|
||||
36: .standard(proto: "get_canned_message_module_part1_request"),
|
||||
37: .standard(proto: "get_canned_message_module_part1_response"),
|
||||
38: .standard(proto: "get_canned_message_module_part2_request"),
|
||||
39: .standard(proto: "get_canned_message_module_part2_response"),
|
||||
40: .standard(proto: "get_canned_message_module_part3_request"),
|
||||
41: .standard(proto: "get_canned_message_module_part3_response"),
|
||||
42: .standard(proto: "get_canned_message_module_part4_request"),
|
||||
43: .standard(proto: "get_canned_message_module_part4_response"),
|
||||
44: .standard(proto: "set_canned_message_module_part1"),
|
||||
45: .standard(proto: "set_canned_message_module_part2"),
|
||||
46: .standard(proto: "set_canned_message_module_part3"),
|
||||
47: .standard(proto: "set_canned_message_module_part4"),
|
||||
36: .standard(proto: "get_canned_message_module_messages_request"),
|
||||
37: .standard(proto: "get_canned_message_module_messages_response"),
|
||||
44: .standard(proto: "set_canned_message_module_messages"),
|
||||
51: .standard(proto: "shutdown_seconds"),
|
||||
52: .standard(proto: "get_device_metadata_request"),
|
||||
53: .standard(proto: "get_device_metadata_response"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -957,6 +856,14 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
self.variant = .confirmSetModuleConfig(v)
|
||||
}
|
||||
}()
|
||||
case 18: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getAllChannelRequest(v)
|
||||
}
|
||||
}()
|
||||
case 32: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
|
|
@ -994,7 +901,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart1Request(v)
|
||||
self.variant = .getCannedMessageModuleMessagesRequest(v)
|
||||
}
|
||||
}()
|
||||
case 37: try {
|
||||
|
|
@ -1002,55 +909,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart1Response(v)
|
||||
}
|
||||
}()
|
||||
case 38: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart2Request(v)
|
||||
}
|
||||
}()
|
||||
case 39: try {
|
||||
var v: String?
|
||||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart2Response(v)
|
||||
}
|
||||
}()
|
||||
case 40: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart3Request(v)
|
||||
}
|
||||
}()
|
||||
case 41: try {
|
||||
var v: String?
|
||||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart3Response(v)
|
||||
}
|
||||
}()
|
||||
case 42: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart4Request(v)
|
||||
}
|
||||
}()
|
||||
case 43: try {
|
||||
var v: String?
|
||||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getCannedMessageModulePart4Response(v)
|
||||
self.variant = .getCannedMessageModuleMessagesResponse(v)
|
||||
}
|
||||
}()
|
||||
case 44: try {
|
||||
|
|
@ -1058,31 +917,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .setCannedMessageModulePart1(v)
|
||||
}
|
||||
}()
|
||||
case 45: try {
|
||||
var v: String?
|
||||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .setCannedMessageModulePart2(v)
|
||||
}
|
||||
}()
|
||||
case 46: try {
|
||||
var v: String?
|
||||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .setCannedMessageModulePart3(v)
|
||||
}
|
||||
}()
|
||||
case 47: try {
|
||||
var v: String?
|
||||
try decoder.decodeSingularStringField(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .setCannedMessageModulePart4(v)
|
||||
self.variant = .setCannedMessageModuleMessages(v)
|
||||
}
|
||||
}()
|
||||
case 51: try {
|
||||
|
|
@ -1093,6 +928,27 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
self.variant = .shutdownSeconds(v)
|
||||
}
|
||||
}()
|
||||
case 52: try {
|
||||
var v: UInt32?
|
||||
try decoder.decodeSingularUInt32Field(value: &v)
|
||||
if let v = v {
|
||||
if self.variant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getDeviceMetadataRequest(v)
|
||||
}
|
||||
}()
|
||||
case 53: try {
|
||||
var v: DeviceMetadata?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .getDeviceMetadataResponse(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .getDeviceMetadataResponse(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1160,6 +1016,10 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
guard case .confirmSetModuleConfig(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 17)
|
||||
}()
|
||||
case .getAllChannelRequest?: try {
|
||||
guard case .getAllChannelRequest(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 18)
|
||||
}()
|
||||
case .confirmSetChannel?: try {
|
||||
guard case .confirmSetChannel(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 32)
|
||||
|
|
@ -1176,58 +1036,30 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
guard case .rebootSeconds(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 35)
|
||||
}()
|
||||
case .getCannedMessageModulePart1Request?: try {
|
||||
guard case .getCannedMessageModulePart1Request(let v)? = self.variant else { preconditionFailure() }
|
||||
case .getCannedMessageModuleMessagesRequest?: try {
|
||||
guard case .getCannedMessageModuleMessagesRequest(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 36)
|
||||
}()
|
||||
case .getCannedMessageModulePart1Response?: try {
|
||||
guard case .getCannedMessageModulePart1Response(let v)? = self.variant else { preconditionFailure() }
|
||||
case .getCannedMessageModuleMessagesResponse?: try {
|
||||
guard case .getCannedMessageModuleMessagesResponse(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 37)
|
||||
}()
|
||||
case .getCannedMessageModulePart2Request?: try {
|
||||
guard case .getCannedMessageModulePart2Request(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 38)
|
||||
}()
|
||||
case .getCannedMessageModulePart2Response?: try {
|
||||
guard case .getCannedMessageModulePart2Response(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 39)
|
||||
}()
|
||||
case .getCannedMessageModulePart3Request?: try {
|
||||
guard case .getCannedMessageModulePart3Request(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 40)
|
||||
}()
|
||||
case .getCannedMessageModulePart3Response?: try {
|
||||
guard case .getCannedMessageModulePart3Response(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 41)
|
||||
}()
|
||||
case .getCannedMessageModulePart4Request?: try {
|
||||
guard case .getCannedMessageModulePart4Request(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 42)
|
||||
}()
|
||||
case .getCannedMessageModulePart4Response?: try {
|
||||
guard case .getCannedMessageModulePart4Response(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 43)
|
||||
}()
|
||||
case .setCannedMessageModulePart1?: try {
|
||||
guard case .setCannedMessageModulePart1(let v)? = self.variant else { preconditionFailure() }
|
||||
case .setCannedMessageModuleMessages?: try {
|
||||
guard case .setCannedMessageModuleMessages(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 44)
|
||||
}()
|
||||
case .setCannedMessageModulePart2?: try {
|
||||
guard case .setCannedMessageModulePart2(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 45)
|
||||
}()
|
||||
case .setCannedMessageModulePart3?: try {
|
||||
guard case .setCannedMessageModulePart3(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 46)
|
||||
}()
|
||||
case .setCannedMessageModulePart4?: try {
|
||||
guard case .setCannedMessageModulePart4(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 47)
|
||||
}()
|
||||
case .shutdownSeconds?: try {
|
||||
guard case .shutdownSeconds(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 51)
|
||||
}()
|
||||
case .getDeviceMetadataRequest?: try {
|
||||
guard case .getDeviceMetadataRequest(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 52)
|
||||
}()
|
||||
case .getDeviceMetadataResponse?: try {
|
||||
guard case .getDeviceMetadataResponse(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 53)
|
||||
}()
|
||||
case nil: break
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
|
|
@ -1248,6 +1080,7 @@ extension AdminMessage.ConfigType: SwiftProtobuf._ProtoNameProviding {
|
|||
3: .same(proto: "WIFI_CONFIG"),
|
||||
4: .same(proto: "DISPLAY_CONFIG"),
|
||||
5: .same(proto: "LORA_CONFIG"),
|
||||
6: .same(proto: "BLUETOOTH_CONFIG"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,19 +29,7 @@ struct CannedMessageModuleConfig {
|
|||
|
||||
///
|
||||
/// Predefined messages for canned message module separated by '|' characters.
|
||||
var messagesPart1: String = String()
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var messagesPart2: String = String()
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var messagesPart3: String = String()
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
var messagesPart4: String = String()
|
||||
var messages: String = String()
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
|
|
@ -57,10 +45,7 @@ extension CannedMessageModuleConfig: @unchecked Sendable {}
|
|||
extension CannedMessageModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = "CannedMessageModuleConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
11: .same(proto: "messagesPart1"),
|
||||
12: .same(proto: "messagesPart2"),
|
||||
13: .same(proto: "messagesPart3"),
|
||||
14: .same(proto: "messagesPart4"),
|
||||
1: .same(proto: "messages"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -69,36 +54,21 @@ extension CannedMessageModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 11: try { try decoder.decodeSingularStringField(value: &self.messagesPart1) }()
|
||||
case 12: try { try decoder.decodeSingularStringField(value: &self.messagesPart2) }()
|
||||
case 13: try { try decoder.decodeSingularStringField(value: &self.messagesPart3) }()
|
||||
case 14: try { try decoder.decodeSingularStringField(value: &self.messagesPart4) }()
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.messages) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.messagesPart1.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.messagesPart1, fieldNumber: 11)
|
||||
}
|
||||
if !self.messagesPart2.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.messagesPart2, fieldNumber: 12)
|
||||
}
|
||||
if !self.messagesPart3.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.messagesPart3, fieldNumber: 13)
|
||||
}
|
||||
if !self.messagesPart4.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.messagesPart4, fieldNumber: 14)
|
||||
if !self.messages.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.messages, fieldNumber: 1)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: CannedMessageModuleConfig, rhs: CannedMessageModuleConfig) -> Bool {
|
||||
if lhs.messagesPart1 != rhs.messagesPart1 {return false}
|
||||
if lhs.messagesPart2 != rhs.messagesPart2 {return false}
|
||||
if lhs.messagesPart3 != rhs.messagesPart3 {return false}
|
||||
if lhs.messagesPart4 != rhs.messagesPart4 {return false}
|
||||
if lhs.messages != rhs.messages {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ struct Config {
|
|||
set {payloadVariant = .lora(newValue)}
|
||||
}
|
||||
|
||||
var bluetooth: Config.BluetoothConfig {
|
||||
get {
|
||||
if case .bluetooth(let v)? = payloadVariant {return v}
|
||||
return Config.BluetoothConfig()
|
||||
}
|
||||
set {payloadVariant = .bluetooth(newValue)}
|
||||
}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
///
|
||||
|
|
@ -88,6 +96,7 @@ struct Config {
|
|||
case wifi(Config.WiFiConfig)
|
||||
case display(Config.DisplayConfig)
|
||||
case lora(Config.LoRaConfig)
|
||||
case bluetooth(Config.BluetoothConfig)
|
||||
|
||||
#if !swift(>=4.1)
|
||||
static func ==(lhs: Config.OneOf_PayloadVariant, rhs: Config.OneOf_PayloadVariant) -> Bool {
|
||||
|
|
@ -119,6 +128,10 @@ struct Config {
|
|||
guard case .lora(let l) = lhs, case .lora(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
case (.bluetooth, .bluetooth): return {
|
||||
guard case .bluetooth(let l) = lhs, case .bluetooth(let r) = rhs else { preconditionFailure() }
|
||||
return l == r
|
||||
}()
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
|
@ -359,7 +372,7 @@ struct Config {
|
|||
|
||||
///
|
||||
/// Power Config\
|
||||
/// See [power management](/docs/software/other/power) for additional power management state machine option details.
|
||||
/// See [Power Config](/docs/settings/config/power) for additional power config details.
|
||||
struct PowerConfig {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
|
@ -509,6 +522,15 @@ struct Config {
|
|||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// Enable WiFi (disables Bluetooth)
|
||||
var enabled: Bool = false
|
||||
|
||||
///
|
||||
/// If set, this node will try to join the specified wifi network and
|
||||
/// acquire an address via DHCP
|
||||
var mode: Config.WiFiConfig.WiFiMode = .client
|
||||
|
||||
///
|
||||
/// If set, this node will try to join the specified wifi network and
|
||||
/// acquire an address via DHCP
|
||||
|
|
@ -518,22 +540,53 @@ struct Config {
|
|||
/// If set, will be use to authenticate to the named wifi
|
||||
var psk: String = String()
|
||||
|
||||
///
|
||||
/// If set, the node will operate as an AP (and DHCP server), otherwise it
|
||||
/// will be a station
|
||||
var apMode: Bool = false
|
||||
|
||||
///
|
||||
/// If set, the node AP will broadcast as a hidden SSID
|
||||
var apHidden: Bool = false
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
enum WiFiMode: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
|
||||
///
|
||||
/// This mode is used to connect to an external WiFi network
|
||||
case client // = 0
|
||||
|
||||
///
|
||||
/// In this mode the node will operate as an AP (and DHCP server)
|
||||
case accessPoint // = 1
|
||||
|
||||
///
|
||||
/// If set, the node AP will broadcast as a hidden SSID
|
||||
case accessPointHidden // = 2
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
init() {
|
||||
self = .client
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .client
|
||||
case 1: self = .accessPoint
|
||||
case 2: self = .accessPointHidden
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .client: return 0
|
||||
case .accessPoint: return 1
|
||||
case .accessPointHidden: return 2
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
///
|
||||
/// TODO: REPLACE
|
||||
/// Display Config
|
||||
struct DisplayConfig {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
|
@ -553,6 +606,11 @@ struct Config {
|
|||
/// Potentially useful for devices without user buttons.
|
||||
var autoScreenCarouselSecs: UInt32 = 0
|
||||
|
||||
///
|
||||
/// If this is set, the displayed compass will always point north. if unset, the old behaviour
|
||||
/// (top of display is heading direction) is used.
|
||||
var compassNorthTop: Bool = false
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
///
|
||||
|
|
@ -861,6 +919,68 @@ struct Config {
|
|||
init() {}
|
||||
}
|
||||
|
||||
struct BluetoothConfig {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// Enable Bluetooth on the device
|
||||
var enabled: Bool = false
|
||||
|
||||
///
|
||||
/// Determines the pairing strategy for the device
|
||||
var mode: Config.BluetoothConfig.PairingMode = .randomPin
|
||||
|
||||
///
|
||||
/// Specified pin for PairingMode.FixedPin
|
||||
var fixedPin: UInt32 = 0
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
enum PairingMode: SwiftProtobuf.Enum {
|
||||
typealias RawValue = Int
|
||||
|
||||
///
|
||||
/// Device generates a random pin that will be shown on the screen of the device for pairing
|
||||
case randomPin // = 0
|
||||
|
||||
///
|
||||
/// Device requires a specified fixed pin for pairing
|
||||
case fixedPin // = 1
|
||||
|
||||
///
|
||||
/// Device requires no pin for pairing
|
||||
case noPin // = 2
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
init() {
|
||||
self = .randomPin
|
||||
}
|
||||
|
||||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .randomPin
|
||||
case 1: self = .fixedPin
|
||||
case 2: self = .noPin
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
var rawValue: Int {
|
||||
switch self {
|
||||
case .randomPin: return 0
|
||||
case .fixedPin: return 1
|
||||
case .noPin: return 2
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
|
|
@ -916,6 +1036,15 @@ extension Config.PowerConfig.ChargeCurrent: CaseIterable {
|
|||
]
|
||||
}
|
||||
|
||||
extension Config.WiFiConfig.WiFiMode: CaseIterable {
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
static var allCases: [Config.WiFiConfig.WiFiMode] = [
|
||||
.client,
|
||||
.accessPoint,
|
||||
.accessPointHidden,
|
||||
]
|
||||
}
|
||||
|
||||
extension Config.DisplayConfig.GpsCoordinateFormat: CaseIterable {
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
static var allCases: [Config.DisplayConfig.GpsCoordinateFormat] = [
|
||||
|
|
@ -960,6 +1089,15 @@ extension Config.LoRaConfig.ModemPreset: CaseIterable {
|
|||
]
|
||||
}
|
||||
|
||||
extension Config.BluetoothConfig.PairingMode: CaseIterable {
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
static var allCases: [Config.BluetoothConfig.PairingMode] = [
|
||||
.randomPin,
|
||||
.fixedPin,
|
||||
.noPin,
|
||||
]
|
||||
}
|
||||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
|
|
@ -972,11 +1110,14 @@ extension Config.PositionConfig.PositionFlags: @unchecked Sendable {}
|
|||
extension Config.PowerConfig: @unchecked Sendable {}
|
||||
extension Config.PowerConfig.ChargeCurrent: @unchecked Sendable {}
|
||||
extension Config.WiFiConfig: @unchecked Sendable {}
|
||||
extension Config.WiFiConfig.WiFiMode: @unchecked Sendable {}
|
||||
extension Config.DisplayConfig: @unchecked Sendable {}
|
||||
extension Config.DisplayConfig.GpsCoordinateFormat: @unchecked Sendable {}
|
||||
extension Config.LoRaConfig: @unchecked Sendable {}
|
||||
extension Config.LoRaConfig.RegionCode: @unchecked Sendable {}
|
||||
extension Config.LoRaConfig.ModemPreset: @unchecked Sendable {}
|
||||
extension Config.BluetoothConfig: @unchecked Sendable {}
|
||||
extension Config.BluetoothConfig.PairingMode: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
|
@ -990,6 +1131,7 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas
|
|||
4: .same(proto: "wifi"),
|
||||
5: .same(proto: "display"),
|
||||
6: .same(proto: "lora"),
|
||||
7: .same(proto: "bluetooth"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1076,6 +1218,19 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas
|
|||
self.payloadVariant = .lora(v)
|
||||
}
|
||||
}()
|
||||
case 7: try {
|
||||
var v: Config.BluetoothConfig?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .bluetooth(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .bluetooth(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1111,6 +1266,10 @@ extension Config: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBas
|
|||
guard case .lora(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}()
|
||||
case .bluetooth?: try {
|
||||
guard case .bluetooth(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
}()
|
||||
case nil: break
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
|
|
@ -1377,10 +1536,10 @@ extension Config.PowerConfig.ChargeCurrent: SwiftProtobuf._ProtoNameProviding {
|
|||
extension Config.WiFiConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = Config.protoMessageName + ".WiFiConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "ssid"),
|
||||
2: .same(proto: "psk"),
|
||||
3: .standard(proto: "ap_mode"),
|
||||
4: .standard(proto: "ap_hidden"),
|
||||
1: .same(proto: "enabled"),
|
||||
2: .same(proto: "mode"),
|
||||
3: .same(proto: "ssid"),
|
||||
4: .same(proto: "psk"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1389,47 +1548,56 @@ extension Config.WiFiConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.ssid) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.psk) }()
|
||||
case 3: try { try decoder.decodeSingularBoolField(value: &self.apMode) }()
|
||||
case 4: try { try decoder.decodeSingularBoolField(value: &self.apHidden) }()
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &self.enabled) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self.mode) }()
|
||||
case 3: try { try decoder.decodeSingularStringField(value: &self.ssid) }()
|
||||
case 4: try { try decoder.decodeSingularStringField(value: &self.psk) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.enabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.enabled, fieldNumber: 1)
|
||||
}
|
||||
if self.mode != .client {
|
||||
try visitor.visitSingularEnumField(value: self.mode, fieldNumber: 2)
|
||||
}
|
||||
if !self.ssid.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.ssid, fieldNumber: 1)
|
||||
try visitor.visitSingularStringField(value: self.ssid, fieldNumber: 3)
|
||||
}
|
||||
if !self.psk.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.psk, fieldNumber: 2)
|
||||
}
|
||||
if self.apMode != false {
|
||||
try visitor.visitSingularBoolField(value: self.apMode, fieldNumber: 3)
|
||||
}
|
||||
if self.apHidden != false {
|
||||
try visitor.visitSingularBoolField(value: self.apHidden, fieldNumber: 4)
|
||||
try visitor.visitSingularStringField(value: self.psk, fieldNumber: 4)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Config.WiFiConfig, rhs: Config.WiFiConfig) -> Bool {
|
||||
if lhs.enabled != rhs.enabled {return false}
|
||||
if lhs.mode != rhs.mode {return false}
|
||||
if lhs.ssid != rhs.ssid {return false}
|
||||
if lhs.psk != rhs.psk {return false}
|
||||
if lhs.apMode != rhs.apMode {return false}
|
||||
if lhs.apHidden != rhs.apHidden {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Config.WiFiConfig.WiFiMode: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "Client"),
|
||||
1: .same(proto: "AccessPoint"),
|
||||
2: .same(proto: "AccessPointHidden"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = Config.protoMessageName + ".DisplayConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "screen_on_secs"),
|
||||
2: .standard(proto: "gps_format"),
|
||||
3: .standard(proto: "auto_screen_carousel_secs"),
|
||||
4: .standard(proto: "compass_north_top"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1441,6 +1609,7 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
case 1: try { try decoder.decodeSingularUInt32Field(value: &self.screenOnSecs) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self.gpsFormat) }()
|
||||
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.autoScreenCarouselSecs) }()
|
||||
case 4: try { try decoder.decodeSingularBoolField(value: &self.compassNorthTop) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1456,6 +1625,9 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
if self.autoScreenCarouselSecs != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.autoScreenCarouselSecs, fieldNumber: 3)
|
||||
}
|
||||
if self.compassNorthTop != false {
|
||||
try visitor.visitSingularBoolField(value: self.compassNorthTop, fieldNumber: 4)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -1463,6 +1635,7 @@ extension Config.DisplayConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
if lhs.screenOnSecs != rhs.screenOnSecs {return false}
|
||||
if lhs.gpsFormat != rhs.gpsFormat {return false}
|
||||
if lhs.autoScreenCarouselSecs != rhs.autoScreenCarouselSecs {return false}
|
||||
if lhs.compassNorthTop != rhs.compassNorthTop {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -1594,3 +1767,55 @@ extension Config.LoRaConfig.ModemPreset: SwiftProtobuf._ProtoNameProviding {
|
|||
6: .same(proto: "ShortFast"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Config.BluetoothConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = Config.protoMessageName + ".BluetoothConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "enabled"),
|
||||
2: .same(proto: "mode"),
|
||||
3: .standard(proto: "fixed_pin"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &self.enabled) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self.mode) }()
|
||||
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.fixedPin) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.enabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.enabled, fieldNumber: 1)
|
||||
}
|
||||
if self.mode != .randomPin {
|
||||
try visitor.visitSingularEnumField(value: self.mode, fieldNumber: 2)
|
||||
}
|
||||
if self.fixedPin != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.fixedPin, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Config.BluetoothConfig, rhs: Config.BluetoothConfig) -> Bool {
|
||||
if lhs.enabled != rhs.enabled {return false}
|
||||
if lhs.mode != rhs.mode {return false}
|
||||
if lhs.fixedPin != rhs.fixedPin {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Config.BluetoothConfig.PairingMode: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "RandomPin"),
|
||||
1: .same(proto: "FixedPin"),
|
||||
2: .same(proto: "NoPin"),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
85
Meshtastic/Protobufs/device_metadata.pb.swift
Normal file
85
Meshtastic/Protobufs/device_metadata.pb.swift
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// DO NOT EDIT.
|
||||
// swift-format-ignore-file
|
||||
//
|
||||
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||
// Source: device_metadata.proto
|
||||
//
|
||||
// For information on using the generated types, please see the documentation:
|
||||
// https://github.com/apple/swift-protobuf/
|
||||
|
||||
import Foundation
|
||||
import SwiftProtobuf
|
||||
|
||||
// If the compiler emits an error on this type, it is because this file
|
||||
// was generated by a version of the `protoc` Swift plug-in that is
|
||||
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||
// Please ensure that you are building against the same version of the API
|
||||
// that was used to generate this file.
|
||||
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||
typealias Version = _2
|
||||
}
|
||||
|
||||
///
|
||||
/// Device metadata response
|
||||
struct DeviceMetadata {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// Device firmware version string
|
||||
var firmwareVersion: String = String()
|
||||
|
||||
///
|
||||
/// Device state version
|
||||
var deviceStateVersion: UInt32 = 0
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
extension DeviceMetadata: @unchecked Sendable {}
|
||||
#endif // swift(>=5.5) && canImport(_Concurrency)
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
extension DeviceMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = "DeviceMetadata"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "firmware_version"),
|
||||
2: .standard(proto: "device_state_version"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self.firmwareVersion) }()
|
||||
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.deviceStateVersion) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if !self.firmwareVersion.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.firmwareVersion, fieldNumber: 1)
|
||||
}
|
||||
if self.deviceStateVersion != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.deviceStateVersion, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: DeviceMetadata, rhs: DeviceMetadata) -> Bool {
|
||||
if lhs.firmwareVersion != rhs.firmwareVersion {return false}
|
||||
if lhs.deviceStateVersion != rhs.deviceStateVersion {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -91,6 +91,17 @@ struct LocalConfig {
|
|||
/// Clears the value of `lora`. Subsequent reads from it will return its default value.
|
||||
mutating func clearLora() {_uniqueStorage()._lora = nil}
|
||||
|
||||
///
|
||||
/// The part of the config that is specific to the Bluetooth settings
|
||||
var bluetooth: Config.BluetoothConfig {
|
||||
get {return _storage._bluetooth ?? Config.BluetoothConfig()}
|
||||
set {_uniqueStorage()._bluetooth = newValue}
|
||||
}
|
||||
/// Returns true if `bluetooth` has been explicitly set.
|
||||
var hasBluetooth: Bool {return _storage._bluetooth != nil}
|
||||
/// Clears the value of `bluetooth`. Subsequent reads from it will return its default value.
|
||||
mutating func clearBluetooth() {_uniqueStorage()._bluetooth = nil}
|
||||
|
||||
///
|
||||
/// A version integer used to invalidate old save files when we make
|
||||
/// incompatible changes This integer is set at build time and is private to
|
||||
|
|
@ -221,7 +232,8 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
4: .same(proto: "wifi"),
|
||||
5: .same(proto: "display"),
|
||||
6: .same(proto: "lora"),
|
||||
7: .same(proto: "version"),
|
||||
7: .same(proto: "bluetooth"),
|
||||
8: .same(proto: "version"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
|
|
@ -231,6 +243,7 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
var _wifi: Config.WiFiConfig? = nil
|
||||
var _display: Config.DisplayConfig? = nil
|
||||
var _lora: Config.LoRaConfig? = nil
|
||||
var _bluetooth: Config.BluetoothConfig? = nil
|
||||
var _version: UInt32 = 0
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
|
@ -244,6 +257,7 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
_wifi = source._wifi
|
||||
_display = source._display
|
||||
_lora = source._lora
|
||||
_bluetooth = source._bluetooth
|
||||
_version = source._version
|
||||
}
|
||||
}
|
||||
|
|
@ -269,7 +283,8 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
case 4: try { try decoder.decodeSingularMessageField(value: &_storage._wifi) }()
|
||||
case 5: try { try decoder.decodeSingularMessageField(value: &_storage._display) }()
|
||||
case 6: try { try decoder.decodeSingularMessageField(value: &_storage._lora) }()
|
||||
case 7: try { try decoder.decodeSingularUInt32Field(value: &_storage._version) }()
|
||||
case 7: try { try decoder.decodeSingularMessageField(value: &_storage._bluetooth) }()
|
||||
case 8: try { try decoder.decodeSingularUInt32Field(value: &_storage._version) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -300,8 +315,11 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
try { if let v = _storage._lora {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
try { if let v = _storage._bluetooth {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
} }()
|
||||
if _storage._version != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._version, fieldNumber: 7)
|
||||
try visitor.visitSingularUInt32Field(value: _storage._version, fieldNumber: 8)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
|
|
@ -318,6 +336,7 @@ extension LocalConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
if _storage._wifi != rhs_storage._wifi {return false}
|
||||
if _storage._display != rhs_storage._display {return false}
|
||||
if _storage._lora != rhs_storage._lora {return false}
|
||||
if _storage._bluetooth != rhs_storage._bluetooth {return false}
|
||||
if _storage._version != rhs_storage._version {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ enum HardwareModel: SwiftProtobuf.Enum {
|
|||
/// M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/
|
||||
case m5Stack // = 44
|
||||
|
||||
///
|
||||
/// B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station
|
||||
case stationG1 // = 45
|
||||
|
||||
///
|
||||
/// Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
case privateHw // = 255
|
||||
|
|
@ -166,6 +170,7 @@ enum HardwareModel: SwiftProtobuf.Enum {
|
|||
case 42: self = .nrf52840Pca10059
|
||||
case 43: self = .drDev
|
||||
case 44: self = .m5Stack
|
||||
case 45: self = .stationG1
|
||||
case 255: self = .privateHw
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
|
|
@ -198,6 +203,7 @@ enum HardwareModel: SwiftProtobuf.Enum {
|
|||
case .nrf52840Pca10059: return 42
|
||||
case .drDev: return 43
|
||||
case .m5Stack: return 44
|
||||
case .stationG1: return 45
|
||||
case .privateHw: return 255
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
|
|
@ -235,6 +241,7 @@ extension HardwareModel: CaseIterable {
|
|||
.nrf52840Pca10059,
|
||||
.drDev,
|
||||
.m5Stack,
|
||||
.stationG1,
|
||||
.privateHw,
|
||||
]
|
||||
}
|
||||
|
|
@ -791,23 +798,6 @@ struct User {
|
|||
/// Also, "long_name" should be their licence number.
|
||||
var isLicensed: Bool = false
|
||||
|
||||
///
|
||||
/// Transmit power at antenna connector, in decibel-milliwatt
|
||||
/// An optional self-reported value useful in network planning, discovery
|
||||
/// and positioning - along with ant_gain_dbi and ant_azimuth below
|
||||
var txPowerDbm: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Antenna gain (applicable to both Tx and Rx), in decibel-isotropic
|
||||
var antGainDbi: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Directional antenna true azimuth *if applicable*, in degrees (0-360)
|
||||
/// Only applicable in case of stationary nodes with a directional antenna
|
||||
/// Zero = not applicable (mobile or omni) or not specified
|
||||
/// (use a value of 360 to indicate an antenna azimuth of zero degrees)
|
||||
var antAzimuth: UInt32 = 0
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
|
@ -1075,33 +1065,20 @@ struct DataMessage {
|
|||
/// a message a heart or poop emoji.
|
||||
var emoji: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Location structure
|
||||
var location: Location {
|
||||
get {return _location ?? Location()}
|
||||
set {_location = newValue}
|
||||
}
|
||||
/// Returns true if `location` has been explicitly set.
|
||||
var hasLocation: Bool {return self._location != nil}
|
||||
/// Clears the value of `location`. Subsequent reads from it will return its default value.
|
||||
mutating func clearLocation() {self._location = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _location: Location? = nil
|
||||
}
|
||||
|
||||
///
|
||||
/// Location of a waypoint to associate with a message
|
||||
struct Location {
|
||||
/// Waypoint message, used to share arbitrary locations across the mesh
|
||||
struct Waypoint {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// Id of the location
|
||||
/// Id of the waypoint
|
||||
var id: UInt32 = 0
|
||||
|
||||
///
|
||||
|
|
@ -1113,13 +1090,21 @@ struct Location {
|
|||
var longitudeI: Int32 = 0
|
||||
|
||||
///
|
||||
/// Time the location is to expire (epoch)
|
||||
/// Time the waypoint is to expire (epoch)
|
||||
var expire: UInt32 = 0
|
||||
|
||||
///
|
||||
/// If true, only allow the original sender to update the location.
|
||||
/// If true, only allow the original sender to update the waypoint.
|
||||
var locked: Bool = false
|
||||
|
||||
///
|
||||
/// Name of the waypoint - max 30 chars
|
||||
var name: String = String()
|
||||
|
||||
///*
|
||||
/// Description of the waypoint - max 100 chars
|
||||
var description_p: String = String()
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
|
@ -1485,65 +1470,58 @@ struct NodeInfo {
|
|||
|
||||
///
|
||||
/// The node number
|
||||
var num: UInt32 {
|
||||
get {return _storage._num}
|
||||
set {_uniqueStorage()._num = newValue}
|
||||
}
|
||||
var num: UInt32 = 0
|
||||
|
||||
///
|
||||
/// The user info for this node
|
||||
var user: User {
|
||||
get {return _storage._user ?? User()}
|
||||
set {_uniqueStorage()._user = newValue}
|
||||
get {return _user ?? User()}
|
||||
set {_user = newValue}
|
||||
}
|
||||
/// Returns true if `user` has been explicitly set.
|
||||
var hasUser: Bool {return _storage._user != nil}
|
||||
var hasUser: Bool {return self._user != nil}
|
||||
/// Clears the value of `user`. Subsequent reads from it will return its default value.
|
||||
mutating func clearUser() {_uniqueStorage()._user = nil}
|
||||
mutating func clearUser() {self._user = nil}
|
||||
|
||||
///
|
||||
/// This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true.
|
||||
/// Position.time now indicates the last time we received a POSITION from that node.
|
||||
var position: Position {
|
||||
get {return _storage._position ?? Position()}
|
||||
set {_uniqueStorage()._position = newValue}
|
||||
get {return _position ?? Position()}
|
||||
set {_position = newValue}
|
||||
}
|
||||
/// Returns true if `position` has been explicitly set.
|
||||
var hasPosition: Bool {return _storage._position != nil}
|
||||
var hasPosition: Bool {return self._position != nil}
|
||||
/// Clears the value of `position`. Subsequent reads from it will return its default value.
|
||||
mutating func clearPosition() {_uniqueStorage()._position = nil}
|
||||
mutating func clearPosition() {self._position = nil}
|
||||
|
||||
///
|
||||
/// Returns the Signal-to-noise ratio (SNR) of the last received message,
|
||||
/// as measured by the receiver. Return SNR of the last received message in dB
|
||||
var snr: Float {
|
||||
get {return _storage._snr}
|
||||
set {_uniqueStorage()._snr = newValue}
|
||||
}
|
||||
var snr: Float = 0
|
||||
|
||||
///
|
||||
/// Set to indicate the last time we received a packet from this node
|
||||
var lastHeard: UInt32 {
|
||||
get {return _storage._lastHeard}
|
||||
set {_uniqueStorage()._lastHeard = newValue}
|
||||
}
|
||||
var lastHeard: UInt32 = 0
|
||||
|
||||
///
|
||||
/// The latest device metrics for the node.
|
||||
var deviceMetrics: DeviceMetrics {
|
||||
get {return _storage._deviceMetrics ?? DeviceMetrics()}
|
||||
set {_uniqueStorage()._deviceMetrics = newValue}
|
||||
get {return _deviceMetrics ?? DeviceMetrics()}
|
||||
set {_deviceMetrics = newValue}
|
||||
}
|
||||
/// Returns true if `deviceMetrics` has been explicitly set.
|
||||
var hasDeviceMetrics: Bool {return _storage._deviceMetrics != nil}
|
||||
var hasDeviceMetrics: Bool {return self._deviceMetrics != nil}
|
||||
/// Clears the value of `deviceMetrics`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDeviceMetrics() {_uniqueStorage()._deviceMetrics = nil}
|
||||
mutating func clearDeviceMetrics() {self._deviceMetrics = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
fileprivate var _user: User? = nil
|
||||
fileprivate var _position: Position? = nil
|
||||
fileprivate var _deviceMetrics: DeviceMetrics? = nil
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -2130,7 +2108,7 @@ extension Routing: @unchecked Sendable {}
|
|||
extension Routing.OneOf_Variant: @unchecked Sendable {}
|
||||
extension Routing.Error: @unchecked Sendable {}
|
||||
extension DataMessage: @unchecked Sendable {}
|
||||
extension Location: @unchecked Sendable {}
|
||||
extension Waypoint: @unchecked Sendable {}
|
||||
extension MeshPacket: @unchecked Sendable {}
|
||||
extension MeshPacket.OneOf_PayloadVariant: @unchecked Sendable {}
|
||||
extension MeshPacket.Priority: @unchecked Sendable {}
|
||||
|
|
@ -2176,6 +2154,7 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding {
|
|||
42: .same(proto: "NRF52840_PCA10059"),
|
||||
43: .same(proto: "DR_DEV"),
|
||||
44: .same(proto: "M5STACK"),
|
||||
45: .same(proto: "STATION_G1"),
|
||||
255: .same(proto: "PRIVATE_HW"),
|
||||
]
|
||||
}
|
||||
|
|
@ -2464,9 +2443,6 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase,
|
|||
4: .same(proto: "macaddr"),
|
||||
6: .standard(proto: "hw_model"),
|
||||
7: .standard(proto: "is_licensed"),
|
||||
10: .standard(proto: "tx_power_dbm"),
|
||||
11: .standard(proto: "ant_gain_dbi"),
|
||||
12: .standard(proto: "ant_azimuth"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -2481,9 +2457,6 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase,
|
|||
case 4: try { try decoder.decodeSingularBytesField(value: &self.macaddr) }()
|
||||
case 6: try { try decoder.decodeSingularEnumField(value: &self.hwModel) }()
|
||||
case 7: try { try decoder.decodeSingularBoolField(value: &self.isLicensed) }()
|
||||
case 10: try { try decoder.decodeSingularUInt32Field(value: &self.txPowerDbm) }()
|
||||
case 11: try { try decoder.decodeSingularUInt32Field(value: &self.antGainDbi) }()
|
||||
case 12: try { try decoder.decodeSingularUInt32Field(value: &self.antAzimuth) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -2508,15 +2481,6 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase,
|
|||
if self.isLicensed != false {
|
||||
try visitor.visitSingularBoolField(value: self.isLicensed, fieldNumber: 7)
|
||||
}
|
||||
if self.txPowerDbm != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.txPowerDbm, fieldNumber: 10)
|
||||
}
|
||||
if self.antGainDbi != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.antGainDbi, fieldNumber: 11)
|
||||
}
|
||||
if self.antAzimuth != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.antAzimuth, fieldNumber: 12)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -2527,9 +2491,6 @@ extension User: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase,
|
|||
if lhs.macaddr != rhs.macaddr {return false}
|
||||
if lhs.hwModel != rhs.hwModel {return false}
|
||||
if lhs.isLicensed != rhs.isLicensed {return false}
|
||||
if lhs.txPowerDbm != rhs.txPowerDbm {return false}
|
||||
if lhs.antGainDbi != rhs.antGainDbi {return false}
|
||||
if lhs.antAzimuth != rhs.antAzimuth {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -2677,7 +2638,6 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
6: .standard(proto: "request_id"),
|
||||
7: .standard(proto: "reply_id"),
|
||||
8: .same(proto: "emoji"),
|
||||
9: .same(proto: "location"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -2694,17 +2654,12 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
case 6: try { try decoder.decodeSingularFixed32Field(value: &self.requestID) }()
|
||||
case 7: try { try decoder.decodeSingularFixed32Field(value: &self.replyID) }()
|
||||
case 8: try { try decoder.decodeSingularFixed32Field(value: &self.emoji) }()
|
||||
case 9: try { try decoder.decodeSingularMessageField(value: &self._location) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if self.portnum != .unknownApp {
|
||||
try visitor.visitSingularEnumField(value: self.portnum, fieldNumber: 1)
|
||||
}
|
||||
|
|
@ -2729,9 +2684,6 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
if self.emoji != 0 {
|
||||
try visitor.visitSingularFixed32Field(value: self.emoji, fieldNumber: 8)
|
||||
}
|
||||
try { if let v = self._location {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 9)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -2744,20 +2696,21 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
if lhs.requestID != rhs.requestID {return false}
|
||||
if lhs.replyID != rhs.replyID {return false}
|
||||
if lhs.emoji != rhs.emoji {return false}
|
||||
if lhs._location != rhs._location {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Location: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = "Location"
|
||||
extension Waypoint: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = "Waypoint"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "id"),
|
||||
2: .standard(proto: "latitude_i"),
|
||||
3: .standard(proto: "longitude_i"),
|
||||
4: .same(proto: "expire"),
|
||||
5: .same(proto: "locked"),
|
||||
6: .same(proto: "name"),
|
||||
7: .same(proto: "description"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -2771,6 +2724,8 @@ extension Location: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
case 3: try { try decoder.decodeSingularSFixed32Field(value: &self.longitudeI) }()
|
||||
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.expire) }()
|
||||
case 5: try { try decoder.decodeSingularBoolField(value: &self.locked) }()
|
||||
case 6: try { try decoder.decodeSingularStringField(value: &self.name) }()
|
||||
case 7: try { try decoder.decodeSingularStringField(value: &self.description_p) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -2792,15 +2747,23 @@ extension Location: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
if self.locked != false {
|
||||
try visitor.visitSingularBoolField(value: self.locked, fieldNumber: 5)
|
||||
}
|
||||
if !self.name.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.name, fieldNumber: 6)
|
||||
}
|
||||
if !self.description_p.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.description_p, fieldNumber: 7)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: Location, rhs: Location) -> Bool {
|
||||
static func ==(lhs: Waypoint, rhs: Waypoint) -> Bool {
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.latitudeI != rhs.latitudeI {return false}
|
||||
if lhs.longitudeI != rhs.longitudeI {return false}
|
||||
if lhs.expire != rhs.expire {return false}
|
||||
if lhs.locked != rhs.locked {return false}
|
||||
if lhs.name != rhs.name {return false}
|
||||
if lhs.description_p != rhs.description_p {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -3022,98 +2985,56 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
6: .standard(proto: "device_metrics"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _num: UInt32 = 0
|
||||
var _user: User? = nil
|
||||
var _position: Position? = nil
|
||||
var _snr: Float = 0
|
||||
var _lastHeard: UInt32 = 0
|
||||
var _deviceMetrics: DeviceMetrics? = nil
|
||||
|
||||
static let defaultInstance = _StorageClass()
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_num = source._num
|
||||
_user = source._user
|
||||
_position = source._position
|
||||
_snr = source._snr
|
||||
_lastHeard = source._lastHeard
|
||||
_deviceMetrics = source._deviceMetrics
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularUInt32Field(value: &_storage._num) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._user) }()
|
||||
case 3: try { try decoder.decodeSingularMessageField(value: &_storage._position) }()
|
||||
case 4: try { try decoder.decodeSingularFloatField(value: &_storage._snr) }()
|
||||
case 5: try { try decoder.decodeSingularFixed32Field(value: &_storage._lastHeard) }()
|
||||
case 6: try { try decoder.decodeSingularMessageField(value: &_storage._deviceMetrics) }()
|
||||
default: break
|
||||
}
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularUInt32Field(value: &self.num) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &self._user) }()
|
||||
case 3: try { try decoder.decodeSingularMessageField(value: &self._position) }()
|
||||
case 4: try { try decoder.decodeSingularFloatField(value: &self.snr) }()
|
||||
case 5: try { try decoder.decodeSingularFixed32Field(value: &self.lastHeard) }()
|
||||
case 6: try { try decoder.decodeSingularMessageField(value: &self._deviceMetrics) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if _storage._num != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._num, fieldNumber: 1)
|
||||
}
|
||||
try { if let v = _storage._user {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = _storage._position {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
if _storage._snr != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._snr, fieldNumber: 4)
|
||||
}
|
||||
if _storage._lastHeard != 0 {
|
||||
try visitor.visitSingularFixed32Field(value: _storage._lastHeard, fieldNumber: 5)
|
||||
}
|
||||
try { if let v = _storage._deviceMetrics {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if self.num != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.num, fieldNumber: 1)
|
||||
}
|
||||
try { if let v = self._user {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._position {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
if self.snr != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.snr, fieldNumber: 4)
|
||||
}
|
||||
if self.lastHeard != 0 {
|
||||
try visitor.visitSingularFixed32Field(value: self.lastHeard, fieldNumber: 5)
|
||||
}
|
||||
try { if let v = self._deviceMetrics {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: NodeInfo, rhs: NodeInfo) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._num != rhs_storage._num {return false}
|
||||
if _storage._user != rhs_storage._user {return false}
|
||||
if _storage._position != rhs_storage._position {return false}
|
||||
if _storage._snr != rhs_storage._snr {return false}
|
||||
if _storage._lastHeard != rhs_storage._lastHeard {return false}
|
||||
if _storage._deviceMetrics != rhs_storage._deviceMetrics {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.num != rhs.num {return false}
|
||||
if lhs._user != rhs._user {return false}
|
||||
if lhs._position != rhs._position {return false}
|
||||
if lhs.snr != rhs.snr {return false}
|
||||
if lhs.lastHeard != rhs.lastHeard {return false}
|
||||
if lhs._deviceMetrics != rhs._deviceMetrics {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ struct ModuleConfig {
|
|||
/// If a meshtastic node is able to reach the internet it will normally attempt to gateway any channels that are marked as
|
||||
/// is_uplink_enabled or is_downlink_enabled.
|
||||
/// But if this flag is set, all MQTT features will be disabled and no servers will be contacted.
|
||||
var disabled: Bool = false
|
||||
var enabled: Bool = false
|
||||
|
||||
///
|
||||
/// The server to use for our MQTT global message gateway feature.
|
||||
|
|
@ -473,31 +473,11 @@ struct ModuleConfig {
|
|||
/// Enable/Disable the telemetry measurement module on-device display
|
||||
var environmentScreenEnabled: Bool = false
|
||||
|
||||
///
|
||||
/// Sometimes sensor reads can fail.
|
||||
/// If this happens, we will retry a configurable number of attempts,
|
||||
/// each attempt will be delayed by the minimum required refresh rate for that sensor
|
||||
var environmentReadErrorCountThreshold: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Sometimes we can end up with more than read_error_count_threshold failures.
|
||||
/// In this case, we will stop trying to read from the sensor for a while.
|
||||
/// Wait this long until trying to read from the sensor again
|
||||
var environmentRecoveryInterval: UInt32 = 0
|
||||
|
||||
///
|
||||
/// We'll always read the sensor in Celsius, but sometimes we might want to
|
||||
/// display the results in Fahrenheit as a "user preference".
|
||||
var environmentDisplayFahrenheit: Bool = false
|
||||
|
||||
///
|
||||
/// Specify the sensor type
|
||||
var environmentSensorType: TelemetrySensorType = .notSet
|
||||
|
||||
///
|
||||
/// Specify the peferred GPIO Pin for sensor readings
|
||||
var environmentSensorPin: UInt32 = 0
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
|
@ -865,7 +845,7 @@ extension ModuleConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = ModuleConfig.protoMessageName + ".MQTTConfig"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "disabled"),
|
||||
1: .same(proto: "enabled"),
|
||||
2: .same(proto: "address"),
|
||||
3: .same(proto: "username"),
|
||||
4: .same(proto: "password"),
|
||||
|
|
@ -878,7 +858,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
|
|||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &self.disabled) }()
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &self.enabled) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.address) }()
|
||||
case 3: try { try decoder.decodeSingularStringField(value: &self.username) }()
|
||||
case 4: try { try decoder.decodeSingularStringField(value: &self.password) }()
|
||||
|
|
@ -889,8 +869,8 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.disabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.disabled, fieldNumber: 1)
|
||||
if self.enabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.enabled, fieldNumber: 1)
|
||||
}
|
||||
if !self.address.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.address, fieldNumber: 2)
|
||||
|
|
@ -908,7 +888,7 @@ extension ModuleConfig.MQTTConfig: SwiftProtobuf.Message, SwiftProtobuf._Message
|
|||
}
|
||||
|
||||
static func ==(lhs: ModuleConfig.MQTTConfig, rhs: ModuleConfig.MQTTConfig) -> Bool {
|
||||
if lhs.disabled != rhs.disabled {return false}
|
||||
if lhs.enabled != rhs.enabled {return false}
|
||||
if lhs.address != rhs.address {return false}
|
||||
if lhs.username != rhs.username {return false}
|
||||
if lhs.password != rhs.password {return false}
|
||||
|
|
@ -1184,11 +1164,7 @@ extension ModuleConfig.TelemetryConfig: SwiftProtobuf.Message, SwiftProtobuf._Me
|
|||
2: .standard(proto: "environment_update_interval"),
|
||||
3: .standard(proto: "environment_measurement_enabled"),
|
||||
4: .standard(proto: "environment_screen_enabled"),
|
||||
5: .standard(proto: "environment_read_error_count_threshold"),
|
||||
6: .standard(proto: "environment_recovery_interval"),
|
||||
7: .standard(proto: "environment_display_fahrenheit"),
|
||||
8: .standard(proto: "environment_sensor_type"),
|
||||
9: .standard(proto: "environment_sensor_pin"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1201,11 +1177,7 @@ extension ModuleConfig.TelemetryConfig: SwiftProtobuf.Message, SwiftProtobuf._Me
|
|||
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.environmentUpdateInterval) }()
|
||||
case 3: try { try decoder.decodeSingularBoolField(value: &self.environmentMeasurementEnabled) }()
|
||||
case 4: try { try decoder.decodeSingularBoolField(value: &self.environmentScreenEnabled) }()
|
||||
case 5: try { try decoder.decodeSingularUInt32Field(value: &self.environmentReadErrorCountThreshold) }()
|
||||
case 6: try { try decoder.decodeSingularUInt32Field(value: &self.environmentRecoveryInterval) }()
|
||||
case 7: try { try decoder.decodeSingularBoolField(value: &self.environmentDisplayFahrenheit) }()
|
||||
case 8: try { try decoder.decodeSingularEnumField(value: &self.environmentSensorType) }()
|
||||
case 9: try { try decoder.decodeSingularUInt32Field(value: &self.environmentSensorPin) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1224,21 +1196,9 @@ extension ModuleConfig.TelemetryConfig: SwiftProtobuf.Message, SwiftProtobuf._Me
|
|||
if self.environmentScreenEnabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.environmentScreenEnabled, fieldNumber: 4)
|
||||
}
|
||||
if self.environmentReadErrorCountThreshold != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.environmentReadErrorCountThreshold, fieldNumber: 5)
|
||||
}
|
||||
if self.environmentRecoveryInterval != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.environmentRecoveryInterval, fieldNumber: 6)
|
||||
}
|
||||
if self.environmentDisplayFahrenheit != false {
|
||||
try visitor.visitSingularBoolField(value: self.environmentDisplayFahrenheit, fieldNumber: 7)
|
||||
}
|
||||
if self.environmentSensorType != .notSet {
|
||||
try visitor.visitSingularEnumField(value: self.environmentSensorType, fieldNumber: 8)
|
||||
}
|
||||
if self.environmentSensorPin != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.environmentSensorPin, fieldNumber: 9)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -1247,11 +1207,7 @@ extension ModuleConfig.TelemetryConfig: SwiftProtobuf.Message, SwiftProtobuf._Me
|
|||
if lhs.environmentUpdateInterval != rhs.environmentUpdateInterval {return false}
|
||||
if lhs.environmentMeasurementEnabled != rhs.environmentMeasurementEnabled {return false}
|
||||
if lhs.environmentScreenEnabled != rhs.environmentScreenEnabled {return false}
|
||||
if lhs.environmentReadErrorCountThreshold != rhs.environmentReadErrorCountThreshold {return false}
|
||||
if lhs.environmentRecoveryInterval != rhs.environmentRecoveryInterval {return false}
|
||||
if lhs.environmentDisplayFahrenheit != rhs.environmentDisplayFahrenheit {return false}
|
||||
if lhs.environmentSensorType != rhs.environmentSensorType {return false}
|
||||
if lhs.environmentSensorPin != rhs.environmentSensorPin {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ enum PortNum: SwiftProtobuf.Enum {
|
|||
|
||||
///
|
||||
/// Waypoint payloads.
|
||||
/// Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message
|
||||
case waypointApp // = 8
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -29,49 +29,29 @@ enum TelemetrySensorType: SwiftProtobuf.Enum {
|
|||
/// No external telemetry sensor explicitly set
|
||||
case notSet // = 0
|
||||
|
||||
///
|
||||
/// Moderate accuracy temperature
|
||||
case dht11 // = 1
|
||||
|
||||
///
|
||||
/// High accuracy temperature
|
||||
case ds18B20 // = 2
|
||||
|
||||
///
|
||||
/// Moderate accuracy temperature and humidity
|
||||
case dht12 // = 3
|
||||
|
||||
///
|
||||
/// Moderate accuracy temperature and humidity
|
||||
case dht21 // = 4
|
||||
|
||||
///
|
||||
/// Moderate accuracy temperature and humidity
|
||||
case dht22 // = 5
|
||||
|
||||
///
|
||||
/// High accuracy temperature, pressure, humidity
|
||||
case bme280 // = 6
|
||||
case bme280 // = 1
|
||||
|
||||
///
|
||||
/// High accuracy temperature, pressure, humidity, and air resistance
|
||||
case bme680 // = 7
|
||||
case bme680 // = 2
|
||||
|
||||
///
|
||||
/// Very high accuracy temperature
|
||||
case mcp9808 // = 8
|
||||
|
||||
///
|
||||
/// Moderate accuracy temperature and humidity
|
||||
case shtc3 // = 9
|
||||
case mcp9808 // = 3
|
||||
|
||||
///
|
||||
/// Moderate accuracy current and voltage
|
||||
case ina260 // = 10
|
||||
case ina260 // = 4
|
||||
|
||||
///
|
||||
/// Moderate accuracy current and voltage
|
||||
case ina219 // = 11
|
||||
case ina219 // = 5
|
||||
|
||||
///
|
||||
/// High accuracy temperature and pressure
|
||||
case bmp280 // = 6
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
init() {
|
||||
|
|
@ -81,17 +61,12 @@ enum TelemetrySensorType: SwiftProtobuf.Enum {
|
|||
init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .notSet
|
||||
case 1: self = .dht11
|
||||
case 2: self = .ds18B20
|
||||
case 3: self = .dht12
|
||||
case 4: self = .dht21
|
||||
case 5: self = .dht22
|
||||
case 6: self = .bme280
|
||||
case 7: self = .bme680
|
||||
case 8: self = .mcp9808
|
||||
case 9: self = .shtc3
|
||||
case 10: self = .ina260
|
||||
case 11: self = .ina219
|
||||
case 1: self = .bme280
|
||||
case 2: self = .bme680
|
||||
case 3: self = .mcp9808
|
||||
case 4: self = .ina260
|
||||
case 5: self = .ina219
|
||||
case 6: self = .bmp280
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -99,17 +74,12 @@ enum TelemetrySensorType: SwiftProtobuf.Enum {
|
|||
var rawValue: Int {
|
||||
switch self {
|
||||
case .notSet: return 0
|
||||
case .dht11: return 1
|
||||
case .ds18B20: return 2
|
||||
case .dht12: return 3
|
||||
case .dht21: return 4
|
||||
case .dht22: return 5
|
||||
case .bme280: return 6
|
||||
case .bme680: return 7
|
||||
case .mcp9808: return 8
|
||||
case .shtc3: return 9
|
||||
case .ina260: return 10
|
||||
case .ina219: return 11
|
||||
case .bme280: return 1
|
||||
case .bme680: return 2
|
||||
case .mcp9808: return 3
|
||||
case .ina260: return 4
|
||||
case .ina219: return 5
|
||||
case .bmp280: return 6
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -122,17 +92,12 @@ extension TelemetrySensorType: CaseIterable {
|
|||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
static var allCases: [TelemetrySensorType] = [
|
||||
.notSet,
|
||||
.dht11,
|
||||
.ds18B20,
|
||||
.dht12,
|
||||
.dht21,
|
||||
.dht22,
|
||||
.bme280,
|
||||
.bme680,
|
||||
.mcp9808,
|
||||
.shtc3,
|
||||
.ina260,
|
||||
.ina219,
|
||||
.bmp280,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -285,17 +250,12 @@ extension Telemetry.OneOf_Variant: @unchecked Sendable {}
|
|||
extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding {
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "NotSet"),
|
||||
1: .same(proto: "DHT11"),
|
||||
2: .same(proto: "DS18B20"),
|
||||
3: .same(proto: "DHT12"),
|
||||
4: .same(proto: "DHT21"),
|
||||
5: .same(proto: "DHT22"),
|
||||
6: .same(proto: "BME280"),
|
||||
7: .same(proto: "BME680"),
|
||||
8: .same(proto: "MCP9808"),
|
||||
9: .same(proto: "SHTC3"),
|
||||
10: .same(proto: "INA260"),
|
||||
11: .same(proto: "INA219"),
|
||||
1: .same(proto: "BME280"),
|
||||
2: .same(proto: "BME680"),
|
||||
3: .same(proto: "MCP9808"),
|
||||
4: .same(proto: "INA260"),
|
||||
5: .same(proto: "INA219"),
|
||||
6: .same(proto: "BMP280"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,15 +16,12 @@ struct Connect: View {
|
|||
@EnvironmentObject var bleManager: BLEManager
|
||||
@EnvironmentObject var userSettings: UserSettings
|
||||
|
||||
@State private var showingVersionSheet = false
|
||||
|
||||
@State var initialLoad: Bool = true
|
||||
@State var isPreferredRadio: Bool = false
|
||||
|
||||
@State var firmwareVersion = "0.0.0"
|
||||
@State var minimumVersion = "1.3.27"
|
||||
@State var minimumVersion = "1.3.39"
|
||||
@State var invalidVersion = false
|
||||
|
||||
|
||||
var body: some View {
|
||||
|
||||
|
|
@ -267,23 +264,18 @@ struct Connect: View {
|
|||
|
||||
InvalidVersion(errorText: "1.3 ALPHA PREVIEW this version of the app supports only version \(minimumVersion) and above. Your device has been disconnected.")
|
||||
}
|
||||
|
||||
|
||||
.onChange(of: firmwareVersion) { iv in
|
||||
|
||||
.onChange(of: (self.bleManager.connectedVersion)) { ic in
|
||||
|
||||
bleManager.disconnectPeripheral()
|
||||
}
|
||||
.onChange(of: self.bleManager.isConnected) { ic in
|
||||
|
||||
firmwareVersion = bleManager.lastConnnectionVersion
|
||||
firmwareVersion = self.bleManager.connectedVersion
|
||||
let supportedVersion = firmwareVersion == "0.0.0" || minimumVersion.compare(firmwareVersion, options: .numeric) == .orderedAscending || minimumVersion.compare(firmwareVersion, options: .numeric) == .orderedSame
|
||||
|
||||
invalidVersion = !supportedVersion
|
||||
|
||||
if invalidVersion {
|
||||
|
||||
bleManager.disconnectPeripheral()
|
||||
}
|
||||
|
||||
}
|
||||
.onAppear(perform: {
|
||||
|
||||
|
|
|
|||
22
Meshtastic/Views/Helpers/DistanceText.swift
Normal file
22
Meshtastic/Views/Helpers/DistanceText.swift
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// DistanceText.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/19/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import CoreLocation
|
||||
import MapKit
|
||||
|
||||
struct DistanceText: View {
|
||||
|
||||
var meters: CLLocationDistance
|
||||
|
||||
var body: some View {
|
||||
|
||||
let distanceFormatter = MKDistanceFormatter()
|
||||
|
||||
Text("Distance: \(distanceFormatter.string(fromDistance: Double(meters)))")
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@ struct Contacts: View {
|
|||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
@State var onboarding = true
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "longName", ascending: true)],
|
||||
|
|
|
|||
|
|
@ -213,34 +213,41 @@ struct UserMessageList: View {
|
|||
|
||||
let messageDate = Date(timeIntervalSince1970: TimeInterval(message.messageTimestamp))
|
||||
|
||||
Text("Sent \(messageDate, style: .date) \(messageDate, style: .time)").font(.caption2).foregroundColor(.gray)
|
||||
Text("Sent \(messageDate, style: .date) \(messageDate.formattedDate(format: "h:mm:ss a"))").font(.caption2).foregroundColor(.gray)
|
||||
}
|
||||
|
||||
VStack {
|
||||
|
||||
Text("Received ACK: \(message.receivedACK ? "✔️" : "")")
|
||||
|
||||
}
|
||||
|
||||
if message.receivedACK {
|
||||
|
||||
VStack {
|
||||
|
||||
let ackDate = Date(timeIntervalSince1970: TimeInterval(message.ackTimestamp))
|
||||
|
||||
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
|
||||
if ackDate >= sixMonthsAgo! {
|
||||
|
||||
Text("ACK \(ackDate, style: .date) \(ackDate, style: .time)").font(.caption2).foregroundColor(.gray)
|
||||
|
||||
} else {
|
||||
|
||||
Text("Unknown Age").font(.caption2).foregroundColor(.gray)
|
||||
}
|
||||
|
||||
Text("Received Ack \(message.receivedACK ? "✔️" : "")")
|
||||
}
|
||||
}
|
||||
if message.ackError > 0 {
|
||||
|
||||
let ackErrorVal = RoutingError(rawValue: Int(message.ackError))
|
||||
Text("\(ackErrorVal?.display ?? "No Error" )").fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
VStack {
|
||||
|
||||
let ackDate = Date(timeIntervalSince1970: TimeInterval(message.ackTimestamp))
|
||||
|
||||
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
|
||||
if ackDate >= sixMonthsAgo! {
|
||||
|
||||
Text((ackDate.formattedDate(format: "h:mm:ss a"))).font(.caption2).foregroundColor(.gray)
|
||||
|
||||
} else {
|
||||
|
||||
Text("Unknown Age").font(.caption2).foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
|
||||
if message.ackSNR != 0 {
|
||||
VStack {
|
||||
|
||||
Text("ACK SNR \(String(message.ackSNR))")
|
||||
Text("Ack SNR \(String(message.ackSNR))")
|
||||
.font(.caption2)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
|
|
@ -289,9 +296,21 @@ struct UserMessageList: View {
|
|||
|
||||
HStack {
|
||||
|
||||
if message.receivedACK {
|
||||
|
||||
if currentUser && message.receivedACK {
|
||||
|
||||
// Ack Received
|
||||
Text("Acknowledged").font(.caption2).foregroundColor(.gray)
|
||||
|
||||
} else if currentUser && message.ackError == 0 {
|
||||
|
||||
// Empty Error
|
||||
Text("Waiting to be acknowledged. . .").font(.caption2).foregroundColor(.yellow)
|
||||
|
||||
} else if currentUser && message.ackError > 0 {
|
||||
|
||||
let ackErrorVal = RoutingError(rawValue: Int(message.ackError))
|
||||
Text("\(ackErrorVal?.display ?? "No Error" )").fixedSize(horizontal: false, vertical: true)
|
||||
.font(.caption2).foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -302,9 +321,9 @@ struct UserMessageList: View {
|
|||
Spacer(minLength:50)
|
||||
}
|
||||
}
|
||||
.id(message.messageId)
|
||||
.padding([.leading, .trailing])
|
||||
.frame(maxWidth: .infinity)
|
||||
.id(message.messageId)
|
||||
.alert(isPresented: $showDeleteMessageAlert) {
|
||||
Alert(title: Text("Are you sure you want to delete this message?"), message: Text("This action is permanent."),
|
||||
primaryButton: .destructive(Text("Delete")) {
|
||||
|
|
@ -443,8 +462,8 @@ struct UserMessageList: View {
|
|||
focusedField = nil
|
||||
replyMessageId = 0
|
||||
if sendPositionWithMessage {
|
||||
if bleManager.sendPosition(destNum: user.num, wantResponse: false) {
|
||||
print("Position Sent")
|
||||
if bleManager.sendLocation(destNum: user.num, wantAck: true) {
|
||||
print("Location Sent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ struct LocationHistory: View {
|
|||
|
||||
List {
|
||||
|
||||
ForEach(node.positions!.array as! [PositionEntity], id: \.self) { (mappin: PositionEntity) in
|
||||
ForEach(node.positions!.reversed() as! [PositionEntity], id: \.self) { (mappin: PositionEntity) in
|
||||
|
||||
VStack {
|
||||
|
||||
|
|
@ -88,12 +88,9 @@ struct LocationHistory: View {
|
|||
.font(.subheadline)
|
||||
.foregroundColor(.accentColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text("Time:")
|
||||
.font(.caption)
|
||||
DateTimeText(dateTime: mappin.time)
|
||||
.foregroundColor(.gray)
|
||||
.font(.caption)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ struct NodeDetail: View {
|
|||
) {
|
||||
Button("Shutdown Node?", role: .destructive) {
|
||||
|
||||
if !bleManager.sendShutdown(destNum: node.num, wantResponse: true) {
|
||||
if !bleManager.sendShutdown(destNum: node.num) {
|
||||
|
||||
print("Shutdown Failed")
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ struct NodeDetail: View {
|
|||
|
||||
Button("Reboot Node?", role: .destructive) {
|
||||
|
||||
if !bleManager.sendReboot(destNum: node.num, wantResponse: true) {
|
||||
if !bleManager.sendReboot(destNum: node.num) {
|
||||
|
||||
print("Reboot Failed")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
// A view showing a list of devices that have been seen on the mesh network from the perspective of the connected device.
|
||||
|
||||
import SwiftUI
|
||||
import CoreLocation
|
||||
|
||||
struct NodeList: View {
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ struct NodeList: View {
|
|||
@State var initialLoad: Bool = true
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "lastHeard", ascending: false)],
|
||||
sortDescriptors: [NSSortDescriptor(key: "user.shortName", ascending: true)],
|
||||
animation: .default)
|
||||
|
||||
private var nodes: FetchedResults<NodeInfoEntity>
|
||||
|
|
@ -35,8 +36,8 @@ struct NodeList: View {
|
|||
if nodes.count == 0 {
|
||||
|
||||
Text("Scan for Radios").font(.largeTitle)
|
||||
Text("No LoRa Mesh Nodes Found").font(.title2)
|
||||
Text("Go to the bluetooth section in the bottom right menu and click the Start Scanning button to scan for nearby radios and find your Meshtastic device. Make sure your device is powered on and near your phone or tablet.")
|
||||
Text("No Meshtastic Nodes Found").font(.title2)
|
||||
Text("Go to the bluetooth section in the bottom right menu and click the Start Scanning button to scan for nearby radios and find your Meshtastic device. Make sure your device is powered on and near your iPhone, iPad or Mac.")
|
||||
.font(.body)
|
||||
Text("Once the device shows under Available Devices touch the device you want to connect to and it will pull node information over BLE and populate the node list and mesh map in the Meshtastic app.")
|
||||
Text("Views with bluetooth functionality will show an indicator in the upper right hand corner show if bluetooth is on, and if a device is connected.")
|
||||
|
|
@ -61,7 +62,7 @@ struct NodeList: View {
|
|||
if UIDevice.current.userInterfaceIdiom == .pad { Text(node.user?.longName ?? "Unknown").font(.headline)
|
||||
.offset(x: -15)
|
||||
} else {
|
||||
Text(node.user?.longName ?? "Unknown").font(.title).offset(x: -15)
|
||||
Text(node.user?.longName ?? "Unknown").font(.title2).offset(x: -15)
|
||||
}
|
||||
}
|
||||
.padding(.bottom, 10)
|
||||
|
|
@ -80,21 +81,49 @@ struct NodeList: View {
|
|||
Text("Currently Connected").font(.title3).foregroundColor(Color.accentColor)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
HStack(alignment: .bottom) {
|
||||
|
||||
Image(systemName: "clock.badge.checkmark.fill").font(.title3)
|
||||
.foregroundColor(.accentColor).symbolRenderingMode(.hierarchical)
|
||||
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
|
||||
LastHeardText(lastHeard: node.lastHeard).font(.subheadline).foregroundColor(.gray)
|
||||
|
||||
} else {
|
||||
|
||||
LastHeardText(lastHeard: node.lastHeard).font(.title3).foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
|
||||
if node.positions?.count ?? 0 > 0 && (bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.num != node.num) {
|
||||
|
||||
Spacer()
|
||||
HStack(alignment: .bottom) {
|
||||
|
||||
let lastPostion = node.positions!.reversed()[0] as! PositionEntity
|
||||
|
||||
let myCoord = CLLocation(latitude: LocationHelper.currentLocation.latitude, longitude: LocationHelper.currentLocation.longitude)
|
||||
|
||||
let nodeCoord = CLLocation(latitude: lastPostion.coordinate!.latitude, longitude: lastPostion.coordinate!.longitude)
|
||||
|
||||
let metersAway = nodeCoord.distance(from: myCoord)
|
||||
|
||||
Image(systemName: "lines.measurement.horizontal").font(.title3)
|
||||
.foregroundColor(.accentColor).symbolRenderingMode(.hierarchical)
|
||||
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
|
||||
DistanceText(meters: metersAway).font(.subheadline).foregroundColor(.gray)
|
||||
|
||||
} else {
|
||||
|
||||
DistanceText(meters: metersAway).font(.title3).foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding([.leading, .top, .bottom])
|
||||
}
|
||||
|
|
@ -106,16 +135,9 @@ struct NodeList: View {
|
|||
|
||||
if initialLoad {
|
||||
|
||||
self.bleManager.context = context
|
||||
self.bleManager.userSettings = userSettings
|
||||
self.bleManager.context = context
|
||||
self.initialLoad = false
|
||||
|
||||
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||
|
||||
if nodes.count > 0 {
|
||||
selection = "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ struct TelemetryLog: View {
|
|||
|
||||
List {
|
||||
|
||||
ForEach(node.telemetries!.array as! [TelemetryEntity], id: \.self) { (tel: TelemetryEntity) in
|
||||
ForEach(node.telemetries!.reversed() as! [TelemetryEntity], id: \.self) { (tel: TelemetryEntity) in
|
||||
|
||||
VStack (alignment: .leading) {
|
||||
|
||||
|
|
@ -86,14 +86,10 @@ struct TelemetryLog: View {
|
|||
Text("Environment Metrics")
|
||||
.font(.title)
|
||||
|
||||
let sensor = SensorTypes(rawValue: Int(node.telemetryConfig?.environmentSensorType ?? 0))
|
||||
|
||||
let tempReadingType = (!(node.telemetryConfig?.environmentDisplayFahrenheit ?? true)) ? "°C" : "°F"
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 ||
|
||||
sensor == SensorTypes.mcp9808 {
|
||||
if tel.temperature > 0 {
|
||||
|
||||
Image(systemName: "thermometer")
|
||||
.font(.callout)
|
||||
|
|
@ -104,9 +100,7 @@ struct TelemetryLog: View {
|
|||
.font(.callout)
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 {
|
||||
if tel.relativeHumidity > 0 {
|
||||
|
||||
Image(systemName: "humidity")
|
||||
.font(.callout)
|
||||
|
|
@ -117,8 +111,7 @@ struct TelemetryLog: View {
|
|||
.font(.callout)
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 {
|
||||
if tel.barometricPressure > 0 {
|
||||
|
||||
Image(systemName: "barometer")
|
||||
.font(.callout)
|
||||
|
|
@ -129,7 +122,7 @@ struct TelemetryLog: View {
|
|||
.font(.callout)
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme680 {
|
||||
if tel.gasResistance > 0 {
|
||||
|
||||
Image(systemName: "aqi.medium")
|
||||
.font(.callout)
|
||||
|
|
@ -140,8 +133,7 @@ struct TelemetryLog: View {
|
|||
.font(.callout)
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.ina219 ||
|
||||
sensor == SensorTypes.ina260 {
|
||||
if tel.current > 0 {
|
||||
|
||||
Image(systemName: "directcurrent")
|
||||
.font(.callout)
|
||||
|
|
@ -185,7 +177,7 @@ struct TelemetryLog: View {
|
|||
|
||||
Spacer()
|
||||
Text("Device Metrics")
|
||||
.font(.title)
|
||||
.font(.title3)
|
||||
Spacer()
|
||||
}
|
||||
|
||||
|
|
@ -242,8 +234,6 @@ struct TelemetryLog: View {
|
|||
} else if tel.metricsType == 1 {
|
||||
|
||||
// Environment Metrics
|
||||
let sensor = SensorTypes(rawValue: Int(node.telemetryConfig?.environmentSensorType ?? 0))
|
||||
|
||||
let tempReadingType = (!(node.telemetryConfig?.environmentDisplayFahrenheit ?? true)) ? "°C" : "°F"
|
||||
|
||||
|
||||
|
|
@ -260,10 +250,7 @@ struct TelemetryLog: View {
|
|||
|
||||
HStack {
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 ||
|
||||
sensor == SensorTypes.mcp9808 {
|
||||
if tel.temperature > 0 {
|
||||
|
||||
Image(systemName: "thermometer")
|
||||
.font(.callout)
|
||||
|
|
@ -277,9 +264,7 @@ struct TelemetryLog: View {
|
|||
|
||||
HStack {
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 ||
|
||||
sensor == SensorTypes.shtc3 {
|
||||
if tel.relativeHumidity > 0 {
|
||||
|
||||
Image(systemName: "humidity")
|
||||
.font(.callout)
|
||||
|
|
@ -291,8 +276,7 @@ struct TelemetryLog: View {
|
|||
}
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.ina219 ||
|
||||
sensor == SensorTypes.ina260 {
|
||||
if tel.current > 0 {
|
||||
|
||||
HStack {
|
||||
|
||||
|
|
@ -317,8 +301,7 @@ struct TelemetryLog: View {
|
|||
}
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme280 ||
|
||||
sensor == SensorTypes.bme680 {
|
||||
if tel.barometricPressure > 0 {
|
||||
|
||||
HStack {
|
||||
|
||||
|
|
@ -332,7 +315,7 @@ struct TelemetryLog: View {
|
|||
}
|
||||
}
|
||||
|
||||
if sensor == SensorTypes.bme680 {
|
||||
if tel.gasResistance > 0 {
|
||||
|
||||
HStack {
|
||||
|
||||
|
|
|
|||
26
Meshtastic/Views/Onboarding.swift
Normal file
26
Meshtastic/Views/Onboarding.swift
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Onboarding.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 8/21/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct Onboarding: View {
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Text("🗺️ Set Your Region to Mesh and Message")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(.red)
|
||||
|
||||
Text("Your region is currently set to UNSET, please set your device to the appropriate region under Settings > LoRa, after you set your region your Meshtastic device will reboot.")
|
||||
.font(.callout)
|
||||
.padding()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
167
Meshtastic/Views/Settings/Config/BluetoothConfig.swift
Normal file
167
Meshtastic/Views/Settings/Config/BluetoothConfig.swift
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
//
|
||||
// BluetoothConfig.swift
|
||||
// Meshtastic Apple
|
||||
//
|
||||
// Copyright (c) Garth Vander Houwen 8/18/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct BluetoothConfig: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges = false
|
||||
|
||||
@State var enabled = true
|
||||
/// Determines the pairing strategy for the device
|
||||
@State var mode = 0
|
||||
|
||||
/// Specified pin for PairingMode.FixedPin
|
||||
@State var fixedPin = "123456"
|
||||
|
||||
let numberFormatter: NumberFormatter = {
|
||||
let formatter = NumberFormatter()
|
||||
formatter.numberStyle = .none
|
||||
return formatter
|
||||
}()
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Section(header: Text("Options")) {
|
||||
|
||||
Toggle(isOn: $enabled) {
|
||||
|
||||
Label("Enabled", systemImage: "antenna.radiowaves.left.and.right")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
|
||||
Picker("Pairing Mode", selection: $mode ) {
|
||||
ForEach(BluetoothModes.allCases) { bm in
|
||||
Text(bm.description)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
|
||||
if mode == 1 {
|
||||
|
||||
HStack {
|
||||
Label("Fixed PIN", systemImage: "wallet.pass")
|
||||
TextField("Fixed PIN", text: $fixedPin)
|
||||
.foregroundColor(.gray)
|
||||
.onChange(of: fixedPin, perform: { value in
|
||||
|
||||
let digitCount = fixedPin.utf8.count
|
||||
// Only mess with the value if it is too big
|
||||
if digitCount > 6 || digitCount < 6 {
|
||||
|
||||
fixedPin = "123456"
|
||||
}
|
||||
|
||||
if digitCount < 6 {
|
||||
|
||||
fixedPin = "123456"
|
||||
}
|
||||
})
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.keyboardType(.decimalPad)
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure?",
|
||||
isPresented: $isPresentingSaveConfirm
|
||||
) {
|
||||
Button("Save Bluetooth Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
var bc = Config.BluetoothConfig()
|
||||
bc.enabled = enabled
|
||||
bc.mode = BluetoothModes(rawValue: mode)?.protoEnumValue() ?? Config.BluetoothConfig.PairingMode.randomPin
|
||||
bc.fixedPin = UInt32(fixedPin) ?? 123456
|
||||
|
||||
let adminMessageId = bleManager.saveBluetoothConfig(config: bc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
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
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Display Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.enabled = node!.bluetoothConfig?.enabled ?? true
|
||||
self.mode = Int(node!.bluetoothConfig?.mode ?? 0)
|
||||
//self.fixedPin = (String(node!.bluetoothConfig?.fixedPin) ?? "123456")
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
}
|
||||
.onChange(of: enabled) { newEnabled in
|
||||
|
||||
if node != nil && node!.bluetoothConfig != nil {
|
||||
|
||||
if newEnabled != node!.bluetoothConfig!.enabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: mode) { newMode in
|
||||
|
||||
if node != nil && node!.bluetoothConfig != nil {
|
||||
|
||||
if newMode != node!.bluetoothConfig!.mode { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: fixedPin) { newFixedPin in
|
||||
|
||||
if node != nil && node!.bluetoothConfig != nil {
|
||||
|
||||
if newFixedPin != String(node!.bluetoothConfig!.fixedPin) { hasChanges = true }
|
||||
}
|
||||
}
|
||||
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
|
@ -6,46 +6,6 @@
|
|||
//
|
||||
import SwiftUI
|
||||
|
||||
// Default of 0 is Client
|
||||
enum DeviceRoles: Int, CaseIterable, Identifiable {
|
||||
|
||||
case client = 0
|
||||
case clientMute = 1
|
||||
case router = 2
|
||||
case routerClient = 3
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .client:
|
||||
return "Client (default) - App connected client."
|
||||
case .clientMute:
|
||||
return "Client Mute - Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh."
|
||||
case .router:
|
||||
return "Router - Mesh packets will prefer to be routed over this node. This node will not be used by client apps. The wifi/ble radios and the oled screen will be put to sleep."
|
||||
case .routerClient:
|
||||
return "Router Client - Mesh packets will prefer to be routed over this node. The Router Client can be used as both a Router and an app connected Client."
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.DeviceConfig.Role {
|
||||
|
||||
switch self {
|
||||
|
||||
case .client:
|
||||
return Config.DeviceConfig.Role.client
|
||||
case .clientMute:
|
||||
return Config.DeviceConfig.Role.clientMute
|
||||
case .router:
|
||||
return Config.DeviceConfig.Role.router
|
||||
case .routerClient:
|
||||
return Config.DeviceConfig.Role.routerClient
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DeviceConfig: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
|
|
@ -124,7 +84,7 @@ struct DeviceConfig: View {
|
|||
dc.serialDisabled = !serialEnabled
|
||||
dc.debugLogEnabled = debugLogEnabled
|
||||
|
||||
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveDeviceConfig(config: dc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
@ -153,7 +113,7 @@ struct DeviceConfig: View {
|
|||
) {
|
||||
Button("Erase all device settings?", role: .destructive) {
|
||||
|
||||
if !bleManager.sendFactoryReset(destNum: bleManager.connectedPeripheral.num, wantResponse: true) {
|
||||
if !bleManager.sendFactoryReset(destNum: bleManager.connectedPeripheral.num) {
|
||||
|
||||
print("Factory Reset Failed")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,119 +7,6 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
enum GpsFormats: Int, CaseIterable, Identifiable {
|
||||
|
||||
case gpsFormatDec = 0
|
||||
case gpsFormatDms = 1
|
||||
case gpsFormatUtm = 2
|
||||
case gpsFormatMgrs = 3
|
||||
case gpsFormatOlc = 4
|
||||
case gpsFormatOsgr = 5
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .gpsFormatDec:
|
||||
return "Decimal Degrees Format"
|
||||
case .gpsFormatDms:
|
||||
return "Degrees Minutes Seconds"
|
||||
case .gpsFormatUtm:
|
||||
return "Universal Transverse Mercator"
|
||||
case .gpsFormatMgrs:
|
||||
return "Military Grid Reference System"
|
||||
case .gpsFormatOlc:
|
||||
return "Open Location Code (aka Plus Codes)"
|
||||
case .gpsFormatOsgr:
|
||||
return "Ordnance Survey Grid Reference"
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.DisplayConfig.GpsCoordinateFormat {
|
||||
|
||||
switch self {
|
||||
|
||||
case .gpsFormatDec:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatDec
|
||||
case .gpsFormatDms:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatDms
|
||||
case .gpsFormatUtm:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatUtm
|
||||
case .gpsFormatMgrs:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatMgrs
|
||||
case .gpsFormatOlc:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatOlc
|
||||
case .gpsFormatOsgr:
|
||||
return Config.DisplayConfig.GpsCoordinateFormat.gpsFormatOsgr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default of 0 is One Minute
|
||||
enum ScreenOnIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 0
|
||||
case fifteenMinutes = 900
|
||||
case thirtyMinutes = 1800
|
||||
case oneHour = 3600
|
||||
case max = 31536000 // One Year
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
case .thirtyMinutes:
|
||||
return "Thirty Minutes"
|
||||
case .oneHour:
|
||||
return "One Hour"
|
||||
case .max:
|
||||
return "Always On"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default of 0 is off
|
||||
enum ScreenCarouselIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case off = 0
|
||||
case thirtySeconds = 30
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 600
|
||||
case fifteenMinutes = 900
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .off:
|
||||
return "Off"
|
||||
case .thirtySeconds:
|
||||
return "Thirty Seconds"
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DisplayConfig: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
|
|
@ -134,13 +21,14 @@ struct DisplayConfig: View {
|
|||
@State var screenOnSeconds = 0
|
||||
@State var screenCarouselInterval = 0
|
||||
@State var gpsFormat = 0
|
||||
@State var compassNorthTop = false
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
Section(header: Text("Timing")) {
|
||||
Section(header: Text("Device Screen")) {
|
||||
|
||||
Picker("Screen on for", selection: $screenOnSeconds ) {
|
||||
ForEach(ScreenOnIntervals.allCases) { soi in
|
||||
|
|
@ -161,8 +49,15 @@ struct DisplayConfig: View {
|
|||
|
||||
Text("Automatically toggles to the next page on the screen like a carousel, based the specified interval.")
|
||||
.font(.caption)
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
Toggle(isOn: $compassNorthTop) {
|
||||
|
||||
Label("Always point north", systemImage: "location.north.circle")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
Text("The compass heading on the screen outside of the circle will always point north.")
|
||||
.font(.caption)
|
||||
|
||||
}
|
||||
Section(header: Text("Format")) {
|
||||
Picker("GPS Format", selection: $gpsFormat ) {
|
||||
|
|
@ -203,8 +98,9 @@ struct DisplayConfig: View {
|
|||
dc.gpsFormat = GpsFormats(rawValue: gpsFormat)!.protoEnumValue()
|
||||
dc.screenOnSecs = UInt32(screenOnSeconds)
|
||||
dc.autoScreenCarouselSecs = UInt32(screenCarouselInterval)
|
||||
dc.compassNorthTop = compassNorthTop
|
||||
|
||||
let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveDisplayConfig(config: dc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
@ -234,6 +130,7 @@ struct DisplayConfig: View {
|
|||
self.gpsFormat = Int(node!.displayConfig?.gpsFormat ?? 0)
|
||||
self.screenOnSeconds = Int(node!.displayConfig?.screenOnSeconds ?? 0)
|
||||
self.screenCarouselInterval = Int(node!.displayConfig?.screenCarouselInterval ?? 0)
|
||||
self.compassNorthTop = node!.displayConfig?.compassNorthTop ?? false
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
|
|
@ -252,6 +149,13 @@ struct DisplayConfig: View {
|
|||
if newCarouselSecs != node!.displayConfig!.screenCarouselInterval { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: compassNorthTop) { newCompassNorthTop in
|
||||
|
||||
if node != nil && node!.displayConfig != nil {
|
||||
|
||||
if newCompassNorthTop != node!.displayConfig!.compassNorthTop { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: gpsFormat) { newGpsFormat in
|
||||
|
||||
if node != nil && node!.displayConfig != nil {
|
||||
|
|
|
|||
|
|
@ -7,179 +7,6 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
enum RegionCodes : Int, CaseIterable, Identifiable {
|
||||
|
||||
case unset = 0
|
||||
case us = 1
|
||||
case eu433 = 2
|
||||
case eu868 = 3
|
||||
case cn = 4
|
||||
case jp = 5
|
||||
case anz = 6
|
||||
case kr = 7
|
||||
case tw = 8
|
||||
case ru = 9
|
||||
case `in` = 10
|
||||
case nz865 = 11
|
||||
case th = 12
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
case .unset:
|
||||
return "Please set a region"
|
||||
case .us:
|
||||
return "United States"
|
||||
case .eu433:
|
||||
return "European Union 433mhz"
|
||||
case .eu868:
|
||||
return "European Union 868mhz"
|
||||
case .cn:
|
||||
return "China"
|
||||
case .jp:
|
||||
return "Japan"
|
||||
case .anz:
|
||||
return "Australia / New Zealand"
|
||||
case .kr:
|
||||
return "Korea"
|
||||
case .tw:
|
||||
return "Taiwan"
|
||||
case .ru:
|
||||
return "Russia"
|
||||
case .in:
|
||||
return "India"
|
||||
case .nz865:
|
||||
return "New Zealand 865mhz"
|
||||
case .th:
|
||||
return "Thailand"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func protoEnumValue() -> Config.LoRaConfig.RegionCode {
|
||||
|
||||
switch self {
|
||||
|
||||
case .unset:
|
||||
return Config.LoRaConfig.RegionCode.unset
|
||||
case .us:
|
||||
return Config.LoRaConfig.RegionCode.us
|
||||
case .eu433:
|
||||
return Config.LoRaConfig.RegionCode.eu433
|
||||
case .eu868:
|
||||
return Config.LoRaConfig.RegionCode.eu868
|
||||
case .cn:
|
||||
return Config.LoRaConfig.RegionCode.cn
|
||||
case .jp:
|
||||
return Config.LoRaConfig.RegionCode.jp
|
||||
case .anz:
|
||||
return Config.LoRaConfig.RegionCode.anz
|
||||
case .kr:
|
||||
return Config.LoRaConfig.RegionCode.kr
|
||||
case .tw:
|
||||
return Config.LoRaConfig.RegionCode.tw
|
||||
case .ru:
|
||||
return Config.LoRaConfig.RegionCode.ru
|
||||
case .in:
|
||||
return Config.LoRaConfig.RegionCode.in
|
||||
case .nz865:
|
||||
return Config.LoRaConfig.RegionCode.nz865
|
||||
case .th:
|
||||
return Config.LoRaConfig.RegionCode.th
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ModemPresets : Int, CaseIterable, Identifiable {
|
||||
|
||||
case LongFast = 0
|
||||
case LongSlow = 1
|
||||
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:
|
||||
return "Long Range - Fast"
|
||||
case .LongSlow:
|
||||
return "Long Range - Slow"
|
||||
case .VLongSlow:
|
||||
return "Very Long Range - Slow"
|
||||
case .MedSlow:
|
||||
return "Medium Range - Slow"
|
||||
case .MedFast:
|
||||
return "Medium Range - Fast"
|
||||
case .ShortSlow:
|
||||
return "Short Range - Slow"
|
||||
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 .VLongSlow:
|
||||
return Config.LoRaConfig.ModemPreset.vlongSlow
|
||||
case .MedSlow:
|
||||
return Config.LoRaConfig.ModemPreset.medSlow
|
||||
case .MedFast:
|
||||
return Config.LoRaConfig.ModemPreset.medFast
|
||||
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 = 0
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LoRaConfig: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
|
|
@ -261,7 +88,7 @@ struct LoRaConfig: View {
|
|||
lc.region = RegionCodes(rawValue: region)!.protoEnumValue()
|
||||
lc.modemPreset = ModemPresets(rawValue: modemPreset)!.protoEnumValue()
|
||||
|
||||
let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveLoRaConfig(config: lc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ struct CannedMessagesConfig: View {
|
|||
|
||||
Section(header: Text("Key Mapping")) {
|
||||
|
||||
Picker("inputbrokerEventCw", selection: $inputbrokerEventCw ) {
|
||||
Picker("Clockwise Rotary Event", selection: $inputbrokerEventCw ) {
|
||||
ForEach(InputEventChars.allCases) { iec in
|
||||
Text(iec.description)
|
||||
}
|
||||
|
|
@ -250,7 +250,7 @@ struct CannedMessagesConfig: View {
|
|||
.padding(.top, 10)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Picker("inputbrokerEventCcw", selection: $inputbrokerEventCcw ) {
|
||||
Picker("Counter Clockwise Rotary Event", selection: $inputbrokerEventCcw ) {
|
||||
ForEach(InputEventChars.allCases) { iec in
|
||||
Text(iec.description)
|
||||
}
|
||||
|
|
@ -259,7 +259,7 @@ struct CannedMessagesConfig: View {
|
|||
.padding(.top, 10)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Picker("inputBrokerEventPress", selection: $inputbrokerEventPress ) {
|
||||
Picker("Encoder Press Event", selection: $inputbrokerEventPress ) {
|
||||
ForEach(InputEventChars.allCases) { iec in
|
||||
Text(iec.description)
|
||||
}
|
||||
|
|
@ -320,7 +320,7 @@ struct CannedMessagesConfig: View {
|
|||
cmc.inputbrokerEventCcw = InputEventChars(rawValue: inputbrokerEventCcw)!.protoEnumValue()
|
||||
cmc.inputbrokerEventPress = InputEventChars(rawValue: inputbrokerEventPress)!.protoEnumValue()
|
||||
|
||||
let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveCannedMessageModuleConfig(config: cmc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
// Should show a saved successfully alert once I know that to be true
|
||||
|
|
@ -376,6 +376,9 @@ struct CannedMessagesConfig: View {
|
|||
// RAK Rotary Encoder
|
||||
updown1Enabled = true
|
||||
rotary1Enabled = false
|
||||
inputbrokerPinA = 4
|
||||
inputbrokerPinB = 10
|
||||
inputbrokerPinPress = 3
|
||||
inputbrokerEventCw = InputEventChars.keyUp.rawValue
|
||||
inputbrokerEventCcw = InputEventChars.keyDown.rawValue
|
||||
inputbrokerEventPress = InputEventChars.keySelect.rawValue
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ struct ExternalNotificationConfig: View {
|
|||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node!.myInfo?.hasWifi ?? false))
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
|
|
@ -159,7 +159,7 @@ struct ExternalNotificationConfig: View {
|
|||
enc.output = UInt32(output)
|
||||
enc.outputMs = UInt32(outputMilliseconds)
|
||||
|
||||
let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveExternalNotificationModuleConfig(config: enc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0{
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ struct RangeTestConfig: View {
|
|||
rtc.save = save
|
||||
rtc.sender = UInt32(sender)
|
||||
|
||||
let adminMessageId = bleManager.saveRangeTestModuleConfig(config: rtc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveRangeTestModuleConfig(config: rtc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ struct SerialConfig: View {
|
|||
sc.timeout = UInt32(timeout)
|
||||
sc.mode = SerialModeTypes(rawValue: mode)!.protoEnumValue()
|
||||
|
||||
let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
|
|||
|
|
@ -6,74 +6,6 @@
|
|||
//
|
||||
import SwiftUI
|
||||
|
||||
enum SensorTypes: Int, CaseIterable, Identifiable {
|
||||
|
||||
/// No external telemetry sensor explicitly set
|
||||
case notSet = 0
|
||||
|
||||
/// High accuracy temperature, pressure, humidity
|
||||
case bme280 = 6
|
||||
|
||||
/// High accuracy temperature, pressure, humidity, and air resistance
|
||||
case bme680 = 7
|
||||
|
||||
/// Very high accuracy temperature
|
||||
case mcp9808 = 8
|
||||
|
||||
/// Moderate accuracy temperature and humidity
|
||||
case shtc3 = 9
|
||||
|
||||
/// Moderate accuracy current and voltage
|
||||
case ina260 = 10
|
||||
|
||||
/// Moderate accuracy current and voltage
|
||||
case ina219 = 11
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .notSet:
|
||||
return "Not Set"
|
||||
case .bme280:
|
||||
return "BME280 - Temp, pressure & humidity"
|
||||
case .bme680:
|
||||
return "BME680 - Temp, pressure, humidity & air resistance"
|
||||
case .mcp9808:
|
||||
return "MCP9808 - Temperature"
|
||||
case .shtc3:
|
||||
return "SHTC3 - Temperature & humidity"
|
||||
case .ina260:
|
||||
return "INA260 - Current & voltage"
|
||||
case .ina219:
|
||||
return "INA219 - Current & voltage"
|
||||
}
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> TelemetrySensorType {
|
||||
|
||||
switch self {
|
||||
|
||||
|
||||
case .notSet:
|
||||
return TelemetrySensorType.notSet
|
||||
case .bme280:
|
||||
return TelemetrySensorType.bme280
|
||||
case .bme680:
|
||||
return TelemetrySensorType.bme680
|
||||
case .mcp9808:
|
||||
return TelemetrySensorType.mcp9808
|
||||
case .shtc3:
|
||||
return TelemetrySensorType.shtc3
|
||||
case .ina260:
|
||||
return TelemetrySensorType.ina260
|
||||
case .ina219:
|
||||
return TelemetrySensorType.ina219
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default of 0 is off
|
||||
enum ErrorRecoveryIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
|
|
@ -188,11 +120,8 @@ struct TelemetryConfig: View {
|
|||
@State var deviceUpdateInterval = 0
|
||||
@State var environmentUpdateInterval = 0
|
||||
@State var environmentMeasurementEnabled = false
|
||||
@State var environmentSensorType = 0
|
||||
@State var environmentScreenEnabled = false
|
||||
@State var environmentDisplayFahrenheit = false
|
||||
@State var environmentRecoveryInterval = 0
|
||||
@State var environmentReadErrorCountThreshold = 0
|
||||
|
||||
var body: some View {
|
||||
|
||||
|
|
@ -222,6 +151,9 @@ struct TelemetryConfig: View {
|
|||
}
|
||||
|
||||
Section(header: Text("Sensor Options")) {
|
||||
|
||||
Text("I2C Connected sensors will be detected automatically. Supported sensors are BMP280, BME280, BME680, MCP9808, INA219 and INA260.")
|
||||
.font(.caption)
|
||||
|
||||
Toggle(isOn: $environmentMeasurementEnabled) {
|
||||
|
||||
|
|
@ -229,13 +161,6 @@ struct TelemetryConfig: View {
|
|||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
Picker("Sensor", selection: $environmentSensorType ) {
|
||||
ForEach(SensorTypes.allCases) { st in
|
||||
Text(st.description)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
|
||||
Toggle(isOn: $environmentScreenEnabled) {
|
||||
|
||||
Label("Show on device screen", systemImage: "display")
|
||||
|
|
@ -247,37 +172,6 @@ struct TelemetryConfig: View {
|
|||
Label("Display Fahrenheit", systemImage: "thermometer")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
}
|
||||
|
||||
Section(header: Text("Errors")) {
|
||||
|
||||
Picker("Error Count Threshold", selection: $environmentReadErrorCountThreshold) {
|
||||
ForEach(0..<101) {
|
||||
|
||||
if $0 == 0 {
|
||||
|
||||
Text("Unset")
|
||||
|
||||
} else if $0 % 5 == 0 {
|
||||
|
||||
Text("\($0)")
|
||||
}
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
Text("Sometimes sensor reads can fail. If this happens, we will retry a configurable number of attempts, each attempt will be delayed by the minimum required refresh rate for that sensor")
|
||||
.font(.caption)
|
||||
|
||||
Picker("Error Recovery Interval", selection: $environmentRecoveryInterval ) {
|
||||
ForEach(ErrorRecoveryIntervals.allCases) { eri in
|
||||
Text(eri.description)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
|
||||
Text("Sometimes we can end up with more failures than our error count threshold. In this case, we will stop trying to read from the sensor for a while. Wait this long until trying to read from the sensor again")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
|
@ -306,13 +200,10 @@ struct TelemetryConfig: View {
|
|||
tc.deviceUpdateInterval = UInt32(deviceUpdateInterval)
|
||||
tc.environmentUpdateInterval = UInt32(environmentUpdateInterval)
|
||||
tc.environmentMeasurementEnabled = environmentMeasurementEnabled
|
||||
tc.environmentSensorType = SensorTypes(rawValue: environmentSensorType)!.protoEnumValue()
|
||||
tc.environmentScreenEnabled = environmentScreenEnabled
|
||||
tc.environmentDisplayFahrenheit = environmentDisplayFahrenheit
|
||||
tc.environmentRecoveryInterval = UInt32(environmentRecoveryInterval)
|
||||
tc.environmentReadErrorCountThreshold = UInt32(environmentReadErrorCountThreshold)
|
||||
|
||||
let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveTelemetryModuleConfig(config: tc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
@ -338,16 +229,11 @@ struct TelemetryConfig: View {
|
|||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.deviceUpdateInterval = Int(node!.telemetryConfig?.deviceUpdateInterval ?? 0)
|
||||
self.environmentUpdateInterval = Int(node!.telemetryConfig?.environmentUpdateInterval ?? 0)
|
||||
self.environmentMeasurementEnabled = node!.telemetryConfig?.environmentMeasurementEnabled ?? false
|
||||
self.environmentSensorType = Int(node!.telemetryConfig?.environmentSensorType ?? 0)
|
||||
self.environmentScreenEnabled = node!.telemetryConfig?.environmentScreenEnabled ?? false
|
||||
self.environmentDisplayFahrenheit = node!.telemetryConfig?.environmentDisplayFahrenheit ?? false
|
||||
self.environmentRecoveryInterval = Int(node!.telemetryConfig?.environmentRecoveryInterval ?? 0)
|
||||
self.environmentReadErrorCountThreshold = Int(node!.telemetryConfig?.environmentReadErrorCountThreshold ?? 0)
|
||||
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
|
|
@ -373,13 +259,6 @@ struct TelemetryConfig: View {
|
|||
if newEnvEnabled != node!.telemetryConfig!.environmentMeasurementEnabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentSensorType) { newEnvSensorType in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvSensorType != node!.telemetryConfig!.environmentSensorType { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentScreenEnabled) { newEnvScreenEnabled in
|
||||
|
||||
if node!.telemetryConfig != nil {
|
||||
|
|
@ -394,20 +273,6 @@ struct TelemetryConfig: View {
|
|||
if newEnvDisplayF != node!.telemetryConfig!.environmentDisplayFahrenheit { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentRecoveryInterval) { newEnvRecoveryInterval in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvRecoveryInterval != node!.telemetryConfig!.environmentRecoveryInterval { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: environmentReadErrorCountThreshold) { newEnvReadErrorCountThreshold in
|
||||
|
||||
if node != nil && node!.telemetryConfig != nil {
|
||||
|
||||
if newEnvReadErrorCountThreshold != node!.telemetryConfig!.environmentReadErrorCountThreshold { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,71 +7,6 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
enum GpsUpdateIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case thirtySeconds = 0
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 600
|
||||
case fifteenMinutes = 900
|
||||
case thirtyMinutes = 1800
|
||||
case oneHour = 3600
|
||||
case maxInt32 = 2147483647
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .thirtySeconds:
|
||||
return "Thirty Seconds"
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
case .thirtyMinutes:
|
||||
return "Thirty Minutes"
|
||||
case .oneHour:
|
||||
return "One Hour"
|
||||
case .maxInt32:
|
||||
return "On Boot Only"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum GpsAttemptTimes: Int, CaseIterable, Identifiable {
|
||||
|
||||
case thirtySeconds = 0
|
||||
case oneMinute = 60
|
||||
case fiveMinutes = 300
|
||||
case tenMinutes = 600
|
||||
case fifteenMinutes = 900
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
get {
|
||||
switch self {
|
||||
|
||||
case .thirtySeconds:
|
||||
return "Thirty Seconds"
|
||||
case .oneMinute:
|
||||
return "One Minute"
|
||||
case .fiveMinutes:
|
||||
return "Five Minutes"
|
||||
case .tenMinutes:
|
||||
return "Ten Minutes"
|
||||
case .fifteenMinutes:
|
||||
return "Fifteen Minutes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum PositionBroadcastIntervals: Int, CaseIterable, Identifiable {
|
||||
|
||||
case thirtySeconds = 30
|
||||
|
|
@ -323,7 +258,7 @@ struct PositionConfig: View {
|
|||
pc.gpsAttemptTime = UInt32(gpsAttemptTime)
|
||||
pc.positionBroadcastSecs = UInt32(positionBroadcastSeconds)
|
||||
|
||||
let adminMessageId = bleManager.savePositionConfig(config: pc, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.savePositionConfig(config: pc, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0{
|
||||
|
||||
|
|
@ -370,6 +305,13 @@ struct PositionConfig: View {
|
|||
if newSmartPosition != node!.positionConfig!.smartPositionEnabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: positionBroadcastSeconds) { newPositionBroadcastSeconds in
|
||||
|
||||
if node != nil && node!.positionConfig != nil {
|
||||
|
||||
if newPositionBroadcastSeconds != node!.positionConfig!.positionBroadcastSeconds { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: deviceGpsEnabled) { newDeviceGps in
|
||||
|
||||
if node != nil && node!.positionConfig != nil {
|
||||
|
|
|
|||
202
Meshtastic/Views/Settings/Config/WiFiConfig.swift
Normal file
202
Meshtastic/Views/Settings/Config/WiFiConfig.swift
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
//
|
||||
// WiFiConfig.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright (c) Garth Vander Houwen 8/1/2022
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct WiFiConfig: View {
|
||||
|
||||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
|
||||
var node: NodeInfoEntity?
|
||||
|
||||
@State private var isPresentingSaveConfirm: Bool = false
|
||||
@State var initialLoad: Bool = true
|
||||
@State var hasChanges: Bool = false
|
||||
|
||||
@State var enabled = false
|
||||
@State var ssid = ""
|
||||
@State var password = ""
|
||||
@State var mode = 0
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack {
|
||||
|
||||
Form {
|
||||
|
||||
Text("Enabling WiFi will disable the bluetooth connection to the app.")
|
||||
.font(.title3)
|
||||
|
||||
Section(header: Text("Options")) {
|
||||
|
||||
Toggle(isOn: $enabled) {
|
||||
|
||||
Label("Enabled", systemImage: "wifi")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
||||
|
||||
Picker("Mode", selection: $mode ) {
|
||||
ForEach(WiFiModes.allCases) { lu in
|
||||
Text(lu.description)
|
||||
}
|
||||
}
|
||||
.pickerStyle(DefaultPickerStyle())
|
||||
|
||||
}
|
||||
Section(header: Text("SSID & Password")) {
|
||||
|
||||
HStack {
|
||||
Label("SSID", systemImage: "network")
|
||||
TextField("SSID", text: $ssid)
|
||||
.foregroundColor(.gray)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.onChange(of: ssid, perform: { value in
|
||||
|
||||
let totalBytes = ssid.utf8.count
|
||||
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 32 {
|
||||
|
||||
let firstNBytes = Data(ssid.utf8.prefix(32))
|
||||
|
||||
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
|
||||
|
||||
// Set the shortName back to the last place where it was the right size
|
||||
ssid = maxBytesString
|
||||
}
|
||||
}
|
||||
})
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.keyboardType(.default)
|
||||
|
||||
|
||||
HStack {
|
||||
Label("Password", systemImage: "wallet.pass")
|
||||
TextField("Password", text: $password)
|
||||
.foregroundColor(.gray)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
.onChange(of: password, perform: { value in
|
||||
|
||||
let totalBytes = password.utf8.count
|
||||
|
||||
// Only mess with the value if it is too big
|
||||
if totalBytes > 63 {
|
||||
|
||||
let firstNBytes = Data(password.utf8.prefix(63))
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.keyboardType(.default)
|
||||
}
|
||||
}
|
||||
.disabled(!(node != nil && node!.myInfo?.hasWifi ?? false))
|
||||
|
||||
Button {
|
||||
|
||||
isPresentingSaveConfirm = true
|
||||
|
||||
} label: {
|
||||
|
||||
Label("Save", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil || !hasChanges)
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
.confirmationDialog(
|
||||
|
||||
"Are you sure?",
|
||||
isPresented: $isPresentingSaveConfirm
|
||||
) {
|
||||
Button("Save WiFI Config to \(bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown")?") {
|
||||
|
||||
var wifi = Config.WiFiConfig()
|
||||
wifi.enabled = self.enabled
|
||||
wifi.ssid = self.ssid
|
||||
wifi.psk = self.password
|
||||
wifi.mode = WiFiModes(rawValue: self.mode)?.protoEnumValue() ?? WiFiModes.client.protoEnumValue()
|
||||
|
||||
let adminMessageId = bleManager.saveWiFiConfig(config: wifi, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
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
|
||||
self.hasChanges = false
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("WiFi Config")
|
||||
.navigationBarItems(trailing:
|
||||
|
||||
ZStack {
|
||||
|
||||
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "????")
|
||||
})
|
||||
.onAppear {
|
||||
|
||||
if self.initialLoad{
|
||||
|
||||
self.bleManager.context = context
|
||||
|
||||
self.enabled = (node!.wiFiConfig?.enabled ?? false)
|
||||
self.ssid = node!.wiFiConfig?.ssid ?? ""
|
||||
self.password = node!.wiFiConfig?.password ?? ""
|
||||
self.mode = Int(node!.wiFiConfig?.mode ?? 0)
|
||||
|
||||
self.hasChanges = false
|
||||
self.initialLoad = false
|
||||
}
|
||||
}
|
||||
.onChange(of: enabled) { newEnabled in
|
||||
|
||||
if node != nil && node!.wiFiConfig != nil {
|
||||
|
||||
if newEnabled != node!.wiFiConfig!.enabled { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: ssid) { newSsid in
|
||||
|
||||
if node != nil && node!.wiFiConfig != nil {
|
||||
|
||||
if newSsid != node!.wiFiConfig!.ssid { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: password) { newPassword in
|
||||
|
||||
if node != nil && node!.wiFiConfig != nil {
|
||||
|
||||
if newPassword != node!.wiFiConfig!.password { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: mode) { newMode in
|
||||
|
||||
if node != nil && node!.wiFiConfig != nil {
|
||||
|
||||
if newMode != node!.wiFiConfig!.mode { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
|
@ -69,6 +69,18 @@ struct Settings: View {
|
|||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
NavigationLink() {
|
||||
|
||||
BluetoothConfig(node: nodes.first(where: { $0.num == connectedNodeNum }))
|
||||
} label: {
|
||||
|
||||
Image(systemName: "antenna.radiowaves.left.and.right")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
|
||||
Text("Bluetooth (BLE)")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
NavigationLink {
|
||||
DeviceConfig(node: nodes.first(where: { $0.num == connectedNodeNum }))
|
||||
} label: {
|
||||
|
|
@ -100,6 +112,17 @@ struct Settings: View {
|
|||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
NavigationLink {
|
||||
WiFiConfig(node: nodes.first(where: { $0.num == connectedNodeNum }))
|
||||
} label: {
|
||||
|
||||
Image(systemName: "wifi")
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
|
||||
Text("WiFi (ESP32 Only)")
|
||||
}
|
||||
.disabled(bleManager.connectedPeripheral == nil)
|
||||
|
||||
Text("Default settings values are prefered as they consume no bandwidth when sent over the mesh.")
|
||||
.font(.caption2)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
|
@ -193,8 +216,7 @@ struct Settings: View {
|
|||
|
||||
// Not Implemented:
|
||||
// Store Forward Config - Not Working, TBEAM Only
|
||||
// WiFi Config - Would break connection to device
|
||||
// MQTT Config - Part of WiFi
|
||||
// MQTT Config - Can do from WebUI once WiFi is enabled
|
||||
}
|
||||
.onAppear {
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ struct ShareChannel: View {
|
|||
)
|
||||
Spacer()
|
||||
Text("Channel Name (Long/Slow)").font(.title)
|
||||
Text(String(node!.myInfo!.maxChannels))
|
||||
Spacer()
|
||||
}
|
||||
.frame(width: bounds.size.width, height: bounds.size.height)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,17 @@ struct UserConfig: View {
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
.keyboardType(.default)
|
||||
.disableAutocorrection(true)
|
||||
Text("Long name can be up to 36 bytes long.")
|
||||
.font(.caption)
|
||||
|
||||
HStack {
|
||||
Label("Short Name", systemImage: "circlebadge.fill")
|
||||
TextField("Long Name", text: $shortName)
|
||||
.foregroundColor(.gray)
|
||||
.onChange(of: shortName, perform: { value in
|
||||
|
||||
let totalBytes = shortName.utf8.count
|
||||
|
|
@ -66,16 +77,6 @@ struct UserConfig: View {
|
|||
})
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.keyboardType(.default)
|
||||
.disableAutocorrection(true)
|
||||
Text("Long name can be up to 36 bytes long.")
|
||||
.font(.caption)
|
||||
|
||||
HStack {
|
||||
Label("Short Name", systemImage: "circlebadge.fill")
|
||||
TextField("Long Name", text: $shortName)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.keyboardType(.asciiCapable)
|
||||
.disableAutocorrection(true)
|
||||
Text("The short name is used in maps and messaging and will be appended to the last 4 of the device MAC address to set the device's BLE Name. It can be up to 4 bytes long.")
|
||||
|
|
@ -112,7 +113,7 @@ struct UserConfig: View {
|
|||
u.shortName = shortName
|
||||
u.longName = longName
|
||||
|
||||
let adminMessageId = bleManager.saveUser(config: u, fromUser: node!.user!, toUser: node!.user!, wantResponse: true)
|
||||
let adminMessageId = bleManager.saveUser(config: u, fromUser: node!.user!, toUser: node!.user!)
|
||||
|
||||
if adminMessageId > 0 {
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ fi
|
|||
pdir=$(realpath "../Meshtastic-protobufs")
|
||||
sdir=$(realpath "./Meshtastic/Protobufs")
|
||||
echo "pdir:$pdir sdir:$sdir"
|
||||
pfiles="admin.proto apponly.proto cannedmessages.proto channel.proto config.proto deviceonly.proto localonly.proto mesh.proto module_config.proto mqtt.proto portnums.proto remote_hardware.proto
|
||||
pfiles="admin.proto apponly.proto cannedmessages.proto channel.proto config.proto device_metadata.proto deviceonly.proto localonly.proto mesh.proto module_config.proto mqtt.proto portnums.proto remote_hardware.proto
|
||||
storeforward.proto telemetry.proto"
|
||||
for pf in $pfiles
|
||||
do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue