Merge branch '2.5.19' into AppIntents
9
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
|
@ -52,3 +52,12 @@ body:
|
|||
attributes:
|
||||
label: Additional comments
|
||||
description: Is there anything else that's important for the team to know?
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://meshtastic.org/docs/legal/conduct/).
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
|
|
|||
10
.github/ISSUE_TEMPLATE/feature.yml
vendored
|
|
@ -31,7 +31,7 @@ body:
|
|||
label: Participation
|
||||
description: (Features without participation go to the backlog.)
|
||||
options:
|
||||
- label: I am willing to sponsor this feature.
|
||||
- label: I am willing to pay to sponsor this feature.
|
||||
required: false
|
||||
- label: I am willing to submit a pull request for this feature.
|
||||
required: false
|
||||
|
|
@ -39,3 +39,11 @@ body:
|
|||
attributes:
|
||||
label: Additional comments
|
||||
description: Is there anything else that's important for the team to know?
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our [Code of Conduct](https://meshtastic.org/docs/legal/conduct/).
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
|
|
|||
22
.github/workflows/stale.yml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
name: process stale Issues and PR's
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 6 * * *
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
stale_issues:
|
||||
name: Close Stale Issues
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Stale PR+Issues
|
||||
uses: actions/stale@v9.0.0
|
||||
with:
|
||||
exempt-issue-labels: 'has sponsor,needs sponsor,help wanted,backlog,security issue'
|
||||
exempt-pr-labels: 'has sponsor,needs sponsor,help wanted,backlog,security issue'
|
||||
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
## User settings
|
||||
xcuserdata/
|
||||
SupportingFiles/
|
||||
|
||||
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
|
||||
*.xcscmblueprint
|
||||
|
|
|
|||
23080
Localizable.xcstrings
|
|
@ -7,6 +7,13 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
231B3F212D087A4C0069A07D /* MetricTableColumn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231B3F202D087A4C0069A07D /* MetricTableColumn.swift */; };
|
||||
231B3F222D087A4C0069A07D /* MetricsColumnList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231B3F1F2D087A4C0069A07D /* MetricsColumnList.swift */; };
|
||||
231B3F252D087C3C0069A07D /* EnvironmentDefaultColumns.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231B3F242D087C3C0069A07D /* EnvironmentDefaultColumns.swift */; };
|
||||
231B3F272D0885240069A07D /* MetricsColumnDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231B3F262D0885240069A07D /* MetricsColumnDetail.swift */; };
|
||||
2373AE132D0A216C0086C749 /* MetricsChartSeries.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2373AE122D0A216C0086C749 /* MetricsChartSeries.swift */; };
|
||||
2373AE152D0A24930086C749 /* MetricsSeriesList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2373AE142D0A24930086C749 /* MetricsSeriesList.swift */; };
|
||||
2373AE172D0A26620086C749 /* EnviornmentDefaultSeries.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2373AE162D0A26620086C749 /* EnviornmentDefaultSeries.swift */; };
|
||||
251926852C3BA97800249DF5 /* FavoriteNodeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 251926842C3BA97800249DF5 /* FavoriteNodeButton.swift */; };
|
||||
251926872C3BAE2200249DF5 /* NodeAlertsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 251926862C3BAE2200249DF5 /* NodeAlertsButton.swift */; };
|
||||
2519268A2C3BB1B200249DF5 /* ExchangePositionsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 251926892C3BB1B200249DF5 /* ExchangePositionsButton.swift */; };
|
||||
|
|
@ -30,6 +37,8 @@
|
|||
6DA39D8E2A92DC52007E311C /* MeshtasticAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DA39D8D2A92DC52007E311C /* MeshtasticAppDelegate.swift */; };
|
||||
6DEDA55A2A957B8E00321D2E /* DetectionSensorLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEDA5592A957B8E00321D2E /* DetectionSensorLog.swift */; };
|
||||
6DEDA55C2A9592F900321D2E /* MessageEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEDA55B2A9592F900321D2E /* MessageEntityExtension.swift */; };
|
||||
8D3F8A3F2D44BB02009EAAA4 /* PowerMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D3F8A3E2D44BB02009EAAA4 /* PowerMetrics.swift */; };
|
||||
8D3F8A412D44C2A6009EAAA4 /* PowerMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */; };
|
||||
B399E8A42B6F486400E4488E /* RetryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B399E8A32B6F486400E4488E /* RetryButton.swift */; };
|
||||
B3E905B12B71F7F300654D07 /* TextMessageField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E905B02B71F7F300654D07 /* TextMessageField.swift */; };
|
||||
BC47C2EF2CE0017D008245CA /* MessageNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */; };
|
||||
|
|
@ -174,7 +183,6 @@
|
|||
DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */; };
|
||||
DDC2E18F26CE25FE0042C5E4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */; };
|
||||
DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */; };
|
||||
DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC3B273283F411B00AC321C /* LastHeardText.swift */; };
|
||||
DDC4C9FF2A8D982900CE201C /* DetectionSensorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC4C9FE2A8D982900CE201C /* DetectionSensorConfig.swift */; };
|
||||
DDC4D568275499A500A4208E /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC4D567275499A500A4208E /* Persistence.swift */; };
|
||||
DDC94FC129CE063B0082EA6E /* BatteryLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC94FC029CE063B0082EA6E /* BatteryLevel.swift */; };
|
||||
|
|
@ -218,6 +226,7 @@
|
|||
DDDE5A1129AFE69700490C6C /* MeshActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDE5A0F29AFE69700490C6C /* MeshActivityAttributes.swift */; };
|
||||
DDDE5A1329AFEAB900490C6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDDE5A1229AFEAB900490C6C /* Assets.xcassets */; };
|
||||
DDDE5A1429AFEAB900490C6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDDE5A1229AFEAB900490C6C /* Assets.xcassets */; };
|
||||
DDDFE73F2D0D48FF0044463C /* IgnoreNodeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDFE73E2D0D48FF0044463C /* IgnoreNodeButton.swift */; };
|
||||
DDE0F7C5295F77B700B8AAB3 /* AppSettingsEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE0F7C4295F77B700B8AAB3 /* AppSettingsEnums.swift */; };
|
||||
DDE5B4042B2279A700FCDD05 /* TraceRouteLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE5B4032B2279A700FCDD05 /* TraceRouteLog.swift */; };
|
||||
DDE9659C2B1C3B6A00531070 /* RouteRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE9659B2B1C3B6A00531070 /* RouteRecorder.swift */; };
|
||||
|
|
@ -261,6 +270,13 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
231B3F1F2D087A4C0069A07D /* MetricsColumnList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricsColumnList.swift; sourceTree = "<group>"; };
|
||||
231B3F202D087A4C0069A07D /* MetricTableColumn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricTableColumn.swift; sourceTree = "<group>"; };
|
||||
231B3F242D087C3C0069A07D /* EnvironmentDefaultColumns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentDefaultColumns.swift; sourceTree = "<group>"; };
|
||||
231B3F262D0885240069A07D /* MetricsColumnDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricsColumnDetail.swift; sourceTree = "<group>"; };
|
||||
2373AE122D0A216C0086C749 /* MetricsChartSeries.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricsChartSeries.swift; sourceTree = "<group>"; };
|
||||
2373AE142D0A24930086C749 /* MetricsSeriesList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricsSeriesList.swift; sourceTree = "<group>"; };
|
||||
2373AE162D0A26620086C749 /* EnviornmentDefaultSeries.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnviornmentDefaultSeries.swift; sourceTree = "<group>"; };
|
||||
251926842C3BA97800249DF5 /* FavoriteNodeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteNodeButton.swift; sourceTree = "<group>"; };
|
||||
251926862C3BAE2200249DF5 /* NodeAlertsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeAlertsButton.swift; sourceTree = "<group>"; };
|
||||
251926892C3BB1B200249DF5 /* ExchangePositionsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExchangePositionsButton.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -278,6 +294,9 @@
|
|||
6DA39D8D2A92DC52007E311C /* MeshtasticAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticAppDelegate.swift; sourceTree = "<group>"; };
|
||||
6DEDA5592A957B8E00321D2E /* DetectionSensorLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectionSensorLog.swift; sourceTree = "<group>"; };
|
||||
6DEDA55B2A9592F900321D2E /* MessageEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageEntityExtension.swift; sourceTree = "<group>"; };
|
||||
8D3F8A3D2D44B137009EAAA4 /* MeshtasticDataModelV 49.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 49.xcdatamodel"; sourceTree = "<group>"; };
|
||||
8D3F8A3E2D44BB02009EAAA4 /* PowerMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerMetrics.swift; sourceTree = "<group>"; };
|
||||
8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerMetricsLog.swift; sourceTree = "<group>"; };
|
||||
B399E8A32B6F486400E4488E /* RetryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetryButton.swift; sourceTree = "<group>"; };
|
||||
B3E905B02B71F7F300654D07 /* TextMessageField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextMessageField.swift; sourceTree = "<group>"; };
|
||||
BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageNodeIntent.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -291,6 +310,10 @@
|
|||
BCE2D3C42C7AE369008E6199 /* RestartNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestartNodeIntent.swift; sourceTree = "<group>"; };
|
||||
BCE2D3C62C7B0D0A008E6199 /* ShortcutsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsProvider.swift; sourceTree = "<group>"; };
|
||||
BCE2D3C82C7C377F008E6199 /* FactoryResetNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FactoryResetNodeIntent.swift; sourceTree = "<group>"; };
|
||||
D32BA3912D54617800714840 /* NodeInfoEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NodeInfoEntity+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
D32BA3922D54617800714840 /* NodeInfoEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NodeInfoEntity+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
D32BA3932D54617800714840 /* UserEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserEntity+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
D32BA3942D54617800714840 /* UserEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserEntity+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
D93068D22B8129510066FBC8 /* MessageContextMenuItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageContextMenuItems.swift; sourceTree = "<group>"; };
|
||||
D93068D42B812B700066FBC8 /* MessageDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageDestination.swift; sourceTree = "<group>"; };
|
||||
D93068D62B8146690066FBC8 /* MessageText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageText.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -420,6 +443,7 @@
|
|||
DD9A1A912BA2D2D3001E602E /* MeshtasticDataModelV 30.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 30.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DDA0B6B1294CDC55001356EC /* Channels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channels.swift; sourceTree = "<group>"; };
|
||||
DDA1C48D28DB49D3009933EC /* ChannelRoles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelRoles.swift; sourceTree = "<group>"; };
|
||||
DDA28B1B2D32C89200EF726F /* MeshtasticDataModelV 48.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 48.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshPackets.swift; sourceTree = "<group>"; };
|
||||
DDA951592BC6624100CEA535 /* TelemetryWeather.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelemetryWeather.swift; sourceTree = "<group>"; };
|
||||
DDA9515B2BC6631200CEA535 /* TelemetryEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryEnums.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -459,7 +483,6 @@
|
|||
DDC2E16526CE248F0042C5E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationHelper.swift; sourceTree = "<group>"; };
|
||||
DDC3B273283F411B00AC321C /* LastHeardText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastHeardText.swift; sourceTree = "<group>"; };
|
||||
DDC4C9FE2A8D982900CE201C /* DetectionSensorConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectionSensorConfig.swift; sourceTree = "<group>"; };
|
||||
DDC4CA012A8DAA3800CE201C /* MeshtasticDataModelV16.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV16.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDC4D567275499A500A4208E /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -469,6 +492,7 @@
|
|||
DDCDC69A29467643004C1DDA /* MeshtasticDataModelV3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV3.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserConfig.swift; sourceTree = "<group>"; };
|
||||
DDD28D372C0CD2670063CFA3 /* MeshtasticDataModelV 37.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 37.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DDD3A2B22D5127CF0045EB48 /* ci_pre_xcodebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_pre_xcodebuild.sh; sourceTree = "<group>"; };
|
||||
DDD43FE22A78C8900083A3E9 /* MqttClientProxyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MqttClientProxyManager.swift; sourceTree = "<group>"; };
|
||||
DDD5BB082C285DDC007E03CA /* AppLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLog.swift; sourceTree = "<group>"; };
|
||||
DDD5BB0A2C285E45007E03CA /* LogDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogDetail.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -512,6 +536,8 @@
|
|||
DDDE5A0F29AFE69700490C6C /* MeshActivityAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshActivityAttributes.swift; sourceTree = "<group>"; };
|
||||
DDDE5A1229AFEAB900490C6C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
DDDEE5E229DBE43E00A8E078 /* MeshtasticDataModelV11.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV11.xcdatamodel; sourceTree = "<group>"; };
|
||||
DDDFE73E2D0D48FF0044463C /* IgnoreNodeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IgnoreNodeButton.swift; sourceTree = "<group>"; };
|
||||
DDDFE7402D0D4A070044463C /* MeshtasticDataModelV 47.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 47.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DDE0F7C4295F77B700B8AAB3 /* AppSettingsEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsEnums.swift; sourceTree = "<group>"; };
|
||||
DDE5B4032B2279A700FCDD05 /* TraceRouteLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TraceRouteLog.swift; sourceTree = "<group>"; };
|
||||
DDE5B4052B227E3200FCDD05 /* TraceRouteEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TraceRouteEntityExtension.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -558,9 +584,31 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
231B3F1E2D0879BC0069A07D /* Metrics Visualization */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2373AE122D0A216C0086C749 /* MetricsChartSeries.swift */,
|
||||
231B3F202D087A4C0069A07D /* MetricTableColumn.swift */,
|
||||
231B3F1F2D087A4C0069A07D /* MetricsColumnList.swift */,
|
||||
2373AE142D0A24930086C749 /* MetricsSeriesList.swift */,
|
||||
);
|
||||
path = "Metrics Visualization";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
231B3F232D087C020069A07D /* Metrics Columns */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
231B3F242D087C3C0069A07D /* EnvironmentDefaultColumns.swift */,
|
||||
2373AE162D0A26620086C749 /* EnviornmentDefaultSeries.swift */,
|
||||
231B3F262D0885240069A07D /* MetricsColumnDetail.swift */,
|
||||
);
|
||||
path = "Metrics Columns";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
251926882C3BAF2E00249DF5 /* Actions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDDFE73E2D0D48FF0044463C /* IgnoreNodeButton.swift */,
|
||||
251926842C3BA97800249DF5 /* FavoriteNodeButton.swift */,
|
||||
251926892C3BB1B200249DF5 /* ExchangePositionsButton.swift */,
|
||||
251926862C3BAE2200249DF5 /* NodeAlertsButton.swift */,
|
||||
|
|
@ -627,6 +675,17 @@
|
|||
path = Custom;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D32BA3902D54612800714840 /* CoreData */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D32BA3912D54617800714840 /* NodeInfoEntity+CoreDataClass.swift */,
|
||||
D32BA3922D54617800714840 /* NodeInfoEntity+CoreDataProperties.swift */,
|
||||
D32BA3932D54617800714840 /* UserEntity+CoreDataClass.swift */,
|
||||
D32BA3942D54617800714840 /* UserEntity+CoreDataProperties.swift */,
|
||||
);
|
||||
path = CoreData;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D9C9839E2B79D0C600BDBE6A /* TextMessageField */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -675,6 +734,7 @@
|
|||
6DEDA5592A957B8E00321D2E /* DetectionSensorLog.swift */,
|
||||
DD15E4F42B8BFC8E00654F61 /* PaxCounterLog.swift */,
|
||||
DDE5B4032B2279A700FCDD05 /* TraceRouteLog.swift */,
|
||||
8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */,
|
||||
);
|
||||
path = Nodes;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -867,6 +927,7 @@
|
|||
DDC2E14B26CE248E0042C5E4 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDD3A2B12D5127B40045EB48 /* ci_scripts */,
|
||||
DDDBC87A2BC62E4E001E8DF7 /* Settings.bundle */,
|
||||
25AECD4E2C2F723200862C8E /* Localizable.xcstrings */,
|
||||
DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */,
|
||||
|
|
@ -892,6 +953,7 @@
|
|||
DDC2E15626CE248E0042C5E4 /* Meshtastic */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D32BA3902D54612800714840 /* CoreData */,
|
||||
BCB6137F2C6728E700485544 /* AppIntents */,
|
||||
DD1BD0EC2C603C5B008C0C70 /* Measurement */,
|
||||
25F5D5BC2C3F6D7B008036E3 /* Router */,
|
||||
|
|
@ -940,6 +1002,7 @@
|
|||
DDC2E18826CE24EE0042C5E4 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
231B3F1E2D0879BC0069A07D /* Metrics Visualization */,
|
||||
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */,
|
||||
);
|
||||
path = Model;
|
||||
|
|
@ -983,13 +1046,13 @@
|
|||
DDF924C926FBB953009FE055 /* ConnectedDevice.swift */,
|
||||
DDD94A4F2845C8F5004A87A0 /* DateTimeText.swift */,
|
||||
DDB6ABDA28B0AC6000384BA1 /* DistanceText.swift */,
|
||||
DDC3B273283F411B00AC321C /* LastHeardText.swift */,
|
||||
DDB75A202A12B954006ED576 /* LoRaSignalStrength.swift */,
|
||||
DDB75A1D2A0B0CD0006ED576 /* LoRaSignalStrengthIndicator.swift */,
|
||||
DD97E96528EFD9820056DDA4 /* MeshtasticLogo.swift */,
|
||||
DDF45C332BC1A48E005ED5F2 /* MQTTIcon.swift */,
|
||||
DD5E523D298F5A7D00D21B61 /* Weather */,
|
||||
DD6F65712C6AB8EC0053C113 /* SecureInput.swift */,
|
||||
8D3F8A3E2D44BB02009EAAA4 /* PowerMetrics.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1021,6 +1084,14 @@
|
|||
path = Persistence;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDD3A2B12D5127B40045EB48 /* ci_scripts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DDD3A2B22D5127CF0045EB48 /* ci_pre_xcodebuild.sh */,
|
||||
);
|
||||
path = ci_scripts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DDD43FE12A78C86B0083A3E9 /* Mqtt */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1041,6 +1112,7 @@
|
|||
DDDB26402AABEF7B003AFCB7 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
231B3F232D087C020069A07D /* Metrics Columns */,
|
||||
DDAD49EB2AFAE82500B4425D /* Map */,
|
||||
DDDB26432AAC0206003AFCB7 /* NodeDetail.swift */,
|
||||
DDDB26452AACC0B7003AFCB7 /* NodeInfoItem.swift */,
|
||||
|
|
@ -1208,6 +1280,7 @@
|
|||
"zh-Hant-TW",
|
||||
se,
|
||||
"pt-PT",
|
||||
sr,
|
||||
);
|
||||
mainGroup = DDC2E14B26CE248E0042C5E4;
|
||||
packageReferences = (
|
||||
|
|
@ -1316,11 +1389,13 @@
|
|||
DD5D0A9C2931B9F200F7EA61 /* EthernetModes.swift in Sources */,
|
||||
6DEDA55A2A957B8E00321D2E /* DetectionSensorLog.swift in Sources */,
|
||||
DD798B072915928D005217CD /* ChannelMessageList.swift in Sources */,
|
||||
231B3F272D0885240069A07D /* MetricsColumnDetail.swift in Sources */,
|
||||
DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */,
|
||||
DD77093D2AA1AFA3007A8BF0 /* ChannelTips.swift in Sources */,
|
||||
6D825E622C34786C008DBEE4 /* CommonRegex.swift in Sources */,
|
||||
DD913639270DFF4C00D7ACF3 /* LocalNotificationManager.swift in Sources */,
|
||||
DDDB444C29F8AAA600EE2349 /* Color.swift in Sources */,
|
||||
DDDFE73F2D0D48FF0044463C /* IgnoreNodeButton.swift in Sources */,
|
||||
DDB8F4122A9EE5DD00230ECE /* UserList.swift in Sources */,
|
||||
DDB75A0F2A05920E006ED576 /* FileManager.swift in Sources */,
|
||||
DD3D17E02C3FB67200561584 /* LocalWeatherConditions.swift in Sources */,
|
||||
|
|
@ -1331,11 +1406,13 @@
|
|||
DDB6ABD628AE742000384BA1 /* BluetoothConfig.swift in Sources */,
|
||||
251926902C3CB44900249DF5 /* ClientHistoryButton.swift in Sources */,
|
||||
DDD5BB102C285FB3007E03CA /* AppLogFilter.swift in Sources */,
|
||||
2373AE172D0A26620086C749 /* EnviornmentDefaultSeries.swift in Sources */,
|
||||
DD4640202AFF10F4002A5ECB /* WaypointForm.swift in Sources */,
|
||||
DD769E0328D18BF1001A3F05 /* DeviceMetricsLog.swift in Sources */,
|
||||
DDAF8C5326EB1DF10058C060 /* BLEManager.swift in Sources */,
|
||||
DD15E4F32B8BA56E00654F61 /* PaxCounterConfig.swift in Sources */,
|
||||
DDDB445229F8ACF900EE2349 /* Date.swift in Sources */,
|
||||
2373AE132D0A216C0086C749 /* MetricsChartSeries.swift in Sources */,
|
||||
DDC4D568275499A500A4208E /* Persistence.swift in Sources */,
|
||||
DDD6EEAF29BC024700383354 /* Firmware.swift in Sources */,
|
||||
DD77093B2AA1ABB8007A8BF0 /* BluetoothTips.swift in Sources */,
|
||||
|
|
@ -1345,7 +1422,9 @@
|
|||
DD964FBD296E6B01007C176F /* EmojiOnlyTextField.swift in Sources */,
|
||||
DD8169FF272476C700F4AB02 /* LogDocument.swift in Sources */,
|
||||
DDC94FC129CE063B0082EA6E /* BatteryLevel.swift in Sources */,
|
||||
231B3F252D087C3C0069A07D /* EnvironmentDefaultColumns.swift in Sources */,
|
||||
25F5D5BE2C3F6D87008036E3 /* NavigationState.swift in Sources */,
|
||||
2373AE152D0A24930086C749 /* MetricsSeriesList.swift in Sources */,
|
||||
DD354FD92BD96A0B0061A25F /* IAQScale.swift in Sources */,
|
||||
DDDB445429F8AD1600EE2349 /* Data.swift in Sources */,
|
||||
DDDB26462AACC0B7003AFCB7 /* NodeInfoItem.swift in Sources */,
|
||||
|
|
@ -1430,12 +1509,14 @@
|
|||
DD3CC24C2C498D6C001BD3A2 /* BatteryCompact.swift in Sources */,
|
||||
BCB613812C67290800485544 /* SendWaypointIntent.swift in Sources */,
|
||||
DD1B8F402B35E2F10022AABC /* GPSStatus.swift in Sources */,
|
||||
231B3F212D087A4C0069A07D /* MetricTableColumn.swift in Sources */,
|
||||
231B3F222D087A4C0069A07D /* MetricsColumnList.swift in Sources */,
|
||||
DD8ED9C52898D51F00B3B0AB /* NetworkConfig.swift in Sources */,
|
||||
DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */,
|
||||
DDDE5A1029AFE69700490C6C /* MeshActivityAttributes.swift in Sources */,
|
||||
DD1925B928CDA93900720036 /* SerialConfigEnums.swift in Sources */,
|
||||
251926852C3BA97800249DF5 /* FavoriteNodeButton.swift in Sources */,
|
||||
D9C983A02B79D0E800BDBE6A /* AlertButton.swift in Sources */,
|
||||
8D3F8A412D44C2A6009EAAA4 /* PowerMetricsLog.swift in Sources */,
|
||||
DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */,
|
||||
DD6F65762C6EA5490053C113 /* AckErrors.swift in Sources */,
|
||||
DDDB445029F8AC9C00EE2349 /* UIImage.swift in Sources */,
|
||||
|
|
@ -1452,6 +1533,7 @@
|
|||
DDB6ABE428B13FFF00384BA1 /* DisplayEnums.swift in Sources */,
|
||||
DD4975A52B147BA90026544E /* AmbientLightingConfig.swift in Sources */,
|
||||
D93068D92B81509C0066FBC8 /* TapbackResponses.swift in Sources */,
|
||||
8D3F8A3F2D44BB02009EAAA4 /* PowerMetrics.swift in Sources */,
|
||||
2519268A2C3BB1B200249DF5 /* ExchangePositionsButton.swift in Sources */,
|
||||
DD86D40A287F04F100BAEB7A /* InvalidVersion.swift in Sources */,
|
||||
DDD94A502845C8F5004A87A0 /* DateTimeText.swift in Sources */,
|
||||
|
|
@ -1536,7 +1618,7 @@
|
|||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.5;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.MeshtasticTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
@ -1559,7 +1641,7 @@
|
|||
DEVELOPMENT_TEAM = GCH7VS5Y9R;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.5;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.MeshtasticTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
@ -1716,7 +1798,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.5.9;
|
||||
MARKETING_VERSION = 2.5.19;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1750,7 +1832,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.5.9;
|
||||
MARKETING_VERSION = 2.5.19;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1776,13 +1858,13 @@
|
|||
INFOPLIST_FILE = Widgets/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Widgets;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.5.9;
|
||||
MARKETING_VERSION = 2.5.19;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1809,13 +1891,13 @@
|
|||
INFOPLIST_FILE = Widgets/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Widgets;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.5.9;
|
||||
MARKETING_VERSION = 2.5.19;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1927,6 +2009,9 @@
|
|||
DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
8D3F8A3D2D44B137009EAAA4 /* MeshtasticDataModelV 49.xcdatamodel */,
|
||||
DDA28B1B2D32C89200EF726F /* MeshtasticDataModelV 48.xcdatamodel */,
|
||||
DDDFE7402D0D4A070044463C /* MeshtasticDataModelV 47.xcdatamodel */,
|
||||
DD0BE30C2CB785D8000BA445 /* MeshtasticDataModelV 46.xcdatamodel */,
|
||||
DD6D5A342CA13BA600ED3032 /* MeshtasticDataModelV 45.xcdatamodel */,
|
||||
DD7CF8DA2C93663C008BD10E /* MeshtasticDataModelV 44.xcdatamodel */,
|
||||
|
|
@ -1974,7 +2059,7 @@
|
|||
DD5D0A9A2931AD6B00F7EA61 /* MeshtasticDataModelV2.xcdatamodel */,
|
||||
DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */,
|
||||
);
|
||||
currentVersion = DD0BE30C2CB785D8000BA445 /* MeshtasticDataModelV 46.xcdatamodel */;
|
||||
currentVersion = 8D3F8A3D2D44B137009EAAA4 /* MeshtasticDataModelV 49.xcdatamodel */;
|
||||
name = Meshtastic.xcdatamodeld;
|
||||
path = Meshtastic/Meshtastic.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
|||
|
|
@ -77,6 +77,16 @@
|
|||
value = "oslogToStdio"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
<EnvironmentVariable
|
||||
key = "PUBLIC_MQTT_USERNAME"
|
||||
value = "meshdev"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
<EnvironmentVariable
|
||||
key = "PUBLIC_MQTT_PASSWORD"
|
||||
value = "large4cats"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
|
|
|
|||
61
Meshtastic/AppIntents/NavigateToNodeIntent.swift
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// NavigateToNodeIntent.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Benjamin Faershtein on 2/8/25.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AppIntents
|
||||
import CoreLocation
|
||||
import CoreData
|
||||
import UIKit
|
||||
|
||||
@available(iOS 16.4, *)
|
||||
struct NavigateToNodeIntent: ForegroundContinuableIntent {
|
||||
|
||||
static var title: LocalizedStringResource = "Navigate to Node Position"
|
||||
static var openAppWhenRun: Bool = false
|
||||
|
||||
@Parameter(title: "Node Number")
|
||||
var nodeNum: Int
|
||||
|
||||
@MainActor
|
||||
func perform() async throws -> some IntentResult & ProvidesDialog {
|
||||
if !BLEManager.shared.isConnected {
|
||||
throw AppIntentErrors.AppIntentError.notConnected
|
||||
}
|
||||
|
||||
let fetchNodeInfoRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "NodeInfoEntity")
|
||||
fetchNodeInfoRequest.predicate = NSPredicate(format: "num == %lld", Int64(nodeNum))
|
||||
|
||||
do {
|
||||
guard let fetchedNode = try PersistenceController.shared.container.viewContext.fetch(fetchNodeInfoRequest) as? [NodeInfoEntity],
|
||||
fetchedNode.count == 1 else {
|
||||
throw $nodeNum.needsValueError("Could not find node")
|
||||
}
|
||||
|
||||
let nodeInfo = fetchedNode[0]
|
||||
if let latitude = nodeInfo.latestPosition?.coordinate.latitude,
|
||||
let longitude = nodeInfo.latestPosition?.coordinate.longitude {
|
||||
|
||||
let url = URL(string: "maps://?saddr=&daddr=\(latitude),\(longitude)")
|
||||
|
||||
if let mapURL = url, UIApplication.shared.canOpenURL(mapURL) {
|
||||
// Request to continue in foreground before opening the app
|
||||
try await requestToContinueInForeground()
|
||||
|
||||
// Open Apple Maps for navigation
|
||||
UIApplication.shared.open(mapURL, options: [:], completionHandler: nil)
|
||||
return .result(dialog: "Navigating to node location.")
|
||||
} else {
|
||||
throw AppIntentErrors.AppIntentError.message("Unable to open Apple Maps.")
|
||||
}
|
||||
} else {
|
||||
throw AppIntentErrors.AppIntentError.message("Node does not have a recorded position.")
|
||||
}
|
||||
} catch {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to fetch node data.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "LILYGO-TTGO-LoRa32-V2-1-1-6-Version-433-868-915Mhz-ESP32-LoRa-OLED-0-96.jpg_Q90.jpg_.webp.png",
|
||||
"filename" : "heltec-ht62-esp32c3-sx1262.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
1
Meshtastic/Assets.xcassets/HELTECHT62.imageset/heltec-ht62-esp32c3-sx1262.svg
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
12
Meshtastic/Assets.xcassets/HELTECMESHNODET114.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "heltec-mesh-node-t114-case.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/HELTECMESHNODET114.imageset/heltec-mesh-node-t114-case.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="795.27 277.13 409.46 1319.35"><defs><style>.cls-1{fill:#353535;}.cls-2{fill:#1e1e1d;}.cls-3{fill:#b1a368;}.cls-10,.cls-11,.cls-4,.cls-6,.cls-8,.cls-9{fill:none;}.cls-4,.cls-6{stroke:#050606;}.cls-10,.cls-11,.cls-4,.cls-6,.cls-8{stroke-miterlimit:10;}.cls-4{stroke-width:2.41px;}.cls-5{fill:#30c2db;}.cls-6{stroke-width:3.91px;}.cls-7{fill:#dcf0f2;}.cls-10,.cls-11,.cls-8{stroke:#dcf0f2;}.cls-8{stroke-width:1.81px;}.cls-9{stroke:#17afbf;stroke-linecap:round;stroke-linejoin:round;stroke-width:7.23px;}.cls-10{stroke-width:1.78px;}.cls-11{stroke-width:1.81px;}</style></defs><g id="Layer_7" data-name="Layer 7"><path class="cls-1" d="M915.62,278.34h22.61a35,35,0,0,1,35,35V715.74a0,0,0,0,1,0,0H880.6a0,0,0,0,1,0,0V313.36A35,35,0,0,1,915.62,278.34Z"></path><rect class="cls-2" x="880.6" y="340.15" width="92.65" height="7.54"></rect><rect class="cls-2" x="880.6" y="356.68" width="92.65" height="7.54"></rect><rect class="cls-3" x="885.8" y="844.3" width="84.14" height="19.02"></rect><rect class="cls-3" x="880.6" y="819.07" width="92.65" height="25.23"></rect><rect class="cls-3" x="885.8" y="790.65" width="84.14" height="28.41"></rect><rect class="cls-3" x="880.6" y="723.02" width="92.65" height="67.63"></rect><rect class="cls-3" x="885.8" y="715.74" width="84.14" height="7.28"></rect><rect class="cls-4" x="885.8" y="844.3" width="84.14" height="19.02"></rect><rect class="cls-4" x="880.6" y="819.07" width="92.65" height="25.23"></rect><rect class="cls-4" x="885.8" y="790.65" width="84.14" height="28.41"></rect><rect class="cls-4" x="880.6" y="723.02" width="92.65" height="67.63"></rect><rect class="cls-4" x="885.8" y="715.74" width="84.14" height="7.28"></rect><path class="cls-4" d="M915.62,278.34h22.61a35,35,0,0,1,35,35V715.74a0,0,0,0,1,0,0H880.6a0,0,0,0,1,0,0V313.36A35,35,0,0,1,915.62,278.34Z"></path><rect class="cls-4" x="880.6" y="340.15" width="92.65" height="7.54"></rect><rect class="cls-4" x="880.6" y="356.68" width="92.65" height="7.54"></rect><rect class="cls-5" x="796.48" y="856.3" width="407.05" height="738.98" rx="47.74"></rect><rect class="cls-1" x="900.05" y="973.19" width="202.03" height="354.65" rx="16.4"></rect><rect class="cls-6" x="900.05" y="973.19" width="202.03" height="354.65" rx="16.4"></rect><rect class="cls-7" x="871.51" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><rect class="cls-7" x="1070.16" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><rect class="cls-4" x="871.51" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><rect class="cls-4" x="1070.16" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><circle class="cls-8" cx="841.7" cy="1537.01" r="16.25"></circle><circle class="cls-8" cx="841.7" cy="913.26" r="16.25"></circle><circle class="cls-8" cx="1157.32" cy="913.26" r="16.25"></circle><circle class="cls-8" cx="1157.32" cy="1504.51" r="16.25"></circle><line class="cls-9" x1="942.51" y1="1592.42" x2="942.51" y2="1381.55"></line><line class="cls-9" x1="966.52" y1="1592.42" x2="966.52" y2="1381.55"></line><line class="cls-9" x1="990.57" y1="1592.42" x2="990.57" y2="1381.55"></line><line class="cls-9" x1="1014.59" y1="1592.42" x2="1014.59" y2="1381.55"></line><line class="cls-9" x1="1038.63" y1="1592.42" x2="1038.63" y2="1381.55"></line><line class="cls-9" x1="1062.65" y1="1592.42" x2="1062.65" y2="1381.55"></line><rect class="cls-4" x="796.48" y="856.3" width="407.05" height="738.98" rx="47.74"></rect><path class="cls-10" d="M1040.1,947.74H960.65A13.93,13.93,0,0,1,947,936.64l-10.23-49.2a13.93,13.93,0,0,1,13.64-16.77h97.72a13.93,13.93,0,0,1,13.75,16.18l-8,49.2A13.94,13.94,0,0,1,1040.1,947.74Z"></path><rect class="cls-11" x="816.35" y="870.67" width="365.51" height="703.12" rx="32.37"></rect><rect class="cls-11" x="888.77" y="963.84" width="223.2" height="374.66" rx="25.21"></rect></g></svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Heltec_turq.png",
|
||||
"filename" : "heltec-v3-case.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.2 MiB |
1
Meshtastic/Assets.xcassets/HELTECV3.imageset/heltec-v3-case.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="404.68 390.65 1217.15 959.26"><defs><style>.cls-1{fill:#dfeaf7;}.cls-2{fill:#17907f;}.cls-3{fill:#2b2b2b;}.cls-4,.cls-5{fill:none;stroke:#050606;stroke-miterlimit:10;}.cls-4{stroke-width:2.25px;}.cls-5{stroke-width:4px;}.cls-6{fill:#050606;}</style></defs><g id="Layer_5" data-name="Layer 5"><path class="cls-1" d="M1517.73,392.65h0a102.1,102.1,0,0,0-102.1,102.1V770.37A40.62,40.62,0,0,1,1375,811H455.16a48.49,48.49,0,0,0-48.48,48.48v126a11.85,11.85,0,0,0,3.46,8.37l15.34,15.34a11.81,11.81,0,0,1,3.47,8.37v137.16a11.81,11.81,0,0,1-3.47,8.37l-15.34,15.34a11.85,11.85,0,0,0-3.46,8.37v112.67a48.49,48.49,0,0,0,48.48,48.49H1571.34a48.51,48.51,0,0,0,48.49-48.5V494.75A102.1,102.1,0,0,0,1517.73,392.65Zm-110.61,815V954a33.14,33.14,0,0,1,66.27,0v253.65a33.14,33.14,0,0,1-66.27,0Z"></path><path class="cls-2" d="M1516,439.16c-30.23.91-53.92,26.54-53.92,56.79V770.37A87.11,87.11,0,0,1,1375,857.48H732.31A27.51,27.51,0,0,0,704.8,885v388.93a27.51,27.51,0,0,0,27.51,27.51h828.38a12.7,12.7,0,0,0,12.65-12.65v-794A55.69,55.69,0,0,0,1516,439.16Zm-108.9,768.47V954a33.14,33.14,0,0,1,66.27,0v253.65a33.14,33.14,0,0,1-66.27,0Z"></path><rect class="cls-3" x="787.14" y="943.38" width="429.45" height="224.42"></rect><path class="cls-1" d="M1478.6,915.35A54.23,54.23,0,0,0,1386,953.69v254.23a54.23,54.23,0,1,0,108.45,0V953.69A54,54,0,0,0,1478.6,915.35Zm-5.21,292.28a33.14,33.14,0,0,1-66.27,0V954a33.14,33.14,0,0,1,66.27,0Z"></path></g><g id="Layer_2" data-name="Layer 2"><path class="cls-4" d="M1573.34,494.75v794a12.68,12.68,0,0,1-12.65,12.65H732.31a27.51,27.51,0,0,1-27.51-27.51V885a27.51,27.51,0,0,1,27.51-27.51H1375a87.11,87.11,0,0,0,87.11-87.11V496c0-30.25,23.69-55.88,53.92-56.79A55.69,55.69,0,0,1,1573.34,494.75Z"></path><path class="cls-5" d="M410.14,1178.39,425.49,1163a11.78,11.78,0,0,0,3.46-8.35V1017.5a11.8,11.8,0,0,0-3.46-8.35l-15.35-15.36a11.77,11.77,0,0,1-3.46-8.35v-126A48.47,48.47,0,0,1,455.16,811H1375a40.63,40.63,0,0,0,40.63-40.63V494.75a102.1,102.1,0,0,1,102.1-102.1h0a102.1,102.1,0,0,1,102.1,102.1v804.66a48.51,48.51,0,0,1-48.49,48.5H455.16a48.48,48.48,0,0,1-48.48-48.49V1186.74A11.78,11.78,0,0,1,410.14,1178.39Z"></path><rect class="cls-4" x="1407.12" y="920.85" width="66.26" height="319.9" rx="33.13"></rect><rect class="cls-4" x="1386.03" y="899.46" width="108.46" height="362.69" rx="54.23"></rect><path class="cls-6" d="M639.76,1070.55a2.91,2.91,0,0,1-2.91-2.91v-30.53a5.42,5.42,0,0,0-1.6-3.86l-32.44-32.44a11.86,11.86,0,0,1-3.5-8.44V901a12.52,12.52,0,0,0-12.51-12.51H483.92a12.7,12.7,0,0,0-12.68,12.69v76.78a24.13,24.13,0,0,0,7.11,17.18l14.33,14.33a24.13,24.13,0,0,0,17.18,7.11h50.75a11.86,11.86,0,0,1,8.44,3.5l24.26,24.26a12.47,12.47,0,0,1,3.68,8.88v14.46a2.91,2.91,0,1,1-5.81,0v-14.46a6.72,6.72,0,0,0-2-4.77l-24.26-24.26a6.09,6.09,0,0,0-4.33-1.8H509.86a29.91,29.91,0,0,1-21.29-8.81l-14.33-14.33a29.87,29.87,0,0,1-8.81-21.29V901.14a18.51,18.51,0,0,1,18.49-18.5H586.8A18.34,18.34,0,0,1,605.12,901v91.41a6.09,6.09,0,0,0,1.8,4.33l32.44,32.44a11.19,11.19,0,0,1,3.3,8v30.53A2.9,2.9,0,0,1,639.76,1070.55Z"></path><path class="cls-6" d="M586.8,1289.46H483.92a18.51,18.51,0,0,1-18.49-18.5v-76.78a29.87,29.87,0,0,1,8.81-21.29l14.33-14.34a29.91,29.91,0,0,1,21.29-8.81h50.75a6.09,6.09,0,0,0,4.33-1.8l24.26-24.25a6.74,6.74,0,0,0,2-4.78v-14.46a2.91,2.91,0,0,1,5.81,0v14.46a12.51,12.51,0,0,1-3.68,8.89l-24.26,24.25a11.86,11.86,0,0,1-8.44,3.5H509.86a24.17,24.17,0,0,0-17.18,7.11L478.35,1177a24.09,24.09,0,0,0-7.11,17.18V1271a12.71,12.71,0,0,0,12.68,12.69H586.8a12.53,12.53,0,0,0,12.51-12.52v-91.4a11.83,11.83,0,0,1,3.5-8.44l32.44-32.44a5.46,5.46,0,0,0,1.6-3.87v-30.53a2.91,2.91,0,0,1,5.81,0V1135a11.19,11.19,0,0,1-3.3,8l-32.44,32.45a6.06,6.06,0,0,0-1.8,4.33v91.4A18.35,18.35,0,0,1,586.8,1289.46Z"></path><rect class="cls-4" x="787.14" y="943.38" width="429.45" height="224.42"></rect></g></svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
12
Meshtastic/Assets.xcassets/HELTECVISIONMASTERE213.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "heltec-vision-master-e213.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/HELTECVISIONMASTERE213.imageset/heltec-vision-master-e213.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="528.89 806.04 942.22 446.84"><defs><style>.cls-1{fill:#e8eae8;}.cls-2{fill:#dbdddb;}.cls-3{fill:#c6842a;}.cls-4,.cls-5,.cls-7,.cls-9{fill:none;stroke-miterlimit:10;}.cls-4,.cls-5{stroke:#050606;}.cls-4,.cls-9{stroke-width:2.44px;}.cls-5,.cls-7{stroke-width:1.22px;}.cls-6{fill:#b7b7b7;}.cls-7,.cls-9{stroke:#b7b7b7;}.cls-8{fill:#cbcccb;}.cls-10{fill:#434543;}</style></defs><g id="Layer_4" data-name="Layer 4"><path class="cls-1" d="M1469.9,826.68v390.94a19.43,19.43,0,0,1-19.43,19.43H549.53a19.43,19.43,0,0,1-19.43-19.43V826.68a19.42,19.42,0,0,1,19.43-19.42h900.94A19.42,19.42,0,0,1,1469.9,826.68Z"></path><path class="cls-2" d="M574.23,807.26v429.79h-24.7a19.43,19.43,0,0,1-19.43-19.43V826.68a19.42,19.42,0,0,1,19.43-19.42Z"></path><path class="cls-2" d="M1469.9,826.68v390.94a19.43,19.43,0,0,1-19.43,19.43h-37.56V807.26h37.56A19.42,19.42,0,0,1,1469.9,826.68Z"></path><path class="cls-3" d="M574.23,1129.8h-7.47a4.55,4.55,0,0,1-4.55-4.54V919.05a4.55,4.55,0,0,1,4.55-4.55h7.47"></path><rect class="cls-4" x="530.11" y="807.26" width="939.78" height="429.79" rx="19.42"></rect><line class="cls-5" x1="574.23" y1="807.26" x2="574.23" y2="1237.05"></line><path class="cls-5" d="M574.23,1129.8h-7.47a4.55,4.55,0,0,1-4.55-4.54V919.05a4.55,4.55,0,0,1,4.55-4.55h7.47"></path><rect class="cls-6" x="599.01" y="970.1" width="11.52" height="104.11"></rect><rect class="cls-5" x="599.01" y="970.1" width="11.52" height="104.11"></rect><path class="cls-2" d="M610.53,816.78V935.32l38.37,11.55a7.85,7.85,0,0,1,5.6,7.53V1107a7.87,7.87,0,0,1-7.87,7.87h-36.1v110.58H1406V816.78Zm775.41,384.75H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66h754.51Z"></path><path class="cls-1" d="M1385.94,840.45v361.08H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66Z"></path><path class="cls-7" d="M610.53,816.78V935.32l38.37,11.55a7.85,7.85,0,0,1,5.6,7.53V1107a7.87,7.87,0,0,1-7.87,7.87h-36.1v110.58H1406V816.78Zm775.41,384.75H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66h754.51Z"></path><path class="cls-7" d="M1385.94,840.45v361.08H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66Z"></path><path class="cls-7" d="M1385.94,840.45v361.08H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66Z"></path><line class="cls-7" x1="666.4" y1="1132.79" x2="666.4" y2="1201.53"></line><line class="cls-7" x1="663.66" y1="916.86" x2="663.66" y2="840.45"></line><circle class="cls-8" cx="644.99" cy="878.66" r="10.7"></circle><circle class="cls-8" cx="644.99" cy="1171.55" r="10.7"></circle><circle class="cls-9" cx="644.99" cy="878.66" r="10.7"></circle><circle class="cls-9" cx="644.99" cy="1171.55" r="10.7"></circle><path class="cls-10" d="M1225,1237.05l2.23,11.19a4.25,4.25,0,0,0,4.17,3.42H1249a4.26,4.26,0,0,0,4.18-3.42l2.22-11.19"></path><path class="cls-10" d="M1306.87,1237.05l2.22,11.19a4.26,4.26,0,0,0,4.18,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.22-11.19"></path><path class="cls-10" d="M1388.77,1237.05l2.23,11.19a4.24,4.24,0,0,0,4.17,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.23-11.19"></path><path class="cls-4" d="M1225,1237.05l2.23,11.19a4.25,4.25,0,0,0,4.17,3.42H1249a4.26,4.26,0,0,0,4.18-3.42l2.22-11.19"></path><path class="cls-4" d="M1306.87,1237.05l2.22,11.19a4.26,4.26,0,0,0,4.18,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.22-11.19"></path><path class="cls-4" d="M1388.77,1237.05l2.23,11.19a4.24,4.24,0,0,0,4.17,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.23-11.19"></path><line class="cls-4" x1="1412.9" y1="807.26" x2="1412.9" y2="1237.05"></line></g></svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
12
Meshtastic/Assets.xcassets/HELTECVISIONMASTERE290.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "heltec-vision-master-e290.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/HELTECVISIONMASTERE290.imageset/heltec-vision-master-e290.svg
vendored
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Paper-Meshtastic-2 copy.jpg",
|
||||
"filename" : "heltec-wireless-paper.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 66 KiB |
1
Meshtastic/Assets.xcassets/HELTECWIRELESSPAPER.imageset/heltec-wireless-paper.svg
vendored
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "images.png",
|
||||
"filename" : "heltec-wireless-tracker.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
1
Meshtastic/Assets.xcassets/HELTECWIRELESSTRACKER.imageset/heltec-wireless-tracker.svg
vendored
Normal file
|
After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "heltecwsl.png",
|
||||
"filename" : "heltec-wsl-v3.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
1
Meshtastic/Assets.xcassets/HELTECWSLV3.imageset/heltec-wsl-v3.svg
vendored
Normal file
|
After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 209 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tbeam_supreme.png",
|
||||
"filename" : "tbeam-s3-core.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
1
Meshtastic/Assets.xcassets/LILYGOTBEAMS3CORE.imageset/tbeam-s3-core.svg
vendored
Normal file
|
After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 4.1 MiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "nano_g2_ultra_product_image.jpg",
|
||||
"filename" : "nano-g2-ultra.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
1
Meshtastic/Assets.xcassets/NANOG2ULTRA.imageset/nano-g2-ultra.svg
vendored
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 484 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "RAK_DEV_KIT-2.jpg",
|
||||
"filename" : "promicro.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
1
Meshtastic/Assets.xcassets/PROMICRO.imageset/promicro.svg
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 2.5 MiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "TLORA_olive 1.png",
|
||||
"filename" : "rak11310.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
1
Meshtastic/Assets.xcassets/RAK11310.imageset/rak11310.svg
vendored
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "RAK 4.png",
|
||||
"filename" : "rak4631_case.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.6 MiB |
1
Meshtastic/Assets.xcassets/RAK4631.imageset/rak4631_case.svg
vendored
Normal file
|
After Width: | Height: | Size: 9 KiB |
12
Meshtastic/Assets.xcassets/RPIPICO.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "pico.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
2956
Meshtastic/Assets.xcassets/RPIPICO.imageset/pico.svg
vendored
Normal file
|
After Width: | Height: | Size: 102 KiB |
12
Meshtastic/Assets.xcassets/SEEEDXIAOS3.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "seeed-xiao-s3.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/SEEEDXIAOS3.imageset/seeed-xiao-s3.svg
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
12
Meshtastic/Assets.xcassets/SENSECAPINDICATOR.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "seeed-sensecap-indicator.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/SENSECAPINDICATOR.imageset/seeed-sensecap-indicator.svg
vendored
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
12
Meshtastic/Assets.xcassets/STATIONG2.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "station-g2.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/STATIONG2.imageset/station-g2.svg
vendored
Normal file
|
After Width: | Height: | Size: 31 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tbeam.png",
|
||||
"filename" : "tbeam.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
BIN
Meshtastic/Assets.xcassets/TBEAM.imageset/tbeam.png
vendored
|
Before Width: | Height: | Size: 1.7 MiB |
1
Meshtastic/Assets.xcassets/TBEAM.imageset/tbeam.svg
vendored
Normal file
|
After Width: | Height: | Size: 112 KiB |
12
Meshtastic/Assets.xcassets/TDECK.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "t-deck.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TDECK.imageset/t-deck.svg
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "LILYGO-TTGO-SoftRF-T-Echo-NRF52840-LoRa-SX1262-433-868-915MHz-Wireless-Module-L76K-GPS-1.png",
|
||||
"filename" : "t-echo.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 430 KiB |
1
Meshtastic/Assets.xcassets/TECHO.imageset/t-echo.svg
vendored
Normal file
|
After Width: | Height: | Size: 8 KiB |
|
Before Width: | Height: | Size: 457 KiB |
12
Meshtastic/Assets.xcassets/TLORAC6.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-c6.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAC6.imageset/tlora-c6.svg
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
12
Meshtastic/Assets.xcassets/TLORAT3S3EPAPER.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-t3s3-epaper.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAT3S3EPAPER.imageset/tlora-t3s3-epaper.svg
vendored
Normal file
|
After Width: | Height: | Size: 6 KiB |
12
Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-t3s3-v1.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAT3S3V1.imageset/tlora-t3s3-v1.svg
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 4 MiB |
12
Meshtastic/Assets.xcassets/TLORAV211P6.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-v2-1-1_6.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAV211P6.imageset/tlora-v2-1-1_6.svg
vendored
Normal file
|
After Width: | Height: | Size: 26 KiB |
12
Meshtastic/Assets.xcassets/TLORAV211P8.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tlora-v2-1-1_8.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TLORAV211P8.imageset/tlora-v2-1-1_8.svg
vendored
Normal file
|
After Width: | Height: | Size: 26 KiB |
12
Meshtastic/Assets.xcassets/TRACKERT1000E.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "tracker-t1000-e.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TRACKERT1000E.imageset/tracker-t1000-e.svg
vendored
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
12
Meshtastic/Assets.xcassets/TWATCHS3.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "t-watch-s3.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/TWATCHS3.imageset/t-watch-s3.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="733.42 451.82 573.87 931.48"><defs><style>.cls-1{fill:#8e8d8e;}.cls-2{fill:#383839;}.cls-3{fill:#cccccb;}.cls-4{fill:#222226;}.cls-5,.cls-6{fill:none;stroke:#050606;stroke-miterlimit:10;}.cls-5{stroke-width:1.87px;}.cls-6{stroke-width:3.77px;}.cls-7{fill:#4c4c4d;}</style></defs><g id="Layer_4" data-name="Layer 4"><path class="cls-1" d="M1277.27,847.59h4.35a8.09,8.09,0,0,1,8.09,8.08v138a8.09,8.09,0,0,1-8.09,8.09h-4.35"></path><path class="cls-1" d="M1277.27,732.73h18a10.14,10.14,0,0,1,10.14,10.14v43A10.14,10.14,0,0,1,1295.26,796h-18a0,0,0,0,1,0,0V732.73A0,0,0,0,1,1277.27,732.73Z"></path><path class="cls-2" d="M1256.49,1200.6h0a14.19,14.19,0,0,1-2.83,12.5c-8.13,9.86-19.94,18.58-46,30.75-19.15,9-28.65,16-38.35,29.6a93.15,93.15,0,0,0-8.7,14.61c-6.95,15.17-11.77,44.44-11.77,65.66v3.61a24.09,24.09,0,0,1-24.1,24.09H887.83a24.09,24.09,0,0,1-24.1-24.09v-3.61c0-21.22-4.82-50.49-11.77-65.66a93.15,93.15,0,0,0-8.7-14.61c-9.7-13.63-19.2-20.65-38.35-29.6-26.06-12.17-37.87-20.89-46-30.75a14.22,14.22,0,0,1-2.82-12.5h0"></path><path class="cls-2" d="M756.09,634.53h0a14.19,14.19,0,0,1,2.83-12.5c8.12-9.86,19.93-18.58,46-30.75,19.15-8.95,28.65-16,38.35-29.6a93.15,93.15,0,0,0,8.7-14.61c6.95-15.17,11.77-44.44,11.77-65.66V477.8a24.09,24.09,0,0,1,24.1-24.09h236.92a24.09,24.09,0,0,1,24.1,24.09v3.61c0,21.22,4.82,50.49,11.77,65.66a93.15,93.15,0,0,0,8.7,14.61c9.7,13.63,19.2,20.65,38.35,29.6,26,12.17,37.86,20.89,46,30.75a14.19,14.19,0,0,1,2.83,12.5h0"></path><rect class="cls-3" x="735.31" y="598.25" width="541.96" height="638.99" rx="96.44"></rect><path class="cls-2" d="M1247.38,694.68v446.11a66.63,66.63,0,0,1-66.54,66.56H831.75a66.62,66.62,0,0,1-66.56-66.56V694.68a66.63,66.63,0,0,1,66.56-66.55h349.09A66.64,66.64,0,0,1,1247.38,694.68Z"></path><rect class="cls-4" x="817.71" y="721.76" width="379.03" height="388.6"></rect><path class="cls-5" d="M1247.38,694.68v446.11a66.63,66.63,0,0,1-66.54,66.56H831.75a66.62,66.62,0,0,1-66.56-66.56V694.68a66.63,66.63,0,0,1,66.56-66.55h349.09A66.64,66.64,0,0,1,1247.38,694.68Z"></path><rect class="cls-6" x="735.31" y="598.25" width="541.96" height="638.99" rx="96.44"></rect><path class="cls-6" d="M1256.49,1200.6h0a14.19,14.19,0,0,1-2.83,12.5c-8.13,9.86-19.94,18.58-46,30.75-19.15,9-28.65,16-38.35,29.6a93.15,93.15,0,0,0-8.7,14.61c-6.95,15.17-11.77,44.44-11.77,65.66v3.61a24.09,24.09,0,0,1-24.1,24.09H887.83a24.09,24.09,0,0,1-24.1-24.09v-3.61c0-21.22-4.82-50.49-11.77-65.66a93.15,93.15,0,0,0-8.7-14.61c-9.7-13.63-19.2-20.65-38.35-29.6-26.06-12.17-37.87-20.89-46-30.75a14.22,14.22,0,0,1-2.82-12.5h0"></path><path class="cls-6" d="M756.09,634.53h0a14.19,14.19,0,0,1,2.83-12.5c8.12-9.86,19.93-18.58,46-30.75,19.15-8.95,28.65-16,38.35-29.6a93.15,93.15,0,0,0,8.7-14.61c6.95-15.17,11.77-44.44,11.77-65.66V477.8a24.09,24.09,0,0,1,24.1-24.09h236.92a24.09,24.09,0,0,1,24.1,24.09v3.61c0,21.22,4.82,50.49,11.77,65.66a93.15,93.15,0,0,0,8.7,14.61c9.7,13.63,19.2,20.65,38.35,29.6,26,12.17,37.86,20.89,46,30.75a14.19,14.19,0,0,1,2.83,12.5h0"></path><rect class="cls-5" x="817.71" y="721.76" width="379.03" height="388.6"></rect><path class="cls-6" d="M1277.27,847.59h4.35a8.09,8.09,0,0,1,8.09,8.08v138a8.09,8.09,0,0,1-8.09,8.09h-4.35"></path><path class="cls-6" d="M1277.27,732.73h18a10.14,10.14,0,0,1,10.14,10.14v43A10.14,10.14,0,0,1,1295.26,796h-18a0,0,0,0,1,0,0V732.73A0,0,0,0,1,1277.27,732.73Z"></path><circle class="cls-7" cx="1083.08" cy="1177.35" r="16.6"></circle><rect class="cls-2" x="1280.24" y="739.77" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="750.91" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="762.06" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="773.2" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="784.34" width="16.77" height="4.59" rx="2.29"></rect></g></svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "play_store_icon_114px-2.png",
|
||||
"filename" : "unknown.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 12 KiB |
129
Meshtastic/Assets.xcassets/UNSET.imageset/unknown.svg
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
class="svg-icon"
|
||||
style="overflow:hidden;fill:currentColor"
|
||||
viewBox="0 0 909.87988 546.85529"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xml:space="preserve"
|
||||
width="909.87988"
|
||||
height="546.85529"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs3"><style
|
||||
id="style1">.cls-1{fill:#383838;}.cls-2{fill:#9f9f9e;}.cls-3{fill:#cbcccb;}.cls-4{fill:#b7b7b7;}.cls-5{fill:#353535;}.cls-6{fill:#b1a368;}.cls-7{fill:#2c2d2d;}.cls-10,.cls-11,.cls-8,.cls-9{fill:none;stroke:#050606;}.cls-10,.cls-11,.cls-8{stroke-miterlimit:10;}.cls-8,.cls-9{stroke-width:2px;}.cls-9{stroke-linecap:round;stroke-linejoin:round;}.cls-10{stroke-width:2.04px;}.cls-11{stroke-width:1.99px;}.cls-12{fill:#c08c2d;}.cls-13{fill:#af7a2b;}</style></defs><g
|
||||
id="Layer_7"
|
||||
data-name="Layer 7"
|
||||
transform="translate(-646.6554,-758.05941)"><path
|
||||
class="cls-2"
|
||||
d="m 1545.1753,893.49468 h 4.69 a 5.67,5.67 0 0 1 5.67,5.67 v 84.64998 a 5.67,5.67 0 0 1 -5.67,5.67 h -4.69"
|
||||
id="path1-4" /><rect
|
||||
class="cls-3"
|
||||
x="647.6554"
|
||||
y="862.80469"
|
||||
width="897.52002"
|
||||
height="441.10999"
|
||||
rx="11.7"
|
||||
id="rect2" /><path
|
||||
class="cls-2"
|
||||
d="m 681.12532,862.80468 v 113.47998 a 3.67,3.67 0 0 0 3.67,3.67 h 41 a 2.35,2.35 0 0 1 2.35,2.35 V 1303.9147 H 1517.6053 V 862.80468 Z M 1492.6453,1278.9147 H 753.18532 V 972.01466 a 17.06,17.06 0 0 0 -17.06,-17.06 h -27.5 a 2.5,2.5 0 0 1 -2.5,-2.5 v -62.14998 a 2.5,2.5 0 0 1 2.5,-2.5 h 783.99998 z"
|
||||
id="path2-7" /><path
|
||||
class="cls-3"
|
||||
d="M 1492.6453,887.80468 V 1278.9147 H 753.18532 V 972.01466 a 17,17 0 0 0 -7.2,-13.92 v -70.28998 z"
|
||||
id="path3-7" /><path
|
||||
class="cls-4"
|
||||
d="m 745.98532,887.80468 v 70.28998 a 17,17 0 0 0 -9.86,-3.14 h -27.5 a 2.5,2.5 0 0 1 -2.5,-2.5 v -62.14998 a 2.5,2.5 0 0 1 2.5,-2.5 z"
|
||||
id="path4" /><rect
|
||||
class="cls-2"
|
||||
x="672.10535"
|
||||
y="1011.4448"
|
||||
width="13.53"
|
||||
height="148.39999"
|
||||
id="rect4" /><path
|
||||
class="cls-6"
|
||||
d="m 1077.2923,853.76468 h 71.71 a 2.55,2.55 0 0 1 2.55,2.55 v 6.48 h -76.8 v -6.48 a 2.55,2.55 0 0 1 2.54,-2.55 z"
|
||||
id="path7" /><path
|
||||
class="cls-8"
|
||||
d="m 1082.9205,761.22647 h 60.8838 a 6.1958134,4.8451518 0 0 1 6.1958,4.84516 v 77.32638 h -73.2754 v -77.32638 a 6.1958134,4.8451518 0 0 1 6.1958,-4.84516 z"
|
||||
id="path39"
|
||||
style="fill:#b1a368" /><rect
|
||||
class="cls-8"
|
||||
x="1066.9833"
|
||||
y="778.19855"
|
||||
width="91.504646"
|
||||
height="55.957298"
|
||||
rx="5.5511622"
|
||||
id="rect39"
|
||||
style="fill:#b1a368" /><path
|
||||
class="cls-2"
|
||||
d="m 1158.4522,782.53954 v 47.24724 a 5.5153484,4.3130254 0 0 1 -5.5512,4.34102 h -80.3665 a 5.5511623,4.341032 0 0 1 -5.587,-4.34102 v -47.24724 a 5.5511623,4.341032 0 0 1 5.587,-4.34103 h 80.5098 a 5.5153484,4.3130254 0 0 1 5.4079,4.34103 z"
|
||||
id="path41-4"
|
||||
style="fill:none;stroke:#050606;stroke-width:3.16706;stroke-miterlimit:10" /><rect
|
||||
class="cls-6"
|
||||
x="1079.9424"
|
||||
y="843.73468"
|
||||
width="65.989998"
|
||||
height="10.03"
|
||||
id="rect8" /><path
|
||||
class="cls-8"
|
||||
d="M 1492.6453,887.80468 V 1278.9147 H 753.18532 V 972.01466 a 17.06,17.06 0 0 0 -17.06,-17.06 h -27.5 a 2.5,2.5 0 0 1 -2.5,-2.5 v -62.14998 a 2.5,2.5 0 0 1 2.5,-2.5 h 783.99998 m 25,-25 H 681.12532 v 113.47998 a 3.68,3.68 0 0 0 3.67,3.67 h 41 a 2.35,2.35 0 0 1 2.35,2.35 V 1303.9147 H 1517.6053 V 862.80468 Z"
|
||||
id="path10" /><line
|
||||
class="cls-8"
|
||||
x1="745.99536"
|
||||
y1="958.09467"
|
||||
x2="745.99536"
|
||||
y2="887.80469"
|
||||
id="line10" /><rect
|
||||
class="cls-8"
|
||||
x="672.10535"
|
||||
y="1011.4448"
|
||||
width="13.53"
|
||||
height="148.39999"
|
||||
id="rect11" /><path
|
||||
class="cls-8"
|
||||
d="m 1545.1753,893.49468 h 4.69 a 5.67,5.67 0 0 1 5.67,5.67 v 84.64998 a 5.67,5.67 0 0 1 -5.67,5.67 h -4.69"
|
||||
id="path14" /><path
|
||||
class="cls-10"
|
||||
d="m 1077.2923,853.76468 h 71.71 a 2.55,2.55 0 0 1 2.55,2.55 v 6.48 h -76.8 v -6.48 a 2.55,2.55 0 0 1 2.54,-2.55 z"
|
||||
id="path16" /><rect
|
||||
class="cls-11"
|
||||
x="1079.9424"
|
||||
y="843.73468"
|
||||
width="65.989998"
|
||||
height="10.03"
|
||||
id="rect17" /><path
|
||||
class="cls-2"
|
||||
d="m 725.27532,910.38466 a 14,14 0 1 0 14,14 13.95,13.95 0 0 0 -14,-14 z m 0,21.5 a 7.55,7.55 0 1 1 7.54,-7.55 7.55,7.55 0 0 1 -7.54,7.55 z"
|
||||
id="path19" /><circle
|
||||
class="cls-8"
|
||||
cx="725.27539"
|
||||
cy="924.33466"
|
||||
r="7.5500002"
|
||||
id="circle19" /><circle
|
||||
class="cls-8"
|
||||
cx="725.27539"
|
||||
cy="924.33466"
|
||||
r="13.95"
|
||||
id="circle20" /><path
|
||||
d="m 445.36309,440.05365 c 0,11.52004 10.38375,20.85861 23.19309,20.85861 12.80937,0 23.19311,-9.33857 23.19311,-20.85861 0,-11.52005 -10.38374,-20.85861 -23.19311,-20.85861 -12.80934,0 -23.19309,9.33856 -23.19309,20.85861 z"
|
||||
fill="#ccc"
|
||||
id="path1"
|
||||
style="overflow:hidden;fill:#4d4d4d;stroke-width:0.458227"
|
||||
transform="translate(646.6554,758.05941)" /><path
|
||||
d="m 469.40305,538.40107 c -119.83415,0 -217.31582,-93.40624 -217.31582,-208.23067 0,-114.82425 97.48167,-208.23058 217.31582,-208.23058 119.83417,0 217.31585,93.40633 217.31585,208.23058 0,114.82443 -97.48168,208.23067 -217.31585,208.23067 z m 0,-386.58065 c -102.63515,0 -186.13149,80.00572 -186.13149,178.34998 0,98.32948 83.49634,178.34997 186.13149,178.34997 102.61966,0 186.13151,-80.01997 186.13151,-178.34997 0,-98.34426 -83.51185,-178.34998 -186.13151,-178.34998 z"
|
||||
fill="#ccc"
|
||||
id="path2"
|
||||
style="overflow:hidden;fill:#4d4d4d;stroke-width:0.474832"
|
||||
transform="translate(646.6554,758.05941)" /><path
|
||||
d="m 468.55618,391.96713 c -8.53552,0 -15.46205,-6.22977 -15.46205,-13.90533 v -23.51468 c 0,-22.75028 19.32709,-40.13201 36.39722,-55.47009 12.50833,-11.26363 25.45056,-22.88885 25.45056,-32.16398 0,-23.18095 -20.81195,-42.03718 -46.38573,-42.03718 -26.0067,0 -46.38619,18.0497 -46.38619,41.09158 0,7.67594 -6.92654,13.90533 -15.46208,13.90533 -8.53554,0 -15.46207,-6.22977 -15.46207,-13.9058 0,-37.99002 34.68046,-68.90262 77.31034,-68.90262 42.62989,0 77.31034,31.32967 77.31034,69.84869 0,20.81694 -17.54944,36.5856 -34.51132,51.84064 -13.452,12.07016 -27.33645,24.55758 -27.33645,35.77907 v 23.51468 c 0,7.6764 -6.92702,13.91969 -15.46257,13.91969 z"
|
||||
fill="#ccc"
|
||||
id="path3"
|
||||
style="overflow:hidden;fill:#4d4d4d;stroke-width:0.458227;stroke:#000000;stroke-opacity:1"
|
||||
transform="translate(646.6554,758.05941)" /><rect
|
||||
class="cls-8"
|
||||
x="647.6554"
|
||||
y="862.80469"
|
||||
width="897.52002"
|
||||
height="441.10999"
|
||||
rx="11.7"
|
||||
id="rect28" /></g></svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
12
Meshtastic/Assets.xcassets/WIOWM1110.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "wio-tracker-wm1110.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/WIOWM1110.imageset/wio-tracker-wm1110.svg
vendored
Normal file
|
After Width: | Height: | Size: 91 KiB |
12
Meshtastic/Assets.xcassets/WISMESHTAP.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "rak-wismeshtap.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Meshtastic/Assets.xcassets/WISMESHTAP.imageset/rak-wismeshtap.svg
vendored
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
15
Meshtastic/CoreData/NodeInfoEntity+CoreDataClass.swift
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// NodeInfoEntity+CoreDataClass.swift
|
||||
//
|
||||
//
|
||||
// Created by Brian Floersch on 2/5/25.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
@objc(NodeInfoEntity)
|
||||
public class NodeInfoEntity: NSManagedObject {
|
||||
|
||||
}
|
||||
200
Meshtastic/CoreData/NodeInfoEntity+CoreDataProperties.swift
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// NodeInfoEntity+CoreDataProperties.swift
|
||||
//
|
||||
//
|
||||
// Created by Brian Floersch on 2/5/25.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
extension NodeInfoEntity {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<NodeInfoEntity> {
|
||||
return NSFetchRequest<NodeInfoEntity>(entityName: "NodeInfoEntity")
|
||||
}
|
||||
|
||||
@NSManaged public var bleName: String?
|
||||
@NSManaged public var channel: Int32
|
||||
@NSManaged public var favorite: Bool
|
||||
@NSManaged public var firstHeard: Date?
|
||||
@NSManaged public var hopsAway: Int32
|
||||
@NSManaged public var id: Int64
|
||||
@NSManaged public var ignored: Bool
|
||||
@NSManaged public var lastHeard: Date?
|
||||
@NSManaged public var num: Int64
|
||||
@NSManaged public var peripheralId: String?
|
||||
@NSManaged public var rssi: Int32
|
||||
@NSManaged public var sessionExpiration: Date?
|
||||
@NSManaged public var sessionPasskey: Data?
|
||||
@NSManaged public var snr: Float
|
||||
@NSManaged public var viaMqtt: Bool
|
||||
@NSManaged public var ambientLightingConfig: AmbientLightingConfigEntity?
|
||||
@NSManaged public var bluetoothConfig: BluetoothConfigEntity?
|
||||
@NSManaged public var cannedMessageConfig: CannedMessageConfigEntity?
|
||||
@NSManaged public var detectionSensorConfig: DetectionSensorConfigEntity?
|
||||
@NSManaged public var deviceConfig: DeviceConfigEntity?
|
||||
@NSManaged public var displayConfig: DisplayConfigEntity?
|
||||
@NSManaged public var externalNotificationConfig: ExternalNotificationConfigEntity?
|
||||
@NSManaged public var loRaConfig: LoRaConfigEntity?
|
||||
@NSManaged public var metadata: DeviceMetadataEntity?
|
||||
@NSManaged public var mqttConfig: MQTTConfigEntity?
|
||||
@NSManaged public var myInfo: MyInfoEntity?
|
||||
@NSManaged public var networkConfig: NetworkConfigEntity?
|
||||
@NSManaged public var pax: NSOrderedSet?
|
||||
@NSManaged public var paxCounterConfig: PaxCounterConfigEntity?
|
||||
@NSManaged public var positionConfig: PositionConfigEntity?
|
||||
@NSManaged public var positions: NSOrderedSet?
|
||||
@NSManaged public var powerConfig: PowerConfigEntity?
|
||||
@NSManaged public var rangeTestConfig: RangeTestConfigEntity?
|
||||
@NSManaged public var rtttlConfig: RTTTLConfigEntity?
|
||||
@NSManaged public var securityConfig: SecurityConfigEntity?
|
||||
@NSManaged public var serialConfig: SerialConfigEntity?
|
||||
@NSManaged public var storeForwardConfig: StoreForwardConfigEntity?
|
||||
@NSManaged public var telemetries: NSOrderedSet?
|
||||
@NSManaged public var telemetryConfig: TelemetryConfigEntity?
|
||||
@NSManaged public var traceRoutes: NSOrderedSet?
|
||||
@NSManaged public var user: UserEntity?
|
||||
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for pax
|
||||
extension NodeInfoEntity {
|
||||
|
||||
@objc(insertObject:inPaxAtIndex:)
|
||||
@NSManaged public func insertIntoPax(_ value: PaxCounterEntity, at idx: Int)
|
||||
|
||||
@objc(removeObjectFromPaxAtIndex:)
|
||||
@NSManaged public func removeFromPax(at idx: Int)
|
||||
|
||||
@objc(insertPax:atIndexes:)
|
||||
@NSManaged public func insertIntoPax(_ values: [PaxCounterEntity], at indexes: NSIndexSet)
|
||||
|
||||
@objc(removePaxAtIndexes:)
|
||||
@NSManaged public func removeFromPax(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectInPaxAtIndex:withObject:)
|
||||
@NSManaged public func replacePax(at idx: Int, with value: PaxCounterEntity)
|
||||
|
||||
@objc(replacePaxAtIndexes:withPax:)
|
||||
@NSManaged public func replacePax(at indexes: NSIndexSet, with values: [PaxCounterEntity])
|
||||
|
||||
@objc(addPaxObject:)
|
||||
@NSManaged public func addToPax(_ value: PaxCounterEntity)
|
||||
|
||||
@objc(removePaxObject:)
|
||||
@NSManaged public func removeFromPax(_ value: PaxCounterEntity)
|
||||
|
||||
@objc(addPax:)
|
||||
@NSManaged public func addToPax(_ values: NSOrderedSet)
|
||||
|
||||
@objc(removePax:)
|
||||
@NSManaged public func removeFromPax(_ values: NSOrderedSet)
|
||||
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for positions
|
||||
extension NodeInfoEntity {
|
||||
|
||||
@objc(insertObject:inPositionsAtIndex:)
|
||||
@NSManaged public func insertIntoPositions(_ value: PositionEntity, at idx: Int)
|
||||
|
||||
@objc(removeObjectFromPositionsAtIndex:)
|
||||
@NSManaged public func removeFromPositions(at idx: Int)
|
||||
|
||||
@objc(insertPositions:atIndexes:)
|
||||
@NSManaged public func insertIntoPositions(_ values: [PositionEntity], at indexes: NSIndexSet)
|
||||
|
||||
@objc(removePositionsAtIndexes:)
|
||||
@NSManaged public func removeFromPositions(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectInPositionsAtIndex:withObject:)
|
||||
@NSManaged public func replacePositions(at idx: Int, with value: PositionEntity)
|
||||
|
||||
@objc(replacePositionsAtIndexes:withPositions:)
|
||||
@NSManaged public func replacePositions(at indexes: NSIndexSet, with values: [PositionEntity])
|
||||
|
||||
@objc(addPositionsObject:)
|
||||
@NSManaged public func addToPositions(_ value: PositionEntity)
|
||||
|
||||
@objc(removePositionsObject:)
|
||||
@NSManaged public func removeFromPositions(_ value: PositionEntity)
|
||||
|
||||
@objc(addPositions:)
|
||||
@NSManaged public func addToPositions(_ values: NSOrderedSet)
|
||||
|
||||
@objc(removePositions:)
|
||||
@NSManaged public func removeFromPositions(_ values: NSOrderedSet)
|
||||
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for telemetries
|
||||
extension NodeInfoEntity {
|
||||
|
||||
@objc(insertObject:inTelemetriesAtIndex:)
|
||||
@NSManaged public func insertIntoTelemetries(_ value: TelemetryEntity, at idx: Int)
|
||||
|
||||
@objc(removeObjectFromTelemetriesAtIndex:)
|
||||
@NSManaged public func removeFromTelemetries(at idx: Int)
|
||||
|
||||
@objc(insertTelemetries:atIndexes:)
|
||||
@NSManaged public func insertIntoTelemetries(_ values: [TelemetryEntity], at indexes: NSIndexSet)
|
||||
|
||||
@objc(removeTelemetriesAtIndexes:)
|
||||
@NSManaged public func removeFromTelemetries(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectInTelemetriesAtIndex:withObject:)
|
||||
@NSManaged public func replaceTelemetries(at idx: Int, with value: TelemetryEntity)
|
||||
|
||||
@objc(replaceTelemetriesAtIndexes:withTelemetries:)
|
||||
@NSManaged public func replaceTelemetries(at indexes: NSIndexSet, with values: [TelemetryEntity])
|
||||
|
||||
@objc(addTelemetriesObject:)
|
||||
@NSManaged public func addToTelemetries(_ value: TelemetryEntity)
|
||||
|
||||
@objc(removeTelemetriesObject:)
|
||||
@NSManaged public func removeFromTelemetries(_ value: TelemetryEntity)
|
||||
|
||||
@objc(addTelemetries:)
|
||||
@NSManaged public func addToTelemetries(_ values: NSOrderedSet)
|
||||
|
||||
@objc(removeTelemetries:)
|
||||
@NSManaged public func removeFromTelemetries(_ values: NSOrderedSet)
|
||||
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for traceRoutes
|
||||
extension NodeInfoEntity {
|
||||
|
||||
@objc(insertObject:inTraceRoutesAtIndex:)
|
||||
@NSManaged public func insertIntoTraceRoutes(_ value: TraceRouteEntity, at idx: Int)
|
||||
|
||||
@objc(removeObjectFromTraceRoutesAtIndex:)
|
||||
@NSManaged public func removeFromTraceRoutes(at idx: Int)
|
||||
|
||||
@objc(insertTraceRoutes:atIndexes:)
|
||||
@NSManaged public func insertIntoTraceRoutes(_ values: [TraceRouteEntity], at indexes: NSIndexSet)
|
||||
|
||||
@objc(removeTraceRoutesAtIndexes:)
|
||||
@NSManaged public func removeFromTraceRoutes(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectInTraceRoutesAtIndex:withObject:)
|
||||
@NSManaged public func replaceTraceRoutes(at idx: Int, with value: TraceRouteEntity)
|
||||
|
||||
@objc(replaceTraceRoutesAtIndexes:withTraceRoutes:)
|
||||
@NSManaged public func replaceTraceRoutes(at indexes: NSIndexSet, with values: [TraceRouteEntity])
|
||||
|
||||
@objc(addTraceRoutesObject:)
|
||||
@NSManaged public func addToTraceRoutes(_ value: TraceRouteEntity)
|
||||
|
||||
@objc(removeTraceRoutesObject:)
|
||||
@NSManaged public func removeFromTraceRoutes(_ value: TraceRouteEntity)
|
||||
|
||||
@objc(addTraceRoutes:)
|
||||
@NSManaged public func addToTraceRoutes(_ values: NSOrderedSet)
|
||||
|
||||
@objc(removeTraceRoutes:)
|
||||
@NSManaged public func removeFromTraceRoutes(_ values: NSOrderedSet)
|
||||
|
||||
}
|
||||
15
Meshtastic/CoreData/UserEntity+CoreDataClass.swift
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// UserEntity+CoreDataClass.swift
|
||||
//
|
||||
//
|
||||
// Created by Brian Floersch on 2/5/25.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
@objc(UserEntity)
|
||||
public class UserEntity: NSManagedObject {
|
||||
|
||||
}
|
||||
108
Meshtastic/CoreData/UserEntity+CoreDataProperties.swift
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// UserEntity+CoreDataProperties.swift
|
||||
//
|
||||
//
|
||||
// Created by Brian Floersch on 2/5/25.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
extension UserEntity {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<UserEntity> {
|
||||
return NSFetchRequest<UserEntity>(entityName: "UserEntity")
|
||||
}
|
||||
|
||||
@NSManaged public var hwDisplayName: String?
|
||||
@NSManaged public var hwModel: String?
|
||||
@NSManaged public var hwModelId: Int32
|
||||
@NSManaged public var isLicensed: Bool
|
||||
@NSManaged public var keyMatch: Bool
|
||||
@NSManaged public var lastMessage: Date?
|
||||
@NSManaged public var longName: String?
|
||||
@NSManaged public var mute: Bool
|
||||
@NSManaged public var newPublicKey: Data?
|
||||
@NSManaged public var num: Int64
|
||||
@NSManaged public var numString: String?
|
||||
@NSManaged public var pkiEncrypted: Bool
|
||||
@NSManaged public var publicKey: Data?
|
||||
@NSManaged public var role: Int32
|
||||
@NSManaged public var shortName: String?
|
||||
@NSManaged public var userId: String?
|
||||
@NSManaged public var receivedMessages: NSOrderedSet?
|
||||
@NSManaged public var sentMessages: NSOrderedSet?
|
||||
@NSManaged public var userNode: NodeInfoEntity?
|
||||
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for receivedMessages
|
||||
extension UserEntity {
|
||||
|
||||
@objc(insertObject:inReceivedMessagesAtIndex:)
|
||||
@NSManaged public func insertIntoReceivedMessages(_ value: MessageEntity, at idx: Int)
|
||||
|
||||
@objc(removeObjectFromReceivedMessagesAtIndex:)
|
||||
@NSManaged public func removeFromReceivedMessages(at idx: Int)
|
||||
|
||||
@objc(insertReceivedMessages:atIndexes:)
|
||||
@NSManaged public func insertIntoReceivedMessages(_ values: [MessageEntity], at indexes: NSIndexSet)
|
||||
|
||||
@objc(removeReceivedMessagesAtIndexes:)
|
||||
@NSManaged public func removeFromReceivedMessages(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectInReceivedMessagesAtIndex:withObject:)
|
||||
@NSManaged public func replaceReceivedMessages(at idx: Int, with value: MessageEntity)
|
||||
|
||||
@objc(replaceReceivedMessagesAtIndexes:withReceivedMessages:)
|
||||
@NSManaged public func replaceReceivedMessages(at indexes: NSIndexSet, with values: [MessageEntity])
|
||||
|
||||
@objc(addReceivedMessagesObject:)
|
||||
@NSManaged public func addToReceivedMessages(_ value: MessageEntity)
|
||||
|
||||
@objc(removeReceivedMessagesObject:)
|
||||
@NSManaged public func removeFromReceivedMessages(_ value: MessageEntity)
|
||||
|
||||
@objc(addReceivedMessages:)
|
||||
@NSManaged public func addToReceivedMessages(_ values: NSOrderedSet)
|
||||
|
||||
@objc(removeReceivedMessages:)
|
||||
@NSManaged public func removeFromReceivedMessages(_ values: NSOrderedSet)
|
||||
|
||||
}
|
||||
|
||||
// MARK: Generated accessors for sentMessages
|
||||
extension UserEntity {
|
||||
|
||||
@objc(insertObject:inSentMessagesAtIndex:)
|
||||
@NSManaged public func insertIntoSentMessages(_ value: MessageEntity, at idx: Int)
|
||||
|
||||
@objc(removeObjectFromSentMessagesAtIndex:)
|
||||
@NSManaged public func removeFromSentMessages(at idx: Int)
|
||||
|
||||
@objc(insertSentMessages:atIndexes:)
|
||||
@NSManaged public func insertIntoSentMessages(_ values: [MessageEntity], at indexes: NSIndexSet)
|
||||
|
||||
@objc(removeSentMessagesAtIndexes:)
|
||||
@NSManaged public func removeFromSentMessages(at indexes: NSIndexSet)
|
||||
|
||||
@objc(replaceObjectInSentMessagesAtIndex:withObject:)
|
||||
@NSManaged public func replaceSentMessages(at idx: Int, with value: MessageEntity)
|
||||
|
||||
@objc(replaceSentMessagesAtIndexes:withSentMessages:)
|
||||
@NSManaged public func replaceSentMessages(at indexes: NSIndexSet, with values: [MessageEntity])
|
||||
|
||||
@objc(addSentMessagesObject:)
|
||||
@NSManaged public func addToSentMessages(_ value: MessageEntity)
|
||||
|
||||
@objc(removeSentMessagesObject:)
|
||||
@NSManaged public func removeFromSentMessages(_ value: MessageEntity)
|
||||
|
||||
@objc(addSentMessages:)
|
||||
@NSManaged public func addToSentMessages(_ values: NSOrderedSet)
|
||||
|
||||
@objc(removeSentMessages:)
|
||||
@NSManaged public func removeFromSentMessages(_ values: NSOrderedSet)
|
||||
|
||||
}
|
||||
|
|
@ -51,6 +51,10 @@ enum MeshMapTypes: Int, CaseIterable, Identifiable {
|
|||
}
|
||||
|
||||
enum MeshMapDistances: Double, CaseIterable, Identifiable {
|
||||
case twoMiles = 3218.69
|
||||
case fiveMiles = 8046.72
|
||||
case tenMiles = 16093.4
|
||||
case twentyFiveMiles = 40233.6
|
||||
case fiftyMiles = 80467.2
|
||||
case oneHundredMiles = 160934
|
||||
case twoHundredMiles = 321869
|
||||
|
|
|
|||
|
|
@ -22,32 +22,35 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
case repeater = 4
|
||||
case router = 2
|
||||
case routerClient = 3
|
||||
case routerLate = 11
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var name: String {
|
||||
switch self {
|
||||
case .client:
|
||||
return "Client"
|
||||
return "device.role.name.client".localized
|
||||
case .clientMute:
|
||||
return "Client Mute"
|
||||
return "device.role.name.clientMute".localized
|
||||
case .router:
|
||||
return "Router"
|
||||
return "device.role.name.router".localized
|
||||
case .routerClient:
|
||||
return "Router & Client"
|
||||
return "device.role.name.routerClient".localized
|
||||
case .repeater:
|
||||
return "Repeater"
|
||||
return "device.role.name.repeater".localized
|
||||
case .tracker:
|
||||
return "Tracker"
|
||||
return "device.role.name.tracker".localized
|
||||
case .sensor:
|
||||
return "Sensor"
|
||||
return "device.role.name.sensor".localized
|
||||
case .tak:
|
||||
return "TAK"
|
||||
return "device.role.name.tak".localized
|
||||
case .takTracker:
|
||||
return "TAK Tracker"
|
||||
return "device.role.name.takTracker".localized
|
||||
case .clientHidden:
|
||||
return "Client Hidden"
|
||||
return "device.role.name.clientHidden".localized
|
||||
case .lostAndFound:
|
||||
return "Lost and Found"
|
||||
return "device.role.name.lostAndFound".localized
|
||||
case .routerLate:
|
||||
return "device.role.name.routerlate".localized
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -75,6 +78,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
return "device.role.clienthidden".localized
|
||||
case .lostAndFound:
|
||||
return "device.role.lostandfound".localized
|
||||
case .routerLate:
|
||||
return "device.role.routerlate".localized
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +89,7 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
return "apps.iphone"
|
||||
case .clientMute:
|
||||
return "speaker.slash"
|
||||
case .router, .routerClient:
|
||||
case .router, .routerClient, .routerLate:
|
||||
return "wifi.router"
|
||||
case .repeater:
|
||||
return "repeat"
|
||||
|
|
@ -127,6 +132,8 @@ enum DeviceRoles: Int, CaseIterable, Identifiable {
|
|||
return Config.DeviceConfig.Role.clientHidden
|
||||
case .lostAndFound:
|
||||
return Config.DeviceConfig.Role.lostAndFound
|
||||
case .routerLate:
|
||||
return Config.DeviceConfig.Role.routerLate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,13 +149,13 @@ enum DisplayModes: Int, CaseIterable, Identifiable {
|
|||
var description: String {
|
||||
switch self {
|
||||
case .defaultMode:
|
||||
return "Default 128x64 screen layout"
|
||||
return "default.128x64.screen.layout".localized
|
||||
case .twoColor:
|
||||
return "Optimized for 2 color displays"
|
||||
return "optimized.for.2.color.displays".localized
|
||||
case .inverted:
|
||||
return "Inverted top bar for 2 Color display"
|
||||
return "inverted.top.bar.for.2.color.display".localized
|
||||
case .color:
|
||||
return "TFT Full Color Displays"
|
||||
return "tft.full.color.displays".localized
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.DisplayConfig.DisplayMode {
|
||||
|
|
|
|||
|
|
@ -83,49 +83,49 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
var description: String {
|
||||
switch self {
|
||||
case .unset:
|
||||
return "Please set a region"
|
||||
return "please.set.a.region".localized
|
||||
case .us:
|
||||
return "United States"
|
||||
return "united.states".localized
|
||||
case .eu433:
|
||||
return "European Union 433mhz"
|
||||
return "european.union.433mhz".localized
|
||||
case .eu868:
|
||||
return "European Union 868mhz"
|
||||
return "european.union.868mhz".localized
|
||||
case .cn:
|
||||
return "China"
|
||||
return "china".localized
|
||||
case .jp:
|
||||
return "Japan"
|
||||
return "japan".localized
|
||||
case .anz:
|
||||
return "Australia / New Zealand"
|
||||
return "australia.new.zealand".localized
|
||||
case .kr:
|
||||
return "Korea"
|
||||
return "korea".localized
|
||||
case .tw:
|
||||
return "Taiwan"
|
||||
return "taiwan".localized
|
||||
case .ru:
|
||||
return "Russia"
|
||||
return "russia".localized
|
||||
case .in:
|
||||
return "India"
|
||||
return "india".localized
|
||||
case .nz865:
|
||||
return "New Zealand 865mhz"
|
||||
return "new.zealand.865mhz".localized
|
||||
case .th:
|
||||
return "Thailand"
|
||||
return "thailand".localized
|
||||
case .ua433:
|
||||
return "Ukraine 433mhz"
|
||||
return "ukraine.433mhz".localized
|
||||
case .ua868:
|
||||
return "Ukraine 868mhz"
|
||||
return "ukraine.868mhz".localized
|
||||
case .lora24:
|
||||
return "2.4 GHZ"
|
||||
return "2.4ghz".localized
|
||||
case .my433:
|
||||
return "Malaysia 433mhz"
|
||||
return "malaysia.433mhz".localized
|
||||
case .my919:
|
||||
return "Malaysia 919mhz"
|
||||
return "malaysia.919mhz".localized
|
||||
case .sg923:
|
||||
return "Singapore 923mhz"
|
||||
return "singapore.923mhz".localized
|
||||
case .ph433:
|
||||
return "Philippines 433mhz"
|
||||
return "philippines.433mhz".localized
|
||||
case .ph868:
|
||||
return "Philippines 868mhz"
|
||||
return "philippines.868mhz".localized
|
||||
case .ph915:
|
||||
return "Philippines 915mhz"
|
||||
return "philippines.915mhz".localized
|
||||
}
|
||||
}
|
||||
var dutyCycle: Int {
|
||||
|
|
@ -176,6 +176,54 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return 100
|
||||
}
|
||||
}
|
||||
var isCountry: Bool {
|
||||
switch self {
|
||||
case .unset:
|
||||
return false
|
||||
case .us:
|
||||
return true
|
||||
case .eu433:
|
||||
return false
|
||||
case .eu868:
|
||||
return false
|
||||
case .cn:
|
||||
return true
|
||||
case .jp:
|
||||
return true
|
||||
case .anz:
|
||||
return false
|
||||
case .kr:
|
||||
return true
|
||||
case .tw:
|
||||
return true
|
||||
case .ru:
|
||||
return true
|
||||
case .in:
|
||||
return true
|
||||
case .nz865:
|
||||
return true
|
||||
case .th:
|
||||
return true
|
||||
case .ua433:
|
||||
return true
|
||||
case .ua868:
|
||||
return true
|
||||
case .lora24:
|
||||
return false
|
||||
case .my433:
|
||||
return true
|
||||
case .my919:
|
||||
return true
|
||||
case .sg923:
|
||||
return true
|
||||
case .ph433:
|
||||
return true
|
||||
case .ph868:
|
||||
return true
|
||||
case .ph915:
|
||||
return true
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.LoRaConfig.RegionCode {
|
||||
|
||||
switch self {
|
||||
|
|
@ -241,25 +289,25 @@ enum ModemPresets: Int, CaseIterable, Identifiable {
|
|||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
switch self {
|
||||
switch self {
|
||||
case .longFast:
|
||||
return "Long Range - Fast"
|
||||
return "long.range.fast".localized
|
||||
case .longSlow:
|
||||
return "Long Range - Slow"
|
||||
return "long.range.slow".localized
|
||||
case .longModerate:
|
||||
return "Long Range - Moderate"
|
||||
return "long.range.moderate".localized
|
||||
case .vLongSlow:
|
||||
return "Very Long Range - Slow"
|
||||
return "very.long.range.slow".localized
|
||||
case .medSlow:
|
||||
return "Medium Range - Slow"
|
||||
return "medium.range.slow".localized
|
||||
case .medFast:
|
||||
return "Medium Range - Fast"
|
||||
return "medium.range.fast".localized
|
||||
case .shortSlow:
|
||||
return "Short Range - Slow"
|
||||
return "short.range.slow".localized
|
||||
case .shortFast:
|
||||
return "Short Range - Fast"
|
||||
return "short.range.fast".localized
|
||||
case .shortTurbo:
|
||||
return "Short Range - Turbo"
|
||||
return "short.range.turbo".localized
|
||||
}
|
||||
}
|
||||
var name: String {
|
||||
|
|
|
|||
|
|
@ -20,17 +20,17 @@ enum Aqi: Int, CaseIterable, Identifiable {
|
|||
var description: String {
|
||||
switch self {
|
||||
case .good:
|
||||
return "Good"
|
||||
return "telemetry.good".localized
|
||||
case .moderate:
|
||||
return "Moderate"
|
||||
return "telemetry.moderate".localized
|
||||
case .sensitive:
|
||||
return "Unhealthy for Sensitive Groups"
|
||||
return "telemetry.sensitive".localized
|
||||
case .unhealthy:
|
||||
return "Unhealthy"
|
||||
return "telementry.unhealthy".localized
|
||||
case .veryUnhealthy:
|
||||
return "Very Unhealthy"
|
||||
return "telementry.veryUnhealthy".localized
|
||||
case .hazardous:
|
||||
return "Hazardous"
|
||||
return "telementry.hazardous".localized
|
||||
}
|
||||
}
|
||||
var color: Color {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,25 @@ func telemetryToCsvFile(telemetry: [TelemetryEntity], metricsType: Int) -> Strin
|
|||
csvString += ", "
|
||||
csvString += dm.time?.formattedDate(format: dateFormatString) ?? "unknown.age".localized
|
||||
}
|
||||
} else if metricsType == 2 {
|
||||
// Create Power Metrics Header
|
||||
csvString = "Channel 1 Voltage, Channel 1 Current, Channel 2 Voltage, Channel 2 Current, Channel 3 Voltage, Channel 3 Current, \("timestamp".localized)"
|
||||
for dm in telemetry where dm.metricsType == 2 {
|
||||
csvString += "\n"
|
||||
csvString += String(dm.powerCh1Voltage)
|
||||
csvString += ", "
|
||||
csvString += String(dm.powerCh1Current)
|
||||
csvString += ", "
|
||||
csvString += String(dm.powerCh2Voltage)
|
||||
csvString += ", "
|
||||
csvString += String(dm.powerCh2Current)
|
||||
csvString += ", "
|
||||
csvString += String(dm.powerCh3Voltage)
|
||||
csvString += ", "
|
||||
csvString += String(dm.powerCh3Current)
|
||||
csvString += ", "
|
||||
csvString += dm.time?.formattedDate(format: dateFormatString) ?? "unknown.age".localized
|
||||
}
|
||||
}
|
||||
return csvString
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ extension NodeInfoEntity {
|
|||
return self.telemetries?.filtered(using: NSPredicate(format: "metricsType == 1")).lastObject as? TelemetryEntity
|
||||
}
|
||||
|
||||
var latestPowerMetrics: TelemetryEntity? {
|
||||
return self.telemetries?.filtered(using: NSPredicate(format: "metricsType == 2")).lastObject as? TelemetryEntity
|
||||
}
|
||||
|
||||
var hasPositions: Bool {
|
||||
return self.positions?.count ?? 0 > 0
|
||||
}
|
||||
|
|
@ -39,6 +43,11 @@ extension NodeInfoEntity {
|
|||
return user?.sensorMessageList.count ?? 0 > 0
|
||||
}
|
||||
|
||||
var hasPowerMetrics: Bool {
|
||||
let powerMetrics = telemetries?.filter { ($0 as AnyObject).metricsType == 2 }
|
||||
return powerMetrics?.count ?? 0 > 0
|
||||
}
|
||||
|
||||
var hasTraceRoutes: Bool {
|
||||
let routes = traceRoutes?.filter { ($0 as AnyObject).response }
|
||||
return routes?.count ?? 0 > 0
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import SwiftUI
|
|||
|
||||
extension PositionEntity {
|
||||
|
||||
static func allPositionsFetchRequest() -> NSFetchRequest<PositionEntity> {
|
||||
@MainActor static func allPositionsFetchRequest() -> NSFetchRequest<PositionEntity> {
|
||||
let request: NSFetchRequest<PositionEntity> = PositionEntity.fetchRequest()
|
||||
request.fetchLimit = 1000
|
||||
request.returnsObjectsAsFaults = false
|
||||
|
|
@ -22,9 +22,9 @@ extension PositionEntity {
|
|||
request.sortDescriptors = [NSSortDescriptor(key: "time", ascending: false)]
|
||||
let positionPredicate = NSPredicate(format: "nodePosition != nil && (nodePosition.user.shortName != nil || nodePosition.user.shortName != '') && latest == true")
|
||||
|
||||
let pointOfInterest = LocationHelper.currentLocation
|
||||
let pointOfInterest = LocationsHandler.currentLocation
|
||||
|
||||
if pointOfInterest.latitude != LocationHelper.DefaultLocation.latitude && pointOfInterest.longitude != LocationHelper.DefaultLocation.longitude {
|
||||
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
|
||||
let d: Double = UserDefaults.meshMapDistance * 1.1
|
||||
let r: Double = 6371009
|
||||
let meanLatitidue = pointOfInterest.latitude * .pi / 180
|
||||
|
|
@ -88,7 +88,7 @@ extension PositionEntity {
|
|||
}
|
||||
|
||||
extension PositionEntity: MKAnnotation {
|
||||
public var coordinate: CLLocationCoordinate2D { nodeCoordinate ?? LocationHelper.DefaultLocation }
|
||||
public var coordinate: CLLocationCoordinate2D { nodeCoordinate ?? LocationsHandler.DefaultLocation }
|
||||
public var title: String? { nodePosition?.user?.shortName ?? "unknown".localized }
|
||||
public var subtitle: String? { time?.formatted() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,48 +33,79 @@ extension UserEntity {
|
|||
let unreadMessages = messageList.filter { ($0 as AnyObject).read == false }
|
||||
return unreadMessages.count
|
||||
}
|
||||
|
||||
/// SVG Images for Vendors who are signed project backers
|
||||
var hardwareImage: String? {
|
||||
guard let hwModel else { return nil }
|
||||
switch hwModel {
|
||||
case "HELTECV1", "HELTECV3", "HELTECV20", "HELTECV21":
|
||||
/// Heltec
|
||||
case "HELTECHT62":
|
||||
return "HELTECHT62"
|
||||
case "HELTECMESHNODET114":
|
||||
return "HELTECMESHNODET114"
|
||||
case "HELTECV3":
|
||||
return "HELTECV3"
|
||||
case "HELTECVISIONMASTERE213":
|
||||
return "HELTECVISIONMASTERE213"
|
||||
case "HELTECVISIONMASTERE290":
|
||||
return "HELTECVISIONMASTERE290"
|
||||
case "HELTECWIRELESSPAPER", "HELTECWIRELESSPAPERV10":
|
||||
return "HELTECWIRELESSPAPER"
|
||||
case "HELTECWIRELESSTRACKER", "HELTECWIRELESSTRACKERV10":
|
||||
return "HELTECWIRELESSTRACKER"
|
||||
case "HELTECWSLV3":
|
||||
return "HELTECWSLV3"
|
||||
case "LILYGOTBEAMSCORE":
|
||||
/// LilyGO
|
||||
case "TDECK":
|
||||
return "TDECK"
|
||||
case "TECHO":
|
||||
return "TECHO"
|
||||
case "TWATCHS3":
|
||||
return "TWATCHS3"
|
||||
case "LILYGOTBEAMS3CORE":
|
||||
return "LILYGOTBEAMS3CORE"
|
||||
case "TBEAM", "TBEAM_V0P7":
|
||||
return "TBEAM"
|
||||
case "TLORAC6":
|
||||
return "TLORAC6"
|
||||
case "TLORAT3S3EPAPER":
|
||||
return "TLORAT3S3EPAPER"
|
||||
case "TLORAT3S3V1":
|
||||
return "TLORAT3S3V1"
|
||||
case "TLORAV211P6":
|
||||
return "TLORAV211P6"
|
||||
case "TLORAV211P8":
|
||||
return "TLORAV211P8"
|
||||
/// Seeed Studio
|
||||
case "SENSECAPINDICATOR":
|
||||
return "SENSECAPINDICATOR"
|
||||
case "TRACKERT1000E":
|
||||
return "TRACKERT1000E"
|
||||
case "SEEEDXIAOS3":
|
||||
return "SEEEDXIAOS3"
|
||||
case "WIOWM1110":
|
||||
return "WIOWM1110"
|
||||
/// RAK Wireless
|
||||
case "RAK4631":
|
||||
return "RAK4631"
|
||||
case "RAK11310":
|
||||
return "RAK11310"
|
||||
case "WISMESHTAP":
|
||||
return "WISMESHTAP"
|
||||
/// B&Q Consulting
|
||||
case "NANOG1", "NANOG1EXPLORER":
|
||||
return "NANOG1"
|
||||
case "NANOG2ULTRA":
|
||||
return "NANOG2ULTRA"
|
||||
case "RAK4631":
|
||||
return "RAK4631"
|
||||
case "RAK11200":
|
||||
return "RAK11200"
|
||||
case "SOLAR_NODE":
|
||||
return "SOLAR_NODE"
|
||||
case "STATIONG1":
|
||||
return "STATIONG1"
|
||||
case "ТВЕАМ", "TBEAMVOP7":
|
||||
return "ТВЕАМ"
|
||||
case "TECHO":
|
||||
return "TECHO"
|
||||
case "TLORAV1", "TLORAV11P3":
|
||||
return "TLORAV1"
|
||||
case "TLORAV2", "TLORAT3S3", "TLORAV211P6", "TLORAV211P8":
|
||||
return "TLORABOARD"
|
||||
case "UNPHONE":
|
||||
return "UNPHONE"
|
||||
case "STATIONG2":
|
||||
return "STATIONG2"
|
||||
/// DIY Devices
|
||||
case "RPIPICO":
|
||||
return "RPIPICO"
|
||||
default:
|
||||
return "UNSET"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func createUser(num: Int64, context: NSManagedObjectContext) -> UserEntity {
|
||||
let newUser = UserEntity(context: context)
|
||||
newUser.num = Int64(num)
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ extension WaypointEntity {
|
|||
}
|
||||
|
||||
extension WaypointEntity: MKAnnotation {
|
||||
public var coordinate: CLLocationCoordinate2D { waypointCoordinate ?? LocationHelper.DefaultLocation }
|
||||
public var coordinate: CLLocationCoordinate2D { waypointCoordinate ?? LocationsHandler.DefaultLocation }
|
||||
public var title: String? { name ?? "Dropped Pin" }
|
||||
public var subtitle: String? {
|
||||
(longDescription ?? "") +
|
||||
|
|
|
|||
|
|
@ -9,6 +9,14 @@ import Foundation
|
|||
|
||||
extension Date {
|
||||
|
||||
var lastHeard: String {
|
||||
if timeIntervalSince1970 > 0 {
|
||||
formatted()
|
||||
} else {
|
||||
"unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func formattedDate(format: String) -> String {
|
||||
let dateformat = DateFormatter()
|
||||
dateformat.dateFormat = format
|
||||
|
|
|
|||
|
|
@ -61,11 +61,10 @@ extension String {
|
|||
}
|
||||
|
||||
func camelCaseToWords() -> String {
|
||||
return unicodeScalars.dropFirst().reduce(String(prefix(1))) {
|
||||
return CharacterSet.uppercaseLetters.contains($1)
|
||||
? $0 + " " + String($1)
|
||||
: $0 + String($1)
|
||||
}
|
||||
return self
|
||||
.replacingOccurrences(of: "([a-z])([A-Z](?=[A-Z])[a-z]*)", with: "$1 $2", options: .regularExpression)
|
||||
.replacingOccurrences(of: "([A-Z])([A-Z][a-z])", with: "$1 $2", options: .regularExpression)
|
||||
.replacingOccurrences(of: "([a-z])([A-Z][a-z])", with: "$1 $2", options: .regularExpression)
|
||||
}
|
||||
|
||||
var length: Int {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
@Published var automaticallyReconnect: Bool = true
|
||||
@Published var mqttProxyConnected: Bool = false
|
||||
@Published var mqttError: String = ""
|
||||
public var minimumVersion = "2.0.0"
|
||||
public var minimumVersion = "2.3.15"
|
||||
public var connectedVersion: String
|
||||
public var isConnecting: Bool = false
|
||||
public var isConnected: Bool = false
|
||||
|
|
@ -242,14 +242,14 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
if errorCode == 6 { // CBError.Code.connectionTimeout The connection has timed out unexpectedly.
|
||||
// Happens when device is manually reset / powered off
|
||||
lastConnectionError = "🚨" + String.localizedStringWithFormat("ble.errorcode.6 %@".localized, e.localizedDescription)
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown", privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)")
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized, privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)")
|
||||
} else if errorCode == 7 { // CBError.Code.peripheralDisconnected The specified device has disconnected from us.
|
||||
// Seems to be what is received when a tbeam sleeps, immediately recconnecting does not work.
|
||||
if UserDefaults.preferredPeripheralId == peripheral.identifier.uuidString {
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: (peripheral.identifier.uuidString),
|
||||
title: "Radio Disconnected",
|
||||
title: "Radio Disconnected".localized,
|
||||
subtitle: "\(peripheral.name ?? "unknown".localized)",
|
||||
content: e.localizedDescription,
|
||||
target: "bluetooth",
|
||||
|
|
@ -258,18 +258,18 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
]
|
||||
manager.schedule()
|
||||
}
|
||||
lastConnectionError = "🚨 \(e.localizedDescription)"
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown", privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)")
|
||||
lastConnectionError = "🚨 \("The specified device has disconnected from us".localized)"
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized, privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)")
|
||||
} else if errorCode == 14 { // Peer removed pairing information
|
||||
// Forgetting and reconnecting seems to be necessary so we need to show the user an error telling them to do that
|
||||
lastConnectionError = "🚨 " + String.localizedStringWithFormat("ble.errorcode.14 %@".localized, e.localizedDescription)
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown") Error Code: \(errorCode, privacy: .public) Error: \(self.lastConnectionError, privacy: .public)")
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized) Error Code: \(errorCode, privacy: .public) Error: \(self.lastConnectionError, privacy: .public)")
|
||||
} else {
|
||||
if UserDefaults.preferredPeripheralId == peripheral.identifier.uuidString {
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: (peripheral.identifier.uuidString),
|
||||
title: "Radio Disconnected",
|
||||
title: "Radio Disconnected".localized,
|
||||
subtitle: "\(peripheral.name ?? "unknown".localized)",
|
||||
content: e.localizedDescription,
|
||||
target: "bluetooth",
|
||||
|
|
@ -279,12 +279,12 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
manager.schedule()
|
||||
}
|
||||
lastConnectionError = "🚨 \(e.localizedDescription)"
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown", privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)")
|
||||
Logger.services.error("🚨 [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized, privacy: .public) Error Code: \(errorCode, privacy: .public) Error: \(e.localizedDescription, privacy: .public)")
|
||||
}
|
||||
} else {
|
||||
// Disconnected without error which indicates user intent to disconnect
|
||||
// Happens when swiping to disconnect
|
||||
Logger.services.info("ℹ️ [BLE] Disconnected: \(peripheral.name ?? "Unknown", privacy: .public): User Initiated Disconnect")
|
||||
Logger.services.info("ℹ️ [BLE] Disconnected: \(peripheral.name ?? "Unknown".localized, privacy: .public): \(String(describing: "User Initiated Disconnect".localized))")
|
||||
}
|
||||
// Start a scan so the disconnected peripheral is moved to the peripherals[] if it is awake
|
||||
self.startScanning()
|
||||
|
|
@ -765,6 +765,15 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
context: context,
|
||||
appState: appState
|
||||
)
|
||||
case .alertApp:
|
||||
textMessageAppPacket(
|
||||
packet: decodedInfo.packet,
|
||||
wantRangeTestPackets: wantRangeTestPackets,
|
||||
critical: true,
|
||||
connectedNode: (self.connectedPeripheral != nil ? connectedPeripheral.num : 0),
|
||||
context: context,
|
||||
appState: appState
|
||||
)
|
||||
case .remoteHardwareApp:
|
||||
MeshLogger.log("🕸️ MESH PACKET received for Remote Hardware App UNHANDLED \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure")")
|
||||
case .positionApp:
|
||||
|
|
@ -834,73 +843,81 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
if let routingMessage = try? RouteDiscovery(serializedBytes: decodedInfo.packet.decoded.payload) {
|
||||
let traceRoute = getTraceRoute(id: Int64(decodedInfo.packet.decoded.requestID), context: context)
|
||||
traceRoute?.response = true
|
||||
if routingMessage.route.count == 0 {
|
||||
let snr = routingMessage.snrBack.count > 0 ? routingMessage.snrBack[0] / 4 : 0
|
||||
traceRoute?.snr = Float(snr)
|
||||
let logString = String.localizedStringWithFormat("mesh.log.traceroute.received.direct %@".localized, String(snr))
|
||||
MeshLogger.log("🪧 \(logString)")
|
||||
} else {
|
||||
guard let connectedNode = getNodeInfo(id: Int64(connectedPeripheral.num), context: context) else {
|
||||
return
|
||||
guard let connectedNode = getNodeInfo(id: Int64(connectedPeripheral.num), context: context) else {
|
||||
return
|
||||
}
|
||||
var hopNodes: [TraceRouteHopEntity] = []
|
||||
let connectedHop = TraceRouteHopEntity(context: context)
|
||||
connectedHop.time = Date()
|
||||
connectedHop.num = connectedPeripheral.num
|
||||
connectedHop.name = connectedNode.user?.longName ?? "???"
|
||||
// If nil, set to unknown, INT8_MIN (-128) then divide by 4
|
||||
connectedHop.snr = Float(routingMessage.snrBack.last ?? -128) / 4
|
||||
if let mostRecent = traceRoute?.node?.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
connectedHop.altitude = mostRecent.altitude
|
||||
connectedHop.latitudeI = mostRecent.latitudeI
|
||||
connectedHop.longitudeI = mostRecent.longitudeI
|
||||
traceRoute?.hasPositions = true
|
||||
}
|
||||
var routeString = "\(connectedNode.user?.longName ?? "???") --> "
|
||||
hopNodes.append(connectedHop)
|
||||
traceRoute?.hopsTowards = Int32(routingMessage.route.count)
|
||||
for (index, node) in routingMessage.route.enumerated() {
|
||||
var hopNode = getNodeInfo(id: Int64(node), context: context)
|
||||
if hopNode == nil && hopNode?.num ?? 0 > 0 && node != 4294967295 {
|
||||
hopNode = createNodeInfo(num: Int64(node), context: context)
|
||||
}
|
||||
var hopNodes: [TraceRouteHopEntity] = []
|
||||
let connectedHop = TraceRouteHopEntity(context: context)
|
||||
connectedHop.time = Date()
|
||||
connectedHop.num = connectedPeripheral.num
|
||||
connectedHop.name = connectedNode.user?.longName ?? "???"
|
||||
connectedHop.snr = Float(routingMessage.snrBack.last ?? 0 / 4)
|
||||
if let mostRecent = traceRoute?.node?.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
connectedHop.altitude = mostRecent.altitude
|
||||
connectedHop.latitudeI = mostRecent.latitudeI
|
||||
connectedHop.longitudeI = mostRecent.longitudeI
|
||||
traceRoute?.hasPositions = true
|
||||
let traceRouteHop = TraceRouteHopEntity(context: context)
|
||||
traceRouteHop.time = Date()
|
||||
if routingMessage.snrTowards.count >= index + 1 {
|
||||
traceRouteHop.snr = Float(routingMessage.snrTowards[index]) / 4
|
||||
} else {
|
||||
// If no snr in route, set unknown
|
||||
traceRouteHop.snr = -32
|
||||
}
|
||||
var routeString = "\(connectedNode.user?.longName ?? "???") --> "
|
||||
hopNodes.append(connectedHop)
|
||||
traceRoute?.hopsTowards = Int32(routingMessage.route.count)
|
||||
for (index, node) in routingMessage.route.enumerated() {
|
||||
var hopNode = getNodeInfo(id: Int64(node), context: context)
|
||||
if hopNode == nil && hopNode?.num ?? 0 > 0 && node != 4294967295 {
|
||||
hopNode = createNodeInfo(num: Int64(node), context: context)
|
||||
if let hn = hopNode, hn.hasPositions {
|
||||
if let mostRecent = hn.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
traceRouteHop.altitude = mostRecent.altitude
|
||||
traceRouteHop.latitudeI = mostRecent.latitudeI
|
||||
traceRouteHop.longitudeI = mostRecent.longitudeI
|
||||
traceRoute?.hasPositions = true
|
||||
}
|
||||
let traceRouteHop = TraceRouteHopEntity(context: context)
|
||||
traceRouteHop.time = Date()
|
||||
if routingMessage.snrTowards.count >= index + 1 {
|
||||
traceRouteHop.snr = Float(routingMessage.snrTowards[index] / 4)
|
||||
}
|
||||
if let hn = hopNode, hn.hasPositions {
|
||||
if let mostRecent = hn.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
traceRouteHop.altitude = mostRecent.altitude
|
||||
traceRouteHop.latitudeI = mostRecent.latitudeI
|
||||
traceRouteHop.longitudeI = mostRecent.longitudeI
|
||||
traceRoute?.hasPositions = true
|
||||
}
|
||||
}
|
||||
traceRouteHop.num = hopNode?.num ?? 0
|
||||
if hopNode != nil {
|
||||
if decodedInfo.packet.rxTime > 0 {
|
||||
hopNode?.lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(decodedInfo.packet.rxTime)))
|
||||
}
|
||||
}
|
||||
hopNodes.append(traceRouteHop)
|
||||
routeString += "\(hopNode?.user?.longName ?? (node == 4294967295 ? "Repeater" : String(hopNode?.num.toHex() ?? "unknown".localized))) \(hopNode?.viaMqtt ?? false ? "MQTT" : "") (\(traceRouteHop.snr > 0 ? hopNode?.snr ?? 0.0 : 0.0)dB) --> "
|
||||
}
|
||||
let destinationHop = TraceRouteHopEntity(context: context)
|
||||
destinationHop.name = traceRoute?.node?.user?.longName ?? "unknown".localized
|
||||
destinationHop.time = Date()
|
||||
destinationHop.snr = Float(routingMessage.snrTowards.last ?? 0 / 4)
|
||||
destinationHop.num = traceRoute?.node?.num ?? 0
|
||||
if let mostRecent = traceRoute?.node?.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
destinationHop.altitude = mostRecent.altitude
|
||||
destinationHop.latitudeI = mostRecent.latitudeI
|
||||
destinationHop.longitudeI = mostRecent.longitudeI
|
||||
traceRoute?.hasPositions = true
|
||||
traceRouteHop.num = hopNode?.num ?? 0
|
||||
if hopNode != nil {
|
||||
if decodedInfo.packet.rxTime > 0 {
|
||||
hopNode?.lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(decodedInfo.packet.rxTime)))
|
||||
}
|
||||
}
|
||||
hopNodes.append(destinationHop)
|
||||
/// Add the destination node to the end of the route towards string and the beginning of teh route back string
|
||||
routeString += "\(traceRoute?.node?.user?.longName ?? "unknown".localized) \((traceRoute?.node?.num ?? 0).toHex()) \(traceRoute?.node?.snr ?? 0 > 0 ? traceRoute?.node?.snr ?? 0 : 0.0)dB)"
|
||||
var routeBackString = "\(traceRoute?.node?.user?.longName ?? "unknown".localized) \((traceRoute?.node?.num ?? 0).toHex()) \(traceRoute?.node?.snr ?? 0 > 0 ? traceRoute?.node?.snr ?? 0 : 0.0)dB) --> "
|
||||
hopNodes.append(traceRouteHop)
|
||||
|
||||
let hopName = hopNode?.user?.longName ?? (node == 4294967295 ? "Repeater" : String(hopNode?.num.toHex() ?? "unknown".localized))
|
||||
let mqttLabel = hopNode?.viaMqtt ?? false ? "MQTT " : ""
|
||||
let snrLabel = (traceRouteHop.snr != -32) ? String(traceRouteHop.snr) : "unknown ".localized
|
||||
routeString += "\(hopName) \(mqttLabel)(\(snrLabel)dB) --> "
|
||||
}
|
||||
let destinationHop = TraceRouteHopEntity(context: context)
|
||||
destinationHop.name = traceRoute?.node?.user?.longName ?? "unknown".localized
|
||||
destinationHop.time = Date()
|
||||
// If nil, set to unknown, INT8_MIN (-128) then divide by 4
|
||||
destinationHop.snr = Float(routingMessage.snrTowards.last ?? -128) / 4
|
||||
destinationHop.num = traceRoute?.node?.num ?? 0
|
||||
if let mostRecent = traceRoute?.node?.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
destinationHop.altitude = mostRecent.altitude
|
||||
destinationHop.latitudeI = mostRecent.latitudeI
|
||||
destinationHop.longitudeI = mostRecent.longitudeI
|
||||
traceRoute?.hasPositions = true
|
||||
}
|
||||
hopNodes.append(destinationHop)
|
||||
/// Add the destination node to the end of the route towards string and the beginning of the route back string
|
||||
routeString += "\(traceRoute?.node?.user?.longName ?? "unknown".localized) \((traceRoute?.node?.num ?? 0).toHex()) (\(destinationHop.snr != -32 ? String(destinationHop.snr) : "unknown ".localized)dB)"
|
||||
traceRoute?.routeText = routeString
|
||||
// Default to -1 only fill in if routeBack is valid below
|
||||
traceRoute?.hopsBack = -1
|
||||
// Only if hopStart is set and there is an SNR entry
|
||||
if decodedInfo.packet.hopStart > 0 && routingMessage.snrBack.count > 0 {
|
||||
traceRoute?.hopsBack = Int32(routingMessage.routeBack.count)
|
||||
var routeBackString = "\(traceRoute?.node?.user?.longName ?? "unknown".localized) \((traceRoute?.node?.num ?? 0).toHex()) --> "
|
||||
for (index, node) in routingMessage.routeBack.enumerated() {
|
||||
var hopNode = getNodeInfo(id: Int64(node), context: context)
|
||||
if hopNode == nil && hopNode?.num ?? 0 > 0 && node != 4294967295 {
|
||||
|
|
@ -910,7 +927,10 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
traceRouteHop.time = Date()
|
||||
traceRouteHop.back = true
|
||||
if routingMessage.snrBack.count >= index + 1 {
|
||||
traceRouteHop.snr = Float(routingMessage.snrBack[index] / 4)
|
||||
traceRouteHop.snr = Float(routingMessage.snrBack[index]) / 4
|
||||
} else {
|
||||
// If no snr in route, set to unknown
|
||||
traceRouteHop.snr = -32
|
||||
}
|
||||
if let hn = hopNode, hn.hasPositions {
|
||||
if let mostRecent = hn.positions?.lastObject as? PositionEntity, mostRecent.time! >= Calendar.current.date(byAdding: .hour, value: -24, to: Date())! {
|
||||
|
|
@ -927,24 +947,45 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
}
|
||||
}
|
||||
hopNodes.append(traceRouteHop)
|
||||
routeBackString += "\(hopNode?.user?.longName ?? (node == 4294967295 ? "Repeater" : String(hopNode?.num.toHex() ?? "unknown".localized))) \(hopNode?.viaMqtt ?? false ? "MQTT" : "") (\(traceRouteHop.snr > 0 ? hopNode?.snr ?? 0.0 : 0.0)dB) --> "
|
||||
|
||||
let hopName = hopNode?.user?.longName ?? (node == 4294967295 ? "Repeater" : String(hopNode?.num.toHex() ?? "unknown".localized))
|
||||
let mqttLabel = hopNode?.viaMqtt ?? false ? "MQTT " : ""
|
||||
let snrLabel = (traceRouteHop.snr != -32) ? String(traceRouteHop.snr) : "unknown ".localized
|
||||
routeBackString += "\(hopName) \(mqttLabel)(\(snrLabel)dB) --> "
|
||||
}
|
||||
routeBackString += "\(connectedNode.user?.longName ?? String(connectedNode.num.toHex())) \(connectedNode.snr > 0 ? connectedNode.snr : 0.0)dB)"
|
||||
traceRoute?.routeText = routeString
|
||||
// If nil, set to unknown, INT8_MIN (-128) then divide by 4
|
||||
let snrBackLast = Float(routingMessage.snrBack.last ?? -128) / 4
|
||||
routeBackString += "\(connectedNode.user?.longName ?? String(connectedNode.num.toHex())) (\(snrBackLast != -32 ? String(snrBackLast) : "unknown ".localized)dB)"
|
||||
traceRoute?.routeBackText = routeBackString
|
||||
traceRoute?.hops = NSOrderedSet(array: hopNodes)
|
||||
traceRoute?.time = Date()
|
||||
do {
|
||||
try context.save()
|
||||
Logger.data.info("💾 Saved Trace Route")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
Logger.data.error("Error Updating Core Data TraceRouteHop: \(nsError, privacy: .public)")
|
||||
}
|
||||
let logString = String.localizedStringWithFormat("mesh.log.traceroute.received.route %@".localized, routeString)
|
||||
MeshLogger.log("🪧 \(logString)")
|
||||
}
|
||||
traceRoute?.hops = NSOrderedSet(array: hopNodes)
|
||||
traceRoute?.time = Date()
|
||||
|
||||
if let tr = traceRoute {
|
||||
let manager = LocalNotificationManager()
|
||||
manager.notifications = [
|
||||
Notification(
|
||||
id: (UUID().uuidString),
|
||||
title: "Traceroute Complete",
|
||||
subtitle: "TR received back from \(destinationHop.name ?? "unknown")",
|
||||
content: "Hops from: \(tr.hopsTowards), Hops back: \(tr.hopsBack)\n\(tr.routeText ?? "unknown".localized)\n\(tr.routeBackText ?? "unknown".localized)",
|
||||
target: "nodes",
|
||||
path: "meshtastic:///nodes?nodenum=\(connectedNode.user?.num ?? 0)"
|
||||
)
|
||||
]
|
||||
manager.schedule()
|
||||
}
|
||||
|
||||
do {
|
||||
try context.save()
|
||||
Logger.data.info("💾 Saved Trace Route")
|
||||
} catch {
|
||||
context.rollback()
|
||||
let nsError = error as NSError
|
||||
Logger.data.error("Error Updating Core Data TraceRouteHop: \(nsError, privacy: .public)")
|
||||
}
|
||||
let logString = String.localizedStringWithFormat("mesh.log.traceroute.received.route %@".localized, routeString)
|
||||
MeshLogger.log("🪧 \(logString)")
|
||||
}
|
||||
case .neighborinfoApp:
|
||||
if let neighborInfo = try? NeighborInfo(serializedBytes: decodedInfo.packet.decoded.payload) {
|
||||
|
|
@ -1870,6 +1911,64 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
return false
|
||||
}
|
||||
|
||||
public func setIgnoredNode(node: NodeInfoEntity, connectedNodeNum: Int64) -> Bool {
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setIgnoredNode = UInt32(node.num)
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedNodeNum)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = true
|
||||
var dataMessage = DataMessage()
|
||||
guard let adminData: Data = try? adminPacket.serializedData() else {
|
||||
return false
|
||||
}
|
||||
dataMessage.payload = adminData
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
meshPacket.decoded = dataMessage
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
guard let binaryData: Data = try? toRadio.serializedData() else {
|
||||
return false
|
||||
}
|
||||
|
||||
if connectedPeripheral?.peripheral.state ?? CBPeripheralState.disconnected == CBPeripheralState.connected {
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func removeIgnoredNode(node: NodeInfoEntity, connectedNodeNum: Int64) -> Bool {
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.removeIgnoredNode = UInt32(node.num)
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(connectedNodeNum)
|
||||
meshPacket.id = UInt32.random(in: UInt32(UInt8.max)..<UInt32.max)
|
||||
meshPacket.priority = MeshPacket.Priority.reliable
|
||||
meshPacket.wantAck = true
|
||||
var dataMessage = DataMessage()
|
||||
guard let adminData: Data = try? adminPacket.serializedData() else {
|
||||
return false
|
||||
}
|
||||
dataMessage.payload = adminData
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
meshPacket.decoded = dataMessage
|
||||
var toRadio: ToRadio!
|
||||
toRadio = ToRadio()
|
||||
toRadio.packet = meshPacket
|
||||
guard let binaryData: Data = try? toRadio.serializedData() else {
|
||||
return false
|
||||
}
|
||||
|
||||
if connectedPeripheral?.peripheral.state ?? CBPeripheralState.disconnected == CBPeripheralState.connected {
|
||||
connectedPeripheral.peripheral.writeValue(binaryData, for: TORADIO_characteristic, type: .withResponse)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func saveLicensedUser(ham: HamParameters, fromUser: UserEntity, toUser: UserEntity, adminIndex: Int32) -> Int64 {
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setHamMode = ham
|
||||
|
|
|
|||
|
|
@ -67,9 +67,11 @@ class LocalNotificationManager {
|
|||
if notification.userNum != nil {
|
||||
content.userInfo["userNum"] = notification.userNum
|
||||
}
|
||||
if notification.critical {
|
||||
content.sound = UNNotificationSound.defaultCritical
|
||||
}
|
||||
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
|
||||
let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: trigger)
|
||||
let request = UNNotificationRequest(identifier: notification.id, content: content, trigger: nil)
|
||||
|
||||
UNUserNotificationCenter.current().add(request) { error in
|
||||
if let error {
|
||||
|
|
@ -101,4 +103,5 @@ struct Notification {
|
|||
var messageId: Int64?
|
||||
var channel: Int32?
|
||||
var userNum: Int64?
|
||||
var critical: Bool = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,12 @@ import OSLog
|
|||
}
|
||||
|
||||
static let DefaultLocation = CLLocationCoordinate2D(latitude: 37.3346, longitude: -122.0090)
|
||||
static var currentLocation: CLLocationCoordinate2D {
|
||||
guard let location = shared.manager.location else {
|
||||
return DefaultLocation
|
||||
}
|
||||
return location.coordinate
|
||||
}
|
||||
|
||||
static var satsInView: Int {
|
||||
var sats = 0
|
||||
|
|
@ -139,4 +145,5 @@ import OSLog
|
|||
}
|
||||
return sats
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||