mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
commit
6a908d8ff3
29 changed files with 2635 additions and 369 deletions
77
.github/workflows/macos-dSYM.yml
vendored
77
.github/workflows/macos-dSYM.yml
vendored
|
|
@ -1,5 +1,10 @@
|
|||
name: Upload dSYM Files
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
|
|
@ -8,14 +13,70 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Generate/Download dSYM Files
|
||||
uses: ./release.sh
|
||||
- name: Select Xcode Version
|
||||
run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
||||
|
||||
- name: Show Xcode Version
|
||||
run: xcodebuild -version
|
||||
|
||||
- name: Setup Environment Variables
|
||||
env:
|
||||
DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }}
|
||||
run: |
|
||||
echo "DATADOG_CLIENT_TOKEN=${DATADOG_CLIENT_TOKEN}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build iOS App and Generate dSYMs
|
||||
env:
|
||||
DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }}
|
||||
run: |
|
||||
# Create build directory
|
||||
mkdir -p ./build/dSYMs
|
||||
|
||||
# Build iOS App Archive with dSYMs
|
||||
xcodebuild \
|
||||
-workspace Meshtastic.xcworkspace \
|
||||
-scheme Meshtastic \
|
||||
-configuration Release \
|
||||
-destination 'generic/platform=iOS' \
|
||||
-archivePath ./build/Meshtastic.xcarchive \
|
||||
DATADOG_CLIENT_TOKEN="${DATADOG_CLIENT_TOKEN}" \
|
||||
DEBUG_INFORMATION_FORMAT=dwarf-with-dsym \
|
||||
DWARF_DSYM_FOLDER_PATH=./build/dSYMs \
|
||||
archive
|
||||
|
||||
- name: Extract dSYMs from Archive
|
||||
run: |
|
||||
# Find and copy all dSYM files from the archive
|
||||
find ./build/Meshtastic.xcarchive -name "*.dSYM" -exec cp -R {} ./build/dSYMs/ \;
|
||||
|
||||
# List what we found
|
||||
echo "Found dSYM files:"
|
||||
find ./build/dSYMs -name "*.dSYM" -type d
|
||||
|
||||
- name: Install Datadog CI
|
||||
run: |
|
||||
npm install -g @datadog/datadog-ci
|
||||
|
||||
- name: Upload dSYMs to Datadog
|
||||
uses: DataDog/upload-dsyms-github-action@v1
|
||||
env:
|
||||
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
|
||||
DATADOG_SITE: datadoghq.com
|
||||
run: |
|
||||
# Upload all dSYM files to Datadog
|
||||
if [ -d "./build/dSYMs" ] && [ "$(find ./build/dSYMs -name "*.dSYM" -type d | wc -l)" -gt 0 ]; then
|
||||
echo "Uploading dSYM files to Datadog..."
|
||||
datadog-ci dsyms upload ./build/dSYMs --dry-run=false
|
||||
else
|
||||
echo "No dSYM files found to upload"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload Build Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
api_key: ${{ secrets.DATADOG_API_KEY }}
|
||||
site: datadoghq.com
|
||||
dsym_paths: |
|
||||
path/to/dsyms/folder
|
||||
path/to/zip/dsyms.zip
|
||||
name: dsym-files
|
||||
path: |
|
||||
./build/dSYMs
|
||||
./build/Meshtastic.xcarchive
|
||||
retention-days: 30
|
||||
|
|
@ -28,8 +28,8 @@ file_length:
|
|||
|
||||
# TODO: should review
|
||||
cyclomatic_complexity:
|
||||
warning: 60
|
||||
error: 70
|
||||
warning: 70
|
||||
error: 80
|
||||
ignores_case_statements: true
|
||||
|
||||
# TODO: should review
|
||||
|
|
@ -57,4 +57,4 @@ custom_rules:
|
|||
name: "Disable `print()`"
|
||||
regex: "((\\bprint)|(Swift\\.print))\\s*\\("
|
||||
message: "Consider using a dedicated log message or the Xcode debugger instead of using `print`. ex. logger.debug(...)"
|
||||
severity: warning
|
||||
severity: warning
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -13,6 +13,8 @@
|
|||
102B5EB12E172F41003D191E /* DatadogRUM in Frameworks */ = {isa = PBXBuildFile; productRef = 102B5EB02E172F41003D191E /* DatadogRUM */; };
|
||||
108FFECB2DD3F43C00BFAA81 /* ShareContactQRDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 108FFECA2DD3F43C00BFAA81 /* ShareContactQRDialog.swift */; };
|
||||
108FFECD2DD4005600BFAA81 /* NodeInfoEntityToNodeInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 108FFECC2DD4005600BFAA81 /* NodeInfoEntityToNodeInfo.swift */; };
|
||||
10D109F22E2047D600536CE6 /* DatadogSessionReplay in Frameworks */ = {isa = PBXBuildFile; productRef = 10D109F12E2047D600536CE6 /* DatadogSessionReplay */; };
|
||||
10D109F42E2047D600536CE6 /* DatadogTrace in Frameworks */ = {isa = PBXBuildFile; productRef = 10D109F32E2047D600536CE6 /* DatadogTrace */; };
|
||||
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 */; };
|
||||
|
|
@ -145,6 +147,7 @@
|
|||
DD6F65792C6EADE60053C113 /* DirectMessagesHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F65782C6EADE60053C113 /* DirectMessagesHelp.swift */; };
|
||||
DD6F657B2C6EC2900053C113 /* LockLegend.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F657A2C6EC2900053C113 /* LockLegend.swift */; };
|
||||
DD73FD1128750779000852D6 /* PositionLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD73FD1028750779000852D6 /* PositionLog.swift */; };
|
||||
DD74ED0D2DC6A0C90059AC10 /* DeviceOnboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD74ED0C2DC6A0B80059AC10 /* DeviceOnboarding.swift */; };
|
||||
DD769E0328D18BF1001A3F05 /* DeviceMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */; };
|
||||
DD77093B2AA1ABB8007A8BF0 /* BluetoothTips.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */; };
|
||||
DD77093D2AA1AFA3007A8BF0 /* ChannelTips.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD77093C2AA1AFA3007A8BF0 /* ChannelTips.swift */; };
|
||||
|
|
@ -200,7 +203,6 @@
|
|||
DDC2E15C26CE248F0042C5E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DDC2E15B26CE248F0042C5E4 /* Assets.xcassets */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
|
|
@ -445,6 +447,7 @@
|
|||
DD6F65782C6EADE60053C113 /* DirectMessagesHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectMessagesHelp.swift; sourceTree = "<group>"; };
|
||||
DD6F657A2C6EC2900053C113 /* LockLegend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockLegend.swift; sourceTree = "<group>"; };
|
||||
DD73FD1028750779000852D6 /* PositionLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionLog.swift; sourceTree = "<group>"; };
|
||||
DD74ED0C2DC6A0B80059AC10 /* DeviceOnboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceOnboarding.swift; sourceTree = "<group>"; };
|
||||
DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceMetricsLog.swift; sourceTree = "<group>"; };
|
||||
DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothTips.swift; sourceTree = "<group>"; };
|
||||
DD77093C2AA1AFA3007A8BF0 /* ChannelTips.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelTips.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -514,7 +517,6 @@
|
|||
DDC2E15E26CE248F0042C5E4 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
|
@ -599,9 +601,11 @@
|
|||
102B5EAD2E172F41003D191E /* DatadogCrashReporting in Frameworks */,
|
||||
25A978BA2C13F8ED0003AAE7 /* MeshtasticProtobufs in Frameworks */,
|
||||
102B5EAB2E172F41003D191E /* DatadogCore in Frameworks */,
|
||||
10D109F22E2047D600536CE6 /* DatadogSessionReplay in Frameworks */,
|
||||
102B5EAF2E172F41003D191E /* DatadogLogs in Frameworks */,
|
||||
102B5EB12E172F41003D191E /* DatadogRUM in Frameworks */,
|
||||
DD0D3D222A55CEB10066DB71 /* CocoaMQTT in Frameworks */,
|
||||
10D109F42E2047D600536CE6 /* DatadogTrace in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -871,6 +875,14 @@
|
|||
path = Help;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DD74ED0B2DC6A0900059AC10 /* Onboarding */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD74ED0C2DC6A0B80059AC10 /* DeviceOnboarding.swift */,
|
||||
);
|
||||
path = Onboarding;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DD7709392AA1ABA1007A8BF0 /* Tips */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1010,11 +1022,12 @@
|
|||
DDC2E18726CE24E40042C5E4 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD6D5A312CA1176A00ED3032 /* Layouts */,
|
||||
DDC2E18D26CE25CB0042C5E4 /* Helpers */,
|
||||
DD47E3D726F2F21A00029299 /* Bluetooth */,
|
||||
DDC2E18D26CE25CB0042C5E4 /* Helpers */,
|
||||
DD6D5A312CA1176A00ED3032 /* Layouts */,
|
||||
DDC2E18B26CE25A70042C5E4 /* Messages */,
|
||||
DD47E3CA26F0E50300029299 /* Nodes */,
|
||||
DD74ED0B2DC6A0900059AC10 /* Onboarding */,
|
||||
DD4A911C2708C57100501B7E /* Settings */,
|
||||
DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */,
|
||||
);
|
||||
|
|
@ -1090,7 +1103,6 @@
|
|||
DDD43FE12A78C86B0083A3E9 /* Mqtt */,
|
||||
DDAF8C5226EB1DF10058C060 /* BLEManager.swift */,
|
||||
DD1BEF492E0292220090CE24 /* KeychainHelper.swift */,
|
||||
DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */,
|
||||
DD913638270DFF4C00D7ACF3 /* LocalNotificationManager.swift */,
|
||||
DDA6B2E828419CF2003E8C16 /* MeshPackets.swift */,
|
||||
DD964FBC296E6B01007C176F /* EmojiOnlyTextField.swift */,
|
||||
|
|
@ -1248,6 +1260,8 @@
|
|||
102B5EAC2E172F41003D191E /* DatadogCrashReporting */,
|
||||
102B5EAE2E172F41003D191E /* DatadogLogs */,
|
||||
102B5EB02E172F41003D191E /* DatadogRUM */,
|
||||
10D109F12E2047D600536CE6 /* DatadogSessionReplay */,
|
||||
10D109F32E2047D600536CE6 /* DatadogTrace */,
|
||||
);
|
||||
productName = MeshtasticClient;
|
||||
productReference = DDC2E15426CE248E0042C5E4 /* Meshtastic.app */;
|
||||
|
|
@ -1419,7 +1433,6 @@
|
|||
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 */,
|
||||
|
|
@ -1468,6 +1481,7 @@
|
|||
DDDB263F2AABEE20003AFCB7 /* NodeList.swift in Sources */,
|
||||
DDD5BB0B2C285E45007E03CA /* LogDetail.swift in Sources */,
|
||||
DDA0B6B2294CDC55001356EC /* Channels.swift in Sources */,
|
||||
DD74ED0D2DC6A0C90059AC10 /* DeviceOnboarding.swift in Sources */,
|
||||
DDE9659C2B1C3B6A00531070 /* RouteRecorder.swift in Sources */,
|
||||
B399E8A42B6F486400E4488E /* RetryButton.swift in Sources */,
|
||||
DDB8F4102A9EE5B400230ECE /* Messages.swift in Sources */,
|
||||
|
|
@ -1842,7 +1856,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.11;
|
||||
MARKETING_VERSION = 2.6.12;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1875,7 +1889,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.11;
|
||||
MARKETING_VERSION = 2.6.12;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1906,7 +1920,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.11;
|
||||
MARKETING_VERSION = 2.6.12;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1938,7 +1952,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.11;
|
||||
MARKETING_VERSION = 2.6.12;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -2046,6 +2060,16 @@
|
|||
package = 102B5EA92E172F41003D191E /* XCRemoteSwiftPackageReference "dd-sdk-ios" */;
|
||||
productName = DatadogRUM;
|
||||
};
|
||||
10D109F12E2047D600536CE6 /* DatadogSessionReplay */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 102B5EA92E172F41003D191E /* XCRemoteSwiftPackageReference "dd-sdk-ios" */;
|
||||
productName = DatadogSessionReplay;
|
||||
};
|
||||
10D109F32E2047D600536CE6 /* DatadogTrace */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 102B5EA92E172F41003D191E /* XCRemoteSwiftPackageReference "dd-sdk-ios" */;
|
||||
productName = DatadogTrace;
|
||||
};
|
||||
25A978B92C13F8ED0003AAE7 /* MeshtasticProtobufs */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = MeshtasticProtobufs;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"originHash" : "0dabe052e9e56f8514254d01df9aa7245e16b28a649d59bac6781d4ac9a79efa",
|
||||
"originHash" : "fd71b247ba909b0eb360db5530e1068363839c5e169dea6f6a9974b2d98276f4",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "cocoamqtt",
|
||||
|
|
|
|||
12
Meshtastic/Assets.xcassets/SEEEDWIOTRACKERL1.imageset/Contents.json
vendored
Normal file
12
Meshtastic/Assets.xcassets/SEEEDWIOTRACKERL1.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "wio_tracker_l1_case.svg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
710
Meshtastic/Assets.xcassets/SEEEDWIOTRACKERL1.imageset/wio_tracker_l1_case.svg
vendored
Normal file
710
Meshtastic/Assets.xcassets/SEEEDWIOTRACKERL1.imageset/wio_tracker_l1_case.svg
vendored
Normal file
|
|
@ -0,0 +1,710 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="431.09 27.94 434.45 897.75474"
|
||||
version="1.1"
|
||||
id="svg97"
|
||||
sodipodi:docname="wio_tracker_l1_case.svg"
|
||||
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
|
||||
width="434.45001"
|
||||
height="897.75476"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview97"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="0.81923274"
|
||||
inkscape:cx="149.53016"
|
||||
inkscape:cy="340.56256"
|
||||
inkscape:window-width="1104"
|
||||
inkscape:window-height="875"
|
||||
inkscape:window-x="7"
|
||||
inkscape:window-y="46"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg97" />
|
||||
<defs
|
||||
id="defs1">
|
||||
<style
|
||||
id="style1">.cls-1{fill:#3b3b3d;}.cls-2{fill:#242426;}.cls-3{fill:#ec6263;}.cls-4{fill:#595859;}.cls-5{fill:#4c4b4f;}.cls-6{fill:#eb612a;}.cls-7{fill:#f6a75e;}.cls-8{fill:#e0b77b;}.cls-9{fill:#1a1a1c;}.cls-10,.cls-11,.cls-12,.cls-13{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-10{stroke-width:1.36px;}.cls-11{stroke-width:1.34px;}.cls-12{stroke-width:1.23px;}.cls-13{stroke-width:1.46px;}.cls-14{fill:#333335;}</style>
|
||||
</defs>
|
||||
<g
|
||||
id="Layer_2"
|
||||
data-name="Layer 2"
|
||||
transform="translate(124,-118.76523)">
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 740.86,685.6 v 336.65 a 21.54,21.54 0 0 1 -21.54,21.53 H 458.69 a 21.55,21.55 0 0 1 -21.55,-21.53 V 655.32 A 17.23,17.23 0 0 1 454.36,638.1 H 555 a 11.72,11.72 0 0 1 8.14,3.29 l 13.48,13 8.94,8.65 a 11.67,11.67 0 0 0 8.13,3.29 h 127.92 a 19.25,19.25 0 0 1 19.25,19.27 z"
|
||||
id="path1" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 619.43,660.89 -11.08,-11.08 a 5.51,5.51 0 0 0 -4,-1.69 h -21.9 a 5.71,5.71 0 0 0 -5.77,5.71 v 0.59 l -13.48,-13 h 45.71 a 16.37,16.37 0 0 1 11.57,4.8 l 20.16,20.17 h -23.13 a 3.2,3.2 0 0 0 1.92,-5.5 z"
|
||||
id="path2" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 617.51,666.36 a 2.11,2.11 0 0 1 -0.36,0 h -19 v 0 z"
|
||||
id="path3" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 437.14,874.52 -3.33,-3.33 a 7,7 0 0 1 -2,-5 V 764.1 a 7,7 0 0 1 2,-4.94 l 3.33,-3.33 z"
|
||||
id="path4" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="m 431.77,774.2 v 0 a 2.7,2.7 0 0 1 2.69,2.69 v 19.68 a 2.69,2.69 0 0 1 -2.69,2.69 v 0 z"
|
||||
id="path5" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="m 431.77,836.51 v 0 a 2.69,2.69 0 0 1 2.69,2.69 v 19.68 a 2.7,2.7 0 0 1 -2.69,2.69 v 0 z"
|
||||
id="path6" />
|
||||
<rect
|
||||
class="cls-1"
|
||||
x="648.89001"
|
||||
y="604.95721"
|
||||
width="52.139999"
|
||||
height="45.419998"
|
||||
rx="1.47"
|
||||
id="rect9" />
|
||||
<rect
|
||||
class="cls-1"
|
||||
x="645.45001"
|
||||
y="611.43719"
|
||||
width="58.369999"
|
||||
height="33.209999"
|
||||
rx="1.9299999"
|
||||
id="rect10" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 676.07,743.46 v 84.2 a 5.37,5.37 0 0 1 -5.35,5.35 H 509.27 a 5.36,5.36 0 0 1 -5.35,-5.35 v -84.2 a 5.34,5.34 0 0 1 5.35,-5.35 h 161.45 a 5.36,5.36 0 0 1 5.35,5.35 z"
|
||||
id="path10" />
|
||||
<path
|
||||
class="cls-4"
|
||||
d="M 672.07,844.7 H 507.91 a 16,16 0 0 1 -16,-16 v -86.28 a 16,16 0 0 1 16,-16 h 91.35 a 10.82,10.82 0 0 0 5.85,-1.71 L 623,713.22 a 17.64,17.64 0 0 1 9.57,-2.8 h 40.58 a 14.9,14.9 0 0 1 14.88,14.88 V 828.68 A 16,16 0 0 1 672.07,844.7 Z M 507.89,733.33 a 9.1,9.1 0 0 0 -9.09,9.09 v 86.26 a 9.12,9.12 0 0 0 9.11,9.11 h 164.16 a 9.11,9.11 0 0 0 9.09,-9.11 V 725.3 a 8,8 0 0 0 -8,-8 h -40.55 a 10.82,10.82 0 0 0 -5.85,1.71 l -18,11.49 a 17.73,17.73 0 0 1 -9.57,2.8 z"
|
||||
id="path11" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="m 673.19,713.87 h -40.57 a 14.36,14.36 0 0 0 -7.71,2.25 L 607,727.62 a 14.33,14.33 0 0 1 -7.72,2.25 H 507.9 a 12.56,12.56 0 0 0 -12.55,12.55 v 86.26 a 12.56,12.56 0 0 0 12.56,12.56 h 164.16 a 12.55,12.55 0 0 0 12.55,-12.56 V 725.3 a 11.42,11.42 0 0 0 -11.43,-11.43 z m 2.88,113.79 a 5.37,5.37 0 0 1 -5.35,5.35 H 509.27 a 5.36,5.36 0 0 1 -5.35,-5.35 v -84.2 a 5.34,5.34 0 0 1 5.35,-5.35 h 161.45 a 5.36,5.36 0 0 1 5.35,5.35 z"
|
||||
id="path12" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="628.69"
|
||||
cy="926.5"
|
||||
r="18.08"
|
||||
id="circle12" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="691.77002"
|
||||
cy="926.5"
|
||||
r="25.82"
|
||||
id="circle13" />
|
||||
<circle
|
||||
class="cls-6"
|
||||
cx="628.69"
|
||||
cy="926.5"
|
||||
r="14.31"
|
||||
id="circle14" />
|
||||
<circle
|
||||
class="cls-6"
|
||||
cx="691.77002"
|
||||
cy="926.5"
|
||||
r="21.16"
|
||||
id="circle15" />
|
||||
<circle
|
||||
class="cls-7"
|
||||
cx="628.69"
|
||||
cy="926.5"
|
||||
r="11.36"
|
||||
id="circle16" />
|
||||
<circle
|
||||
class="cls-7"
|
||||
cx="691.77002"
|
||||
cy="926.5"
|
||||
r="17.809999"
|
||||
id="circle17" />
|
||||
<rect
|
||||
class="cls-8"
|
||||
x="647.82001"
|
||||
y="653.4472"
|
||||
width="55.25"
|
||||
height="7.02"
|
||||
id="rect17" />
|
||||
<rect
|
||||
class="cls-8"
|
||||
x="650.88"
|
||||
y="650.57721"
|
||||
width="48.700001"
|
||||
height="1.9299999"
|
||||
id="rect19" />
|
||||
<rect
|
||||
class="cls-2"
|
||||
x="645.45001"
|
||||
y="614.28723"
|
||||
width="58.369999"
|
||||
height="27.76"
|
||||
id="rect20" />
|
||||
<rect
|
||||
class="cls-2"
|
||||
x="653.03003"
|
||||
y="601.79724"
|
||||
width="44.41"
|
||||
height="2.9400001"
|
||||
id="rect21" />
|
||||
<rect
|
||||
class="cls-1"
|
||||
x="650.88"
|
||||
y="537.74719"
|
||||
width="48.700001"
|
||||
height="64.050003"
|
||||
rx="2.3800001"
|
||||
id="rect22" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 709.54,662.52 v 3.84 h -68 v -3.84 a 1.85,1.85 0 0 1 1.85,-1.85 h 64.34 a 1.85,1.85 0 0 1 1.81,1.85 z"
|
||||
id="path22" />
|
||||
<rect
|
||||
class="cls-5"
|
||||
x="506.41"
|
||||
y="970.47998"
|
||||
width="170.03"
|
||||
height="9.9700003"
|
||||
rx="4.98"
|
||||
id="rect24" />
|
||||
<rect
|
||||
class="cls-5"
|
||||
x="506.41"
|
||||
y="1004.91"
|
||||
width="170.03"
|
||||
height="9.9700003"
|
||||
rx="4.98"
|
||||
id="rect25" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="m 573.49,709.25 h -4.44 a 3.53,3.53 0 0 1 -2.47,-1 l -42.93,-42.7 a 1.17,1.17 0 0 1 0.83,-2 h 4.43 a 3.5,3.5 0 0 1 2.48,1 l 42.93,42.7 a 1.18,1.18 0 0 1 -0.83,2 z"
|
||||
id="path25" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="m 546.14,709.25 h -4.44 a 3.5,3.5 0 0 1 -2.47,-1 l -42.94,-42.7 a 1.18,1.18 0 0 1 0.83,-2 h 4.44 a 3.49,3.49 0 0 1 2.47,1 L 547,707.24 a 1.17,1.17 0 0 1 -0.86,2.01 z"
|
||||
id="path26" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="m 518.78,709.25 h -4.44 a 3.53,3.53 0 0 1 -2.47,-1 l -42.93,-42.7 a 1.17,1.17 0 0 1 0.82,-2 h 4.44 a 3.45,3.45 0 0 1 2.47,1 l 42.94,42.7 a 1.18,1.18 0 0 1 -0.83,2 z"
|
||||
id="path27" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="m 486.12,709.26 h -4.44 a 3.5,3.5 0 0 1 -2.47,-1 l -7,-7 a 1.17,1.17 0 0 1 0.83,-2 h 4.44 a 3.49,3.49 0 0 1 2.47,1 l 7,7 a 1.18,1.18 0 0 1 -0.83,2 z"
|
||||
id="path28" />
|
||||
<path
|
||||
class="cls-5"
|
||||
d="M 721.61,666.36 H 593.73 a 11.67,11.67 0 0 1 -8.13,-3.29 l -8.94,-8.65 -13.48,-13 A 11.72,11.72 0 0 0 555,638.1 H 454.36 a 17.23,17.23 0 0 0 -17.22,17.22 v 366.93 a 21.55,21.55 0 0 0 21.55,21.53 h 260.63 a 21.54,21.54 0 0 0 21.54,-21.53 V 685.6 a 19.25,19.25 0 0 0 -19.25,-19.24 z m 13,355.89 a 15.33,15.33 0 0 1 -15.33,15.31 H 458.69 a 15.35,15.35 0 0 1 -15.33,-15.31 V 655.32 a 11,11 0 0 1 11,-11 H 555 a 5.42,5.42 0 0 1 3.81,1.55 l 22.43,21.67 a 17.86,17.86 0 0 0 12.45,5 h 127.92 a 13.05,13.05 0 0 1 13,13 z"
|
||||
id="path29" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 437.15,655.32 v 366.92 a 21.54,21.54 0 0 0 21.54,21.54 h 260.63 a 21.54,21.54 0 0 0 21.54,-21.54 V 685.6 A 19.24,19.24 0 0 0 721.62,666.37 H 593.73 a 11.7,11.7 0 0 1 -8.13,-3.29 L 563.17,641.39 A 11.7,11.7 0 0 0 555,638.1 H 454.36 a 17.21,17.21 0 0 0 -17.21,17.22 z"
|
||||
id="path30" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 563.17,641.39 h 45.71 a 16.42,16.42 0 0 1 11.58,4.79 l 20.15,20.19"
|
||||
id="path31" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 576.67,654.42 v -0.6 a 5.72,5.72 0 0 1 5.76,-5.71 h 21.9 a 5.53,5.53 0 0 1 4,1.69 l 11.09,11.08 a 3.21,3.21 0 0 1 -2.29,5.49 h -19"
|
||||
id="path32" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 641.49,666.37 v -3.66 a 2.05,2.05 0 0 1 2,-2.05 h 64 a 2.05,2.05 0 0 1 2,2.05 v 3.66"
|
||||
id="path33" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 697.27,660.95719 h 4.94 a 0.87,0.87 0 0 0 0.86,-0.86 v -6.14 a 0.86,0.86 0 0 0 -0.86,-0.86 h -53.64 a 1,1 0 0 0 -1,1 v 5.84 a 1,1 0 0 0 1,1 h 5.17"
|
||||
id="path34" />
|
||||
<path
|
||||
class="cls-11"
|
||||
d="m 701,644.65719 v 4.5 a 1.22,1.22 0 0 1 -1.21,1.22 H 650 a 1.2,1.2 0 0 1 -1.21,-1.22 v -4.5"
|
||||
id="path35" />
|
||||
<path
|
||||
class="cls-11"
|
||||
d="m 648.8,611.43719 v -5.27 a 1.21,1.21 0 0 1 1.21,-1.21 h 49.81 a 1.22,1.22 0 0 1 1.21,1.21 v 5.27"
|
||||
id="path36" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="650.88"
|
||||
y1="650.3772"
|
||||
x2="650.88"
|
||||
y2="653.09723"
|
||||
id="line36" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="699.58002"
|
||||
y1="650.3772"
|
||||
x2="699.58002"
|
||||
y2="653.09723"
|
||||
id="line37" />
|
||||
<rect
|
||||
class="cls-11"
|
||||
x="650.88"
|
||||
y="537.74719"
|
||||
width="48.700001"
|
||||
height="64.050003"
|
||||
rx="2.1400001"
|
||||
id="rect37" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="653.03003"
|
||||
y1="601.79724"
|
||||
x2="653.03003"
|
||||
y2="604.95721"
|
||||
id="line38" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="697.44"
|
||||
y1="601.79724"
|
||||
x2="697.44"
|
||||
y2="604.95721"
|
||||
id="line39" />
|
||||
<rect
|
||||
class="cls-11"
|
||||
x="645.45001"
|
||||
y="611.43719"
|
||||
width="58.369999"
|
||||
height="33.209999"
|
||||
rx="1.92"
|
||||
id="rect45" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="648.89001"
|
||||
y1="614.28723"
|
||||
x2="648.89001"
|
||||
y2="642.04724"
|
||||
id="line45" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="653.63"
|
||||
y1="614.28723"
|
||||
x2="653.63"
|
||||
y2="642.04724"
|
||||
id="line46" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="658.35999"
|
||||
y1="614.28723"
|
||||
x2="658.35999"
|
||||
y2="642.04724"
|
||||
id="line47" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="663.09003"
|
||||
y1="614.28723"
|
||||
x2="663.09003"
|
||||
y2="642.04724"
|
||||
id="line48" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="667.82001"
|
||||
y1="614.28723"
|
||||
x2="667.82001"
|
||||
y2="642.04724"
|
||||
id="line49" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="672.54999"
|
||||
y1="614.28723"
|
||||
x2="672.54999"
|
||||
y2="642.04724"
|
||||
id="line50" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="677.28003"
|
||||
y1="614.28723"
|
||||
x2="677.28003"
|
||||
y2="642.04724"
|
||||
id="line51" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="682.01001"
|
||||
y1="614.28723"
|
||||
x2="682.01001"
|
||||
y2="642.04724"
|
||||
id="line52" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="686.73999"
|
||||
y1="614.28723"
|
||||
x2="686.73999"
|
||||
y2="642.04724"
|
||||
id="line53" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="691.46997"
|
||||
y1="614.28723"
|
||||
x2="691.46997"
|
||||
y2="642.04724"
|
||||
id="line54" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="696.20001"
|
||||
y1="614.28723"
|
||||
x2="696.20001"
|
||||
y2="642.04724"
|
||||
id="line55" />
|
||||
<line
|
||||
class="cls-11"
|
||||
x1="700.92999"
|
||||
y1="614.28723"
|
||||
x2="700.92999"
|
||||
y2="642.04724"
|
||||
id="line56" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="m 676.07,743.46 v 84.2 a 5.37,5.37 0 0 1 -5.35,5.35 H 509.27 a 5.36,5.36 0 0 1 -5.35,-5.35 v -84.2 a 5.34,5.34 0 0 1 5.35,-5.35 h 161.45 a 5.36,5.36 0 0 1 5.35,5.35 z"
|
||||
id="path56" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="m 673.19,713.87 a 11.43,11.43 0 0 1 11.43,11.43 v 103.38 a 12.55,12.55 0 0 1 -12.55,12.56 H 507.91 a 12.56,12.56 0 0 1 -12.56,-12.56 v -86.26 a 12.55,12.55 0 0 1 12.55,-12.55 h 91.34 a 14.33,14.33 0 0 0 7.72,-2.25 l 17.94,-11.49 a 14.37,14.37 0 0 1 7.72,-2.26 z"
|
||||
id="path57" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="468.76001"
|
||||
cy="746.5"
|
||||
r="20.200001"
|
||||
id="circle57" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="468.76001"
|
||||
cy="746.5"
|
||||
r="11.67"
|
||||
id="circle58" />
|
||||
<circle
|
||||
class="cls-14"
|
||||
cx="468.76001"
|
||||
cy="746.5"
|
||||
r="9.3299999"
|
||||
id="circle59" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="468.76001"
|
||||
cy="746.5"
|
||||
r="20.200001"
|
||||
id="circle60" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="468.76001"
|
||||
cy="746.5"
|
||||
r="9.3299999"
|
||||
id="circle61" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="468.76001"
|
||||
cy="746.5"
|
||||
r="11.67"
|
||||
id="circle62" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="475.10999"
|
||||
y1="746.39001"
|
||||
x2="462.42001"
|
||||
y2="746.39001"
|
||||
id="line62" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="468.76001"
|
||||
y1="740.03998"
|
||||
x2="468.76001"
|
||||
y2="752.72998"
|
||||
id="line63" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="711.06"
|
||||
cy="746.5"
|
||||
r="20.200001"
|
||||
id="circle63" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="711.06"
|
||||
cy="746.5"
|
||||
r="11.67"
|
||||
id="circle64" />
|
||||
<circle
|
||||
class="cls-14"
|
||||
cx="711.06"
|
||||
cy="746.5"
|
||||
r="9.3299999"
|
||||
id="circle65" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="711.06"
|
||||
cy="746.5"
|
||||
r="20.200001"
|
||||
id="circle66" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="711.06"
|
||||
cy="746.5"
|
||||
r="9.3299999"
|
||||
id="circle67" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="711.06"
|
||||
cy="746.5"
|
||||
r="11.67"
|
||||
id="circle68" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="717.40997"
|
||||
y1="746.39001"
|
||||
x2="704.71002"
|
||||
y2="746.39001"
|
||||
id="line68" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="711.06"
|
||||
y1="740.03998"
|
||||
x2="711.06"
|
||||
y2="752.72998"
|
||||
id="line69" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="468.76001"
|
||||
cy="1012.62"
|
||||
r="20.200001"
|
||||
id="circle69" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="468.76001"
|
||||
cy="1012.62"
|
||||
r="11.67"
|
||||
id="circle70" />
|
||||
<circle
|
||||
class="cls-14"
|
||||
cx="468.76001"
|
||||
cy="1012.62"
|
||||
r="9.3299999"
|
||||
id="circle71" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="468.76001"
|
||||
cy="1012.62"
|
||||
r="20.200001"
|
||||
id="circle72" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="468.76001"
|
||||
cy="1012.62"
|
||||
r="9.3299999"
|
||||
id="circle73" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="468.76001"
|
||||
cy="1012.62"
|
||||
r="11.67"
|
||||
id="circle74" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="475.10999"
|
||||
y1="1012.51"
|
||||
x2="462.42001"
|
||||
y2="1012.51"
|
||||
id="line74" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="468.76001"
|
||||
y1="1006.16"
|
||||
x2="468.76001"
|
||||
y2="1018.85"
|
||||
id="line75" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="711.06"
|
||||
cy="1012.62"
|
||||
r="20.200001"
|
||||
id="circle75" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="711.06"
|
||||
cy="1012.62"
|
||||
r="11.67"
|
||||
id="circle76" />
|
||||
<circle
|
||||
class="cls-14"
|
||||
cx="711.06"
|
||||
cy="1012.62"
|
||||
r="9.3299999"
|
||||
id="circle77" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="711.06"
|
||||
cy="1012.62"
|
||||
r="20.200001"
|
||||
id="circle78" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="711.06"
|
||||
cy="1012.62"
|
||||
r="9.3299999"
|
||||
id="circle79" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="711.06"
|
||||
cy="1012.62"
|
||||
r="11.67"
|
||||
id="circle80" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="717.40997"
|
||||
y1="1012.51"
|
||||
x2="704.71002"
|
||||
y2="1012.51"
|
||||
id="line80" />
|
||||
<line
|
||||
class="cls-13"
|
||||
x1="711.06"
|
||||
y1="1006.16"
|
||||
x2="711.06"
|
||||
y2="1018.85"
|
||||
id="line81" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="628.69"
|
||||
cy="926.5"
|
||||
r="18.08"
|
||||
id="circle81" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="628.69"
|
||||
cy="926.5"
|
||||
r="14.31"
|
||||
id="circle82" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="691.77002"
|
||||
cy="926.5"
|
||||
r="25.82"
|
||||
id="circle83" />
|
||||
<circle
|
||||
class="cls-13"
|
||||
cx="691.77002"
|
||||
cy="926.5"
|
||||
r="21.16"
|
||||
id="circle84" />
|
||||
<rect
|
||||
class="cls-13"
|
||||
x="506.41"
|
||||
y="970.47998"
|
||||
width="170.03"
|
||||
height="9.9700003"
|
||||
rx="4.98"
|
||||
id="rect84" />
|
||||
<rect
|
||||
class="cls-13"
|
||||
x="506.41"
|
||||
y="1004.91"
|
||||
width="170.03"
|
||||
height="9.9700003"
|
||||
rx="4.98"
|
||||
id="rect85" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="m 573.49,709.25 h -4.44 a 3.53,3.53 0 0 1 -2.47,-1 l -42.93,-42.7 a 1.17,1.17 0 0 1 0.83,-2 h 4.43 a 3.5,3.5 0 0 1 2.48,1 l 42.93,42.7 a 1.18,1.18 0 0 1 -0.83,2 z"
|
||||
id="path85" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="m 546.14,709.25 h -4.44 a 3.5,3.5 0 0 1 -2.47,-1 l -42.94,-42.7 a 1.18,1.18 0 0 1 0.83,-2 h 4.44 a 3.49,3.49 0 0 1 2.47,1 L 547,707.24 a 1.17,1.17 0 0 1 -0.86,2.01 z"
|
||||
id="path86" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="m 518.78,709.25 h -4.44 a 3.53,3.53 0 0 1 -2.47,-1 l -42.93,-42.7 a 1.17,1.17 0 0 1 0.82,-2 h 4.44 a 3.45,3.45 0 0 1 2.47,1 l 42.94,42.7 a 1.18,1.18 0 0 1 -0.83,2 z"
|
||||
id="path87" />
|
||||
<path
|
||||
class="cls-13"
|
||||
d="m 486.12,709.26 h -4.44 a 3.5,3.5 0 0 1 -2.47,-1 l -7,-7 a 1.17,1.17 0 0 1 0.83,-2 h 4.44 a 3.49,3.49 0 0 1 2.47,1 l 7,7 a 1.18,1.18 0 0 1 -0.83,2 z"
|
||||
id="path88" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 437.14,874.52 -3.33,-3.33 a 7,7 0 0 1 -2,-5 V 764.1 a 7,7 0 0 1 2,-4.94 l 3.33,-3.33"
|
||||
id="path89" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 431.77,774.2 v 0 a 2.7,2.7 0 0 1 2.69,2.69 v 19.68 a 2.69,2.69 0 0 1 -2.69,2.69 v 0"
|
||||
id="path90" />
|
||||
<path
|
||||
class="cls-10"
|
||||
d="m 431.77,836.51 v 0 a 2.69,2.69 0 0 1 2.69,2.69 v 19.68 a 2.7,2.7 0 0 1 -2.69,2.69 v 0"
|
||||
id="path91" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M 510.56,867.89 482.76,907 a 5.28,5.28 0 0 1 -7.37,1.24 v 0 a 5.28,5.28 0 0 1 -1.23,-7.36 L 502,861.77 a 5.27,5.27 0 0 1 7.36,-1.24 v 0 a 5.28,5.28 0 0 1 1.2,7.36 z"
|
||||
id="path92" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 568.87,908.2 v 0 a 5.3,5.3 0 0 1 -7.38,-1.24 l -24,-33.77 -24,33.77 a 5.29,5.29 0 0 1 -7.37,1.24 v 0 a 5.29,5.29 0 0 1 -1.23,-7.37 l 26.11,-36.76 2.18,-3.06 a 5.28,5.28 0 0 1 8.61,0 l 2.18,3.06 26.16,36.76 a 5.3,5.3 0 0 1 -1.26,7.37 z"
|
||||
id="path93" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 474.7,958.47 a 2.76,2.76 0 0 1 -2.76,-2.76 V 932.77 A 2.77,2.77 0 0 1 474.7,930 h 7.5 a 9.75,9.75 0 0 1 9.74,9.75 9.75,9.75 0 0 1 -9.74,9.74 h -4.73 v 6.22 a 2.76,2.76 0 0 1 -2.77,2.76 z M 477.47,944 h 4.73 a 4.12,4.12 0 0 0 3,-1.22 4.21,4.21 0 0 0 -3,-7.21 h -4.73 z"
|
||||
id="path94" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 551.49,954.15 -4.7,-6.86 a 8.68,8.68 0 0 0 0.7,-0.65 9.62,9.62 0 0 0 2.86,-6.89 9.75,9.75 0 0 0 -9.74,-9.75 h -7.49 a 2.77,2.77 0 0 0 -2.76,2.77 v 22.94 a 2.76,2.76 0 0 0 5.52,0 v -6.22 h 4.73 c 0.32,0 0.64,0 0.95,0 l 5.36,7.82 a 2.75,2.75 0 0 0 2.29,1.2 2.76,2.76 0 0 0 2.28,-4.32 z m -15.61,-18.62 h 4.73 a 4.23,4.23 0 0 1 4.21,4.22 4.22,4.22 0 0 1 -4.21,4.21 h -4.73 z"
|
||||
id="path95" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 518.81,958.47 a 2.75,2.75 0 0 1 -2.5,-1.6 l -5.83,-12.47 -5.82,12.47 a 2.76,2.76 0 0 1 -5.14,-0.34 l -7.16,-22.94 a 2.77,2.77 0 0 1 5.28,-1.65 l 5,16.13 4.56,-9.77 a 3.59,3.59 0 0 1 6.51,0 l 4.56,9.77 5,-16.13 a 2.761132,2.761132 0 1 1 5.27,1.65 l -7.15,22.94 a 2.78,2.78 0 0 1 -2.46,1.93 z"
|
||||
id="path96" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 562.65,958.47 h -6.13 a 2.77,2.77 0 0 1 -2.77,-2.77 v -22.93 a 2.77,2.77 0 0 1 2.77,-2.77 h 6.13 a 14.24,14.24 0 0 1 0,28.47 z m -3.37,-5.53 h 3.37 a 8.71,8.71 0 0 0 0,-17.41 h -3.37 z"
|
||||
id="path97" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="m 348.12645,153.62741 363.94,355.78 -18.09,16.92 a 24.62,24.62 0 0 1 -33.69,0 l -14.9,-14 a 0.44,0.44 0 0 0 -0.5,-0.09 v 0 a 13.35,13.35 0 0 1 -14.85,-2.89 l -316,-321.58 a 24.13,24.13 0 0 1 1.18,-35 v 0 a 24.13,24.13 0 0 1 32.91,0.86 z"
|
||||
id="path14"
|
||||
style="fill:#353535" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 650.4474,514.85692 c 0,0 -2.75,-3.82 -4.5,-3.27 -1.75,0.55 -3.94,0.3 -1.53,2.72 l 12.9,13 c 0,0 0.75,0.76 0.61,3.43 -0.14,2.67 0.07,5.63 0.65,5.91 0.58,0.28 30.43,1.59 30.64,-0.79 0.21,-2.38 0.67,-6.25 -0.74,-5.68 -1.41,0.57 -11.35,4.43 -19.55,0.05 -8.2,-4.38 -18.48,-15.37 -18.48,-15.37 z"
|
||||
id="path4-6"
|
||||
style="fill:#1d1e1e" />
|
||||
<line
|
||||
class="cls-5"
|
||||
x1="658.21747"
|
||||
y1="537.27698"
|
||||
x2="658.21747"
|
||||
y2="522.17694"
|
||||
id="line13"
|
||||
style="fill:none;stroke:#050606;stroke-width:2px;stroke-miterlimit:10" />
|
||||
<line
|
||||
class="cls-5"
|
||||
x1="689.76752"
|
||||
y1="537.27698"
|
||||
x2="689.76752"
|
||||
y2="529.55695"
|
||||
id="line14"
|
||||
style="fill:none;stroke:#050606;stroke-width:2px;stroke-miterlimit:10" />
|
||||
<line
|
||||
class="cls-5"
|
||||
x1="642.55743"
|
||||
y1="512.43695"
|
||||
x2="658.21747"
|
||||
y2="528.21698"
|
||||
id="line16"
|
||||
style="fill:none;stroke:#050606;stroke-width:2px;stroke-miterlimit:10" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="676.3775"
|
||||
cy="506.29691"
|
||||
r="6"
|
||||
id="circle16-0"
|
||||
style="fill:#1d1e1e" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="676.3775"
|
||||
cy="506.29691"
|
||||
r="6"
|
||||
id="circle17-3"
|
||||
style="fill:none;stroke:#050606;stroke-width:2px;stroke-miterlimit:10" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 21 KiB |
|
|
@ -78,7 +78,7 @@ enum UserTrackingModes: Int, CaseIterable, Identifiable {
|
|||
var description: String {
|
||||
switch self {
|
||||
case .none:
|
||||
return "None".localized
|
||||
return "map.usertrackingmode.none".localized
|
||||
case .follow:
|
||||
return "Follow".localized
|
||||
case .followWithHeading:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
case cn = 4
|
||||
case jp = 5
|
||||
case anz = 6
|
||||
case anz433 = 22
|
||||
case kr = 7
|
||||
case tw = 8
|
||||
case ru = 9
|
||||
|
|
@ -31,6 +32,8 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
case ph433 = 19
|
||||
case ph868 = 20
|
||||
case ph915 = 21
|
||||
case kz433 = 23
|
||||
case kz863 = 24
|
||||
case lora24 = 13
|
||||
var topic: String {
|
||||
switch self {
|
||||
|
|
@ -48,6 +51,8 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
"JP"
|
||||
case .anz:
|
||||
"ANZ"
|
||||
case .anz433:
|
||||
"ANZ_433"
|
||||
case .kr:
|
||||
"KR"
|
||||
case .tw:
|
||||
|
|
@ -76,6 +81,10 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
"ph_868"
|
||||
case .ph915:
|
||||
"ph_915"
|
||||
case .kz433:
|
||||
"KZ_433"
|
||||
case .kz863:
|
||||
"KZ_863"
|
||||
case .lora24:
|
||||
"LORA_24"
|
||||
} }
|
||||
|
|
@ -96,6 +105,8 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return "Japan".localized
|
||||
case .anz:
|
||||
return "Australia / New Zealand".localized
|
||||
case .anz433:
|
||||
return "Australia / New Zealand 433MHz".localized
|
||||
case .kr:
|
||||
return "Korea".localized
|
||||
case .tw:
|
||||
|
|
@ -112,8 +123,6 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return "Ukraine 433MHz".localized
|
||||
case .ua868:
|
||||
return "Ukraine 868MHz".localized
|
||||
case .lora24:
|
||||
return "2.4 Ghz".localized
|
||||
case .my433:
|
||||
return "Malaysia 433MHz".localized
|
||||
case .my919:
|
||||
|
|
@ -126,6 +135,12 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return "Philippines 868MHz".localized
|
||||
case .ph915:
|
||||
return "Philippines 915MHz".localized
|
||||
case .kz433:
|
||||
return "Kazakhstan 433MHz".localized
|
||||
case .kz863:
|
||||
return "Kazakhstan 863MHz".localized
|
||||
case .lora24:
|
||||
return "2.4 Ghz".localized
|
||||
}
|
||||
}
|
||||
var dutyCycle: Int {
|
||||
|
|
@ -174,6 +189,12 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return 100
|
||||
case .ph915:
|
||||
return 100
|
||||
case .anz433:
|
||||
return 100
|
||||
case .kz433:
|
||||
return 100
|
||||
case .kz863:
|
||||
return 100
|
||||
}
|
||||
}
|
||||
var isCountry: Bool {
|
||||
|
|
@ -222,6 +243,12 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return true
|
||||
case .ph915:
|
||||
return true
|
||||
case .anz433:
|
||||
return false
|
||||
case .kz433:
|
||||
return true
|
||||
case .kz863:
|
||||
return true
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> Config.LoRaConfig.RegionCode {
|
||||
|
|
@ -271,6 +298,12 @@ enum RegionCodes: Int, CaseIterable, Identifiable {
|
|||
return Config.LoRaConfig.RegionCode.ph868
|
||||
case .ph915:
|
||||
return Config.LoRaConfig.RegionCode.ph915
|
||||
case .anz433:
|
||||
return Config.LoRaConfig.RegionCode.anz433
|
||||
case .kz433:
|
||||
return Config.LoRaConfig.RegionCode.kz433
|
||||
case .kz863:
|
||||
return Config.LoRaConfig.RegionCode.kz863
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ extension UserEntity {
|
|||
return "SEEEDXIAOS3"
|
||||
case "WIOWM1110":
|
||||
return "WIOWM1110"
|
||||
case "SEEEDSOLARNODE":
|
||||
return "SEEEDSOLARNODE"
|
||||
case "SEEEDWIOTRACKERL1":
|
||||
return "SEEEDWIOTRACKERL1"
|
||||
/// RAK Wireless
|
||||
case "RAK4631":
|
||||
return "RAK4631"
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ extension UserDefaults {
|
|||
case environmentEnableWeatherKit
|
||||
case enableAdministration
|
||||
case mapReportingOptIn
|
||||
case firstLaunch
|
||||
case showDeviceOnboarding
|
||||
case usageDataAndCrashReporting
|
||||
case testIntEnum
|
||||
}
|
||||
|
|
@ -159,6 +161,11 @@ extension UserDefaults {
|
|||
|
||||
@UserDefault(.usageDataAndCrashReporting, defaultValue: true)
|
||||
static var usageDataAndCrashReporting: Bool
|
||||
@UserDefault(.firstLaunch, defaultValue: true)
|
||||
static var firstLaunch: Bool
|
||||
|
||||
@UserDefault(.showDeviceOnboarding, defaultValue: false)
|
||||
static var showDeviceOnboarding: Bool
|
||||
|
||||
@UserDefault(.testIntEnum, defaultValue: .one)
|
||||
static var testIntEnum: TestIntEnum
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
let NONCE_ONLY_DB = 69421
|
||||
private var isWaitingForWantConfigResponse = false
|
||||
|
||||
private var wantConfigTimer: Timer?
|
||||
private var wantConfigRetryCount = 0
|
||||
private let maxWantConfigRetries = 6
|
||||
private var wantConfigTimer: Timer?
|
||||
private var wantConfigRetryCount = 0
|
||||
private let maxWantConfigRetries = 6
|
||||
private let wantConfigTimeoutInterval: TimeInterval = 6.0
|
||||
|
||||
// MARK: init
|
||||
|
|
@ -799,33 +799,42 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
}
|
||||
}
|
||||
}
|
||||
guard let cp = connectedPeripheral else {
|
||||
return
|
||||
}
|
||||
// Channels
|
||||
if decodedInfo.channel.isInitialized && connectedPeripheral != nil {
|
||||
if decodedInfo.channel.isInitialized {
|
||||
nowKnown = true
|
||||
channelPacket(channel: decodedInfo.channel, fromNum: Int64(truncatingIfNeeded: connectedPeripheral.num), context: context)
|
||||
channelPacket(channel: decodedInfo.channel, fromNum: Int64(truncatingIfNeeded: cp.num), context: context)
|
||||
}
|
||||
// Config
|
||||
if decodedInfo.config.isInitialized && !invalidVersion && connectedPeripheral != nil && self.connectedPeripheral?.num != 0 {
|
||||
if decodedInfo.config.isInitialized && !invalidVersion && cp.num != 0 {
|
||||
nowKnown = true
|
||||
localConfig(config: decodedInfo.config, context: context, nodeNum: Int64(truncatingIfNeeded: self.connectedPeripheral.num), nodeLongName: self.connectedPeripheral?.longName ?? "Unknown")
|
||||
localConfig(config: decodedInfo.config, context: context, nodeNum: Int64(truncatingIfNeeded: cp.num), nodeLongName: cp.longName)
|
||||
}
|
||||
// Module Config
|
||||
if decodedInfo.moduleConfig.isInitialized && !invalidVersion && self.connectedPeripheral?.num != 0 {
|
||||
if decodedInfo.moduleConfig.isInitialized && !invalidVersion && cp.num != 0 {
|
||||
onWantConfigResponseReceived()
|
||||
nowKnown = true
|
||||
moduleConfig(config: decodedInfo.moduleConfig, context: context, nodeNum: Int64(truncatingIfNeeded: self.connectedPeripheral.num), nodeLongName: self.connectedPeripheral?.longName ?? "Unknown")
|
||||
moduleConfig(config: decodedInfo.moduleConfig, context: context, nodeNum: Int64(truncatingIfNeeded: cp.num), nodeLongName: cp.longName)
|
||||
if decodedInfo.moduleConfig.payloadVariant == ModuleConfig.OneOf_PayloadVariant.cannedMessage(decodedInfo.moduleConfig.cannedMessage) {
|
||||
if decodedInfo.moduleConfig.cannedMessage.enabled {
|
||||
if let connectedNum = self.connectedPeripheral?.num, connectedNum > 0 {
|
||||
_ = self.getCannedMessageModuleMessages(destNum: connectedNum, wantResponse: true)
|
||||
}
|
||||
_ = self.getCannedMessageModuleMessages(destNum: cp.num, wantResponse: true)
|
||||
|
||||
}
|
||||
}
|
||||
if decodedInfo.config.payloadVariant == Config.OneOf_PayloadVariant.device(decodedInfo.config.device) {
|
||||
var dc = decodedInfo.config.device
|
||||
if dc.tzdef.isEmpty {
|
||||
dc.tzdef = TimeZone.current.posixDescription
|
||||
_ = self.saveTimeZone(config: dc, user: cp.num)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Device Metadata
|
||||
if decodedInfo.metadata.firmwareVersion.count > 0 && !invalidVersion {
|
||||
nowKnown = true
|
||||
deviceMetadataPacket(metadata: decodedInfo.metadata, fromNum: connectedPeripheral.num, context: context)
|
||||
deviceMetadataPacket(metadata: decodedInfo.metadata, fromNum: cp.num, context: context)
|
||||
connectedPeripheral.firmwareVersion = decodedInfo.metadata.firmwareVersion
|
||||
let lastDotIndex = decodedInfo.metadata.firmwareVersion.lastIndex(of: ".")
|
||||
if lastDotIndex == nil {
|
||||
|
|
@ -1084,6 +1093,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
Logger.mesh.info("🕸️ MESH PACKET received for Reticulum Tunnel App UNHANDLED \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure", privacy: .public)")
|
||||
case .keyVerificationApp:
|
||||
Logger.mesh.warning("🕸️ MESH PACKET received for Key Verification App UNHANDLED \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure", privacy: .public)")
|
||||
case .cayenneApp:
|
||||
Logger.mesh.info("🕸️ MESH PACKET received Cayenne App UNHANDLED \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure", privacy: .public)")
|
||||
}
|
||||
|
||||
if decodedInfo.configCompleteID != 0 && decodedInfo.configCompleteID == NONCE_ONLY_CONFIG {
|
||||
|
|
@ -1092,6 +1103,9 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
isSubscribed = true
|
||||
allowDisconnect = true
|
||||
Logger.mesh.info("🤜 [BLE] Want Config Complete. ID:\(decodedInfo.configCompleteID, privacy: .public)")
|
||||
if UserDefaults.firstLaunch {
|
||||
UserDefaults.showDeviceOnboarding = true
|
||||
}
|
||||
if sendTime() {
|
||||
}
|
||||
peripherals.removeAll(where: { $0.peripheral.state == CBPeripheralState.disconnected })
|
||||
|
|
@ -2231,6 +2245,29 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
}
|
||||
return 0
|
||||
}
|
||||
public func saveTimeZone(config: Config.DeviceConfig, user: Int64) -> Int64 {
|
||||
|
||||
var adminPacket = AdminMessage()
|
||||
adminPacket.setConfig.device = config
|
||||
var meshPacket: MeshPacket = MeshPacket()
|
||||
meshPacket.to = UInt32(user)
|
||||
meshPacket.from = UInt32(user)
|
||||
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 0
|
||||
}
|
||||
dataMessage.payload = adminData
|
||||
dataMessage.portnum = PortNum.adminApp
|
||||
meshPacket.decoded = dataMessage
|
||||
let messageDescription = "⌚ Device Config timezone was empty set timezone to \(config.tzdef)"
|
||||
if sendAdminMessageToRadio(meshPacket: meshPacket, adminDescription: messageDescription) {
|
||||
return Int64(meshPacket.id)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
public func saveDisplayConfig(config: Config.DisplayConfig, fromUser: UserEntity, toUser: UserEntity) -> Int64 {
|
||||
var adminPacket = AdminMessage()
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
import Foundation
|
||||
import CoreLocation
|
||||
import MapKit
|
||||
import OSLog
|
||||
|
||||
class LocationHelper: NSObject, ObservableObject, CLLocationManagerDelegate {
|
||||
static let shared = LocationHelper()
|
||||
var locationManager = CLLocationManager()
|
||||
|
||||
// @Published var region = MKCoordinateRegion()
|
||||
@Published var authorizationStatus: CLAuthorizationStatus?
|
||||
override init() {
|
||||
super.init()
|
||||
locationManager.delegate = self
|
||||
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
||||
locationManager.pausesLocationUpdatesAutomatically = true
|
||||
locationManager.allowsBackgroundLocationUpdates = true
|
||||
locationManager.activityType = .other
|
||||
}
|
||||
// Apple Park
|
||||
static let DefaultLocation = CLLocationCoordinate2D(latitude: 37.3346, longitude: -122.0090)
|
||||
static var currentLocation: CLLocationCoordinate2D {
|
||||
guard let location = shared.locationManager.location else {
|
||||
return DefaultLocation
|
||||
}
|
||||
return location.coordinate
|
||||
}
|
||||
static var satsInView: Int {
|
||||
// If we have a position we have a sat
|
||||
var sats = 1
|
||||
if shared.locationManager.location?.verticalAccuracy ?? 0 > 0 {
|
||||
sats = 4
|
||||
if 0...5 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
|
||||
sats = 12
|
||||
} else if 6...15 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
|
||||
sats = 10
|
||||
} else if 16...30 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
|
||||
sats = 9
|
||||
} else if 31...45 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
|
||||
sats = 7
|
||||
} else if 46...60 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
|
||||
sats = 5
|
||||
}
|
||||
} else if shared.locationManager.location?.verticalAccuracy ?? 0 < 0 && 60...300 ~= shared.locationManager.location?.horizontalAccuracy ?? 0 {
|
||||
sats = 3
|
||||
} else if shared.locationManager.location?.verticalAccuracy ?? 0 < 0 && shared.locationManager.location?.horizontalAccuracy ?? 0 > 300 {
|
||||
sats = 2
|
||||
}
|
||||
return sats
|
||||
}
|
||||
|
||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||
switch manager.authorizationStatus {
|
||||
case .authorizedAlways:
|
||||
authorizationStatus = .authorizedAlways
|
||||
case .authorizedWhenInUse:
|
||||
authorizationStatus = .authorizedWhenInUse
|
||||
locationManager.requestLocation()
|
||||
case .restricted:
|
||||
authorizationStatus = .restricted
|
||||
case .denied:
|
||||
authorizationStatus = .denied
|
||||
case .notDetermined:
|
||||
authorizationStatus = .notDetermined
|
||||
locationManager.requestAlwaysAuthorization()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||
|
||||
}
|
||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
||||
Logger.services.error("Location manager error: \(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
|
|
@ -10,14 +10,14 @@ import CoreLocation
|
|||
import OSLog
|
||||
|
||||
// Shared state that manages the `CLLocationManager` and `CLBackgroundActivitySession`.
|
||||
@MainActor class LocationsHandler: ObservableObject {
|
||||
@MainActor class LocationsHandler: NSObject, ObservableObject, @preconcurrency CLLocationManagerDelegate {
|
||||
|
||||
static let shared = LocationsHandler() // Create a single, shared instance of the object.
|
||||
private let manager: CLLocationManager
|
||||
public var manager = CLLocationManager()
|
||||
private var background: CLBackgroundActivitySession?
|
||||
var enableSmartPosition: Bool = UserDefaults.enableSmartPosition
|
||||
|
||||
@Published var locationsArray: [CLLocation]
|
||||
@Published var locationsArray: [CLLocation] = [CLLocation]()
|
||||
@Published var isStationary = false
|
||||
@Published var count = 0
|
||||
@Published var isRecording = false
|
||||
|
|
@ -38,16 +38,29 @@ import OSLog
|
|||
UserDefaults.standard.set(backgroundActivity, forKey: "BGActivitySessionStarted")
|
||||
}
|
||||
}
|
||||
// The continuation we will use to asynchronously ask the user permission to track their location.
|
||||
private var permissionContinuation: CheckedContinuation<CLAuthorizationStatus, Never>?
|
||||
func requestLocationAlwaysPermissions() async -> CLAuthorizationStatus {
|
||||
return await withCheckedContinuation { continuation in
|
||||
self.permissionContinuation = continuation
|
||||
manager.requestAlwaysAuthorization()
|
||||
}
|
||||
}
|
||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||
// This is the line you need to add
|
||||
permissionContinuation?.resume(returning: manager.authorizationStatus)
|
||||
}
|
||||
|
||||
private init() {
|
||||
self.manager = CLLocationManager() // Creating a location manager instance is safe to call here in `MainActor`.
|
||||
override init() {
|
||||
super.init()
|
||||
self.manager.delegate = self
|
||||
self.manager.allowsBackgroundLocationUpdates = true
|
||||
locationsArray = [CLLocation]()
|
||||
}
|
||||
|
||||
func startLocationUpdates() {
|
||||
if self.manager.authorizationStatus == .notDetermined {
|
||||
self.manager.requestWhenInUseAuthorization()
|
||||
let status = self.manager.authorizationStatus
|
||||
guard status == .authorizedAlways || status == .authorizedWhenInUse else {
|
||||
return
|
||||
}
|
||||
Logger.services.info("📍 [App] Starting location updates")
|
||||
Task {
|
||||
|
|
|
|||
|
|
@ -1027,7 +1027,7 @@ func textMessageAppPacket(
|
|||
subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")",
|
||||
content: messageText!,
|
||||
target: "messages",
|
||||
path: "meshtastic:///messages?userNum=\(newMessage.fromUser?.num ?? 0)&messageId=\(newMessage.messageId)",
|
||||
path: "meshtastic:///messages?userNum=\(newMessage.fromUser?.num ?? 0)&messageId=\(newMessage.isEmoji ? newMessage.replyID : newMessage.messageId)",
|
||||
messageId: newMessage.messageId,
|
||||
channel: newMessage.channel,
|
||||
userNum: Int64(packet.from),
|
||||
|
|
@ -1058,7 +1058,7 @@ func textMessageAppPacket(
|
|||
subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")",
|
||||
content: messageText!,
|
||||
target: "messages",
|
||||
path: "meshtastic:///messages?channelId=\(newMessage.channel)&messageId=\(newMessage.messageId)",
|
||||
path: "meshtastic:///messages?channelId=\(newMessage.channel)&messageId=\(newMessage.isEmoji ? newMessage.replyID : newMessage.messageId)",
|
||||
messageId: newMessage.messageId,
|
||||
channel: newMessage.channel,
|
||||
userNum: Int64(newMessage.fromUser?.userId ?? "0"),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import MeshtasticProtobufs
|
|||
import DatadogCore
|
||||
import DatadogCrashReporting
|
||||
import DatadogRUM
|
||||
import DatadogTrace
|
||||
import DatadogLogs
|
||||
|
||||
@main
|
||||
struct MeshtasticAppleApp: App {
|
||||
|
|
@ -41,14 +43,24 @@ struct MeshtasticAppleApp: App {
|
|||
env: environment,
|
||||
site: .us5
|
||||
),
|
||||
trackingConsent: UserDefaults.usageDataAndCrashReporting ? .granted : .notGranted
|
||||
trackingConsent: UserDefaults.usageDataAndCrashReporting ? .granted : .notGranted,
|
||||
)
|
||||
DatadogCrashReporting.CrashReporting.enable()
|
||||
|
||||
Logs.enable()
|
||||
|
||||
Trace.enable(
|
||||
with: Trace.Configuration(
|
||||
sampleRate: 100, networkInfoEnabled: true // 100% sampling for development/testing, reduce for production
|
||||
)
|
||||
)
|
||||
|
||||
RUM.enable(
|
||||
with: RUM.Configuration(
|
||||
applicationID: appID,
|
||||
uiKitViewsPredicate: DefaultUIKitRUMViewsPredicate(),
|
||||
uiKitActionsPredicate: DefaultUIKitRUMActionsPredicate()
|
||||
uiKitActionsPredicate: DefaultUIKitRUMActionsPredicate(),
|
||||
trackBackgroundEvents: true
|
||||
)
|
||||
)
|
||||
self._appState = ObservedObject(wrappedValue: appState)
|
||||
|
|
|
|||
|
|
@ -8,19 +8,6 @@ import CoreData
|
|||
import MeshtasticProtobufs
|
||||
import OSLog
|
||||
|
||||
// MARK: - Safe Conversion Helpers
|
||||
private func safeInt32(from value: UInt32) -> Int32 {
|
||||
return Int32(clamping: value)
|
||||
}
|
||||
|
||||
private func safeInt32(from value: Int) -> Int32 {
|
||||
return Int32(clamping: value)
|
||||
}
|
||||
|
||||
private func safeInt32(from value: UInt64) -> Int32 {
|
||||
return Int32(clamping: value)
|
||||
}
|
||||
|
||||
public func clearStaleNodes(nodeExpireDays: Int, context: NSManagedObjectContext) -> Bool {
|
||||
var nodeExpireTime: TimeInterval {
|
||||
return TimeInterval(-nodeExpireDays * 86400)
|
||||
|
|
@ -807,32 +794,32 @@ func upsertPositionConfigPacket(config: Config.PositionConfig, nodeNum: Int64, s
|
|||
let newPositionConfig = PositionConfigEntity(context: context)
|
||||
newPositionConfig.smartPositionEnabled = config.positionBroadcastSmartEnabled
|
||||
newPositionConfig.deviceGpsEnabled = config.gpsEnabled
|
||||
newPositionConfig.gpsMode = Int32(config.gpsMode.rawValue)
|
||||
newPositionConfig.rxGpio = Int32(config.rxGpio)
|
||||
newPositionConfig.txGpio = Int32(config.txGpio)
|
||||
newPositionConfig.gpsEnGpio = Int32(config.gpsEnGpio)
|
||||
newPositionConfig.gpsMode = Int32(truncatingIfNeeded: config.gpsMode.rawValue)
|
||||
newPositionConfig.rxGpio = Int32(truncatingIfNeeded: config.rxGpio)
|
||||
newPositionConfig.txGpio = Int32(truncatingIfNeeded: config.txGpio)
|
||||
newPositionConfig.gpsEnGpio = Int32(truncatingIfNeeded: config.gpsEnGpio)
|
||||
newPositionConfig.fixedPosition = config.fixedPosition
|
||||
newPositionConfig.positionBroadcastSeconds = Int32(truncatingIfNeeded: config.positionBroadcastSecs)
|
||||
newPositionConfig.broadcastSmartMinimumIntervalSecs = Int32(config.broadcastSmartMinimumIntervalSecs)
|
||||
newPositionConfig.broadcastSmartMinimumDistance = Int32(config.broadcastSmartMinimumDistance)
|
||||
newPositionConfig.positionFlags = Int32(config.positionFlags)
|
||||
newPositionConfig.broadcastSmartMinimumIntervalSecs = Int32(truncatingIfNeeded: config.broadcastSmartMinimumIntervalSecs)
|
||||
newPositionConfig.broadcastSmartMinimumDistance = Int32(truncatingIfNeeded: config.broadcastSmartMinimumDistance)
|
||||
newPositionConfig.positionFlags = Int32(truncatingIfNeeded: config.positionFlags)
|
||||
newPositionConfig.gpsAttemptTime = 900
|
||||
newPositionConfig.gpsUpdateInterval = Int32(config.gpsUpdateInterval)
|
||||
newPositionConfig.gpsUpdateInterval = Int32(truncatingIfNeeded: config.gpsUpdateInterval)
|
||||
fetchedNode[0].positionConfig = newPositionConfig
|
||||
} else {
|
||||
fetchedNode[0].positionConfig?.smartPositionEnabled = config.positionBroadcastSmartEnabled
|
||||
fetchedNode[0].positionConfig?.deviceGpsEnabled = config.gpsEnabled
|
||||
fetchedNode[0].positionConfig?.gpsMode = Int32(config.gpsMode.rawValue)
|
||||
fetchedNode[0].positionConfig?.rxGpio = Int32(config.rxGpio)
|
||||
fetchedNode[0].positionConfig?.txGpio = Int32(config.txGpio)
|
||||
fetchedNode[0].positionConfig?.gpsEnGpio = Int32(config.gpsEnGpio)
|
||||
fetchedNode[0].positionConfig?.gpsMode = Int32(truncatingIfNeeded: config.gpsMode.rawValue)
|
||||
fetchedNode[0].positionConfig?.rxGpio = Int32(truncatingIfNeeded: config.rxGpio)
|
||||
fetchedNode[0].positionConfig?.txGpio = Int32(truncatingIfNeeded: config.txGpio)
|
||||
fetchedNode[0].positionConfig?.gpsEnGpio = Int32(truncatingIfNeeded: config.gpsEnGpio)
|
||||
fetchedNode[0].positionConfig?.fixedPosition = config.fixedPosition
|
||||
fetchedNode[0].positionConfig?.positionBroadcastSeconds = Int32(truncatingIfNeeded: config.positionBroadcastSecs)
|
||||
fetchedNode[0].positionConfig?.broadcastSmartMinimumIntervalSecs = Int32(config.broadcastSmartMinimumIntervalSecs)
|
||||
fetchedNode[0].positionConfig?.broadcastSmartMinimumDistance = Int32(config.broadcastSmartMinimumDistance)
|
||||
fetchedNode[0].positionConfig?.broadcastSmartMinimumIntervalSecs = Int32(truncatingIfNeeded: config.broadcastSmartMinimumIntervalSecs)
|
||||
fetchedNode[0].positionConfig?.broadcastSmartMinimumDistance = Int32(truncatingIfNeeded: config.broadcastSmartMinimumDistance)
|
||||
fetchedNode[0].positionConfig?.gpsAttemptTime = 900
|
||||
fetchedNode[0].positionConfig?.gpsUpdateInterval = Int32(config.gpsUpdateInterval)
|
||||
fetchedNode[0].positionConfig?.positionFlags = Int32(config.positionFlags)
|
||||
fetchedNode[0].positionConfig?.gpsUpdateInterval = Int32(truncatingIfNeeded: config.gpsUpdateInterval)
|
||||
fetchedNode[0].positionConfig?.positionFlags = Int32(truncatingIfNeeded: config.positionFlags)
|
||||
}
|
||||
if sessionPasskey != nil {
|
||||
fetchedNode[0].sessionPasskey = sessionPasskey
|
||||
|
|
@ -937,6 +924,8 @@ func upsertSecurityConfigPacket(config: Config.SecurityConfig, nodeNum: Int64, s
|
|||
fetchedNode[0].securityConfig?.adminKey = config.adminKey[0]
|
||||
if config.adminKey.count > 1 {
|
||||
fetchedNode[0].securityConfig?.adminKey2 = config.adminKey[1]
|
||||
}
|
||||
if config.adminKey.count > 2 {
|
||||
fetchedNode[0].securityConfig?.adminKey3 = config.adminKey[2]
|
||||
}
|
||||
}
|
||||
|
|
@ -1512,23 +1501,23 @@ func upsertTelemetryModuleConfigPacket(config: ModuleConfig.TelemetryConfig, nod
|
|||
if !fetchedNode.isEmpty {
|
||||
if fetchedNode[0].telemetryConfig == nil {
|
||||
let newTelemetryConfig = TelemetryConfigEntity(context: context)
|
||||
newTelemetryConfig.deviceUpdateInterval = safeInt32(from: config.deviceUpdateInterval)
|
||||
newTelemetryConfig.environmentUpdateInterval = safeInt32(from: config.environmentUpdateInterval)
|
||||
newTelemetryConfig.deviceUpdateInterval = Int32(truncatingIfNeeded: config.deviceUpdateInterval)
|
||||
newTelemetryConfig.environmentUpdateInterval = Int32(truncatingIfNeeded: config.environmentUpdateInterval)
|
||||
newTelemetryConfig.environmentMeasurementEnabled = config.environmentMeasurementEnabled
|
||||
newTelemetryConfig.environmentScreenEnabled = config.environmentScreenEnabled
|
||||
newTelemetryConfig.environmentDisplayFahrenheit = config.environmentDisplayFahrenheit
|
||||
newTelemetryConfig.powerMeasurementEnabled = config.powerMeasurementEnabled
|
||||
newTelemetryConfig.powerUpdateInterval = safeInt32(from: config.powerUpdateInterval)
|
||||
newTelemetryConfig.powerUpdateInterval = Int32(truncatingIfNeeded: config.powerUpdateInterval)
|
||||
newTelemetryConfig.powerScreenEnabled = config.powerScreenEnabled
|
||||
fetchedNode[0].telemetryConfig = newTelemetryConfig
|
||||
} else {
|
||||
fetchedNode[0].telemetryConfig?.deviceUpdateInterval = safeInt32(from: config.deviceUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.environmentUpdateInterval = safeInt32(from: config.environmentUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.deviceUpdateInterval = Int32(truncatingIfNeeded: config.deviceUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.environmentUpdateInterval = Int32(truncatingIfNeeded: config.environmentUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.environmentMeasurementEnabled = config.environmentMeasurementEnabled
|
||||
fetchedNode[0].telemetryConfig?.environmentScreenEnabled = config.environmentScreenEnabled
|
||||
fetchedNode[0].telemetryConfig?.environmentDisplayFahrenheit = config.environmentDisplayFahrenheit
|
||||
fetchedNode[0].telemetryConfig?.powerMeasurementEnabled = config.powerMeasurementEnabled
|
||||
fetchedNode[0].telemetryConfig?.powerUpdateInterval = safeInt32(from: config.powerUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.powerUpdateInterval = Int32(truncatingIfNeeded: config.powerUpdateInterval)
|
||||
fetchedNode[0].telemetryConfig?.powerScreenEnabled = config.powerScreenEnabled
|
||||
}
|
||||
if sessionPasskey != nil {
|
||||
|
|
|
|||
|
|
@ -923,6 +923,20 @@
|
|||
],
|
||||
"requiresDfu": true
|
||||
},
|
||||
{
|
||||
"hwModel": 100,
|
||||
"hwModelSlug": "SEEED_WIO_TRACKER_L1_EINK",
|
||||
"platformioTarget": "seeed_wio_tracker_L1_eink",
|
||||
"architecture": "nrf52840",
|
||||
"activelySupported": false,
|
||||
"supportLevel": 1,
|
||||
"displayName": "Seeed Wio Tracker L1 E-Ink",
|
||||
"tags": [
|
||||
"Seeed"
|
||||
],
|
||||
"requiresDfu": true,
|
||||
"hasInkHud": true
|
||||
},
|
||||
{
|
||||
"hwModel": 97,
|
||||
"hwModelSlug": "CROWPANEL",
|
||||
|
|
|
|||
|
|
@ -27,20 +27,6 @@ struct Connect: View {
|
|||
@State var presentingSwitchPreferredPeripheral = false
|
||||
@State var selectedPeripherialId = ""
|
||||
|
||||
init () {
|
||||
let notificationCenter = UNUserNotificationCenter.current()
|
||||
notificationCenter.getNotificationSettings(completionHandler: { (settings) in
|
||||
if settings.authorizationStatus == .notDetermined {
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound, .criticalAlert]) { success, error in
|
||||
if success {
|
||||
Logger.services.info("Notifications are all set!")
|
||||
} else if let error = error {
|
||||
Logger.services.error("\(error.localizedDescription, privacy: .public)")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@
|
|||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@ObservedObject
|
||||
var appState: AppState
|
||||
@ObservedObject var appState: AppState
|
||||
|
||||
@ObservedObject
|
||||
var router: Router
|
||||
@ObservedObject var router: Router
|
||||
@State var isShowingDeviceOnboardingFlow: Bool = false
|
||||
|
||||
init(appState: AppState, router: Router) {
|
||||
self.appState = appState
|
||||
|
|
@ -58,6 +57,21 @@ struct ContentView: View {
|
|||
.font(.title)
|
||||
}
|
||||
.tag(NavigationState.Tab.settings)
|
||||
}.sheet(
|
||||
isPresented: $isShowingDeviceOnboardingFlow,
|
||||
onDismiss: {
|
||||
UserDefaults.firstLaunch = false
|
||||
}, content: {
|
||||
DeviceOnboarding()
|
||||
}
|
||||
)
|
||||
.onAppear {
|
||||
if UserDefaults.firstLaunch {
|
||||
isShowingDeviceOnboardingFlow = true
|
||||
}
|
||||
}
|
||||
.onChange(of: UserDefaults.showDeviceOnboarding) { newValue in
|
||||
isShowingDeviceOnboardingFlow = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,6 +284,9 @@ struct NodeList: View {
|
|||
// Make sure the ZStack passes through accessibility to the ConnectedDevice component
|
||||
.accessibilityElement(children: .contain)
|
||||
)
|
||||
.onDisappear {
|
||||
router.navigationState.nodeListSelectedNodeNum = nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ContentUnavailableView("Select Node", systemImage: "flipphone")
|
||||
|
|
|
|||
284
Meshtastic/Views/Onboarding/DeviceOnboarding.swift
Normal file
284
Meshtastic/Views/Onboarding/DeviceOnboarding.swift
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
import CoreBluetooth
|
||||
import OSLog
|
||||
import SwiftUI
|
||||
import Foundation
|
||||
import MapKit
|
||||
|
||||
struct DeviceOnboarding: View {
|
||||
enum SetupGuide: Hashable {
|
||||
case notifications
|
||||
case location
|
||||
}
|
||||
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
@State var navigationPath: [SetupGuide] = []
|
||||
@State var locationStatus = LocationsHandler.shared.manager.authorizationStatus
|
||||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
/// The Title View
|
||||
var title: some View {
|
||||
VStack {
|
||||
Text("Welcome to")
|
||||
.font(.title2.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
Text("Meshtastic")
|
||||
.font(.largeTitle.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
|
||||
var welcomeView: some View {
|
||||
VStack {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack {
|
||||
// Title
|
||||
title
|
||||
.padding(.top)
|
||||
// Onboarding
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
makeRow(
|
||||
icon: "antenna.radiowaves.left.and.right",
|
||||
title: "Stay Connected Anywhere",
|
||||
subtitle: "Communicate off-the-grid with your friends and community without cell service."
|
||||
)
|
||||
|
||||
makeRow(
|
||||
icon: "point.3.connected.trianglepath.dotted",
|
||||
title: "Create Your Own Networks",
|
||||
subtitle: "Easily set up private mesh networks for secure and reliable communication in remote areas."
|
||||
)
|
||||
|
||||
makeRow(
|
||||
icon: "location",
|
||||
title: "Track and Share Locations",
|
||||
subtitle: "Share your location in real-time and keep your group coordinated with integrated GPS features."
|
||||
)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
Spacer()
|
||||
if bleManager.isSwitchedOn {
|
||||
Button {
|
||||
Task {
|
||||
await goToNextStep(after: nil)
|
||||
}
|
||||
} label: {
|
||||
Text("Get started")
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var notificationView: some View {
|
||||
VStack {
|
||||
VStack {
|
||||
Text("App Notifications")
|
||||
.font(.largeTitle.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
Text("Send Notifications")
|
||||
.font(.title2.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
makeRow(
|
||||
icon: "message",
|
||||
title: "Incoming Messages",
|
||||
subtitle: "Meshtastic notifications for channel messages and direct messages"
|
||||
)
|
||||
makeRow(
|
||||
icon: "flipphone",
|
||||
title: "New Nodes",
|
||||
subtitle: "Allow Meshtastic to send notifications for messages, newly discovered nodes and low battery alerts for the connected device."
|
||||
)
|
||||
makeRow(
|
||||
icon: "battery.25percent",
|
||||
title: "Low Battery",
|
||||
subtitle: "Allow Meshtastic to send notifications for messages, newly discovered nodes and low battery alerts for the connected device."
|
||||
)
|
||||
Text("Critical Alerts")
|
||||
.font(.title2.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
makeRow(
|
||||
icon: "exclamationmark.triangle.fill",
|
||||
subtitle: "Select packets sent as critical will ignore the mute switch and Do Not Disturb settings in the OS notification center."
|
||||
)
|
||||
}
|
||||
.padding()
|
||||
Spacer()
|
||||
Button {
|
||||
Task {
|
||||
await requestNotificationsPermissions()
|
||||
await goToNextStep(after: .notifications)
|
||||
}
|
||||
} label: {
|
||||
Text("Configure notification permissions")
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
|
||||
var locationView: some View {
|
||||
VStack {
|
||||
VStack {
|
||||
Text("Phone Location")
|
||||
.font(.largeTitle.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
Text("Meshtastic uses your phone's location to enable a number of features. You can update your location permissions at any time from Settings > App Settings > Open Settings.")
|
||||
.font(.body.bold())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
makeRow(
|
||||
icon: "location",
|
||||
title: "Share Location",
|
||||
subtitle: "Use your phone GPS to send locations to your node to instead of using a hardware GPS on your node."
|
||||
)
|
||||
makeRow(
|
||||
icon: "lines.measurement.horizontal",
|
||||
title: "Distance Measurements",
|
||||
subtitle: "Used to display the distance between your phone and other Meshtastic nodes where positions are available."
|
||||
)
|
||||
makeRow(
|
||||
icon: "line.3.horizontal.decrease.circle",
|
||||
title: "Distance Filters",
|
||||
subtitle: "Filter the node list and mesh map based on proximity to your phone."
|
||||
)
|
||||
makeRow(
|
||||
icon: "mappin",
|
||||
title: "Mesh Map Location",
|
||||
subtitle: "Enables the blue location dot for your phone in the mesh map."
|
||||
)
|
||||
}
|
||||
.padding()
|
||||
Spacer()
|
||||
Button {
|
||||
Task {
|
||||
await requestLocationPermissions()
|
||||
}
|
||||
} label: {
|
||||
Text("Configure Location Permissions")
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.padding()
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack(path: $navigationPath) {
|
||||
welcomeView
|
||||
.navigationDestination(for: SetupGuide.self) { guide in
|
||||
switch guide {
|
||||
case .notifications:
|
||||
notificationView
|
||||
case .location:
|
||||
locationView
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar(.hidden)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func makeRow(
|
||||
icon: String,
|
||||
title: String = "",
|
||||
subtitle: String
|
||||
) -> some View {
|
||||
HStack(alignment: .center) {
|
||||
Image(systemName: icon)
|
||||
.resizable()
|
||||
.symbolRenderingMode(.multicolor)
|
||||
.font(.subheadline)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.padding()
|
||||
.frame(width: 72, height: 72)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text(title)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
.foregroundColor(.primary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
||||
Text(subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}.multilineTextAlignment(.leading)
|
||||
}.accessibilityElement(children: .combine)
|
||||
}
|
||||
|
||||
// MARK: Navigation
|
||||
func goToNextStep(after step: SetupGuide?) async {
|
||||
switch step {
|
||||
case .none:
|
||||
let status = await UNUserNotificationCenter.current().notificationSettings().authorizationStatus
|
||||
let criticalAlert = await UNUserNotificationCenter.current().notificationSettings().criticalAlertSetting
|
||||
if status == .notDetermined && criticalAlert == .notSupported {
|
||||
navigationPath.append(.notifications)
|
||||
} else {
|
||||
fallthrough
|
||||
}
|
||||
case .notifications:
|
||||
locationStatus = LocationsHandler.shared.manager.authorizationStatus
|
||||
if locationStatus == .notDetermined || locationStatus == .restricted || locationStatus == .denied {
|
||||
navigationPath.append(.location)
|
||||
} else {
|
||||
fallthrough
|
||||
}
|
||||
case .location:
|
||||
let status = LocationsHandler.shared.manager.authorizationStatus
|
||||
if status != .notDetermined && status != .restricted && status != .denied {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Permission Checks
|
||||
func requestNotificationsPermissions() async {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
do {
|
||||
let success = try await center.requestAuthorization(options: [.alert, .badge, .sound, .criticalAlert])
|
||||
if success {
|
||||
Logger.services.info("Notification permissions are enabled")
|
||||
} else {
|
||||
Logger.services.info("Notification permissions denied")
|
||||
}
|
||||
} catch {
|
||||
Logger.services.error("Notification permissions error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
func requestLocationPermissions() async {
|
||||
locationStatus = await LocationsHandler.shared.requestLocationAlwaysPermissions()
|
||||
if locationStatus != .notDetermined {
|
||||
Logger.services.info("Location permissions are enabled")
|
||||
} else {
|
||||
Logger.services.info("Location permissions denied")
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
|
@ -334,11 +334,5 @@ struct DeviceConfig: View {
|
|||
self.tripleClickAsAdHocPing = node?.deviceConfig?.tripleClickAsAdHocPing ?? false
|
||||
self.ledHeartbeatEnabled = node?.deviceConfig?.ledHeartbeatEnabled ?? true
|
||||
self.tzdef = node?.deviceConfig?.tzdef ?? ""
|
||||
if self.tzdef.isEmpty {
|
||||
self.tzdef = TimeZone.current.posixDescription
|
||||
self.hasChanges = true
|
||||
} else {
|
||||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -436,6 +436,12 @@ public struct Config: Sendable {
|
|||
/// Non-notification system buzzer tones only.
|
||||
/// Buzzer is enabled only for non-notification tones such as button presses, startup, shutdown, but not for alerts.
|
||||
case systemOnly // = 3
|
||||
|
||||
///
|
||||
/// Direct Message notifications only.
|
||||
/// Buzzer is enabled only for direct messages and alerts, but not for button presses.
|
||||
/// External notification config determines the specifics of the notification behavior.
|
||||
case directMsgOnly // = 4
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
|
|
@ -448,6 +454,7 @@ public struct Config: Sendable {
|
|||
case 1: self = .disabled
|
||||
case 2: self = .notificationsOnly
|
||||
case 3: self = .systemOnly
|
||||
case 4: self = .directMsgOnly
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -458,6 +465,7 @@ public struct Config: Sendable {
|
|||
case .disabled: return 1
|
||||
case .notificationsOnly: return 2
|
||||
case .systemOnly: return 3
|
||||
case .directMsgOnly: return 4
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -468,6 +476,7 @@ public struct Config: Sendable {
|
|||
.disabled,
|
||||
.notificationsOnly,
|
||||
.systemOnly,
|
||||
.directMsgOnly,
|
||||
]
|
||||
|
||||
}
|
||||
|
|
@ -1579,6 +1588,18 @@ public struct Config: Sendable {
|
|||
///
|
||||
/// Philippines 915mhz
|
||||
case ph915 // = 21
|
||||
|
||||
///
|
||||
/// Australia / New Zealand 433MHz
|
||||
case anz433 // = 22
|
||||
|
||||
///
|
||||
/// Kazakhstan 433MHz
|
||||
case kz433 // = 23
|
||||
|
||||
///
|
||||
/// Kazakhstan 863MHz
|
||||
case kz863 // = 24
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
|
|
@ -1609,6 +1630,9 @@ public struct Config: Sendable {
|
|||
case 19: self = .ph433
|
||||
case 20: self = .ph868
|
||||
case 21: self = .ph915
|
||||
case 22: self = .anz433
|
||||
case 23: self = .kz433
|
||||
case 24: self = .kz863
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -1637,6 +1661,9 @@ public struct Config: Sendable {
|
|||
case .ph433: return 19
|
||||
case .ph868: return 20
|
||||
case .ph915: return 21
|
||||
case .anz433: return 22
|
||||
case .kz433: return 23
|
||||
case .kz863: return 24
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -1665,6 +1692,9 @@ public struct Config: Sendable {
|
|||
.ph433,
|
||||
.ph868,
|
||||
.ph915,
|
||||
.anz433,
|
||||
.kz433,
|
||||
.kz863,
|
||||
]
|
||||
|
||||
}
|
||||
|
|
@ -2247,6 +2277,7 @@ extension Config.DeviceConfig.BuzzerMode: SwiftProtobuf._ProtoNameProviding {
|
|||
1: .same(proto: "DISABLED"),
|
||||
2: .same(proto: "NOTIFICATIONS_ONLY"),
|
||||
3: .same(proto: "SYSTEM_ONLY"),
|
||||
4: .same(proto: "DIRECT_MSG_ONLY"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -2992,6 +3023,9 @@ extension Config.LoRaConfig.RegionCode: SwiftProtobuf._ProtoNameProviding {
|
|||
19: .same(proto: "PH_433"),
|
||||
20: .same(proto: "PH_868"),
|
||||
21: .same(proto: "PH_915"),
|
||||
22: .same(proto: "ANZ_433"),
|
||||
23: .same(proto: "KZ_433"),
|
||||
24: .same(proto: "KZ_863"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,53 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
|
|||
typealias Version = _2
|
||||
}
|
||||
|
||||
public enum CompassMode: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
|
||||
///
|
||||
/// Compass with dynamic ring and heading
|
||||
case dynamic // = 0
|
||||
|
||||
///
|
||||
/// Compass with fixed ring and heading
|
||||
case fixedRing // = 1
|
||||
|
||||
///
|
||||
/// Compass with heading and freeze option
|
||||
case freezeHeading // = 2
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
self = .dynamic
|
||||
}
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .dynamic
|
||||
case 1: self = .fixedRing
|
||||
case 2: self = .freezeHeading
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: Int {
|
||||
switch self {
|
||||
case .dynamic: return 0
|
||||
case .fixedRing: return 1
|
||||
case .freezeHeading: return 2
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
public static let allCases: [CompassMode] = [
|
||||
.dynamic,
|
||||
.fixedRing,
|
||||
.freezeHeading,
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public enum Theme: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
|
||||
|
|
@ -350,6 +397,29 @@ public struct DeviceUIConfig: @unchecked Sendable {
|
|||
/// Clears the value of `mapData`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearMapData() {_uniqueStorage()._mapData = nil}
|
||||
|
||||
///
|
||||
/// Compass mode
|
||||
public var compassMode: CompassMode {
|
||||
get {return _storage._compassMode}
|
||||
set {_uniqueStorage()._compassMode = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// RGB color for BaseUI
|
||||
/// 0xRRGGBB format, e.g. 0xFF0000 for red
|
||||
public var screenRgbColor: UInt32 {
|
||||
get {return _storage._screenRgbColor}
|
||||
set {_uniqueStorage()._screenRgbColor = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Clockface analog style
|
||||
/// true for analog clockface, false for digital clockface
|
||||
public var isClockfaceAnalog: Bool {
|
||||
get {return _storage._isClockfaceAnalog}
|
||||
set {_uniqueStorage()._isClockfaceAnalog = newValue}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
|
@ -482,6 +552,14 @@ public struct Map: Sendable {
|
|||
|
||||
fileprivate let _protobuf_package = "meshtastic"
|
||||
|
||||
extension CompassMode: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "DYNAMIC"),
|
||||
1: .same(proto: "FIXED_RING"),
|
||||
2: .same(proto: "FREEZE_HEADING"),
|
||||
]
|
||||
}
|
||||
|
||||
extension Theme: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "DARK"),
|
||||
|
|
@ -533,6 +611,9 @@ extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
|
|||
13: .standard(proto: "node_highlight"),
|
||||
14: .standard(proto: "calibration_data"),
|
||||
15: .standard(proto: "map_data"),
|
||||
16: .standard(proto: "compass_mode"),
|
||||
17: .standard(proto: "screen_rgb_color"),
|
||||
18: .standard(proto: "is_clockface_analog"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
|
|
@ -551,6 +632,9 @@ extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
|
|||
var _nodeHighlight: NodeHighlight? = nil
|
||||
var _calibrationData: Data = Data()
|
||||
var _mapData: Map? = nil
|
||||
var _compassMode: CompassMode = .dynamic
|
||||
var _screenRgbColor: UInt32 = 0
|
||||
var _isClockfaceAnalog: Bool = false
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
|
|
@ -580,6 +664,9 @@ extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
|
|||
_nodeHighlight = source._nodeHighlight
|
||||
_calibrationData = source._calibrationData
|
||||
_mapData = source._mapData
|
||||
_compassMode = source._compassMode
|
||||
_screenRgbColor = source._screenRgbColor
|
||||
_isClockfaceAnalog = source._isClockfaceAnalog
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -613,6 +700,9 @@ extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
|
|||
case 13: try { try decoder.decodeSingularMessageField(value: &_storage._nodeHighlight) }()
|
||||
case 14: try { try decoder.decodeSingularBytesField(value: &_storage._calibrationData) }()
|
||||
case 15: try { try decoder.decodeSingularMessageField(value: &_storage._mapData) }()
|
||||
case 16: try { try decoder.decodeSingularEnumField(value: &_storage._compassMode) }()
|
||||
case 17: try { try decoder.decodeSingularUInt32Field(value: &_storage._screenRgbColor) }()
|
||||
case 18: try { try decoder.decodeSingularBoolField(value: &_storage._isClockfaceAnalog) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -670,6 +760,15 @@ extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
|
|||
try { if let v = _storage._mapData {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 15)
|
||||
} }()
|
||||
if _storage._compassMode != .dynamic {
|
||||
try visitor.visitSingularEnumField(value: _storage._compassMode, fieldNumber: 16)
|
||||
}
|
||||
if _storage._screenRgbColor != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._screenRgbColor, fieldNumber: 17)
|
||||
}
|
||||
if _storage._isClockfaceAnalog != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._isClockfaceAnalog, fieldNumber: 18)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
|
@ -694,6 +793,9 @@ extension DeviceUIConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
|
|||
if _storage._nodeHighlight != rhs_storage._nodeHighlight {return false}
|
||||
if _storage._calibrationData != rhs_storage._calibrationData {return false}
|
||||
if _storage._mapData != rhs_storage._mapData {return false}
|
||||
if _storage._compassMode != rhs_storage._compassMode {return false}
|
||||
if _storage._screenRgbColor != rhs_storage._screenRgbColor {return false}
|
||||
if _storage._isClockfaceAnalog != rhs_storage._isClockfaceAnalog {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
|
|
|
|||
|
|
@ -442,15 +442,15 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
/// Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin
|
||||
case crowpanel // = 97
|
||||
|
||||
///*
|
||||
///
|
||||
/// Lilygo LINK32 board with sensors
|
||||
case link32 // = 98
|
||||
|
||||
///*
|
||||
///
|
||||
/// Seeed Tracker L1
|
||||
case seeedWioTrackerL1 // = 99
|
||||
|
||||
///*
|
||||
///
|
||||
/// Seeed Tracker L1 EINK driver
|
||||
case seeedWioTrackerL1Eink // = 100
|
||||
|
||||
|
|
@ -458,18 +458,30 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
/// Reserved ID for future and past use
|
||||
case qwantzTinyArms // = 101
|
||||
|
||||
///*
|
||||
///
|
||||
/// Lilygo T-Deck Pro
|
||||
case tDeckPro // = 102
|
||||
|
||||
///*
|
||||
///
|
||||
/// Lilygo TLora Pager
|
||||
case tLoraPager // = 103
|
||||
|
||||
///*
|
||||
///
|
||||
/// GAT562 Mesh Trial Tracker
|
||||
case gat562MeshTrialTracker // = 104
|
||||
|
||||
///
|
||||
/// RAKwireless WisMesh Tag
|
||||
case wismeshTag // = 105
|
||||
|
||||
///
|
||||
/// RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/
|
||||
case rak3312 // = 106
|
||||
|
||||
///
|
||||
/// Elecrow ThinkNode M5 https://www.elecrow.com/wiki/ThinkNode_M5_Meshtastic_LoRa_Signal_Transceiver_ESP32-S3.html
|
||||
case thinknodeM5 // = 107
|
||||
|
||||
///
|
||||
/// ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
/// Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||
|
|
@ -588,6 +600,9 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case 102: self = .tDeckPro
|
||||
case 103: self = .tLoraPager
|
||||
case 104: self = .gat562MeshTrialTracker
|
||||
case 105: self = .wismeshTag
|
||||
case 106: self = .rak3312
|
||||
case 107: self = .thinknodeM5
|
||||
case 255: self = .privateHw
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
|
|
@ -700,6 +715,9 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case .tDeckPro: return 102
|
||||
case .tLoraPager: return 103
|
||||
case .gat562MeshTrialTracker: return 104
|
||||
case .wismeshTag: return 105
|
||||
case .rak3312: return 106
|
||||
case .thinknodeM5: return 107
|
||||
case .privateHw: return 255
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
|
|
@ -812,6 +830,9 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
.tDeckPro,
|
||||
.tLoraPager,
|
||||
.gat562MeshTrialTracker,
|
||||
.wismeshTag,
|
||||
.rak3312,
|
||||
.thinknodeM5,
|
||||
.privateHw,
|
||||
]
|
||||
|
||||
|
|
@ -1059,7 +1080,7 @@ public enum ExcludedModules: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
/// Paxcounter module
|
||||
case paxcounterConfig // = 4096
|
||||
|
||||
///
|
||||
///
|
||||
/// Bluetooth config (not technically a module, but used to indicate bluetooth capabilities)
|
||||
case bluetoothConfig // = 8192
|
||||
|
||||
|
|
@ -3640,6 +3661,9 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding {
|
|||
102: .same(proto: "T_DECK_PRO"),
|
||||
103: .same(proto: "T_LORA_PAGER"),
|
||||
104: .same(proto: "GAT562_MESH_TRIAL_TRACKER"),
|
||||
105: .same(proto: "WISMESH_TAG"),
|
||||
106: .same(proto: "RAK3312"),
|
||||
107: .same(proto: "THINKNODE_M5"),
|
||||
255: .same(proto: "PRIVATE_HW"),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,12 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
/// ENCODING: Fragmented RNS Packet. Handled by Meshtastic RNS interface
|
||||
case reticulumTunnelApp // = 76
|
||||
|
||||
///
|
||||
/// App for transporting Cayenne Low Power Payload, popular for LoRaWAN sensor nodes. Offers ability to send
|
||||
/// arbitrary telemetry over meshtastic that is not covered by telemetry.proto
|
||||
/// ENCODING: CayenneLLP
|
||||
case cayenneApp // = 77
|
||||
|
||||
///
|
||||
/// Private applications should use portnums >= 256.
|
||||
/// To simplify initial development and testing you can use "PRIVATE_APP"
|
||||
|
|
@ -252,6 +258,7 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case 73: self = .mapReportApp
|
||||
case 74: self = .powerstressApp
|
||||
case 76: self = .reticulumTunnelApp
|
||||
case 77: self = .cayenneApp
|
||||
case 256: self = .privateApp
|
||||
case 257: self = .atakForwarder
|
||||
case 511: self = .max
|
||||
|
|
@ -289,6 +296,7 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case .mapReportApp: return 73
|
||||
case .powerstressApp: return 74
|
||||
case .reticulumTunnelApp: return 76
|
||||
case .cayenneApp: return 77
|
||||
case .privateApp: return 256
|
||||
case .atakForwarder: return 257
|
||||
case .max: return 511
|
||||
|
|
@ -326,6 +334,7 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
.mapReportApp,
|
||||
.powerstressApp,
|
||||
.reticulumTunnelApp,
|
||||
.cayenneApp,
|
||||
.privateApp,
|
||||
.atakForwarder,
|
||||
.max,
|
||||
|
|
@ -365,6 +374,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
|
|||
73: .same(proto: "MAP_REPORT_APP"),
|
||||
74: .same(proto: "POWERSTRESS_APP"),
|
||||
76: .same(proto: "RETICULUM_TUNNEL_APP"),
|
||||
77: .same(proto: "CAYENNE_APP"),
|
||||
256: .same(proto: "PRIVATE_APP"),
|
||||
257: .same(proto: "ATAK_FORWARDER"),
|
||||
511: .same(proto: "MAX"),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
|
|||
}
|
||||
|
||||
/// Note: There are no 'PowerMon' messages normally in use (PowerMons are sent only as structured logs - slogs).
|
||||
///But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us)
|
||||
/// But we wrap our State enum in this message to effectively nest a namespace (without our linter yelling at us)
|
||||
public struct PowerMon: Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
|
@ -30,7 +30,7 @@ public struct PowerMon: Sendable {
|
|||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
/// Any significant power changing event in meshtastic should be tagged with a powermon state transition.
|
||||
///If you are making new meshtastic features feel free to add new entries at the end of this definition.
|
||||
/// If you are making new meshtastic features feel free to add new entries at the end of this definition.
|
||||
public enum State: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
case none // = 0
|
||||
|
|
@ -57,8 +57,8 @@ public struct PowerMon: Sendable {
|
|||
case wifiOn // = 1024
|
||||
|
||||
///
|
||||
///GPS is actively trying to find our location
|
||||
///See GPSPowerState for more details
|
||||
/// GPS is actively trying to find our location
|
||||
/// See GPSPowerState for more details
|
||||
case gpsActive // = 2048
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
|
|
@ -143,8 +143,8 @@ public struct PowerStressMessage: Sendable {
|
|||
|
||||
///
|
||||
/// What operation would we like the UUT to perform.
|
||||
///note: senders should probably set want_response in their request packets, so that they can know when the state
|
||||
///machine has started processing their request
|
||||
/// note: senders should probably set want_response in their request packets, so that they can know when the state
|
||||
/// machine has started processing their request
|
||||
public enum Opcode: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,10 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
///
|
||||
/// PCT2075 Temperature Sensor
|
||||
case pct2075 // = 39
|
||||
|
||||
///
|
||||
/// ADS1X15 ADC
|
||||
case ads1X15 // = 40
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
|
|
@ -232,6 +236,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case 37: self = .rak12035
|
||||
case 38: self = .max17261
|
||||
case 39: self = .pct2075
|
||||
case 40: self = .ads1X15
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -278,6 +283,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case .rak12035: return 37
|
||||
case .max17261: return 38
|
||||
case .pct2075: return 39
|
||||
case .ads1X15: return 40
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -324,6 +330,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
.rak12035,
|
||||
.max17261,
|
||||
.pct2075,
|
||||
.ads1X15,
|
||||
]
|
||||
|
||||
}
|
||||
|
|
@ -732,6 +739,116 @@ public struct PowerMetrics: Sendable {
|
|||
/// Clears the value of `ch3Current`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh3Current() {self._ch3Current = nil}
|
||||
|
||||
///
|
||||
/// Voltage (Ch4)
|
||||
public var ch4Voltage: Float {
|
||||
get {return _ch4Voltage ?? 0}
|
||||
set {_ch4Voltage = newValue}
|
||||
}
|
||||
/// Returns true if `ch4Voltage` has been explicitly set.
|
||||
public var hasCh4Voltage: Bool {return self._ch4Voltage != nil}
|
||||
/// Clears the value of `ch4Voltage`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh4Voltage() {self._ch4Voltage = nil}
|
||||
|
||||
///
|
||||
/// Current (Ch4)
|
||||
public var ch4Current: Float {
|
||||
get {return _ch4Current ?? 0}
|
||||
set {_ch4Current = newValue}
|
||||
}
|
||||
/// Returns true if `ch4Current` has been explicitly set.
|
||||
public var hasCh4Current: Bool {return self._ch4Current != nil}
|
||||
/// Clears the value of `ch4Current`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh4Current() {self._ch4Current = nil}
|
||||
|
||||
///
|
||||
/// Voltage (Ch5)
|
||||
public var ch5Voltage: Float {
|
||||
get {return _ch5Voltage ?? 0}
|
||||
set {_ch5Voltage = newValue}
|
||||
}
|
||||
/// Returns true if `ch5Voltage` has been explicitly set.
|
||||
public var hasCh5Voltage: Bool {return self._ch5Voltage != nil}
|
||||
/// Clears the value of `ch5Voltage`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh5Voltage() {self._ch5Voltage = nil}
|
||||
|
||||
///
|
||||
/// Current (Ch5)
|
||||
public var ch5Current: Float {
|
||||
get {return _ch5Current ?? 0}
|
||||
set {_ch5Current = newValue}
|
||||
}
|
||||
/// Returns true if `ch5Current` has been explicitly set.
|
||||
public var hasCh5Current: Bool {return self._ch5Current != nil}
|
||||
/// Clears the value of `ch5Current`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh5Current() {self._ch5Current = nil}
|
||||
|
||||
///
|
||||
/// Voltage (Ch6)
|
||||
public var ch6Voltage: Float {
|
||||
get {return _ch6Voltage ?? 0}
|
||||
set {_ch6Voltage = newValue}
|
||||
}
|
||||
/// Returns true if `ch6Voltage` has been explicitly set.
|
||||
public var hasCh6Voltage: Bool {return self._ch6Voltage != nil}
|
||||
/// Clears the value of `ch6Voltage`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh6Voltage() {self._ch6Voltage = nil}
|
||||
|
||||
///
|
||||
/// Current (Ch6)
|
||||
public var ch6Current: Float {
|
||||
get {return _ch6Current ?? 0}
|
||||
set {_ch6Current = newValue}
|
||||
}
|
||||
/// Returns true if `ch6Current` has been explicitly set.
|
||||
public var hasCh6Current: Bool {return self._ch6Current != nil}
|
||||
/// Clears the value of `ch6Current`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh6Current() {self._ch6Current = nil}
|
||||
|
||||
///
|
||||
/// Voltage (Ch7)
|
||||
public var ch7Voltage: Float {
|
||||
get {return _ch7Voltage ?? 0}
|
||||
set {_ch7Voltage = newValue}
|
||||
}
|
||||
/// Returns true if `ch7Voltage` has been explicitly set.
|
||||
public var hasCh7Voltage: Bool {return self._ch7Voltage != nil}
|
||||
/// Clears the value of `ch7Voltage`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh7Voltage() {self._ch7Voltage = nil}
|
||||
|
||||
///
|
||||
/// Current (Ch7)
|
||||
public var ch7Current: Float {
|
||||
get {return _ch7Current ?? 0}
|
||||
set {_ch7Current = newValue}
|
||||
}
|
||||
/// Returns true if `ch7Current` has been explicitly set.
|
||||
public var hasCh7Current: Bool {return self._ch7Current != nil}
|
||||
/// Clears the value of `ch7Current`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh7Current() {self._ch7Current = nil}
|
||||
|
||||
///
|
||||
/// Voltage (Ch8)
|
||||
public var ch8Voltage: Float {
|
||||
get {return _ch8Voltage ?? 0}
|
||||
set {_ch8Voltage = newValue}
|
||||
}
|
||||
/// Returns true if `ch8Voltage` has been explicitly set.
|
||||
public var hasCh8Voltage: Bool {return self._ch8Voltage != nil}
|
||||
/// Clears the value of `ch8Voltage`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh8Voltage() {self._ch8Voltage = nil}
|
||||
|
||||
///
|
||||
/// Current (Ch8)
|
||||
public var ch8Current: Float {
|
||||
get {return _ch8Current ?? 0}
|
||||
set {_ch8Current = newValue}
|
||||
}
|
||||
/// Returns true if `ch8Current` has been explicitly set.
|
||||
public var hasCh8Current: Bool {return self._ch8Current != nil}
|
||||
/// Clears the value of `ch8Current`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCh8Current() {self._ch8Current = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
|
@ -742,6 +859,16 @@ public struct PowerMetrics: Sendable {
|
|||
fileprivate var _ch2Current: Float? = nil
|
||||
fileprivate var _ch3Voltage: Float? = nil
|
||||
fileprivate var _ch3Current: Float? = nil
|
||||
fileprivate var _ch4Voltage: Float? = nil
|
||||
fileprivate var _ch4Current: Float? = nil
|
||||
fileprivate var _ch5Voltage: Float? = nil
|
||||
fileprivate var _ch5Current: Float? = nil
|
||||
fileprivate var _ch6Voltage: Float? = nil
|
||||
fileprivate var _ch6Current: Float? = nil
|
||||
fileprivate var _ch7Voltage: Float? = nil
|
||||
fileprivate var _ch7Current: Float? = nil
|
||||
fileprivate var _ch8Voltage: Float? = nil
|
||||
fileprivate var _ch8Current: Float? = nil
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -894,6 +1021,28 @@ public struct AirQualityMetrics: Sendable {
|
|||
/// Clears the value of `co2`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCo2() {self._co2 = nil}
|
||||
|
||||
///
|
||||
/// CO2 sensor temperature in degC
|
||||
public var co2Temperature: Float {
|
||||
get {return _co2Temperature ?? 0}
|
||||
set {_co2Temperature = newValue}
|
||||
}
|
||||
/// Returns true if `co2Temperature` has been explicitly set.
|
||||
public var hasCo2Temperature: Bool {return self._co2Temperature != nil}
|
||||
/// Clears the value of `co2Temperature`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCo2Temperature() {self._co2Temperature = nil}
|
||||
|
||||
///
|
||||
/// CO2 sensor relative humidity in %
|
||||
public var co2Humidity: Float {
|
||||
get {return _co2Humidity ?? 0}
|
||||
set {_co2Humidity = newValue}
|
||||
}
|
||||
/// Returns true if `co2Humidity` has been explicitly set.
|
||||
public var hasCo2Humidity: Bool {return self._co2Humidity != nil}
|
||||
/// Clears the value of `co2Humidity`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearCo2Humidity() {self._co2Humidity = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
|
@ -911,6 +1060,8 @@ public struct AirQualityMetrics: Sendable {
|
|||
fileprivate var _particles50Um: UInt32? = nil
|
||||
fileprivate var _particles100Um: UInt32? = nil
|
||||
fileprivate var _co2: UInt32? = nil
|
||||
fileprivate var _co2Temperature: Float? = nil
|
||||
fileprivate var _co2Humidity: Float? = nil
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -1104,85 +1255,91 @@ public struct HostMetrics: Sendable {
|
|||
|
||||
///
|
||||
/// Types of Measurements the telemetry module is equipped to handle
|
||||
public struct Telemetry: Sendable {
|
||||
public struct Telemetry: @unchecked Sendable {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
///
|
||||
/// Seconds since 1970 - or 0 for unknown/unset
|
||||
public var time: UInt32 = 0
|
||||
public var time: UInt32 {
|
||||
get {return _storage._time}
|
||||
set {_uniqueStorage()._time = newValue}
|
||||
}
|
||||
|
||||
public var variant: Telemetry.OneOf_Variant? = nil
|
||||
public var variant: OneOf_Variant? {
|
||||
get {return _storage._variant}
|
||||
set {_uniqueStorage()._variant = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Key native device metrics such as battery level
|
||||
public var deviceMetrics: DeviceMetrics {
|
||||
get {
|
||||
if case .deviceMetrics(let v)? = variant {return v}
|
||||
if case .deviceMetrics(let v)? = _storage._variant {return v}
|
||||
return DeviceMetrics()
|
||||
}
|
||||
set {variant = .deviceMetrics(newValue)}
|
||||
set {_uniqueStorage()._variant = .deviceMetrics(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Weather station or other environmental metrics
|
||||
public var environmentMetrics: EnvironmentMetrics {
|
||||
get {
|
||||
if case .environmentMetrics(let v)? = variant {return v}
|
||||
if case .environmentMetrics(let v)? = _storage._variant {return v}
|
||||
return EnvironmentMetrics()
|
||||
}
|
||||
set {variant = .environmentMetrics(newValue)}
|
||||
set {_uniqueStorage()._variant = .environmentMetrics(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Air quality metrics
|
||||
public var airQualityMetrics: AirQualityMetrics {
|
||||
get {
|
||||
if case .airQualityMetrics(let v)? = variant {return v}
|
||||
if case .airQualityMetrics(let v)? = _storage._variant {return v}
|
||||
return AirQualityMetrics()
|
||||
}
|
||||
set {variant = .airQualityMetrics(newValue)}
|
||||
set {_uniqueStorage()._variant = .airQualityMetrics(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Power Metrics
|
||||
public var powerMetrics: PowerMetrics {
|
||||
get {
|
||||
if case .powerMetrics(let v)? = variant {return v}
|
||||
if case .powerMetrics(let v)? = _storage._variant {return v}
|
||||
return PowerMetrics()
|
||||
}
|
||||
set {variant = .powerMetrics(newValue)}
|
||||
set {_uniqueStorage()._variant = .powerMetrics(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Local device mesh statistics
|
||||
public var localStats: LocalStats {
|
||||
get {
|
||||
if case .localStats(let v)? = variant {return v}
|
||||
if case .localStats(let v)? = _storage._variant {return v}
|
||||
return LocalStats()
|
||||
}
|
||||
set {variant = .localStats(newValue)}
|
||||
set {_uniqueStorage()._variant = .localStats(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Health telemetry metrics
|
||||
public var healthMetrics: HealthMetrics {
|
||||
get {
|
||||
if case .healthMetrics(let v)? = variant {return v}
|
||||
if case .healthMetrics(let v)? = _storage._variant {return v}
|
||||
return HealthMetrics()
|
||||
}
|
||||
set {variant = .healthMetrics(newValue)}
|
||||
set {_uniqueStorage()._variant = .healthMetrics(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Linux host metrics
|
||||
public var hostMetrics: HostMetrics {
|
||||
get {
|
||||
if case .hostMetrics(let v)? = variant {return v}
|
||||
if case .hostMetrics(let v)? = _storage._variant {return v}
|
||||
return HostMetrics()
|
||||
}
|
||||
set {variant = .hostMetrics(newValue)}
|
||||
set {_uniqueStorage()._variant = .hostMetrics(newValue)}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
|
@ -1213,6 +1370,8 @@ public struct Telemetry: Sendable {
|
|||
}
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -1281,6 +1440,7 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding {
|
|||
37: .same(proto: "RAK12035"),
|
||||
38: .same(proto: "MAX17261"),
|
||||
39: .same(proto: "PCT2075"),
|
||||
40: .same(proto: "ADS1X15"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -1597,6 +1757,16 @@ extension PowerMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
4: .standard(proto: "ch2_current"),
|
||||
5: .standard(proto: "ch3_voltage"),
|
||||
6: .standard(proto: "ch3_current"),
|
||||
7: .standard(proto: "ch4_voltage"),
|
||||
8: .standard(proto: "ch4_current"),
|
||||
9: .standard(proto: "ch5_voltage"),
|
||||
10: .standard(proto: "ch5_current"),
|
||||
11: .standard(proto: "ch6_voltage"),
|
||||
12: .standard(proto: "ch6_current"),
|
||||
13: .standard(proto: "ch7_voltage"),
|
||||
14: .standard(proto: "ch7_current"),
|
||||
15: .standard(proto: "ch8_voltage"),
|
||||
16: .standard(proto: "ch8_current"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1611,6 +1781,16 @@ extension PowerMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
case 4: try { try decoder.decodeSingularFloatField(value: &self._ch2Current) }()
|
||||
case 5: try { try decoder.decodeSingularFloatField(value: &self._ch3Voltage) }()
|
||||
case 6: try { try decoder.decodeSingularFloatField(value: &self._ch3Current) }()
|
||||
case 7: try { try decoder.decodeSingularFloatField(value: &self._ch4Voltage) }()
|
||||
case 8: try { try decoder.decodeSingularFloatField(value: &self._ch4Current) }()
|
||||
case 9: try { try decoder.decodeSingularFloatField(value: &self._ch5Voltage) }()
|
||||
case 10: try { try decoder.decodeSingularFloatField(value: &self._ch5Current) }()
|
||||
case 11: try { try decoder.decodeSingularFloatField(value: &self._ch6Voltage) }()
|
||||
case 12: try { try decoder.decodeSingularFloatField(value: &self._ch6Current) }()
|
||||
case 13: try { try decoder.decodeSingularFloatField(value: &self._ch7Voltage) }()
|
||||
case 14: try { try decoder.decodeSingularFloatField(value: &self._ch7Current) }()
|
||||
case 15: try { try decoder.decodeSingularFloatField(value: &self._ch8Voltage) }()
|
||||
case 16: try { try decoder.decodeSingularFloatField(value: &self._ch8Current) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1639,6 +1819,36 @@ extension PowerMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
try { if let v = self._ch3Current {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 6)
|
||||
} }()
|
||||
try { if let v = self._ch4Voltage {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 7)
|
||||
} }()
|
||||
try { if let v = self._ch4Current {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 8)
|
||||
} }()
|
||||
try { if let v = self._ch5Voltage {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 9)
|
||||
} }()
|
||||
try { if let v = self._ch5Current {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 10)
|
||||
} }()
|
||||
try { if let v = self._ch6Voltage {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 11)
|
||||
} }()
|
||||
try { if let v = self._ch6Current {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 12)
|
||||
} }()
|
||||
try { if let v = self._ch7Voltage {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 13)
|
||||
} }()
|
||||
try { if let v = self._ch7Current {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 14)
|
||||
} }()
|
||||
try { if let v = self._ch8Voltage {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 15)
|
||||
} }()
|
||||
try { if let v = self._ch8Current {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 16)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -1649,6 +1859,16 @@ extension PowerMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
if lhs._ch2Current != rhs._ch2Current {return false}
|
||||
if lhs._ch3Voltage != rhs._ch3Voltage {return false}
|
||||
if lhs._ch3Current != rhs._ch3Current {return false}
|
||||
if lhs._ch4Voltage != rhs._ch4Voltage {return false}
|
||||
if lhs._ch4Current != rhs._ch4Current {return false}
|
||||
if lhs._ch5Voltage != rhs._ch5Voltage {return false}
|
||||
if lhs._ch5Current != rhs._ch5Current {return false}
|
||||
if lhs._ch6Voltage != rhs._ch6Voltage {return false}
|
||||
if lhs._ch6Current != rhs._ch6Current {return false}
|
||||
if lhs._ch7Voltage != rhs._ch7Voltage {return false}
|
||||
if lhs._ch7Current != rhs._ch7Current {return false}
|
||||
if lhs._ch8Voltage != rhs._ch8Voltage {return false}
|
||||
if lhs._ch8Current != rhs._ch8Current {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -1670,6 +1890,8 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
11: .standard(proto: "particles_50um"),
|
||||
12: .standard(proto: "particles_100um"),
|
||||
13: .same(proto: "co2"),
|
||||
14: .standard(proto: "co2_temperature"),
|
||||
15: .standard(proto: "co2_humidity"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1691,6 +1913,8 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
case 11: try { try decoder.decodeSingularUInt32Field(value: &self._particles50Um) }()
|
||||
case 12: try { try decoder.decodeSingularUInt32Field(value: &self._particles100Um) }()
|
||||
case 13: try { try decoder.decodeSingularUInt32Field(value: &self._co2) }()
|
||||
case 14: try { try decoder.decodeSingularFloatField(value: &self._co2Temperature) }()
|
||||
case 15: try { try decoder.decodeSingularFloatField(value: &self._co2Humidity) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1740,6 +1964,12 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
try { if let v = self._co2 {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 13)
|
||||
} }()
|
||||
try { if let v = self._co2Temperature {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 14)
|
||||
} }()
|
||||
try { if let v = self._co2Humidity {
|
||||
try visitor.visitSingularFloatField(value: v, fieldNumber: 15)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -1757,6 +1987,8 @@ extension AirQualityMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
if lhs._particles50Um != rhs._particles50Um {return false}
|
||||
if lhs._particles100Um != rhs._particles100Um {return false}
|
||||
if lhs._co2 != rhs._co2 {return false}
|
||||
if lhs._co2Temperature != rhs._co2Temperature {return false}
|
||||
if lhs._co2Humidity != rhs._co2Humidity {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -2011,154 +2243,196 @@ extension Telemetry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
|
|||
8: .standard(proto: "host_metrics"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _time: UInt32 = 0
|
||||
var _variant: Telemetry.OneOf_Variant?
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
// The type itself is protecting the reference to its storage via CoW semantics.
|
||||
// This will force a copy to be made of this reference when the first mutation occurs;
|
||||
// hence, it is safe to mark this as `nonisolated(unsafe)`.
|
||||
static nonisolated(unsafe) let defaultInstance = _StorageClass()
|
||||
#else
|
||||
static let defaultInstance = _StorageClass()
|
||||
#endif
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_time = source._time
|
||||
_variant = source._variant
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularFixed32Field(value: &self.time) }()
|
||||
case 2: try {
|
||||
var v: DeviceMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .deviceMetrics(let m) = current {v = m}
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularFixed32Field(value: &_storage._time) }()
|
||||
case 2: try {
|
||||
var v: DeviceMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .deviceMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .deviceMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 3: try {
|
||||
var v: EnvironmentMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .environmentMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .environmentMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 4: try {
|
||||
var v: AirQualityMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .airQualityMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .airQualityMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 5: try {
|
||||
var v: PowerMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .powerMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .powerMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 6: try {
|
||||
var v: LocalStats?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .localStats(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .localStats(v)
|
||||
}
|
||||
}()
|
||||
case 7: try {
|
||||
var v: HealthMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .healthMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .healthMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 8: try {
|
||||
var v: HostMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._variant {
|
||||
hadOneofValue = true
|
||||
if case .hostMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._variant = .hostMetrics(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .deviceMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 3: try {
|
||||
var v: EnvironmentMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .environmentMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .environmentMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 4: try {
|
||||
var v: AirQualityMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .airQualityMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .airQualityMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 5: try {
|
||||
var v: PowerMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .powerMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .powerMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 6: try {
|
||||
var v: LocalStats?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .localStats(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .localStats(v)
|
||||
}
|
||||
}()
|
||||
case 7: try {
|
||||
var v: HealthMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .healthMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .healthMetrics(v)
|
||||
}
|
||||
}()
|
||||
case 8: try {
|
||||
var v: HostMetrics?
|
||||
var hadOneofValue = false
|
||||
if let current = self.variant {
|
||||
hadOneofValue = true
|
||||
if case .hostMetrics(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.variant = .hostMetrics(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if self.time != 0 {
|
||||
try visitor.visitSingularFixed32Field(value: self.time, fieldNumber: 1)
|
||||
}
|
||||
switch self.variant {
|
||||
case .deviceMetrics?: try {
|
||||
guard case .deviceMetrics(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
}()
|
||||
case .environmentMetrics?: try {
|
||||
guard case .environmentMetrics(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}()
|
||||
case .airQualityMetrics?: try {
|
||||
guard case .airQualityMetrics(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
}()
|
||||
case .powerMetrics?: try {
|
||||
guard case .powerMetrics(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}()
|
||||
case .localStats?: try {
|
||||
guard case .localStats(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}()
|
||||
case .healthMetrics?: try {
|
||||
guard case .healthMetrics(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
}()
|
||||
case .hostMetrics?: try {
|
||||
guard case .hostMetrics(let v)? = self.variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 8)
|
||||
}()
|
||||
case nil: break
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if _storage._time != 0 {
|
||||
try visitor.visitSingularFixed32Field(value: _storage._time, fieldNumber: 1)
|
||||
}
|
||||
switch _storage._variant {
|
||||
case .deviceMetrics?: try {
|
||||
guard case .deviceMetrics(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
}()
|
||||
case .environmentMetrics?: try {
|
||||
guard case .environmentMetrics(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}()
|
||||
case .airQualityMetrics?: try {
|
||||
guard case .airQualityMetrics(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
}()
|
||||
case .powerMetrics?: try {
|
||||
guard case .powerMetrics(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}()
|
||||
case .localStats?: try {
|
||||
guard case .localStats(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}()
|
||||
case .healthMetrics?: try {
|
||||
guard case .healthMetrics(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
}()
|
||||
case .hostMetrics?: try {
|
||||
guard case .hostMetrics(let v)? = _storage._variant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 8)
|
||||
}()
|
||||
case nil: break
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Telemetry, rhs: Telemetry) -> Bool {
|
||||
if lhs.time != rhs.time {return false}
|
||||
if lhs.variant != rhs.variant {return false}
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._time != rhs_storage._time {return false}
|
||||
if _storage._variant != rhs_storage._variant {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue