mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
commit
882b4ef89b
19 changed files with 1590 additions and 258 deletions
|
|
@ -352,6 +352,7 @@
|
|||
DD007BAD2AA4E91200F5FA12 /* MyInfoEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoEntityExtension.swift; sourceTree = "<group>"; };
|
||||
DD007BAF2AA5981000F5FA12 /* NodeInfoEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfoEntityExtension.swift; sourceTree = "<group>"; };
|
||||
DD05296F2B77F454008E44CD /* MeshtasticDataModelV 26.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 26.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD0836AB2DE7C7CB00A3A973 /* MeshtasticDataModelV 52.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 52.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD0BE30C2CB785D8000BA445 /* MeshtasticDataModelV 46.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 46.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD0BE30F2CB9FDC4000BA445 /* DetectionSensorEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectionSensorEnums.swift; sourceTree = "<group>"; };
|
||||
DD0E20FF2B892E1300F2D100 /* MeshtasticDataModelV 28.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 28.xcdatamodel"; sourceTree = "<group>"; };
|
||||
|
|
@ -1806,7 +1807,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.3;
|
||||
MARKETING_VERSION = 2.6.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1839,7 +1840,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.3;
|
||||
MARKETING_VERSION = 2.6.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1870,7 +1871,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.3;
|
||||
MARKETING_VERSION = 2.6.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1902,7 +1903,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.3;
|
||||
MARKETING_VERSION = 2.6.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -2001,6 +2002,7 @@
|
|||
DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
DD0836AB2DE7C7CB00A3A973 /* MeshtasticDataModelV 52.xcdatamodel */,
|
||||
DD63CB4E2DD4FBEA00AFCAE2 /* MeshtasticDataModelV 51.xcdatamodel */,
|
||||
233E99B32D84969500CC3A77 /* MeshtasticDataModelV 50.xcdatamodel */,
|
||||
8D3F8A3D2D44B137009EAAA4 /* MeshtasticDataModelV 49.xcdatamodel */,
|
||||
|
|
@ -2053,7 +2055,7 @@
|
|||
DD5D0A9A2931AD6B00F7EA61 /* MeshtasticDataModelV2.xcdatamodel */,
|
||||
DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */,
|
||||
);
|
||||
currentVersion = DD63CB4E2DD4FBEA00AFCAE2 /* MeshtasticDataModelV 51.xcdatamodel */;
|
||||
currentVersion = DD0836AB2DE7C7CB00A3A973 /* MeshtasticDataModelV 52.xcdatamodel */;
|
||||
name = Meshtastic.xcdatamodeld;
|
||||
path = Meshtastic/Meshtastic.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ extension ChannelEntity {
|
|||
channel.settings.psk = self.psk ?? Data()
|
||||
channel.role = Channel.Role(rawValue: Int(self.role)) ?? Channel.Role.secondary
|
||||
channel.settings.moduleSettings.positionPrecision = UInt32(self.positionPrecision)
|
||||
channel.settings.moduleSettings.isClientMuted = self.mute
|
||||
return channel
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -659,7 +659,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
manager.notifications = [
|
||||
Notification(
|
||||
id: UUID().uuidString,
|
||||
title: "Firmware Notification",
|
||||
title: "Firmware Notification".localized,
|
||||
subtitle: "\(decodedInfo.clientNotification.level)".capitalized,
|
||||
content: decodedInfo.clientNotification.message,
|
||||
target: "settings",
|
||||
|
|
@ -667,7 +667,7 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
)
|
||||
]
|
||||
manager.schedule()
|
||||
Logger.data.error("⚠️ Client Notification \((try? decodedInfo.clientNotification.jsonString()) ?? "JSON Decode Failure")")
|
||||
Logger.data.error("⚠️ Client Notification: \(decodedInfo.clientNotification.message, privacy: .public)")
|
||||
}
|
||||
|
||||
switch decodedInfo.packet.decoded.portnum {
|
||||
|
|
@ -978,6 +978,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
Logger.mesh.info("🕸️ MESH PACKET received for Power Stress App UNHANDLED \((try? decodedInfo.packet.jsonString()) ?? "JSON Decode Failure", privacy: .public)")
|
||||
case .reticulumTunnelApp:
|
||||
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)")
|
||||
}
|
||||
|
||||
if decodedInfo.configCompleteID != 0 && decodedInfo.configCompleteID == configNonce {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>MeshtasticDataModelV 51.xcdatamodel</string>
|
||||
<string>MeshtasticDataModelV 52.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,506 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="23788" systemVersion="24D81" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="AmbientLightingConfigEntity" representedClassName="AmbientLightingConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="blue" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="green" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ledState" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="red" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="ambientLightingConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="ambientLightingConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="BluetoothConfigEntity" representedClassName="BluetoothConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceLoggingEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPin" optional="YES" attributeType="Integer 32" defaultValueString="123456" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="bluetoothConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="bluetoothConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="CannedMessageConfigEntity" representedClassName="CannedMessageConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCcw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventCw" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerEventPress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinA" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinB" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="inputbrokerPinPress" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="messages" optional="YES" attributeType="String" minValueString="0" maxValueString="198"/>
|
||||
<attribute name="rotary1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="updown1Enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="cannedMessagesConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="cannedMessageConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="ChannelEntity" representedClassName="ChannelEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="downlinkEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="id" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="index" attributeType="Integer 32" minValueString="0" maxValueString="13" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="mute" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
<attribute name="positionPrecision" optional="YES" attributeType="Integer 32" defaultValueString="32" usesScalarValueType="YES"/>
|
||||
<attribute name="psk" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="role" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="uplinkEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<relationship name="myInfoChannel" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MyInfoEntity" inverseName="channels" inverseEntity="MyInfoEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="index"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="DetectionSensorConfigEntity" representedClassName="DetectionSensorConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="minimumBroadcastSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="monitorPin" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
<attribute name="sendBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="stateBroadcastSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="triggerType" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="usePullup" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<relationship name="detectionSensorConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="detectionSensorConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DeviceConfigEntity" representedClassName="DeviceConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="buttonGpio" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="buzzerGpio" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="debugLogEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="disableTripleClick" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="doubleTapAsButtonPress" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="isManaged" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="ledHeartbeatEnabled" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="nodeInfoBroadcastSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rebroadcastMode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="role" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="serialEnabled" optional="YES" attributeType="Boolean" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="tripleClickAsAdHocPing" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="tzdef" optional="YES" attributeType="String"/>
|
||||
<relationship name="deviceConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="deviceConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DeviceMetadataEntity" representedClassName="DeviceMetadataEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="canShutdown" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="deviceStateVersion" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="excludedModules" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="firmwareVersion" optional="YES" attributeType="String"/>
|
||||
<attribute name="hasBluetooth" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hasEthernet" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hasWifi" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="hwModel" optional="YES" attributeType="String"/>
|
||||
<attribute name="positionFlags" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="role" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="metadataNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="metadata" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="DisplayConfigEntity" representedClassName="DisplayConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="compassNorthTop" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="displayMode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="flipScreen" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsFormat" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="headingBold" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="oledType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenCarouselInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="screenOnSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="units" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="wakeOnTapOrMotion" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<relationship name="displayConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="displayConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="ExternalNotificationConfigEntity" representedClassName="ExternalNotificationConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="active" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBell" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBellBuzzer" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertBellVibra" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessage" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessageBuzzer" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="alertMessageVibra" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="nagTimeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="output" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputBuzzer" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputMilliseconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="outputVibra" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="useI2SAsBuzzer" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="usePWM" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<relationship name="externalNotificationConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="externalNotificationConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="LocationEntity" representedClassName="LocationEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="heading" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="id" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="speed" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="routeLocation" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RouteEntity" inverseName="locations" inverseEntity="RouteEntity"/>
|
||||
</entity>
|
||||
<entity name="LoRaConfigEntity" representedClassName="LoRaConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bandwidth" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelNum" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="codingRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="frequencyOffset" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="hopLimit" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ignoreMqtt" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="modemPreset" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="okToMqtt" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="overrideDutyCycle" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="overrideFrequency" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="regionCode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="spreadFactor" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sx126xRxBoostedGain" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="txEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="txPower" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="usePreset" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<relationship name="loRaConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="loRaConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MessageEntity" representedClassName="MessageEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ackError" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackSNR" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="ackTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="admin" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="adminDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="channel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="isEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="messageId" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="messagePayload" optional="YES" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="messagePayloadMarkdown" optional="YES" attributeType="String"/>
|
||||
<attribute name="messageTimestamp" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="pkiEncrypted" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="portNum" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="publicKey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="read" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="realACK" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="receivedACK" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="replyID" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rssi" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="fromUser" optional="YES" maxCount="1" deletionRule="Nullify" ordered="YES" destinationEntity="UserEntity" inverseName="sentMessages" inverseEntity="UserEntity"/>
|
||||
<relationship name="toUser" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="receivedMessages" inverseEntity="UserEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="messageId"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="MQTTConfigEntity" representedClassName="MQTTConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="address" optional="YES" attributeType="String"/>
|
||||
<attribute name="enabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="encryptionEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="jsonEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="mapPositionPrecision" optional="YES" attributeType="Integer 32" defaultValueString="13" usesScalarValueType="YES"/>
|
||||
<attribute name="mapPublishIntervalSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="mapReportingEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="mapReportingShouldReportLocation" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="password" optional="YES" attributeType="String" maxValueString="30"/>
|
||||
<attribute name="proxyToClientEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="root" optional="YES" attributeType="String" defaultValueString="msh"/>
|
||||
<attribute name="tlsEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="username" optional="YES" attributeType="String" maxValueString="30"/>
|
||||
<relationship name="mqttConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="mqttConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="MyInfoEntity" representedClassName="MyInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="adminIndex" optional="YES" attributeType="Integer 32" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="deviceId" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="minAppVersion" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="myNodeNum" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="peripheralId" optional="YES" attributeType="String"/>
|
||||
<attribute name="rebootCount" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="registered" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<relationship name="channels" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="ChannelEntity" inverseName="myInfoChannel" inverseEntity="ChannelEntity"/>
|
||||
<relationship name="myInfoNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="myInfo" inverseEntity="NodeInfoEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="myNodeNum"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="NetworkConfigEntity" representedClassName="NetworkConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="dns" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="enabledProtocols" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ethEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="gateway" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ip" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ntpServer" optional="YES" attributeType="String"/>
|
||||
<attribute name="subnet" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="wifiEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="wifiMode" optional="YES" attributeType="Integer 32" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="wifiPsk" optional="YES" attributeType="String" minValueString="0" maxValueString="60"/>
|
||||
<attribute name="wifiSsid" optional="YES" attributeType="String" minValueString="0" maxValueString="30"/>
|
||||
<relationship name="networkConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="networkConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="NodeInfoEntity" representedClassName="NodeInfoEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bleName" optional="YES" attributeType="String"/>
|
||||
<attribute name="channel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="favorite" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="firstHeard" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="hopsAway" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="ignored" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="lastHeard" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="peripheralId" optional="YES" attributeType="String"/>
|
||||
<attribute name="rssi" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="sessionExpiration" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="sessionPasskey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="viaMqtt" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<relationship name="ambientLightingConfig" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="AmbientLightingConfigEntity" inverseName="ambientLightingConfigNode" inverseEntity="AmbientLightingConfigEntity"/>
|
||||
<relationship name="bluetoothConfig" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="BluetoothConfigEntity" inverseName="bluetoothConfigNode" inverseEntity="BluetoothConfigEntity"/>
|
||||
<relationship name="cannedMessageConfig" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="CannedMessageConfigEntity" inverseName="cannedMessagesConfigNode" inverseEntity="CannedMessageConfigEntity"/>
|
||||
<relationship name="detectionSensorConfig" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="DetectionSensorConfigEntity" inverseName="detectionSensorConfigNode" inverseEntity="DetectionSensorConfigEntity"/>
|
||||
<relationship name="deviceConfig" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="DeviceConfigEntity" inverseName="deviceConfigNode" inverseEntity="DeviceConfigEntity"/>
|
||||
<relationship name="displayConfig" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="DisplayConfigEntity" inverseName="displayConfigNode" inverseEntity="DisplayConfigEntity"/>
|
||||
<relationship name="externalNotificationConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ExternalNotificationConfigEntity" inverseName="externalNotificationConfigNode" inverseEntity="ExternalNotificationConfigEntity"/>
|
||||
<relationship name="loRaConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="LoRaConfigEntity" inverseName="loRaConfigNode" inverseEntity="LoRaConfigEntity"/>
|
||||
<relationship name="metadata" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="DeviceMetadataEntity" inverseName="metadataNode" inverseEntity="DeviceMetadataEntity"/>
|
||||
<relationship name="mqttConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MQTTConfigEntity" inverseName="mqttConfigNode" inverseEntity="MQTTConfigEntity"/>
|
||||
<relationship name="myInfo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MyInfoEntity" inverseName="myInfoNode" inverseEntity="MyInfoEntity"/>
|
||||
<relationship name="networkConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NetworkConfigEntity" inverseName="networkConfigNode" inverseEntity="NetworkConfigEntity"/>
|
||||
<relationship name="pax" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PaxCounterEntity" inverseName="paxNode" inverseEntity="PaxCounterEntity"/>
|
||||
<relationship name="paxCounterConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PaxCounterConfigEntity" inverseName="paxCounterConfigNode" inverseEntity="PaxCounterConfigEntity"/>
|
||||
<relationship name="positionConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PositionConfigEntity" inverseName="positionConfigNode" inverseEntity="PositionConfigEntity"/>
|
||||
<relationship name="positions" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="PositionEntity" inverseName="nodePosition" inverseEntity="PositionEntity"/>
|
||||
<relationship name="powerConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="PowerConfigEntity" inverseName="powerConfigNode" inverseEntity="PowerConfigEntity"/>
|
||||
<relationship name="rangeTestConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RangeTestConfigEntity" inverseName="rangeTestConfigNode" inverseEntity="RangeTestConfigEntity"/>
|
||||
<relationship name="rtttlConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="RTTTLConfigEntity" inverseName="rtttlConfigNode" inverseEntity="RTTTLConfigEntity"/>
|
||||
<relationship name="securityConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SecurityConfigEntity" inverseName="securityConfigNode" inverseEntity="SecurityConfigEntity"/>
|
||||
<relationship name="serialConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SerialConfigEntity" inverseName="serialConfigNode" inverseEntity="SerialConfigEntity"/>
|
||||
<relationship name="storeForwardConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="StoreForwardConfigEntity" inverseName="storeForwardConfigNode" inverseEntity="StoreForwardConfigEntity"/>
|
||||
<relationship name="telemetries" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TelemetryEntity" inverseName="nodeTelemetry" inverseEntity="TelemetryEntity"/>
|
||||
<relationship name="telemetryConfig" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TelemetryConfigEntity" inverseName="telemetryConfigNode" inverseEntity="TelemetryConfigEntity"/>
|
||||
<relationship name="traceRoutes" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="TraceRouteEntity" inverseName="node" inverseEntity="TraceRouteEntity"/>
|
||||
<relationship name="user" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="UserEntity" inverseName="userNode" inverseEntity="UserEntity"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="num"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="PaxCounterConfigEntity" representedClassName="PaxCounterConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="bleThreshold" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="updateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="wifiThreshold" optional="YES" attributeType="Integer 32" defaultValueString="-80" usesScalarValueType="YES"/>
|
||||
<relationship name="paxCounterConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="paxCounterConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PaxCounterEntity" representedClassName="PaxCounterEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ble" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="uptime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="wifi" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="paxNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="pax" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PositionConfigEntity" representedClassName="PositionConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="broadcastSmartMinimumDistance" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="broadcastSmartMinimumIntervalSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="deviceGpsEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="fixedPosition" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsAttemptTime" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsEnGpio" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsMode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="gpsUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="positionBroadcastSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="positionFlags" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="rxGpio" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="smartPositionEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="txGpio" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="positionConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positionConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PositionEntity" representedClassName="PositionEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="heading" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="latest" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="precisionBits" optional="YES" attributeType="Integer 32" defaultValueString="32" usesScalarValueType="YES"/>
|
||||
<attribute name="rssi" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="satsInView" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="seqNo" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="speed" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="nodePosition" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="positions" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="PowerConfigEntity" representedClassName="PowerConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="adcMultiplierOverride" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="deviceBatteryInaAddress" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="isPowerSaving" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="lsSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="minWakeSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="onBatteryShutdownAfterSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="waitBluetoothSecs" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="powerConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="powerConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="RangeTestConfigEntity" representedClassName="RangeTestConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="save" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="sender" optional="YES" attributeType="Integer 32" usesScalarValueType="YES"/>
|
||||
<relationship name="rangeTestConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rangeTestConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="RouteEntity" representedClassName="RouteEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="color" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="distance" optional="YES" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="elevationGain" optional="YES" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="endDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="id" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
<attribute name="notes" optional="YES" attributeType="String"/>
|
||||
<relationship name="locations" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="LocationEntity" inverseName="routeLocation" inverseEntity="LocationEntity"/>
|
||||
</entity>
|
||||
<entity name="RTTTLConfigEntity" representedClassName="RTTTLConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="ringtone" optional="YES" attributeType="String" maxValueString="228" defaultValueString=""/>
|
||||
<relationship name="rtttlConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="rtttlConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="SecurityConfigEntity" representedClassName="SecurityConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="adminChannelEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="adminKey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="adminKey2" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="adminKey3" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="bluetoothLoggingEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="debugLogApiEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="isManaged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="privateKey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="publicKey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="serialEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<relationship name="securityConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="securityConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="SerialConfigEntity" representedClassName="SerialConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="baudRate" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="overrideConsoleSerialPort" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="serialConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="serialConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="StoreForwardConfigEntity" representedClassName="StoreForwardConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="enabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="heartbeat" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="historyReturnMax" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="historyReturnWindow" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="isRouter" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="lastHeartbeat" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="lastRequest" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="records" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="storeForwardConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="storeForwardConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryConfigEntity" representedClassName="TelemetryConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="deviceUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentDisplayFahrenheit" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentMeasurementEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentScreenEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="environmentUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="powerMeasurementEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="powerScreenEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="powerUpdateInterval" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<relationship name="telemetryConfigNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetryConfig" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TelemetryEntity" representedClassName="TelemetryEntity" syncable="YES">
|
||||
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="batteryLevel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelUtilization" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="gasResistance" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="iaq" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="irLux" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="lux" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="metricsType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numOnlineNodes" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numPacketsRx" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numPacketsRxBad" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numPacketsTx" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numRxDupe" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numTotalNodes" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numTxRelay" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numTxRelayCanceled" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="powerCh1Current" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="powerCh1Voltage" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="powerCh2Current" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="powerCh2Voltage" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="powerCh3Current" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="powerCh3Voltage" optional="YES" attributeType="Float" usesScalarValueType="YES"/>
|
||||
<attribute name="radiation" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="rainfall1H" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="rainfall24H" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="relativeHumidity" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="rssi" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="soilMoisture" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="soilTemperature" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="temperature" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="uptimeSeconds" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="uvLux" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="voltage" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="weight" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="whiteLux" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="windDirection" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="windGust" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="windLull" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="windSpeed" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<relationship name="nodeTelemetry" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="telemetries" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TraceRouteEntity" representedClassName="TraceRouteEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hasPositions" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="hopsBack" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="hopsTowards" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="response" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="routeBackText" optional="YES" attributeType="String"/>
|
||||
<attribute name="routeText" optional="YES" attributeType="String"/>
|
||||
<attribute name="sent" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="hops" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="TraceRouteHopEntity" inverseName="traceRoute" inverseEntity="TraceRouteHopEntity"/>
|
||||
<relationship name="node" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="traceRoutes" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="TraceRouteHopEntity" representedClassName="TraceRouteHopEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="back" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
<attribute name="num" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="time" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="traceRoute" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="TraceRouteEntity" inverseName="hops" inverseEntity="TraceRouteEntity"/>
|
||||
</entity>
|
||||
<entity name="UserEntity" representedClassName="UserEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="hwDisplayName" optional="YES" attributeType="String"/>
|
||||
<attribute name="hwModel" attributeType="String"/>
|
||||
<attribute name="hwModelId" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="keyMatch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="lastMessage" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="longName" attributeType="String"/>
|
||||
<attribute name="mute" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="newPublicKey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numString" optional="YES" attributeType="String"/>
|
||||
<attribute name="pkiEncrypted" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="publicKey" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="role" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="unmessagable" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="userNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="user" inverseEntity="NodeInfoEntity"/>
|
||||
</entity>
|
||||
<entity name="WaypointEntity" representedClassName="WaypointEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="created" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="expire" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="icon" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="id" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="lastUpdated" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="latitudeI" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="locked" attributeType="Integer 64" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="longDescription" optional="YES" attributeType="String" maxValueString="100"/>
|
||||
<attribute name="longitudeI" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="name" attributeType="String" minValueString="1" maxValueString="30"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
</model>
|
||||
|
|
@ -283,17 +283,16 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext)
|
|||
fetchedNode[0].telemetries? = NSOrderedSet(array: newTelemetries)
|
||||
}
|
||||
if nodeInfoMessage.hasUser {
|
||||
/// Seeing Some crashes here ?
|
||||
fetchedNode[0].user!.userId = nodeInfoMessage.user.id
|
||||
fetchedNode[0].user!.num = Int64(nodeInfoMessage.num)
|
||||
fetchedNode[0].user!.longName = nodeInfoMessage.user.longName
|
||||
fetchedNode[0].user!.shortName = nodeInfoMessage.user.shortName
|
||||
fetchedNode[0].user!.role = Int32(nodeInfoMessage.user.role.rawValue)
|
||||
fetchedNode[0].user!.hwModel = String(describing: nodeInfoMessage.user.hwModel).uppercased()
|
||||
fetchedNode[0].user!.hwModelId = Int32(nodeInfoMessage.user.hwModel.rawValue)
|
||||
fetchedNode[0].user?.userId = nodeInfoMessage.user.id
|
||||
fetchedNode[0].user?.num = Int64(nodeInfoMessage.num)
|
||||
fetchedNode[0].user?.longName = nodeInfoMessage.user.longName
|
||||
fetchedNode[0].user?.shortName = nodeInfoMessage.user.shortName
|
||||
fetchedNode[0].user?.role = Int32(nodeInfoMessage.user.role.rawValue)
|
||||
fetchedNode[0].user?.hwModel = String(describing: nodeInfoMessage.user.hwModel).uppercased()
|
||||
fetchedNode[0].user?.hwModelId = Int32(nodeInfoMessage.user.hwModel.rawValue)
|
||||
/// For nodes that have the optional isUnmessagable boolean use that, otherwise excluded roles that are unmessagable by default
|
||||
if nodeInfoMessage.user.hasIsUnmessagable {
|
||||
fetchedNode[0].user!.unmessagable = nodeInfoMessage.user.isUnmessagable
|
||||
fetchedNode[0].user?.unmessagable = nodeInfoMessage.user.isUnmessagable
|
||||
} else {
|
||||
let roles = [-1, 2, 4, 5, 6, 7, 10, 11]
|
||||
let containsRole = roles.contains(Int(fetchedNode[0].user?.role ?? -1))
|
||||
|
|
@ -304,13 +303,13 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext)
|
|||
}
|
||||
}
|
||||
if !nodeInfoMessage.user.publicKey.isEmpty {
|
||||
fetchedNode[0].user!.pkiEncrypted = true
|
||||
fetchedNode[0].user!.publicKey = nodeInfoMessage.user.publicKey
|
||||
fetchedNode[0].user?.pkiEncrypted = true
|
||||
fetchedNode[0].user?.publicKey = nodeInfoMessage.user.publicKey
|
||||
}
|
||||
Task {
|
||||
Api().loadDeviceHardwareData { (hw) in
|
||||
let dh = hw.first(where: { $0.hwModel == fetchedNode[0].user?.hwModelId ?? 0 })
|
||||
fetchedNode[0].user!.hwDisplayName = dh?.displayName
|
||||
fetchedNode[0].user?.hwDisplayName = dh?.displayName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -384,7 +383,7 @@ func upsertPositionPacket (packet: MeshPacket, context: NSManagedObjectContext)
|
|||
} else {
|
||||
position.time = Date(timeIntervalSince1970: TimeInterval(Int64(positionMessage.time)))
|
||||
}
|
||||
guard let mutablePositions = fetchedNode[0].positions!.mutableCopy() as? NSMutableOrderedSet else {
|
||||
guard let mutablePositions = fetchedNode[0].positions?.mutableCopy() as? NSMutableOrderedSet else {
|
||||
return
|
||||
}
|
||||
/// Don't save nearly the same position over and over. If the next position is less than 10 meters from the new position, delete the previous position and save the new one.
|
||||
|
|
@ -1231,6 +1230,7 @@ func upsertMqttModuleConfigPacket(config: ModuleConfig.MQTTConfig, nodeNum: Int6
|
|||
newMQTTConfig.jsonEnabled = config.jsonEnabled
|
||||
newMQTTConfig.tlsEnabled = config.tlsEnabled
|
||||
newMQTTConfig.mapReportingEnabled = config.mapReportingEnabled
|
||||
newMQTTConfig.mapReportingShouldReportLocation = config.mapReportSettings.shouldReportLocation
|
||||
newMQTTConfig.mapPositionPrecision = Int32(config.mapReportSettings.positionPrecision)
|
||||
newMQTTConfig.mapPublishIntervalSecs = Int32(config.mapReportSettings.publishIntervalSecs)
|
||||
fetchedNode[0].mqttConfig = newMQTTConfig
|
||||
|
|
|
|||
|
|
@ -11,27 +11,22 @@ struct MeshtasticLogo: View {
|
|||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
|
||||
#if targetEnvironment(macCatalyst)
|
||||
VStack {
|
||||
Image("logo-white")
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(.accentColor)
|
||||
.scaledToFit()
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.padding(.top, 5)
|
||||
.offset(x: -15)
|
||||
#else
|
||||
VStack {
|
||||
Image(colorScheme == .dark ? "logo-white" : "logo-black")
|
||||
.resizable()
|
||||
.renderingMode(.template)
|
||||
.scaledToFit()
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.offset(x: -15)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@ struct ChannelList: View {
|
|||
|
||||
var restrictedChannels = ["gpio", "mqtt", "serial", "admin"]
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(keyPath: \ChannelEntity.index, ascending: true)],
|
||||
predicate: nil,
|
||||
animation: .default
|
||||
) private var channels: FetchedResults<ChannelEntity>
|
||||
|
||||
@ViewBuilder
|
||||
private func makeChannelRow(
|
||||
myInfo: MyInfoEntity,
|
||||
|
|
@ -87,6 +93,9 @@ struct ChannelList: View {
|
|||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
if channel.mute {
|
||||
Image(systemName: "bell.slash")
|
||||
}
|
||||
}
|
||||
|
||||
if channel.allPrivateMessages.count > 0 {
|
||||
|
|
@ -103,7 +112,7 @@ struct ChannelList: View {
|
|||
var body: some View {
|
||||
VStack {
|
||||
// Display Contacts for the rest of the non admin channels
|
||||
if let node, let myInfo = node.myInfo, let channels = myInfo.channels?.array as? [ChannelEntity] {
|
||||
if let node, let myInfo = node.myInfo {
|
||||
List(selection: $channelSelection) {
|
||||
ForEach(channels) { (channel: ChannelEntity) in
|
||||
if !restrictedChannels.contains(channel.name?.lowercased() ?? "") {
|
||||
|
|
@ -119,7 +128,7 @@ struct ChannelList: View {
|
|||
}
|
||||
}
|
||||
Button {
|
||||
channel.mute = !channel.mute
|
||||
channel.mute.toggle()
|
||||
do {
|
||||
let adminMessageId = bleManager.saveChannel(channel: channel.protoBuf, fromUser: node.user!, toUser: node.user!)
|
||||
if adminMessageId > 0 {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ struct UserList: View {
|
|||
@State private var isPkiEncrypted = false
|
||||
@State private var isFavorite = false
|
||||
@State private var isIgnored = false
|
||||
@State private var isUnmessagable = false
|
||||
@State private var isEnvironment = false
|
||||
@State private var distanceFilter = false
|
||||
@State private var maxDistance: Double = 800000
|
||||
|
|
@ -40,18 +39,6 @@ struct UserList: View {
|
|||
roleFilter
|
||||
]}
|
||||
|
||||
@FetchRequest(
|
||||
sortDescriptors: [NSSortDescriptor(key: "lastMessage", ascending: false),
|
||||
NSSortDescriptor(key: "userNode.favorite", ascending: false),
|
||||
NSSortDescriptor(key: "pkiEncrypted", ascending: false),
|
||||
NSSortDescriptor(key: "userNode.lastHeard", ascending: false),
|
||||
NSSortDescriptor(key: "longName", ascending: true)],
|
||||
predicate: NSPredicate(
|
||||
format: "userNode.ignored == NO AND unmessagable = NO"
|
||||
), animation: .spring
|
||||
)
|
||||
var users: FetchedResults<UserEntity>
|
||||
|
||||
@Binding var node: NodeInfoEntity?
|
||||
@Binding var userSelection: UserEntity?
|
||||
|
||||
|
|
@ -61,196 +48,161 @@ struct UserList: View {
|
|||
let localeDateFormat = DateFormatter.dateFormat(fromTemplate: "yyMMdd", options: 0, locale: Locale.current)
|
||||
let dateFormatString = (localeDateFormat ?? "MM/dd/YY")
|
||||
VStack {
|
||||
List(users, selection: $userSelection) { (user: UserEntity) in
|
||||
let mostRecent = user.messageList.last
|
||||
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 ))))
|
||||
let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0
|
||||
let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0
|
||||
if user.num != bleManager.connectedPeripheral?.num ?? 0 {
|
||||
NavigationLink(value: user) {
|
||||
ZStack {
|
||||
Image(systemName: "circle.fill")
|
||||
.opacity(user.unreadMessages > 0 ? 1 : 0)
|
||||
.font(.system(size: 10))
|
||||
.foregroundColor(.accentColor)
|
||||
.brightness(0.2)
|
||||
}
|
||||
FilteredUserList(
|
||||
searchText: searchText,
|
||||
viaLora: viaLora,
|
||||
viaMqtt: viaMqtt,
|
||||
isOnline: isOnline,
|
||||
isPkiEncrypted: isPkiEncrypted,
|
||||
isFavorite: isFavorite,
|
||||
isIgnored: isIgnored,
|
||||
isEnvironment: isEnvironment,
|
||||
distanceFilter: distanceFilter,
|
||||
maxDistance: maxDistance,
|
||||
hopsAway: hopsAway,
|
||||
roleFilter: roleFilter,
|
||||
deviceRoles: deviceRoles,
|
||||
userSelection: $userSelection
|
||||
) { users in
|
||||
List(users, selection: $userSelection) { (user: UserEntity) in
|
||||
let mostRecent = user.messageList.last
|
||||
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 ))))
|
||||
let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0
|
||||
let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0
|
||||
if user.num != bleManager.connectedPeripheral?.num ?? 0 {
|
||||
NavigationLink(value: user) {
|
||||
ZStack {
|
||||
Image(systemName: "circle.fill")
|
||||
.opacity(user.unreadMessages > 0 ? 1 : 0)
|
||||
.font(.system(size: 10))
|
||||
.foregroundColor(.accentColor)
|
||||
.brightness(0.2)
|
||||
}
|
||||
|
||||
CircleText(text: user.shortName ?? "?", color: Color(UIColor(hex: UInt32(user.num))))
|
||||
CircleText(text: user.shortName ?? "?", color: Color(UIColor(hex: UInt32(user.num))))
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
if user.pkiEncrypted {
|
||||
if !user.keyMatch {
|
||||
/// Public Key on the User and the Public Key on the Last Message don't match
|
||||
Image(systemName: "key.slash")
|
||||
.foregroundColor(.red)
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
if user.pkiEncrypted {
|
||||
if !user.keyMatch {
|
||||
/// Public Key on the User and the Public Key on the Last Message don't match
|
||||
Image(systemName: "key.slash")
|
||||
.foregroundColor(.red)
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
Image(systemName: "lock.open.fill")
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
Text(user.longName ?? "Unknown".localized)
|
||||
.font(.headline)
|
||||
.allowsTightening(true)
|
||||
Spacer()
|
||||
if user.userNode?.favorite ?? false {
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
if user.messageList.count > 0 {
|
||||
if lastMessageDay == currentDay {
|
||||
Text(lastMessageTime, style: .time )
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} else if lastMessageDay == (currentDay - 1) {
|
||||
Text("Yesterday")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) {
|
||||
Text(lastMessageTime.formattedDate(format: dateFormatString))
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} else if lastMessageDay < (currentDay - 1800) {
|
||||
Text(lastMessageTime.formattedDate(format: dateFormatString))
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if user.messageList.count > 0 {
|
||||
HStack(alignment: .top) {
|
||||
Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 62)
|
||||
.contextMenu {
|
||||
Button {
|
||||
if node != nil && !(user.userNode?.favorite ?? false) {
|
||||
let success = bleManager.setFavoriteNode(node: user.userNode!, connectedNodeNum: Int64(node!.num))
|
||||
if success {
|
||||
user.userNode?.favorite = !(user.userNode?.favorite ?? false)
|
||||
Logger.data.info("Favorited a node")
|
||||
}
|
||||
} else {
|
||||
Image(systemName: "lock.open.fill")
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
Text(user.longName ?? "Unknown".localized)
|
||||
.font(.headline)
|
||||
.allowsTightening(true)
|
||||
Spacer()
|
||||
if user.userNode?.favorite ?? false {
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundColor(.yellow)
|
||||
}
|
||||
if user.messageList.count > 0 {
|
||||
if lastMessageDay == currentDay {
|
||||
Text(lastMessageTime, style: .time )
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} else if lastMessageDay == (currentDay - 1) {
|
||||
Text("Yesterday")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) {
|
||||
Text(lastMessageTime.formattedDate(format: dateFormatString))
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
} else if lastMessageDay < (currentDay - 1800) {
|
||||
Text(lastMessageTime.formattedDate(format: dateFormatString))
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
let success = bleManager.removeFavoriteNode(node: user.userNode!, connectedNodeNum: Int64(node!.num))
|
||||
if success {
|
||||
user.userNode?.favorite = !(user.userNode?.favorite ?? false)
|
||||
Logger.data.info("Unfavorited a node")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if user.messageList.count > 0 {
|
||||
HStack(alignment: .top) {
|
||||
Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.secondary)
|
||||
context.refresh(user, mergeChanges: true)
|
||||
do {
|
||||
try context.save()
|
||||
} catch {
|
||||
context.rollback()
|
||||
Logger.data.error("Save Node Favorite Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 62)
|
||||
.contextMenu {
|
||||
Button {
|
||||
|
||||
if node != nil && !(user.userNode?.favorite ?? false) {
|
||||
let success = bleManager.setFavoriteNode(node: user.userNode!, connectedNodeNum: Int64(node!.num))
|
||||
if success {
|
||||
user.userNode?.favorite = !(user.userNode?.favorite ?? true)
|
||||
Logger.data.info("Favorited a node")
|
||||
}
|
||||
} else {
|
||||
let success = bleManager.removeFavoriteNode(node: user.userNode!, connectedNodeNum: Int64(node!.num))
|
||||
if success {
|
||||
user.userNode?.favorite = !(user.userNode?.favorite ?? true)
|
||||
Logger.data.info("Un Favorited a node")
|
||||
}
|
||||
}
|
||||
context.refresh(user, mergeChanges: true)
|
||||
do {
|
||||
try context.save()
|
||||
} catch {
|
||||
context.rollback()
|
||||
Logger.data.error("Save Node Favorite Error")
|
||||
}
|
||||
} label: {
|
||||
Label((user.userNode?.favorite ?? false) ? "Un-Favorite" : "Favorite", systemImage: (user.userNode?.favorite ?? false) ? "star.slash.fill" : "star.fill")
|
||||
}
|
||||
Button {
|
||||
user.mute = !user.mute
|
||||
do {
|
||||
try context.save()
|
||||
} catch {
|
||||
context.rollback()
|
||||
Logger.data.error("Save User Mute Error")
|
||||
}
|
||||
} label: {
|
||||
Label(user.mute ? "Show Alerts" : "Hide Alerts", systemImage: user.mute ? "bell" : "bell.slash")
|
||||
}
|
||||
if user.messageList.count > 0 {
|
||||
Button(role: .destructive) {
|
||||
isPresentingDeleteUserMessagesConfirm = true
|
||||
userSelection = user
|
||||
} label: {
|
||||
Label("Delete Messages", systemImage: "trash")
|
||||
Label((user.userNode?.favorite ?? false) ? "Un-Favorite" : "Favorite", systemImage: (user.userNode?.favorite ?? false) ? "star.slash.fill" : "star.fill")
|
||||
}
|
||||
Button {
|
||||
user.mute = !user.mute
|
||||
do {
|
||||
try context.save()
|
||||
} catch {
|
||||
context.rollback()
|
||||
Logger.data.error("Save User Mute Error")
|
||||
}
|
||||
} label: {
|
||||
Label(user.mute ? "Show Alerts" : "Hide Alerts", systemImage: user.mute ? "bell" : "bell.slash")
|
||||
}
|
||||
if user.messageList.count > 0 {
|
||||
Button(role: .destructive) {
|
||||
isPresentingDeleteUserMessagesConfirm = true
|
||||
userSelection = user
|
||||
} label: {
|
||||
Label("Delete Messages", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.confirmationDialog(
|
||||
"This conversation will be deleted.",
|
||||
isPresented: $isPresentingDeleteUserMessagesConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button(role: .destructive) {
|
||||
deleteUserMessages(user: userSelection!, context: context)
|
||||
context.refresh(node!.user!, mergeChanges: true)
|
||||
} label: {
|
||||
Text("Delete")
|
||||
.confirmationDialog(
|
||||
"This conversation will be deleted.",
|
||||
isPresented: $isPresentingDeleteUserMessagesConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button(role: .destructive) {
|
||||
deleteUserMessages(user: userSelection!, context: context)
|
||||
context.refresh(node!.user!, mergeChanges: true)
|
||||
} label: {
|
||||
Text("Delete")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(.plain)
|
||||
.navigationTitle(String.localizedStringWithFormat("Contacts (%@)", String(users.count)))
|
||||
}
|
||||
.listStyle(.plain)
|
||||
.navigationTitle(String.localizedStringWithFormat("Contacts (%@)".localized, String(users.count == 0 ? 0 : users.count - 1)))
|
||||
.sheet(isPresented: $editingFilters) {
|
||||
NodeListFilter(filterTitle: "Contact Filters", viaLora: $viaLora, viaMqtt: $viaMqtt, isOnline: $isOnline, isPkiEncrypted: $isPkiEncrypted, isFavorite: $isFavorite, isIgnored: $isIgnored, isEnvironment: $isEnvironment, distanceFilter: $distanceFilter, maximumDistance: $maxDistance, hopsAway: $hopsAway, roleFilter: $roleFilter, deviceRoles: $deviceRoles)
|
||||
}
|
||||
.sheet(isPresented: $showingHelp) {
|
||||
DirectMessagesHelp()
|
||||
}
|
||||
.onChange(of: searchText) {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: viaLora) {
|
||||
if !viaLora && !viaMqtt {
|
||||
viaMqtt = true
|
||||
}
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: viaMqtt) {
|
||||
if !viaLora && !viaMqtt {
|
||||
viaLora = true
|
||||
}
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: [deviceRoles]) {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: hopsAway) {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: [boolFilters]) {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: maxDistance) {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onChange(of: isPkiEncrypted) {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.onFirstAppear {
|
||||
Task {
|
||||
await searchUserList()
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
|
|
@ -281,23 +233,50 @@ struct UserList: View {
|
|||
.padding(5)
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.padding(.bottom, 5)
|
||||
.searchable(text: $searchText, placement: users.count > 10 ? .navigationBarDrawer(displayMode: .always) : .automatic, prompt: "Find a contact")
|
||||
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Find a contact")
|
||||
.disableAutocorrection(true)
|
||||
.scrollDismissesKeyboard(.immediately)
|
||||
}
|
||||
}
|
||||
private func searchUserList() async {
|
||||
}
|
||||
|
||||
/// Case Insensitive Search Text Predicates
|
||||
let searchPredicates = ["userId", "numString", "hwModel", "hwDisplayName", "longName", "shortName"].map { property in
|
||||
return NSPredicate(format: "%K CONTAINS[c] %@", property, searchText)
|
||||
}
|
||||
/// Create a compound predicate using each text search preicate as an OR
|
||||
let textSearchPredicate = NSCompoundPredicate(type: .or, subpredicates: searchPredicates)
|
||||
/// Create an array of predicates to hold our AND predicates
|
||||
struct FilteredUserList<Content: View>: View {
|
||||
@FetchRequest var fetchRequest: FetchedResults<UserEntity>
|
||||
let content: (FetchedResults<UserEntity>) -> Content
|
||||
|
||||
var body: some View {
|
||||
content(fetchRequest)
|
||||
}
|
||||
|
||||
init(
|
||||
searchText: String,
|
||||
viaLora: Bool,
|
||||
viaMqtt: Bool,
|
||||
isOnline: Bool,
|
||||
isPkiEncrypted: Bool,
|
||||
isFavorite: Bool,
|
||||
isIgnored: Bool,
|
||||
isEnvironment: Bool,
|
||||
distanceFilter: Bool,
|
||||
maxDistance: Double,
|
||||
hopsAway: Double,
|
||||
roleFilter: Bool,
|
||||
deviceRoles: Set<Int>,
|
||||
userSelection: Binding<UserEntity?>,
|
||||
@ViewBuilder content: @escaping (FetchedResults<UserEntity>) -> Content
|
||||
) {
|
||||
self.content = content
|
||||
// Build predicates based on filter variables
|
||||
var predicates: [NSPredicate] = []
|
||||
/// Mqtt and lora
|
||||
// Search text predicates
|
||||
if !searchText.isEmpty {
|
||||
let searchPredicates = ["userId", "numString", "hwModel", "hwDisplayName", "longName", "shortName"].map { property in
|
||||
return NSPredicate(format: "%K CONTAINS[c] %@", property, searchText)
|
||||
}
|
||||
let textSearchPredicate = NSCompoundPredicate(type: .or, subpredicates: searchPredicates)
|
||||
predicates.append(textSearchPredicate)
|
||||
}
|
||||
// Mqtt and lora
|
||||
if !(viaLora && viaMqtt) {
|
||||
if viaLora {
|
||||
let loraPredicate = NSPredicate(format: "userNode.viaMqtt == NO")
|
||||
|
|
@ -306,11 +285,8 @@ struct UserList: View {
|
|||
let mqttPredicate = NSPredicate(format: "userNode.viaMqtt == YES")
|
||||
predicates.append(mqttPredicate)
|
||||
}
|
||||
} else {
|
||||
let mqttPredicate = NSPredicate(format: "NOT (userNode.viaMqtt == YES)")
|
||||
predicates.append(mqttPredicate)
|
||||
}
|
||||
/// Roles
|
||||
// Roles
|
||||
if roleFilter && deviceRoles.count > 0 {
|
||||
var rolesArray: [NSPredicate] = []
|
||||
for dr in deviceRoles {
|
||||
|
|
@ -320,40 +296,32 @@ struct UserList: View {
|
|||
let compoundPredicate = NSCompoundPredicate(type: .or, subpredicates: rolesArray)
|
||||
predicates.append(compoundPredicate)
|
||||
}
|
||||
/// Hops Away
|
||||
if hopsAway == 0.0 {
|
||||
// Hops Away
|
||||
if hopsAway == 0 {
|
||||
let hopsAwayPredicate = NSPredicate(format: "userNode.hopsAway == %i", Int32(hopsAway))
|
||||
predicates.append(hopsAwayPredicate)
|
||||
} else if hopsAway > -1.0 {
|
||||
let hopsAwayPredicate = NSPredicate(format: "userNode.hopsAway > 0 AND userNode.hopsAway <= %i", Int32(hopsAway))
|
||||
predicates.append(hopsAwayPredicate)
|
||||
}
|
||||
/// Online
|
||||
// Online
|
||||
if isOnline {
|
||||
let isOnlinePredicate = NSPredicate(format: "userNode.lastHeard >= %@", Calendar.current.date(byAdding: .minute, value: -120, to: Date())! as NSDate)
|
||||
predicates.append(isOnlinePredicate)
|
||||
}
|
||||
/// Encrypted
|
||||
// Encrypted
|
||||
if isPkiEncrypted {
|
||||
let isPkiEncryptedPredicate = NSPredicate(format: "pkiEncrypted == YES")
|
||||
predicates.append(isPkiEncryptedPredicate)
|
||||
}
|
||||
/// Favorites
|
||||
// Favorites
|
||||
if isFavorite {
|
||||
let isFavoritePredicate = NSPredicate(format: "userNode.favorite == YES")
|
||||
predicates.append(isFavoritePredicate)
|
||||
}
|
||||
/// Ignored
|
||||
let isIgnoredPredicate = NSPredicate(format: "userNode.ignored == NO")
|
||||
predicates.append(isIgnoredPredicate)
|
||||
/// Unmessagable
|
||||
let isUnmessagablePredicate = NSPredicate(format: "unmessagable == NO")
|
||||
predicates.append(isUnmessagablePredicate)
|
||||
|
||||
/// Distance
|
||||
// Distance
|
||||
if distanceFilter {
|
||||
let pointOfInterest = LocationsHandler.currentLocation
|
||||
|
||||
if pointOfInterest.latitude != LocationsHandler.DefaultLocation.latitude && pointOfInterest.longitude != LocationsHandler.DefaultLocation.longitude {
|
||||
let d: Double = maxDistance * 1.1
|
||||
let r: Double = 6371009
|
||||
|
|
@ -368,11 +336,26 @@ struct UserList: View {
|
|||
predicates.append(distancePredicate)
|
||||
}
|
||||
}
|
||||
if !searchText.isEmpty {
|
||||
let filterPredicates = NSCompoundPredicate(type: .and, subpredicates: predicates)
|
||||
users.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: [textSearchPredicate, filterPredicates])
|
||||
} else {
|
||||
users.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
|
||||
}
|
||||
// Always apply unmessagable and connected node filters
|
||||
let isUnmessagablePredicate = NSPredicate(format: "unmessagable == NO")
|
||||
predicates.append(isUnmessagablePredicate)
|
||||
let isIgnoredPredicate = NSPredicate(format: "userNode.ignored == NO")
|
||||
predicates.append(isIgnoredPredicate)
|
||||
let isConnectedNodePredicate = NSPredicate(format: "NOT (numString CONTAINS %@)", String(UserDefaults.preferredPeripheralNum))
|
||||
predicates.append(isConnectedNodePredicate)
|
||||
// Combine all predicates
|
||||
let finalPredicate = predicates.isEmpty ? NSPredicate(value: true) : NSCompoundPredicate(type: .and, subpredicates: predicates)
|
||||
// Initialize the fetch request with the combined predicate
|
||||
_fetchRequest = FetchRequest<UserEntity>(
|
||||
sortDescriptors: [
|
||||
NSSortDescriptor(key: "lastMessage", ascending: false),
|
||||
NSSortDescriptor(key: "userNode.favorite", ascending: false),
|
||||
NSSortDescriptor(key: "pkiEncrypted", ascending: false),
|
||||
NSSortDescriptor(key: "userNode.lastHeard", ascending: false),
|
||||
NSSortDescriptor(key: "longName", ascending: true)
|
||||
],
|
||||
predicate: finalPredicate,
|
||||
animation: .spring
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ struct NodeDetail: View {
|
|||
let connectedNode,
|
||||
self.bleManager.connectedPeripheral != nil {
|
||||
Section("Administration") {
|
||||
if connectedNode.myInfo?.hasAdmin ?? false {
|
||||
if UserDefaults.enableAdministration {
|
||||
Button {
|
||||
let adminMessageId = bleManager.requestDeviceMetadata(
|
||||
fromUser: connectedNode.user!,
|
||||
|
|
|
|||
|
|
@ -91,20 +91,21 @@ struct NodeListFilter: View {
|
|||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.listRowSeparator(.visible)
|
||||
Toggle(isOn: $isIgnored) {
|
||||
|
||||
Label {
|
||||
Text("Ignored")
|
||||
} icon: {
|
||||
|
||||
Image(systemName: "minus.circle.fill")
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
if filterTitle == "Node Filters" {
|
||||
Toggle(isOn: $isIgnored) {
|
||||
|
||||
Label {
|
||||
Text("Ignored")
|
||||
} icon: {
|
||||
|
||||
Image(systemName: "minus.circle.fill")
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
Toggle(isOn: $isEnvironment) {
|
||||
Label {
|
||||
Text("Environment")
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ struct Firmware: View {
|
|||
}
|
||||
}
|
||||
Api().loadFirmwareReleaseData { (fw) in
|
||||
latestStable = fw.releases.stable.first
|
||||
let archString = currentDevice?.architecture.rawValue ?? ""
|
||||
let ls = fw.releases.stable.first(where: { $0.zipURL.contains(archString) == true })
|
||||
latestStable = fw.releases.stable.first
|
||||
latestAlpha = fw.releases.alpha.first
|
||||
}
|
||||
|
|
|
|||
|
|
@ -498,6 +498,16 @@ public struct AdminMessage: @unchecked Sendable {
|
|||
set {payloadVariant = .addContact(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Initiate or respond to a key verification request
|
||||
public var keyVerification: KeyVerificationAdmin {
|
||||
get {
|
||||
if case .keyVerification(let v)? = payloadVariant {return v}
|
||||
return KeyVerificationAdmin()
|
||||
}
|
||||
set {payloadVariant = .keyVerification(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared.
|
||||
public var factoryResetDevice: Int32 {
|
||||
|
|
@ -719,6 +729,9 @@ public struct AdminMessage: @unchecked Sendable {
|
|||
/// Add a contact (User) to the nodedb
|
||||
case addContact(SharedContact)
|
||||
///
|
||||
/// Initiate or respond to a key verification request
|
||||
case keyVerification(KeyVerificationAdmin)
|
||||
///
|
||||
/// Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared.
|
||||
case factoryResetDevice(Int32)
|
||||
///
|
||||
|
|
@ -1077,6 +1090,98 @@ public struct SharedContact: Sendable {
|
|||
fileprivate var _user: User? = nil
|
||||
}
|
||||
|
||||
///
|
||||
/// This message is used by a client to initiate or complete a key verification
|
||||
public struct KeyVerificationAdmin: 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.
|
||||
|
||||
public var messageType: KeyVerificationAdmin.MessageType = .initiateVerification
|
||||
|
||||
///
|
||||
/// The nodenum we're requesting
|
||||
public var remoteNodenum: UInt32 = 0
|
||||
|
||||
///
|
||||
/// The nonce is used to track the connection
|
||||
public var nonce: UInt64 = 0
|
||||
|
||||
///
|
||||
/// The 4 digit code generated by the remote node, and communicated outside the mesh
|
||||
public var securityNumber: UInt32 {
|
||||
get {return _securityNumber ?? 0}
|
||||
set {_securityNumber = newValue}
|
||||
}
|
||||
/// Returns true if `securityNumber` has been explicitly set.
|
||||
public var hasSecurityNumber: Bool {return self._securityNumber != nil}
|
||||
/// Clears the value of `securityNumber`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearSecurityNumber() {self._securityNumber = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
///
|
||||
/// Three stages of this request.
|
||||
public enum MessageType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
public typealias RawValue = Int
|
||||
|
||||
///
|
||||
/// This is the first stage, where a client initiates
|
||||
case initiateVerification // = 0
|
||||
|
||||
///
|
||||
/// After the nonce has been returned over the mesh, the client prompts for the security number
|
||||
/// And uses this message to provide it to the node.
|
||||
case provideSecurityNumber // = 1
|
||||
|
||||
///
|
||||
/// Once the user has compared the verification message, this message notifies the node.
|
||||
case doVerify // = 2
|
||||
|
||||
///
|
||||
/// This is the cancel path, can be taken at any point
|
||||
case doNotVerify // = 3
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
self = .initiateVerification
|
||||
}
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 0: self = .initiateVerification
|
||||
case 1: self = .provideSecurityNumber
|
||||
case 2: self = .doVerify
|
||||
case 3: self = .doNotVerify
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: Int {
|
||||
switch self {
|
||||
case .initiateVerification: return 0
|
||||
case .provideSecurityNumber: return 1
|
||||
case .doVerify: return 2
|
||||
case .doNotVerify: return 3
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||
public static let allCases: [KeyVerificationAdmin.MessageType] = [
|
||||
.initiateVerification,
|
||||
.provideSecurityNumber,
|
||||
.doVerify,
|
||||
.doNotVerify,
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _securityNumber: UInt32? = nil
|
||||
}
|
||||
|
||||
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||
|
||||
fileprivate let _protobuf_package = "meshtastic"
|
||||
|
|
@ -1130,6 +1235,7 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
64: .standard(proto: "begin_edit_settings"),
|
||||
65: .standard(proto: "commit_edit_settings"),
|
||||
66: .standard(proto: "add_contact"),
|
||||
67: .standard(proto: "key_verification"),
|
||||
94: .standard(proto: "factory_reset_device"),
|
||||
95: .standard(proto: "reboot_ota_seconds"),
|
||||
96: .standard(proto: "exit_simulator"),
|
||||
|
|
@ -1585,6 +1691,19 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
self.payloadVariant = .addContact(v)
|
||||
}
|
||||
}()
|
||||
case 67: try {
|
||||
var v: KeyVerificationAdmin?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .keyVerification(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .keyVerification(v)
|
||||
}
|
||||
}()
|
||||
case 94: try {
|
||||
var v: Int32?
|
||||
try decoder.decodeSingularInt32Field(value: &v)
|
||||
|
|
@ -1833,6 +1952,10 @@ extension AdminMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
guard case .addContact(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 66)
|
||||
}()
|
||||
case .keyVerification?: try {
|
||||
guard case .keyVerification(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 67)
|
||||
}()
|
||||
case .factoryResetDevice?: try {
|
||||
guard case .factoryResetDevice(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularInt32Field(value: v, fieldNumber: 94)
|
||||
|
|
@ -2040,3 +2163,66 @@ extension SharedContact: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyVerificationAdmin: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".KeyVerificationAdmin"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "message_type"),
|
||||
2: .standard(proto: "remote_nodenum"),
|
||||
3: .same(proto: "nonce"),
|
||||
4: .standard(proto: "security_number"),
|
||||
]
|
||||
|
||||
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.decodeSingularEnumField(value: &self.messageType) }()
|
||||
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.remoteNodenum) }()
|
||||
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.nonce) }()
|
||||
case 4: try { try decoder.decodeSingularUInt32Field(value: &self._securityNumber) }()
|
||||
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.messageType != .initiateVerification {
|
||||
try visitor.visitSingularEnumField(value: self.messageType, fieldNumber: 1)
|
||||
}
|
||||
if self.remoteNodenum != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.remoteNodenum, fieldNumber: 2)
|
||||
}
|
||||
if self.nonce != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.nonce, fieldNumber: 3)
|
||||
}
|
||||
try { if let v = self._securityNumber {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: KeyVerificationAdmin, rhs: KeyVerificationAdmin) -> Bool {
|
||||
if lhs.messageType != rhs.messageType {return false}
|
||||
if lhs.remoteNodenum != rhs.remoteNodenum {return false}
|
||||
if lhs.nonce != rhs.nonce {return false}
|
||||
if lhs._securityNumber != rhs._securityNumber {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyVerificationAdmin.MessageType: SwiftProtobuf._ProtoNameProviding {
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
0: .same(proto: "INITIATE_VERIFICATION"),
|
||||
1: .same(proto: "PROVIDE_SECURITY_NUMBER"),
|
||||
2: .same(proto: "DO_VERIFY"),
|
||||
3: .same(proto: "DO_NOT_VERIFY"),
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -756,6 +756,10 @@ public struct Config: Sendable {
|
|||
/// Flags for enabling/disabling network protocols
|
||||
public var enabledProtocols: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Enable/Disable ipv6 support
|
||||
public var ipv6Enabled: Bool = false
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public enum AddressMode: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||
|
|
@ -2385,6 +2389,7 @@ extension Config.NetworkConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
8: .standard(proto: "ipv4_config"),
|
||||
9: .standard(proto: "rsyslog_server"),
|
||||
10: .standard(proto: "enabled_protocols"),
|
||||
11: .standard(proto: "ipv6_enabled"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -2402,6 +2407,7 @@ extension Config.NetworkConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
case 8: try { try decoder.decodeSingularMessageField(value: &self._ipv4Config) }()
|
||||
case 9: try { try decoder.decodeSingularStringField(value: &self.rsyslogServer) }()
|
||||
case 10: try { try decoder.decodeSingularUInt32Field(value: &self.enabledProtocols) }()
|
||||
case 11: try { try decoder.decodeSingularBoolField(value: &self.ipv6Enabled) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -2439,6 +2445,9 @@ extension Config.NetworkConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
if self.enabledProtocols != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.enabledProtocols, fieldNumber: 10)
|
||||
}
|
||||
if self.ipv6Enabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.ipv6Enabled, fieldNumber: 11)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -2452,6 +2461,7 @@ extension Config.NetworkConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
|
|||
if lhs._ipv4Config != rhs._ipv4Config {return false}
|
||||
if lhs.rsyslogServer != rhs.rsyslogServer {return false}
|
||||
if lhs.enabledProtocols != rhs.enabledProtocols {return false}
|
||||
if lhs.ipv6Enabled != rhs.ipv6Enabled {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,6 +227,14 @@ public struct NodeInfoLite: @unchecked Sendable {
|
|||
set {_uniqueStorage()._nextHop = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Bitfield for storing booleans.
|
||||
/// LSB 0 is_key_manually_verified
|
||||
public var bitfield: UInt32 {
|
||||
get {return _storage._bitfield}
|
||||
set {_uniqueStorage()._bitfield = newValue}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
|
@ -608,6 +616,7 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
10: .standard(proto: "is_favorite"),
|
||||
11: .standard(proto: "is_ignored"),
|
||||
12: .standard(proto: "next_hop"),
|
||||
13: .same(proto: "bitfield"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
|
|
@ -623,6 +632,7 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
var _isFavorite: Bool = false
|
||||
var _isIgnored: Bool = false
|
||||
var _nextHop: UInt32 = 0
|
||||
var _bitfield: UInt32 = 0
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
|
|
@ -649,6 +659,7 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
_isFavorite = source._isFavorite
|
||||
_isIgnored = source._isIgnored
|
||||
_nextHop = source._nextHop
|
||||
_bitfield = source._bitfield
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -679,6 +690,7 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
case 10: try { try decoder.decodeSingularBoolField(value: &_storage._isFavorite) }()
|
||||
case 11: try { try decoder.decodeSingularBoolField(value: &_storage._isIgnored) }()
|
||||
case 12: try { try decoder.decodeSingularUInt32Field(value: &_storage._nextHop) }()
|
||||
case 13: try { try decoder.decodeSingularUInt32Field(value: &_storage._bitfield) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -727,6 +739,9 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
if _storage._nextHop != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._nextHop, fieldNumber: 12)
|
||||
}
|
||||
if _storage._bitfield != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._bitfield, fieldNumber: 13)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
|
@ -748,6 +763,7 @@ extension NodeInfoLite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
|
|||
if _storage._isFavorite != rhs_storage._isFavorite {return false}
|
||||
if _storage._isIgnored != rhs_storage._isIgnored {return false}
|
||||
if _storage._nextHop != rhs_storage._nextHop {return false}
|
||||
if _storage._bitfield != rhs_storage._bitfield {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
|
|
|
|||
|
|
@ -442,6 +442,22 @@ 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
|
||||
|
||||
///
|
||||
/// Reserved ID for future and past use
|
||||
case qwantzTinyArms // = 101
|
||||
|
||||
///
|
||||
/// ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
/// 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.
|
||||
|
|
@ -553,6 +569,10 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case 95: self = .seeedSolarNode
|
||||
case 96: self = .nomadstarMeteorPro
|
||||
case 97: self = .crowpanel
|
||||
case 98: self = .link32
|
||||
case 99: self = .seeedWioTrackerL1
|
||||
case 100: self = .seeedWioTrackerL1Eink
|
||||
case 101: self = .qwantzTinyArms
|
||||
case 255: self = .privateHw
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
|
|
@ -658,6 +678,10 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case .seeedSolarNode: return 95
|
||||
case .nomadstarMeteorPro: return 96
|
||||
case .crowpanel: return 97
|
||||
case .link32: return 98
|
||||
case .seeedWioTrackerL1: return 99
|
||||
case .seeedWioTrackerL1Eink: return 100
|
||||
case .qwantzTinyArms: return 101
|
||||
case .privateHw: return 255
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
|
|
@ -763,6 +787,10 @@ public enum HardwareModel: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
.seeedSolarNode,
|
||||
.nomadstarMeteorPro,
|
||||
.crowpanel,
|
||||
.link32,
|
||||
.seeedWioTrackerL1,
|
||||
.seeedWioTrackerL1Eink,
|
||||
.qwantzTinyArms,
|
||||
.privateHw,
|
||||
]
|
||||
|
||||
|
|
@ -1820,6 +1848,31 @@ public struct DataMessage: @unchecked Sendable {
|
|||
fileprivate var _bitfield: UInt32? = nil
|
||||
}
|
||||
|
||||
///
|
||||
/// The actual over-the-mesh message doing KeyVerification
|
||||
public struct KeyVerification: @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.
|
||||
|
||||
///
|
||||
/// random value Selected by the requesting node
|
||||
public var nonce: UInt64 = 0
|
||||
|
||||
///
|
||||
/// The final authoritative hash, only to be sent by NodeA at the end of the handshake
|
||||
public var hash1: Data = Data()
|
||||
|
||||
///
|
||||
/// The intermediary hash (actually derived from hash1),
|
||||
/// sent from NodeB to NodeA in response to the initial message.
|
||||
public var hash2: Data = Data()
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
///
|
||||
/// Waypoint message, used to share arbitrary locations across the mesh
|
||||
public struct Waypoint: Sendable {
|
||||
|
|
@ -2441,6 +2494,15 @@ public struct NodeInfo: @unchecked Sendable {
|
|||
set {_uniqueStorage()._isIgnored = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// True if node public key has been verified.
|
||||
/// Persists between NodeDB internal clean ups
|
||||
/// LSB 0 of the bitfield
|
||||
public var isKeyManuallyVerified: Bool {
|
||||
get {return _storage._isKeyManuallyVerified}
|
||||
set {_uniqueStorage()._isKeyManuallyVerified = newValue}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
|
@ -2903,13 +2965,94 @@ public struct ClientNotification: Sendable {
|
|||
/// The message body of the notification
|
||||
public var message: String = String()
|
||||
|
||||
public var payloadVariant: ClientNotification.OneOf_PayloadVariant? = nil
|
||||
|
||||
public var keyVerificationNumberInform: KeyVerificationNumberInform {
|
||||
get {
|
||||
if case .keyVerificationNumberInform(let v)? = payloadVariant {return v}
|
||||
return KeyVerificationNumberInform()
|
||||
}
|
||||
set {payloadVariant = .keyVerificationNumberInform(newValue)}
|
||||
}
|
||||
|
||||
public var keyVerificationNumberRequest: KeyVerificationNumberRequest {
|
||||
get {
|
||||
if case .keyVerificationNumberRequest(let v)? = payloadVariant {return v}
|
||||
return KeyVerificationNumberRequest()
|
||||
}
|
||||
set {payloadVariant = .keyVerificationNumberRequest(newValue)}
|
||||
}
|
||||
|
||||
public var keyVerificationFinal: KeyVerificationFinal {
|
||||
get {
|
||||
if case .keyVerificationFinal(let v)? = payloadVariant {return v}
|
||||
return KeyVerificationFinal()
|
||||
}
|
||||
set {payloadVariant = .keyVerificationFinal(newValue)}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public enum OneOf_PayloadVariant: Equatable, Sendable {
|
||||
case keyVerificationNumberInform(KeyVerificationNumberInform)
|
||||
case keyVerificationNumberRequest(KeyVerificationNumberRequest)
|
||||
case keyVerificationFinal(KeyVerificationFinal)
|
||||
|
||||
}
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _replyID: UInt32? = nil
|
||||
}
|
||||
|
||||
public struct KeyVerificationNumberInform: 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.
|
||||
|
||||
public var nonce: UInt64 = 0
|
||||
|
||||
public var remoteLongname: String = String()
|
||||
|
||||
public var securityNumber: UInt32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct KeyVerificationNumberRequest: 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.
|
||||
|
||||
public var nonce: UInt64 = 0
|
||||
|
||||
public var remoteLongname: String = String()
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public struct KeyVerificationFinal: 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.
|
||||
|
||||
public var nonce: UInt64 = 0
|
||||
|
||||
public var remoteLongname: String = String()
|
||||
|
||||
public var isSender: Bool = false
|
||||
|
||||
public var verificationCharacters: String = String()
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
///
|
||||
/// Individual File info for the device
|
||||
public struct FileInfo: Sendable {
|
||||
|
|
@ -3431,6 +3574,10 @@ extension HardwareModel: SwiftProtobuf._ProtoNameProviding {
|
|||
95: .same(proto: "SEEED_SOLAR_NODE"),
|
||||
96: .same(proto: "NOMADSTAR_METEOR_PRO"),
|
||||
97: .same(proto: "CROWPANEL"),
|
||||
98: .same(proto: "LINK_32"),
|
||||
99: .same(proto: "SEEED_WIO_TRACKER_L1"),
|
||||
100: .same(proto: "SEEED_WIO_TRACKER_L1_EINK"),
|
||||
101: .same(proto: "QWANTZ_TINY_ARMS"),
|
||||
255: .same(proto: "PRIVATE_HW"),
|
||||
]
|
||||
}
|
||||
|
|
@ -4075,6 +4222,50 @@ extension DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
|
|||
}
|
||||
}
|
||||
|
||||
extension KeyVerification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".KeyVerification"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "nonce"),
|
||||
2: .same(proto: "hash1"),
|
||||
3: .same(proto: "hash2"),
|
||||
]
|
||||
|
||||
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.decodeSingularUInt64Field(value: &self.nonce) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self.hash1) }()
|
||||
case 3: try { try decoder.decodeSingularBytesField(value: &self.hash2) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.nonce != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.nonce, fieldNumber: 1)
|
||||
}
|
||||
if !self.hash1.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.hash1, fieldNumber: 2)
|
||||
}
|
||||
if !self.hash2.isEmpty {
|
||||
try visitor.visitSingularBytesField(value: self.hash2, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: KeyVerification, rhs: KeyVerification) -> Bool {
|
||||
if lhs.nonce != rhs.nonce {return false}
|
||||
if lhs.hash1 != rhs.hash1 {return false}
|
||||
if lhs.hash2 != rhs.hash2 {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Waypoint: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".Waypoint"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
|
@ -4511,6 +4702,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
9: .standard(proto: "hops_away"),
|
||||
10: .standard(proto: "is_favorite"),
|
||||
11: .standard(proto: "is_ignored"),
|
||||
12: .standard(proto: "is_key_manually_verified"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
|
|
@ -4525,6 +4717,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
var _hopsAway: UInt32? = nil
|
||||
var _isFavorite: Bool = false
|
||||
var _isIgnored: Bool = false
|
||||
var _isKeyManuallyVerified: Bool = false
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
|
|
@ -4550,6 +4743,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
_hopsAway = source._hopsAway
|
||||
_isFavorite = source._isFavorite
|
||||
_isIgnored = source._isIgnored
|
||||
_isKeyManuallyVerified = source._isKeyManuallyVerified
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4579,6 +4773,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
case 9: try { try decoder.decodeSingularUInt32Field(value: &_storage._hopsAway) }()
|
||||
case 10: try { try decoder.decodeSingularBoolField(value: &_storage._isFavorite) }()
|
||||
case 11: try { try decoder.decodeSingularBoolField(value: &_storage._isIgnored) }()
|
||||
case 12: try { try decoder.decodeSingularBoolField(value: &_storage._isKeyManuallyVerified) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -4624,6 +4819,9 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
if _storage._isIgnored != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._isIgnored, fieldNumber: 11)
|
||||
}
|
||||
if _storage._isKeyManuallyVerified != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._isKeyManuallyVerified, fieldNumber: 12)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
|
@ -4644,6 +4842,7 @@ extension NodeInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
|
|||
if _storage._hopsAway != rhs_storage._hopsAway {return false}
|
||||
if _storage._isFavorite != rhs_storage._isFavorite {return false}
|
||||
if _storage._isIgnored != rhs_storage._isIgnored {return false}
|
||||
if _storage._isKeyManuallyVerified != rhs_storage._isKeyManuallyVerified {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
|
|
@ -5146,6 +5345,9 @@ extension ClientNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
|
|||
2: .same(proto: "time"),
|
||||
3: .same(proto: "level"),
|
||||
4: .same(proto: "message"),
|
||||
11: .standard(proto: "key_verification_number_inform"),
|
||||
12: .standard(proto: "key_verification_number_request"),
|
||||
13: .standard(proto: "key_verification_final"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -5158,6 +5360,45 @@ extension ClientNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
|
|||
case 2: try { try decoder.decodeSingularFixed32Field(value: &self.time) }()
|
||||
case 3: try { try decoder.decodeSingularEnumField(value: &self.level) }()
|
||||
case 4: try { try decoder.decodeSingularStringField(value: &self.message) }()
|
||||
case 11: try {
|
||||
var v: KeyVerificationNumberInform?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .keyVerificationNumberInform(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .keyVerificationNumberInform(v)
|
||||
}
|
||||
}()
|
||||
case 12: try {
|
||||
var v: KeyVerificationNumberRequest?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .keyVerificationNumberRequest(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .keyVerificationNumberRequest(v)
|
||||
}
|
||||
}()
|
||||
case 13: try {
|
||||
var v: KeyVerificationFinal?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .keyVerificationFinal(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .keyVerificationFinal(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -5180,6 +5421,21 @@ extension ClientNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
|
|||
if !self.message.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.message, fieldNumber: 4)
|
||||
}
|
||||
switch self.payloadVariant {
|
||||
case .keyVerificationNumberInform?: try {
|
||||
guard case .keyVerificationNumberInform(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 11)
|
||||
}()
|
||||
case .keyVerificationNumberRequest?: try {
|
||||
guard case .keyVerificationNumberRequest(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 12)
|
||||
}()
|
||||
case .keyVerificationFinal?: try {
|
||||
guard case .keyVerificationFinal(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 13)
|
||||
}()
|
||||
case nil: break
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -5188,6 +5444,139 @@ extension ClientNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
|
|||
if lhs.time != rhs.time {return false}
|
||||
if lhs.level != rhs.level {return false}
|
||||
if lhs.message != rhs.message {return false}
|
||||
if lhs.payloadVariant != rhs.payloadVariant {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyVerificationNumberInform: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".KeyVerificationNumberInform"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "nonce"),
|
||||
2: .standard(proto: "remote_longname"),
|
||||
3: .standard(proto: "security_number"),
|
||||
]
|
||||
|
||||
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.decodeSingularUInt64Field(value: &self.nonce) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.remoteLongname) }()
|
||||
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.securityNumber) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.nonce != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.nonce, fieldNumber: 1)
|
||||
}
|
||||
if !self.remoteLongname.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.remoteLongname, fieldNumber: 2)
|
||||
}
|
||||
if self.securityNumber != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.securityNumber, fieldNumber: 3)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: KeyVerificationNumberInform, rhs: KeyVerificationNumberInform) -> Bool {
|
||||
if lhs.nonce != rhs.nonce {return false}
|
||||
if lhs.remoteLongname != rhs.remoteLongname {return false}
|
||||
if lhs.securityNumber != rhs.securityNumber {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyVerificationNumberRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".KeyVerificationNumberRequest"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "nonce"),
|
||||
2: .standard(proto: "remote_longname"),
|
||||
]
|
||||
|
||||
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.decodeSingularUInt64Field(value: &self.nonce) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.remoteLongname) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.nonce != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.nonce, fieldNumber: 1)
|
||||
}
|
||||
if !self.remoteLongname.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.remoteLongname, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: KeyVerificationNumberRequest, rhs: KeyVerificationNumberRequest) -> Bool {
|
||||
if lhs.nonce != rhs.nonce {return false}
|
||||
if lhs.remoteLongname != rhs.remoteLongname {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension KeyVerificationFinal: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".KeyVerificationFinal"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "nonce"),
|
||||
2: .standard(proto: "remote_longname"),
|
||||
3: .same(proto: "isSender"),
|
||||
4: .standard(proto: "verification_characters"),
|
||||
]
|
||||
|
||||
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.decodeSingularUInt64Field(value: &self.nonce) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self.remoteLongname) }()
|
||||
case 3: try { try decoder.decodeSingularBoolField(value: &self.isSender) }()
|
||||
case 4: try { try decoder.decodeSingularStringField(value: &self.verificationCharacters) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.nonce != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.nonce, fieldNumber: 1)
|
||||
}
|
||||
if !self.remoteLongname.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.remoteLongname, fieldNumber: 2)
|
||||
}
|
||||
if self.isSender != false {
|
||||
try visitor.visitSingularBoolField(value: self.isSender, fieldNumber: 3)
|
||||
}
|
||||
if !self.verificationCharacters.isEmpty {
|
||||
try visitor.visitSingularStringField(value: self.verificationCharacters, fieldNumber: 4)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: KeyVerificationFinal, rhs: KeyVerificationFinal) -> Bool {
|
||||
if lhs.nonce != rhs.nonce {return false}
|
||||
if lhs.remoteLongname != rhs.remoteLongname {return false}
|
||||
if lhs.isSender != rhs.isSender {return false}
|
||||
if lhs.verificationCharacters != rhs.verificationCharacters {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
/// Same as Text Message but used for critical alerts.
|
||||
case alertApp // = 11
|
||||
|
||||
///
|
||||
/// Module/port for handling key verification requests.
|
||||
case keyVerificationApp // = 12
|
||||
|
||||
///
|
||||
/// Provides a 'ping' service that replies to any packet it receives.
|
||||
/// Also serves as a small example module.
|
||||
|
|
@ -232,6 +236,7 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case 9: self = .audioApp
|
||||
case 10: self = .detectionSensorApp
|
||||
case 11: self = .alertApp
|
||||
case 12: self = .keyVerificationApp
|
||||
case 32: self = .replyApp
|
||||
case 33: self = .ipTunnelApp
|
||||
case 34: self = .paxcounterApp
|
||||
|
|
@ -268,6 +273,7 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case .audioApp: return 9
|
||||
case .detectionSensorApp: return 10
|
||||
case .alertApp: return 11
|
||||
case .keyVerificationApp: return 12
|
||||
case .replyApp: return 32
|
||||
case .ipTunnelApp: return 33
|
||||
case .paxcounterApp: return 34
|
||||
|
|
@ -304,6 +310,7 @@ public enum PortNum: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
.audioApp,
|
||||
.detectionSensorApp,
|
||||
.alertApp,
|
||||
.keyVerificationApp,
|
||||
.replyApp,
|
||||
.ipTunnelApp,
|
||||
.paxcounterApp,
|
||||
|
|
@ -342,6 +349,7 @@ extension PortNum: SwiftProtobuf._ProtoNameProviding {
|
|||
9: .same(proto: "AUDIO_APP"),
|
||||
10: .same(proto: "DETECTION_SENSOR_APP"),
|
||||
11: .same(proto: "ALERT_APP"),
|
||||
12: .same(proto: "KEY_VERIFICATION_APP"),
|
||||
32: .same(proto: "REPLY_APP"),
|
||||
33: .same(proto: "IP_TUNNEL_APP"),
|
||||
34: .same(proto: "PAXCOUNTER_APP"),
|
||||
|
|
|
|||
|
|
@ -180,6 +180,10 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
///
|
||||
/// MAX17261 lipo battery gauge
|
||||
case max17261 // = 38
|
||||
|
||||
///
|
||||
/// PCT2075 Temperature Sensor
|
||||
case pct2075 // = 39
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
|
|
@ -227,6 +231,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case 36: self = .dps310
|
||||
case 37: self = .rak12035
|
||||
case 38: self = .max17261
|
||||
case 39: self = .pct2075
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -272,6 +277,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
case .dps310: return 36
|
||||
case .rak12035: return 37
|
||||
case .max17261: return 38
|
||||
case .pct2075: return 39
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -317,6 +323,7 @@ public enum TelemetrySensorType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
|||
.dps310,
|
||||
.rak12035,
|
||||
.max17261,
|
||||
.pct2075,
|
||||
]
|
||||
|
||||
}
|
||||
|
|
@ -959,6 +966,14 @@ public struct LocalStats: Sendable {
|
|||
/// This will always be zero for ROUTERs/REPEATERs. If this number is high, some other node(s) is/are relaying faster than you.
|
||||
public var numTxRelayCanceled: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Number of bytes used in the heap
|
||||
public var heapTotalBytes: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Number of bytes free in the heap
|
||||
public var heapFreeBytes: UInt32 = 0
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
|
@ -1013,6 +1028,80 @@ public struct HealthMetrics: Sendable {
|
|||
fileprivate var _temperature: Float? = nil
|
||||
}
|
||||
|
||||
///
|
||||
/// Linux host metrics
|
||||
public struct HostMetrics: 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.
|
||||
|
||||
///
|
||||
/// Host system uptime
|
||||
public var uptimeSeconds: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Host system free memory
|
||||
public var freememBytes: UInt64 = 0
|
||||
|
||||
///
|
||||
/// Host system disk space free for /
|
||||
public var diskfree1Bytes: UInt64 = 0
|
||||
|
||||
///
|
||||
/// Secondary system disk space free
|
||||
public var diskfree2Bytes: UInt64 {
|
||||
get {return _diskfree2Bytes ?? 0}
|
||||
set {_diskfree2Bytes = newValue}
|
||||
}
|
||||
/// Returns true if `diskfree2Bytes` has been explicitly set.
|
||||
public var hasDiskfree2Bytes: Bool {return self._diskfree2Bytes != nil}
|
||||
/// Clears the value of `diskfree2Bytes`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearDiskfree2Bytes() {self._diskfree2Bytes = nil}
|
||||
|
||||
///
|
||||
/// Tertiary disk space free
|
||||
public var diskfree3Bytes: UInt64 {
|
||||
get {return _diskfree3Bytes ?? 0}
|
||||
set {_diskfree3Bytes = newValue}
|
||||
}
|
||||
/// Returns true if `diskfree3Bytes` has been explicitly set.
|
||||
public var hasDiskfree3Bytes: Bool {return self._diskfree3Bytes != nil}
|
||||
/// Clears the value of `diskfree3Bytes`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearDiskfree3Bytes() {self._diskfree3Bytes = nil}
|
||||
|
||||
///
|
||||
/// Host system one minute load in 1/100ths
|
||||
public var load1: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Host system five minute load in 1/100ths
|
||||
public var load5: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Host system fifteen minute load in 1/100ths
|
||||
public var load15: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Optional User-provided string for arbitrary host system information
|
||||
/// that doesn't make sense as a dedicated entry.
|
||||
public var userString: String {
|
||||
get {return _userString ?? String()}
|
||||
set {_userString = newValue}
|
||||
}
|
||||
/// Returns true if `userString` has been explicitly set.
|
||||
public var hasUserString: Bool {return self._userString != nil}
|
||||
/// Clears the value of `userString`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearUserString() {self._userString = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _diskfree2Bytes: UInt64? = nil
|
||||
fileprivate var _diskfree3Bytes: UInt64? = nil
|
||||
fileprivate var _userString: String? = nil
|
||||
}
|
||||
|
||||
///
|
||||
/// Types of Measurements the telemetry module is equipped to handle
|
||||
public struct Telemetry: Sendable {
|
||||
|
|
@ -1086,6 +1175,16 @@ public struct Telemetry: Sendable {
|
|||
set {variant = .healthMetrics(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Linux host metrics
|
||||
public var hostMetrics: HostMetrics {
|
||||
get {
|
||||
if case .hostMetrics(let v)? = variant {return v}
|
||||
return HostMetrics()
|
||||
}
|
||||
set {variant = .hostMetrics(newValue)}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public enum OneOf_Variant: Equatable, Sendable {
|
||||
|
|
@ -1107,6 +1206,9 @@ public struct Telemetry: Sendable {
|
|||
///
|
||||
/// Health telemetry metrics
|
||||
case healthMetrics(HealthMetrics)
|
||||
///
|
||||
/// Linux host metrics
|
||||
case hostMetrics(HostMetrics)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1178,6 +1280,7 @@ extension TelemetrySensorType: SwiftProtobuf._ProtoNameProviding {
|
|||
36: .same(proto: "DPS310"),
|
||||
37: .same(proto: "RAK12035"),
|
||||
38: .same(proto: "MAX17261"),
|
||||
39: .same(proto: "PCT2075"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -1673,6 +1776,8 @@ extension LocalStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
9: .standard(proto: "num_rx_dupe"),
|
||||
10: .standard(proto: "num_tx_relay"),
|
||||
11: .standard(proto: "num_tx_relay_canceled"),
|
||||
12: .standard(proto: "heap_total_bytes"),
|
||||
13: .standard(proto: "heap_free_bytes"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1692,6 +1797,8 @@ extension LocalStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
case 9: try { try decoder.decodeSingularUInt32Field(value: &self.numRxDupe) }()
|
||||
case 10: try { try decoder.decodeSingularUInt32Field(value: &self.numTxRelay) }()
|
||||
case 11: try { try decoder.decodeSingularUInt32Field(value: &self.numTxRelayCanceled) }()
|
||||
case 12: try { try decoder.decodeSingularUInt32Field(value: &self.heapTotalBytes) }()
|
||||
case 13: try { try decoder.decodeSingularUInt32Field(value: &self.heapFreeBytes) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
|
@ -1731,6 +1838,12 @@ extension LocalStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
if self.numTxRelayCanceled != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.numTxRelayCanceled, fieldNumber: 11)
|
||||
}
|
||||
if self.heapTotalBytes != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.heapTotalBytes, fieldNumber: 12)
|
||||
}
|
||||
if self.heapFreeBytes != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.heapFreeBytes, fieldNumber: 13)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
@ -1746,6 +1859,8 @@ extension LocalStats: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
if lhs.numRxDupe != rhs.numRxDupe {return false}
|
||||
if lhs.numTxRelay != rhs.numTxRelay {return false}
|
||||
if lhs.numTxRelayCanceled != rhs.numTxRelayCanceled {return false}
|
||||
if lhs.heapTotalBytes != rhs.heapTotalBytes {return false}
|
||||
if lhs.heapFreeBytes != rhs.heapFreeBytes {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
@ -1799,6 +1914,90 @@ extension HealthMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementa
|
|||
}
|
||||
}
|
||||
|
||||
extension HostMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".HostMetrics"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .standard(proto: "uptime_seconds"),
|
||||
2: .standard(proto: "freemem_bytes"),
|
||||
3: .standard(proto: "diskfree1_bytes"),
|
||||
4: .standard(proto: "diskfree2_bytes"),
|
||||
5: .standard(proto: "diskfree3_bytes"),
|
||||
6: .same(proto: "load1"),
|
||||
7: .same(proto: "load5"),
|
||||
8: .same(proto: "load15"),
|
||||
9: .standard(proto: "user_string"),
|
||||
]
|
||||
|
||||
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.decodeSingularUInt32Field(value: &self.uptimeSeconds) }()
|
||||
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.freememBytes) }()
|
||||
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.diskfree1Bytes) }()
|
||||
case 4: try { try decoder.decodeSingularUInt64Field(value: &self._diskfree2Bytes) }()
|
||||
case 5: try { try decoder.decodeSingularUInt64Field(value: &self._diskfree3Bytes) }()
|
||||
case 6: try { try decoder.decodeSingularUInt32Field(value: &self.load1) }()
|
||||
case 7: try { try decoder.decodeSingularUInt32Field(value: &self.load5) }()
|
||||
case 8: try { try decoder.decodeSingularUInt32Field(value: &self.load15) }()
|
||||
case 9: try { try decoder.decodeSingularStringField(value: &self._userString) }()
|
||||
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.uptimeSeconds != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.uptimeSeconds, fieldNumber: 1)
|
||||
}
|
||||
if self.freememBytes != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.freememBytes, fieldNumber: 2)
|
||||
}
|
||||
if self.diskfree1Bytes != 0 {
|
||||
try visitor.visitSingularUInt64Field(value: self.diskfree1Bytes, fieldNumber: 3)
|
||||
}
|
||||
try { if let v = self._diskfree2Bytes {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 4)
|
||||
} }()
|
||||
try { if let v = self._diskfree3Bytes {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 5)
|
||||
} }()
|
||||
if self.load1 != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.load1, fieldNumber: 6)
|
||||
}
|
||||
if self.load5 != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.load5, fieldNumber: 7)
|
||||
}
|
||||
if self.load15 != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.load15, fieldNumber: 8)
|
||||
}
|
||||
try { if let v = self._userString {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 9)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: HostMetrics, rhs: HostMetrics) -> Bool {
|
||||
if lhs.uptimeSeconds != rhs.uptimeSeconds {return false}
|
||||
if lhs.freememBytes != rhs.freememBytes {return false}
|
||||
if lhs.diskfree1Bytes != rhs.diskfree1Bytes {return false}
|
||||
if lhs._diskfree2Bytes != rhs._diskfree2Bytes {return false}
|
||||
if lhs._diskfree3Bytes != rhs._diskfree3Bytes {return false}
|
||||
if lhs.load1 != rhs.load1 {return false}
|
||||
if lhs.load5 != rhs.load5 {return false}
|
||||
if lhs.load15 != rhs.load15 {return false}
|
||||
if lhs._userString != rhs._userString {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension Telemetry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
public static let protoMessageName: String = _protobuf_package + ".Telemetry"
|
||||
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
|
@ -1809,6 +2008,7 @@ extension Telemetry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
|
|||
5: .standard(proto: "power_metrics"),
|
||||
6: .standard(proto: "local_stats"),
|
||||
7: .standard(proto: "health_metrics"),
|
||||
8: .standard(proto: "host_metrics"),
|
||||
]
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
|
|
@ -1896,6 +2096,19 @@ extension Telemetry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -1934,6 +2147,10 @@ extension Telemetry: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
|
|||
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 unknownFields.traverse(visitor: &visitor)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ if [ ! -x "$(which protoc)" ]; then
|
|||
brew install swift-protobuf
|
||||
fi
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
git submodule foreach --recursive git pull origin master
|
||||
|
||||
protoc --proto_path=./protobufs --swift_opt=Visibility=Public --swift_out=./MeshtasticProtobufs/Sources ./protobufs/meshtastic/*.proto
|
||||
|
||||
echo "Done generating the swift files from the proto files."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue