mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #788 from meshtastic/nodedetails-environment-section
Nodedetails environment section
This commit is contained in:
commit
b430bff139
24 changed files with 1597 additions and 625 deletions
|
|
@ -73,6 +73,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"%@ %@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%1$@ %2$@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@ %lld" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
|
|
@ -6953,6 +6963,12 @@
|
|||
},
|
||||
"Enter DFU Mode" : {
|
||||
|
||||
},
|
||||
"environment" : {
|
||||
|
||||
},
|
||||
"Environment" : {
|
||||
|
||||
},
|
||||
"Environment Metrics Log" : {
|
||||
|
||||
|
|
@ -8081,6 +8097,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Gusts %@" : {
|
||||
|
||||
},
|
||||
"Hardware" : {
|
||||
|
||||
|
|
@ -8217,6 +8236,9 @@
|
|||
},
|
||||
"Hide Alerts" : {
|
||||
|
||||
},
|
||||
"HIGH" : {
|
||||
|
||||
},
|
||||
"History Return Max" : {
|
||||
|
||||
|
|
@ -8265,6 +8287,9 @@
|
|||
},
|
||||
"Humidity" : {
|
||||
|
||||
},
|
||||
"HUMIDITY" : {
|
||||
|
||||
},
|
||||
"hybrid" : {
|
||||
"extractionState" : "migrated",
|
||||
|
|
@ -11339,6 +11364,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"LOW" : {
|
||||
|
||||
},
|
||||
"Managed Device" : {
|
||||
|
||||
|
|
@ -16577,6 +16605,9 @@
|
|||
},
|
||||
"Press Pin" : {
|
||||
|
||||
},
|
||||
"PRESSURE" : {
|
||||
|
||||
},
|
||||
"Primary" : {
|
||||
|
||||
|
|
@ -20839,6 +20870,9 @@
|
|||
},
|
||||
"The compass heading on the screen outside of the circle will always point north." : {
|
||||
|
||||
},
|
||||
"The dew point is %@ right now." : {
|
||||
|
||||
},
|
||||
"The fastest that position updates will be sent if the minimum distance has been satisfied" : {
|
||||
|
||||
|
|
@ -22363,6 +22397,9 @@
|
|||
},
|
||||
"Waypoint Options" : {
|
||||
|
||||
},
|
||||
"Weather Conditions" : {
|
||||
|
||||
},
|
||||
"Web Flasher" : {
|
||||
|
||||
|
|
@ -22384,6 +22421,9 @@
|
|||
},
|
||||
"WiFi Options" : {
|
||||
|
||||
},
|
||||
"WIND" : {
|
||||
|
||||
},
|
||||
"x" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@
|
|||
DD3CC6BE28E4CD9800FA9159 /* BatteryGauge.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */; };
|
||||
DD3CC6C028E7A60700FA9159 /* MessagingEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6BF28E7A60700FA9159 /* MessagingEnums.swift */; };
|
||||
DD3CC6C228EB9D4900FA9159 /* UpdateCoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6C128EB9D4900FA9159 /* UpdateCoreData.swift */; };
|
||||
DD3D17E02C3FB67200561584 /* LocalWeatherConditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3D17DF2C3FB67200561584 /* LocalWeatherConditions.swift */; };
|
||||
DD41582628582E9B009B0E59 /* DeviceConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41582528582E9B009B0E59 /* DeviceConfig.swift */; };
|
||||
DD415828285859C4009B0E59 /* TelemetryConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD415827285859C4009B0E59 /* TelemetryConfig.swift */; };
|
||||
DD41582A28585C32009B0E59 /* RangeTestConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD41582928585C32009B0E59 /* RangeTestConfig.swift */; };
|
||||
|
|
@ -294,6 +295,7 @@
|
|||
DD3CC6BF28E7A60700FA9159 /* MessagingEnums.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagingEnums.swift; sourceTree = "<group>"; };
|
||||
DD3CC6C128EB9D4900FA9159 /* UpdateCoreData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateCoreData.swift; sourceTree = "<group>"; };
|
||||
DD3D17DC2C3D7B1400561584 /* MeshtasticDataModelV 39.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 39.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD3D17DF2C3FB67200561584 /* LocalWeatherConditions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalWeatherConditions.swift; sourceTree = "<group>"; };
|
||||
DD41582528582E9B009B0E59 /* DeviceConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceConfig.swift; sourceTree = "<group>"; };
|
||||
DD415827285859C4009B0E59 /* TelemetryConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryConfig.swift; sourceTree = "<group>"; };
|
||||
DD41582928585C32009B0E59 /* RangeTestConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RangeTestConfig.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -316,6 +318,7 @@
|
|||
DD6193742862F6E600E59241 /* ExternalNotificationConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalNotificationConfig.swift; sourceTree = "<group>"; };
|
||||
DD6193762862F90F00E59241 /* CannedMessagesConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CannedMessagesConfig.swift; sourceTree = "<group>"; };
|
||||
DD6193782863875F00E59241 /* SerialConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerialConfig.swift; sourceTree = "<group>"; };
|
||||
DD68BAE72C417A74004C01A0 /* MeshtasticDataModelV 40.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 40.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD73FD1028750779000852D6 /* PositionLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionLog.swift; sourceTree = "<group>"; };
|
||||
DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceMetricsLog.swift; sourceTree = "<group>"; };
|
||||
DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothTips.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -605,6 +608,7 @@
|
|||
DDA9515D2BC6F56F00CEA535 /* IndoorAirQuality.swift */,
|
||||
DD354FD82BD96A0B0061A25F /* IAQScale.swift */,
|
||||
DD41A61429AB0035003C5A37 /* NodeWeatherForecast.swift */,
|
||||
DD3D17DF2C3FB67200561584 /* LocalWeatherConditions.swift */,
|
||||
);
|
||||
path = Weather;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1134,6 +1138,7 @@
|
|||
DDDB444C29F8AAA600EE2349 /* Color.swift in Sources */,
|
||||
DDB8F4122A9EE5DD00230ECE /* UserList.swift in Sources */,
|
||||
DDB75A0F2A05920E006ED576 /* FileManager.swift in Sources */,
|
||||
DD3D17E02C3FB67200561584 /* LocalWeatherConditions.swift in Sources */,
|
||||
DD1933782B084F4200771CD5 /* Measurement.swift in Sources */,
|
||||
DD4F23CD28779A3C001D37CB /* EnvironmentMetricsLog.swift in Sources */,
|
||||
DD93800E2BA74D0C008BEC06 /* ChannelForm.swift in Sources */,
|
||||
|
|
@ -1454,7 +1459,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.3.16;
|
||||
MARKETING_VERSION = 2.3.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1489,7 +1494,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.3.16;
|
||||
MARKETING_VERSION = 2.3.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -1521,7 +1526,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.3.16;
|
||||
MARKETING_VERSION = 2.3.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1554,7 +1559,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.3.16;
|
||||
MARKETING_VERSION = 2.3.17;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = gvh.MeshtasticClient.Widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
@ -1657,6 +1662,7 @@
|
|||
DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
DD68BAE72C417A74004C01A0 /* MeshtasticDataModelV 40.xcdatamodel */,
|
||||
DD3D17DC2C3D7B1400561584 /* MeshtasticDataModelV 39.xcdatamodel */,
|
||||
DDD5BB142C28680D007E03CA /* MeshtasticDataModelV 38.xcdatamodel */,
|
||||
DDD28D372C0CD2670063CFA3 /* MeshtasticDataModelV 37.xcdatamodel */,
|
||||
|
|
@ -1697,7 +1703,7 @@
|
|||
DD5D0A9A2931AD6B00F7EA61 /* MeshtasticDataModelV2.xcdatamodel */,
|
||||
DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */,
|
||||
);
|
||||
currentVersion = DD3D17DC2C3D7B1400561584 /* MeshtasticDataModelV 39.xcdatamodel */;
|
||||
currentVersion = DD68BAE72C417A74004C01A0 /* MeshtasticDataModelV 40.xcdatamodel */;
|
||||
name = Meshtastic.xcdatamodeld;
|
||||
path = Meshtastic/Meshtastic.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@
|
|||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"originHash" : "c5be9820b6e5add3da0e3bd134c3826b3eece5f926d667cb3800a26572f9e63c",
|
||||
"originHash" : "74b3ad6215f078d89f4436b6ce0e318f145842efa3453bbe055ab76057de7d6b",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "cocoamqtt",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,14 @@ import CoreData
|
|||
|
||||
extension NodeInfoEntity {
|
||||
|
||||
var latestPosition: PositionEntity? {
|
||||
return self.positions?.lastObject as? PositionEntity
|
||||
}
|
||||
|
||||
var latestEnvironmentMetrics: TelemetryEntity? {
|
||||
return self.telemetries?.filtered(using: NSPredicate(format: "metricsType == 1")).lastObject as? TelemetryEntity
|
||||
}
|
||||
|
||||
var hasPositions: Bool {
|
||||
return positions?.count ?? 0 > 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ extension Float {
|
|||
mf.numberFormatter.maximumFractionDigits = 0
|
||||
return mf.string(from: temperature)
|
||||
}
|
||||
func shortFormattedTemperature() -> String {
|
||||
let temperature = Measurement<UnitTemperature>(value: Double(self), unit: .celsius)
|
||||
let mf = MeasurementFormatter()
|
||||
mf.unitStyle = .short
|
||||
mf.numberFormatter.maximumFractionDigits = 0
|
||||
return mf.string(from: temperature)
|
||||
}
|
||||
func localeTemperature() -> Double {
|
||||
let temperature = Measurement<UnitTemperature>(value: Double(self), unit: .celsius)
|
||||
let locale = NSLocale.current as NSLocale
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ extension UserDefaults {
|
|||
case channelMessageNotifications
|
||||
case modemPreset
|
||||
case firmwareVersion
|
||||
case environmentEnableWeatherKit
|
||||
case testIntEnum
|
||||
}
|
||||
|
||||
|
|
@ -161,6 +162,9 @@ extension UserDefaults {
|
|||
|
||||
@UserDefault(.firmwareVersion, defaultValue: "0.0.0")
|
||||
static var firmwareVersion: String
|
||||
|
||||
@UserDefault(.environmentEnableWeatherKit, defaultValue: true)
|
||||
static var environmentEnableWeatherKit: Bool
|
||||
|
||||
@UserDefault(.testIntEnum, defaultValue: .one)
|
||||
static var testIntEnum: TestIntEnum
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
|
|||
telemetry.voltage = telemetryMessage.deviceMetrics.voltage
|
||||
telemetry.uptimeSeconds = Int32(telemetryMessage.deviceMetrics.uptimeSeconds)
|
||||
telemetry.metricsType = 0
|
||||
Logger.statistics.info("📈 [Mesh Statistics] Channel Utilization: \(telemetryMessage.deviceMetrics.channelUtilization) Airtime: \(telemetryMessage.deviceMetrics.airUtilTx) for Node: \(packet.from.toHex())")
|
||||
Logger.statistics.info("📈 [Mesh Statistics] Channel Utilization: \(telemetryMessage.deviceMetrics.channelUtilization, privacy: .public) Airtime: \(telemetryMessage.deviceMetrics.airUtilTx, privacy: .public)) for Node: \(packet.from.toHex(), privacy: .public))")
|
||||
} else if telemetryMessage.variant == Telemetry.OneOf_Variant.environmentMetrics(telemetryMessage.environmentMetrics) {
|
||||
// Environment Metrics
|
||||
telemetry.barometricPressure = telemetryMessage.environmentMetrics.barometricPressure
|
||||
|
|
@ -676,12 +676,16 @@ func telemetryPacket(packet: MeshPacket, connectedNode: Int64, context: NSManage
|
|||
telemetry.temperature = telemetryMessage.environmentMetrics.temperature
|
||||
telemetry.current = telemetryMessage.environmentMetrics.current
|
||||
telemetry.voltage = telemetryMessage.environmentMetrics.voltage
|
||||
telemetry.weight = telemetryMessage.environmentMetrics.weight
|
||||
telemetry.windSpeed = telemetryMessage.environmentMetrics.windSpeed
|
||||
telemetry.windGust = telemetryMessage.environmentMetrics.windGust
|
||||
telemetry.windLull = telemetryMessage.environmentMetrics.windLull
|
||||
telemetry.windDirection = Int32(truncatingIfNeeded: telemetryMessage.environmentMetrics.windDirection)
|
||||
telemetry.metricsType = 1
|
||||
}
|
||||
telemetry.snr = packet.rxSnr
|
||||
telemetry.rssi = packet.rxRssi
|
||||
telemetry.time = Date(timeIntervalSince1970: TimeInterval(Int64(truncatingIfNeeded: telemetryMessage.time)))
|
||||
|
||||
guard let mutableTelemetries = fetchedNode[0].telemetries!.mutableCopy() as? NSMutableOrderedSet else {
|
||||
return
|
||||
}
|
||||
|
|
@ -802,6 +806,9 @@ func textMessageAppPacket(packet: MeshPacket, wantRangeTestPackets: Bool, connec
|
|||
}
|
||||
if fetchedUsers.first(where: { $0.num == packet.from }) != nil {
|
||||
newMessage.fromUser = fetchedUsers.first(where: { $0.num == packet.from })
|
||||
if packet.rxTime > 0 {
|
||||
newMessage.fromUser?.userNode?.lastHeard = Date(timeIntervalSince1970: TimeInterval(Int64(packet.rxTime)))
|
||||
}
|
||||
}
|
||||
newMessage.messagePayload = messageText
|
||||
newMessage.messagePayloadMarkdown = generateMessageMarkdown(message: messageText!)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>MeshtasticDataModelV 39.xcdatamodel</string>
|
||||
<string>MeshtasticDataModelV 40.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,464 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22758" systemVersion="23G5061b" 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"/>
|
||||
<fetchedProperty name="allPrivateMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="channel == $FETCH_SOURCE.index AND toUser == nil AND isEmoji == false"/>
|
||||
</fetchedProperty>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="index"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="DetectionSensorConfigEntity" representedClassName="DetectionSensorConfigEntity" syncable="YES" codeGenerationType="class">
|
||||
<attribute name="detectionTriggeredHigh" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<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="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="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="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="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="portNum" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<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="receivedTimestamp" optional="YES" attributeType="Integer 32" defaultValueString="0" 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"/>
|
||||
<fetchedProperty name="tapbacks" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="replyID == $FETCH_SOURCE.messageId AND isEmoji == true"/>
|
||||
</fetchedProperty>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="messageId"/>
|
||||
</uniquenessConstraint>
|
||||
</uniquenessConstraints>
|
||||
</entity>
|
||||
<entity name="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="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="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"/>
|
||||
<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"/>
|
||||
<fetchedProperty name="allMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="toUser == nil"/>
|
||||
</fetchedProperty>
|
||||
<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="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="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="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="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="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" codeGenerationType="class">
|
||||
<attribute name="airUtilTx" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="barometricPressure" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="batteryLevel" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="channelUtilization" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="current" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="gasResistance" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="iaq" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="metricsType" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="relativeHumidity" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="rssi" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="snr" 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="voltage" optional="YES" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||
<attribute name="weight" 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="altitude" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="hasPositions" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="latitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="longitudeI" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="num" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="response" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="route" optional="YES" attributeType="Transformable" customClassName="[UInt32]"/>
|
||||
<attribute name="routeText" optional="YES" attributeType="String"/>
|
||||
<attribute name="time" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="hops" optional="YES" toMany="YES" deletionRule="Nullify" 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="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="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="hwModel" attributeType="String"/>
|
||||
<attribute name="isLicensed" optional="YES" attributeType="Boolean" defaultValueString="NO" 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="num" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="numString" optional="YES" attributeType="String"/>
|
||||
<attribute name="role" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="shortName" attributeType="String"/>
|
||||
<attribute name="userId" attributeType="String"/>
|
||||
<relationship name="receivedMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="toUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="sentMessages" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="MessageEntity" inverseName="fromUser" inverseEntity="MessageEntity"/>
|
||||
<relationship name="userNode" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NodeInfoEntity" inverseName="user" inverseEntity="NodeInfoEntity"/>
|
||||
<fetchedProperty name="allMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="((toUser.num == $FETCH_SOURCE.num) OR (fromUser.num == $FETCH_SOURCE.num)) AND toUser != nil AND fromUser != nil AND isEmoji == false AND admin = false AND portNum != 10 "/>
|
||||
</fetchedProperty>
|
||||
<fetchedProperty name="detectionSensorMessages" optional="YES">
|
||||
<fetchRequest name="fetchedPropertyFetchRequest" entity="MessageEntity" predicateString="(fromUser.num == $FETCH_SOURCE.num) AND portNum = 10"/>
|
||||
</fetchedProperty>
|
||||
</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>
|
||||
189
Meshtastic/Views/Helpers/Weather/LocalWeatherConditions.swift
Normal file
189
Meshtastic/Views/Helpers/Weather/LocalWeatherConditions.swift
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
//
|
||||
// LocalWeatherConditions.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Garth Vander Houwen on 7/9/24.
|
||||
//
|
||||
import SwiftUI
|
||||
import MapKit
|
||||
import WeatherKit
|
||||
import OSLog
|
||||
|
||||
struct LocalWeatherConditions: View {
|
||||
private let gridItemLayout = Array(repeating: GridItem(.flexible(), spacing: 10), count: 2)
|
||||
@State var location: CLLocation?
|
||||
/// Weather
|
||||
/// The current weather condition for the city.
|
||||
@State private var condition: WeatherCondition?
|
||||
@State private var temperature: String = ""
|
||||
@State private var dewPoint: String = ""
|
||||
@State private var humidity: Int?
|
||||
@State private var pressure: Measurement<UnitPressure>?
|
||||
@State private var windSpeed: String = ""
|
||||
@State private var windGust: String = ""
|
||||
@State private var windDirection: Measurement<UnitAngle>?
|
||||
@State private var windCompassDirection: String = ""
|
||||
@State private var symbolName: String = "cloud.fill"
|
||||
@State private var attributionLink: URL?
|
||||
@State private var attributionLogo: URL?
|
||||
|
||||
@Environment(\.colorScheme) var colorScheme: ColorScheme
|
||||
var body: some View {
|
||||
if location != nil {
|
||||
VStack {
|
||||
LazyVGrid(columns: gridItemLayout) {
|
||||
WeatherConditionsCompactWidget(temperature: temperature, symbolName: symbolName, description: condition?.description.uppercased() ?? "??")
|
||||
HumidityCompactWidget(humidity: humidity ?? 0, dewPoint: dewPoint)
|
||||
PressureCompactWidget(pressure: String(pressure?.value ?? 0.0 / 100), unit: pressure?.unit.symbol ?? "??", low: pressure?.value ?? 0.0 <= 1009.144)
|
||||
WindCompactWidget(speed: windSpeed, gust: windGust, direction: windCompassDirection)
|
||||
}
|
||||
}
|
||||
.padding(.top)
|
||||
.task {
|
||||
do {
|
||||
if location != nil {
|
||||
let weather = try await WeatherService.shared.weather(for: location!)
|
||||
let numFormatter = NumberFormatter()
|
||||
let measurementFormatter = MeasurementFormatter()
|
||||
numFormatter.maximumFractionDigits = 0
|
||||
measurementFormatter.numberFormatter = numFormatter
|
||||
measurementFormatter.unitStyle = .short
|
||||
measurementFormatter.locale = Locale.current
|
||||
condition = weather.currentWeather.condition
|
||||
temperature = measurementFormatter.string(from: weather.currentWeather.temperature)
|
||||
dewPoint = measurementFormatter.string(from: weather.currentWeather.dewPoint)
|
||||
humidity = Int(weather.currentWeather.humidity * 100)
|
||||
pressure = weather.currentWeather.pressure
|
||||
windSpeed = measurementFormatter.string(from: weather.currentWeather.wind.speed)
|
||||
windGust = measurementFormatter.string(from: weather.currentWeather.wind.gust ?? Measurement(value: 0.0, unit: weather.currentWeather.wind.gust!.unit))
|
||||
windDirection = weather.currentWeather.wind.direction
|
||||
windCompassDirection = weather.currentWeather.wind.compassDirection.description
|
||||
symbolName = weather.currentWeather.symbolName
|
||||
let attribution = try await WeatherService.shared.attribution
|
||||
attributionLink = attribution.legalPageURL
|
||||
attributionLogo = colorScheme == .light ? attribution.combinedMarkLightURL : attribution.combinedMarkDarkURL
|
||||
}
|
||||
} catch {
|
||||
Logger.services.error("Could not gather weather information: \(error.localizedDescription)")
|
||||
condition = .clear
|
||||
symbolName = "cloud.fill"
|
||||
}
|
||||
}
|
||||
VStack {
|
||||
HStack {
|
||||
AsyncImage(url: attributionLogo) { image in
|
||||
image
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
} placeholder: {
|
||||
ProgressView()
|
||||
.controlSize(.mini)
|
||||
}
|
||||
.frame(height: 10)
|
||||
Link("Other data sources", destination: attributionLink ?? URL(string: "https://weather-data.apple.com/legal-attribution.html")!)
|
||||
.font(.caption2)
|
||||
}
|
||||
.padding(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WeatherConditionsCompactWidget: View {
|
||||
let temperature: String
|
||||
let symbolName: String
|
||||
let description: String
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Label { Text(description) } icon: { Image(systemName: symbolName).symbolRenderingMode(.multicolor) }
|
||||
.font(.caption)
|
||||
Text(temperature)
|
||||
.font(temperature.length < 4 ? .system(size: 90) : .system(size: 60) )
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 175)
|
||||
.background(.tertiary, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
|
||||
}
|
||||
}
|
||||
|
||||
struct HumidityCompactWidget: View {
|
||||
let humidity: Int
|
||||
let dewPoint: String
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Label { Text("HUMIDITY") } icon: { Image(systemName: "humidity").symbolRenderingMode(.multicolor) }
|
||||
.font(.caption)
|
||||
Text("\(humidity)%")
|
||||
.font(.largeTitle)
|
||||
.padding(.bottom)
|
||||
Text("The dew point is \(dewPoint) right now.")
|
||||
.lineLimit(3)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.font(.caption)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 175)
|
||||
.background(.tertiary, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
|
||||
}
|
||||
}
|
||||
|
||||
struct PressureCompactWidget: View {
|
||||
let pressure: String
|
||||
let unit: String
|
||||
let low: Bool
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Label { Text("PRESSURE") } icon: { Image(systemName: "gauge").symbolRenderingMode(.multicolor) }
|
||||
.font(.caption2)
|
||||
Text(pressure)
|
||||
.font(pressure.length < 7 ? .system(size: 35) : .system(size: 30) )
|
||||
Text(low ? "LOW" : "HIGH")
|
||||
.padding(.bottom)
|
||||
Text(unit)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 175)
|
||||
.background(.tertiary, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
|
||||
}
|
||||
}
|
||||
|
||||
struct WindCompactWidget: View {
|
||||
let speed: String
|
||||
let gust: String
|
||||
let direction: String
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Label { Text("WIND") } icon: { Image(systemName: "wind").foregroundColor(.accentColor) }
|
||||
.font(.caption)
|
||||
Text("\(direction)")
|
||||
.font(.caption)
|
||||
.padding(.bottom, 10)
|
||||
Text(speed)
|
||||
.font(.system(size: 35))
|
||||
Text("Gusts \(gust)")
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 175)
|
||||
.background(.tertiary, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
|
||||
}
|
||||
}
|
||||
|
||||
/// Magnus Formula
|
||||
func calculateDewPoint(temp: Float, relativeHumidity: Float) -> Double {
|
||||
let a: Float = 17.27
|
||||
let b: Float = 237.7
|
||||
let alpha = ((a * temp) / (b + temp)) + log(relativeHumidity / 100.0)
|
||||
let dewPoint = (b * alpha) / (a - alpha)
|
||||
let dewPointUnit = Measurement<UnitTemperature>(value: Double(dewPoint), unit: .celsius)
|
||||
let locale = NSLocale.current as NSLocale
|
||||
let localeUnit = locale.object(forKey: NSLocale.Key(rawValue: "kCFLocaleTemperatureUnitKey"))
|
||||
var format: UnitTemperature = .celsius
|
||||
|
||||
if localeUnit! as? String == "Fahrenheit" {
|
||||
format = .fahrenheit
|
||||
}
|
||||
return dewPointUnit.converted(to: format).value
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ struct ChannelList: 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] {
|
||||
List(channels, id: \.self) { (channel: ChannelEntity) in
|
||||
List(channels, id: \.self, selection: $channelSelection) { (channel: ChannelEntity) in
|
||||
if !restrictedChannels.contains(channel.name?.lowercased() ?? "") {
|
||||
makeNavigationLink(myInfo: myInfo, channel: channel)
|
||||
.frame(height: 62)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ struct UserList: View {
|
|||
@State private var viaMqtt = true
|
||||
@State private var isOnline = false
|
||||
@State private var isFavorite = false
|
||||
@State private var isEnvironment = false
|
||||
@State private var distanceFilter = false
|
||||
@State private var maxDistance: Double = 800000
|
||||
@State private var hopsAway: Double = -1.0
|
||||
|
|
@ -171,7 +172,7 @@ struct UserList: View {
|
|||
.listStyle(.plain)
|
||||
.navigationTitle(String.localizedStringWithFormat("contacts %@".localized, String(users.count == 0 ? 0 : users.count - 1)))
|
||||
.sheet(isPresented: $isEditingFilters) {
|
||||
NodeListFilter(filterTitle: "Contact Filters", viaLora: $viaLora, viaMqtt: $viaMqtt, isOnline: $isOnline, isFavorite: $isFavorite, distanceFilter: $distanceFilter, maximumDistance: $maxDistance, hopsAway: $hopsAway, roleFilter: $roleFilter, deviceRoles: $deviceRoles)
|
||||
NodeListFilter(filterTitle: "Contact Filters", viaLora: $viaLora, viaMqtt: $viaMqtt, isOnline: $isOnline, isFavorite: $isFavorite, isEnvironment: $isEnvironment, distanceFilter: $distanceFilter, maximumDistance: $maxDistance, hopsAway: $hopsAway, roleFilter: $roleFilter, deviceRoles: $deviceRoles)
|
||||
}
|
||||
.onChange(of: searchText) { _ in
|
||||
searchUserList()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import CoreLocation
|
|||
import OSLog
|
||||
|
||||
struct NodeDetail: View {
|
||||
private let gridItemLayout = Array(repeating: GridItem(.flexible(), spacing: 10), count: 2)
|
||||
private static let relativeFormatter: RelativeDateTimeFormatter = {
|
||||
let formatter = RelativeDateTimeFormatter()
|
||||
formatter.unitsStyle = .full
|
||||
|
|
@ -157,7 +158,33 @@ struct NodeDetail: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if node.hasPositions && UserDefaults.environmentEnableWeatherKit || node.hasEnvironmentMetrics {
|
||||
Section("Environment") {
|
||||
if !node.hasEnvironmentMetrics {
|
||||
LocalWeatherConditions(location: node.latestPosition?.nodeLocation)
|
||||
} else {
|
||||
VStack {
|
||||
if node.latestEnvironmentMetrics?.iaq ?? -1 > 0 {
|
||||
IndoorAirQuality(iaq: Int(node.latestEnvironmentMetrics?.iaq ?? 0), displayMode: .gradient)
|
||||
.padding(.vertical)
|
||||
}
|
||||
LazyVGrid(columns: gridItemLayout) {
|
||||
WeatherConditionsCompactWidget(temperature: String(node.latestEnvironmentMetrics?.temperature.shortFormattedTemperature() ?? "99°"), symbolName: "cloud.sun", description: "TEMP")
|
||||
if node.latestEnvironmentMetrics?.relativeHumidity ?? 0.0 > 0.0 {
|
||||
HumidityCompactWidget(humidity: Int(node.latestEnvironmentMetrics?.relativeHumidity ?? 0.0), dewPoint: String(format: "%.0f", calculateDewPoint(temp: node.latestEnvironmentMetrics?.temperature ?? 0.0, relativeHumidity: node.latestEnvironmentMetrics?.relativeHumidity ?? 0.0)) + "°")
|
||||
}
|
||||
if node.latestEnvironmentMetrics?.barometricPressure ?? 0.0 > 0.0 {
|
||||
PressureCompactWidget(pressure: String(format: "%.2f", node.latestEnvironmentMetrics?.barometricPressure ?? 0.0), unit: "hPA", low: node.latestEnvironmentMetrics?.barometricPressure ?? 0.0 <= 1009.144)
|
||||
}
|
||||
if node.latestEnvironmentMetrics?.windSpeed ?? 0.0 > 0.0 {
|
||||
WindCompactWidget(speed: String(node.latestEnvironmentMetrics?.windSpeed ?? 0.0), gust: String(node.latestEnvironmentMetrics?.windGust ?? 0.0), direction: "")
|
||||
}
|
||||
}
|
||||
.padding(node.latestEnvironmentMetrics?.iaq ?? -1 > 0 ? .bottom : .vertical)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Section("Logs") {
|
||||
// Metrics
|
||||
NavigationLink {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ struct NodeInfoItem: View {
|
|||
.foregroundColor(getRssiColor(rssi: node.rssi))
|
||||
.font(.caption2)
|
||||
}
|
||||
.frame(minWidth: 90, maxWidth: 180)
|
||||
.frame(minWidth: 100, maxWidth: 140)
|
||||
}
|
||||
|
||||
if node.telemetries?.count ?? 0 > 0 {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ struct NodeListFilter: View {
|
|||
@Binding var viaMqtt: Bool
|
||||
@Binding var isOnline: Bool
|
||||
@Binding var isFavorite: Bool
|
||||
@Binding var isEnvironment: Bool
|
||||
@Binding var distanceFilter: Bool
|
||||
@Binding var maximumDistance: Double
|
||||
@Binding var hopsAway: Double
|
||||
|
|
@ -34,6 +35,7 @@ struct NodeListFilter: View {
|
|||
} icon: {
|
||||
Image(systemName: "dot.radiowaves.left.and.right")
|
||||
.rotationEffect(.degrees(-90))
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
|
@ -43,6 +45,7 @@ struct NodeListFilter: View {
|
|||
Text("Via Mqtt")
|
||||
} icon: {
|
||||
Image(systemName: "dot.radiowaves.up.forward")
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
|
@ -68,8 +71,19 @@ struct NodeListFilter: View {
|
|||
} icon: {
|
||||
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundColor(.yellow)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
.listRowSeparator(.visible)
|
||||
|
||||
Toggle(isOn: $isEnvironment) {
|
||||
|
||||
Label {
|
||||
Text("Environment")
|
||||
} icon: {
|
||||
Image(systemName: "cloud.sun")
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
|
|
|
|||
|
|
@ -18,12 +18,21 @@ struct NodeList: View {
|
|||
@State private var viaMqtt = true
|
||||
@State private var isOnline = false
|
||||
@State private var isFavorite = false
|
||||
@State private var isEnvironment = false
|
||||
@State private var distanceFilter = false
|
||||
@State private var maxDistance: Double = 800000
|
||||
@State private var hopsAway: Double = -1.0
|
||||
@State private var roleFilter = false
|
||||
@State private var deviceRoles: Set<Int> = []
|
||||
|
||||
var boolFilters: [Bool] {[
|
||||
isOnline,
|
||||
isFavorite,
|
||||
isEnvironment,
|
||||
distanceFilter,
|
||||
roleFilter
|
||||
]}
|
||||
|
||||
@State var isEditingFilters = false
|
||||
|
||||
@SceneStorage("selectedDetailView") var selectedDetailView: String?
|
||||
|
|
@ -37,7 +46,7 @@ struct NodeList: View {
|
|||
NSSortDescriptor(key: "lastHeard", ascending: false),
|
||||
NSSortDescriptor(key: "user.longName", ascending: true),
|
||||
],
|
||||
animation: .default
|
||||
animation: .spring
|
||||
)
|
||||
var nodes: FetchedResults<NodeInfoEntity>
|
||||
|
||||
|
|
@ -92,6 +101,7 @@ struct NodeList: View {
|
|||
viaMqtt: $viaMqtt,
|
||||
isOnline: $isOnline,
|
||||
isFavorite: $isFavorite,
|
||||
isEnvironment: $isEnvironment,
|
||||
distanceFilter: $distanceFilter,
|
||||
maximumDistance: $maxDistance,
|
||||
hopsAway: $hopsAway,
|
||||
|
|
@ -203,6 +213,11 @@ struct NodeList: View {
|
|||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: boolFilters) { _ in
|
||||
Task {
|
||||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: [deviceRoles]) { _ in
|
||||
Task {
|
||||
await searchNodeList()
|
||||
|
|
@ -213,26 +228,11 @@ struct NodeList: View {
|
|||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: isOnline) { _ in
|
||||
Task {
|
||||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: isFavorite) { _ in
|
||||
Task {
|
||||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: maxDistance) { _ in
|
||||
Task {
|
||||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: distanceFilter) { _ in
|
||||
Task {
|
||||
await searchNodeList()
|
||||
}
|
||||
}
|
||||
.onChange(of: (appState.navigationPath)) { newPath in
|
||||
|
||||
guard let deepLink = newPath else {
|
||||
|
|
@ -299,7 +299,6 @@ struct NodeList: View {
|
|||
let hopsAwayPredicate = NSPredicate(format: "hopsAway > 0 AND hopsAway <= %i", Int32(hopsAway))
|
||||
predicates.append(hopsAwayPredicate)
|
||||
}
|
||||
|
||||
/// Online
|
||||
if isOnline {
|
||||
let isOnlinePredicate = NSPredicate(format: "lastHeard >= %@", Calendar.current.date(byAdding: .minute, value: -15, to: Date())! as NSDate)
|
||||
|
|
@ -310,6 +309,11 @@ struct NodeList: View {
|
|||
let isFavoritePredicate = NSPredicate(format: "favorite == YES")
|
||||
predicates.append(isFavoritePredicate)
|
||||
}
|
||||
/// Environment
|
||||
if isEnvironment {
|
||||
let environmentPredicate = NSPredicate(format: "SUBQUERY(telemetries, $tel, $tel.metricsType == 1).@count > 0")
|
||||
predicates.append(environmentPredicate)
|
||||
}
|
||||
/// Distance
|
||||
if distanceFilter {
|
||||
let pointOfInterest = LocationHelper.currentLocation
|
||||
|
|
@ -328,7 +332,6 @@ struct NodeList: View {
|
|||
predicates.append(distancePredicate)
|
||||
}
|
||||
}
|
||||
|
||||
if predicates.count > 0 || !searchText.isEmpty {
|
||||
if !searchText.isEmpty {
|
||||
let filterPredicates = NSCompoundPredicate(type: .and, subpredicates: predicates)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct AppSettings: View {
|
|||
@State var totalDownloadedTileSize = ""
|
||||
@State private var isPresentingCoreDataResetConfirm = false
|
||||
@State private var isPresentingDeleteMapTilesConfirm = false
|
||||
@AppStorage("environmentEnableWeatherKit") private var environmentEnableWeatherKit: Bool = true
|
||||
var body: some View {
|
||||
VStack {
|
||||
Form {
|
||||
|
|
@ -23,6 +24,14 @@ struct AppSettings: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
Section(header: Text("environment")) {
|
||||
VStack(alignment: .leading) {
|
||||
Toggle(isOn: $environmentEnableWeatherKit) {
|
||||
Label("Weather Conditions", systemImage: "cloud.sun")
|
||||
}
|
||||
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
||||
}
|
||||
}
|
||||
Section(header: Text("App Data")) {
|
||||
Button {
|
||||
isPresentingCoreDataResetConfirm = true
|
||||
|
|
|
|||
|
|
@ -33,27 +33,24 @@ public struct ChannelSet {
|
|||
|
||||
///
|
||||
/// Channel list with settings
|
||||
public var settings: [ChannelSettings] {
|
||||
get {return _storage._settings}
|
||||
set {_uniqueStorage()._settings = newValue}
|
||||
}
|
||||
public var settings: [ChannelSettings] = []
|
||||
|
||||
///
|
||||
/// LoRa config
|
||||
public var loraConfig: Config.LoRaConfig {
|
||||
get {return _storage._loraConfig ?? Config.LoRaConfig()}
|
||||
set {_uniqueStorage()._loraConfig = newValue}
|
||||
get {return _loraConfig ?? Config.LoRaConfig()}
|
||||
set {_loraConfig = newValue}
|
||||
}
|
||||
/// Returns true if `loraConfig` has been explicitly set.
|
||||
public var hasLoraConfig: Bool {return _storage._loraConfig != nil}
|
||||
public var hasLoraConfig: Bool {return self._loraConfig != nil}
|
||||
/// Clears the value of `loraConfig`. Subsequent reads from it will return its default value.
|
||||
public mutating func clearLoraConfig() {_uniqueStorage()._loraConfig = nil}
|
||||
public mutating func clearLoraConfig() {self._loraConfig = nil}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
fileprivate var _loraConfig: Config.LoRaConfig? = nil
|
||||
}
|
||||
|
||||
#if swift(>=5.5) && canImport(_Concurrency)
|
||||
|
|
@ -71,78 +68,36 @@ extension ChannelSet: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
|
|||
2: .standard(proto: "lora_config"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _settings: [ChannelSettings] = []
|
||||
var _loraConfig: Config.LoRaConfig? = nil
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
// The type itself is protecting the reference to its storage via CoW semantics.
|
||||
// This will force a copy to be made of this reference when the first mutation occurs;
|
||||
// hence, it is safe to mark this as `nonisolated(unsafe)`.
|
||||
static nonisolated(unsafe) let defaultInstance = _StorageClass()
|
||||
#else
|
||||
static let defaultInstance = _StorageClass()
|
||||
#endif
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_settings = source._settings
|
||||
_loraConfig = source._loraConfig
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeRepeatedMessageField(value: &_storage._settings) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._loraConfig) }()
|
||||
default: break
|
||||
}
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.settings) }()
|
||||
case 2: try { try decoder.decodeSingularMessageField(value: &self._loraConfig) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if !_storage._settings.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: _storage._settings, fieldNumber: 1)
|
||||
}
|
||||
try { if let v = _storage._loraConfig {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
// 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.settings.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.settings, fieldNumber: 1)
|
||||
}
|
||||
try { if let v = self._loraConfig {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChannelSet, rhs: ChannelSet) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._settings != rhs_storage._settings {return false}
|
||||
if _storage._loraConfig != rhs_storage._loraConfig {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.settings != rhs.settings {return false}
|
||||
if lhs._loraConfig != rhs._loraConfig {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1087,7 +1087,10 @@ public struct Config {
|
|||
///
|
||||
/// When enabled, the `modem_preset` fields will be adhered to, else the `bandwidth`/`spread_factor`/`coding_rate`
|
||||
/// will be taked from their respective manually defined fields
|
||||
public var usePreset: Bool = false
|
||||
public var usePreset: Bool {
|
||||
get {return _storage._usePreset}
|
||||
set {_uniqueStorage()._usePreset = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Either modem_config or bandwidth/spreading/coding will be specified - NOT BOTH.
|
||||
|
|
@ -1095,51 +1098,78 @@ public struct Config {
|
|||
/// Because protobufs take ZERO space when the value is zero this works out nicely.
|
||||
/// This value is replaced by bandwidth/spread_factor/coding_rate.
|
||||
/// If you'd like to experiment with other options add them to MeshRadio.cpp in the device code.
|
||||
public var modemPreset: Config.LoRaConfig.ModemPreset = .longFast
|
||||
public var modemPreset: Config.LoRaConfig.ModemPreset {
|
||||
get {return _storage._modemPreset}
|
||||
set {_uniqueStorage()._modemPreset = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Bandwidth in MHz
|
||||
/// Certain bandwidth numbers are 'special' and will be converted to the
|
||||
/// appropriate floating point value: 31 -> 31.25MHz
|
||||
public var bandwidth: UInt32 = 0
|
||||
public var bandwidth: UInt32 {
|
||||
get {return _storage._bandwidth}
|
||||
set {_uniqueStorage()._bandwidth = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// A number from 7 to 12.
|
||||
/// Indicates number of chirps per symbol as 1<<spread_factor.
|
||||
public var spreadFactor: UInt32 = 0
|
||||
public var spreadFactor: UInt32 {
|
||||
get {return _storage._spreadFactor}
|
||||
set {_uniqueStorage()._spreadFactor = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// The denominator of the coding rate.
|
||||
/// ie for 4/5, the value is 5. 4/8 the value is 8.
|
||||
public var codingRate: UInt32 = 0
|
||||
public var codingRate: UInt32 {
|
||||
get {return _storage._codingRate}
|
||||
set {_uniqueStorage()._codingRate = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// This parameter is for advanced users with advanced test equipment, we do not recommend most users use it.
|
||||
/// A frequency offset that is added to to the calculated band center frequency.
|
||||
/// Used to correct for crystal calibration errors.
|
||||
public var frequencyOffset: Float = 0
|
||||
public var frequencyOffset: Float {
|
||||
get {return _storage._frequencyOffset}
|
||||
set {_uniqueStorage()._frequencyOffset = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// The region code for the radio (US, CN, EU433, etc...)
|
||||
public var region: Config.LoRaConfig.RegionCode = .unset
|
||||
public var region: Config.LoRaConfig.RegionCode {
|
||||
get {return _storage._region}
|
||||
set {_uniqueStorage()._region = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Maximum number of hops. This can't be greater than 7.
|
||||
/// Default of 3
|
||||
/// Attempting to set a value > 7 results in the default
|
||||
public var hopLimit: UInt32 = 0
|
||||
public var hopLimit: UInt32 {
|
||||
get {return _storage._hopLimit}
|
||||
set {_uniqueStorage()._hopLimit = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Disable TX from the LoRa radio. Useful for hot-swapping antennas and other tests.
|
||||
/// Defaults to false
|
||||
public var txEnabled: Bool = false
|
||||
public var txEnabled: Bool {
|
||||
get {return _storage._txEnabled}
|
||||
set {_uniqueStorage()._txEnabled = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// If zero, then use default max legal continuous power (ie. something that won't
|
||||
/// burn out the radio hardware)
|
||||
/// In most cases you should use zero here.
|
||||
/// Units are in dBm.
|
||||
public var txPower: Int32 = 0
|
||||
public var txPower: Int32 {
|
||||
get {return _storage._txPower}
|
||||
set {_uniqueStorage()._txPower = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// This controls the actual hardware frequency the radio transmits on.
|
||||
|
|
@ -1149,17 +1179,26 @@ public struct Config {
|
|||
/// algorithm to derive the channel number")
|
||||
/// If using the hash algorithm the channel number will be: hash(channel_name) %
|
||||
/// NUM_CHANNELS (Where num channels depends on the regulatory region).
|
||||
public var channelNum: UInt32 = 0
|
||||
public var channelNum: UInt32 {
|
||||
get {return _storage._channelNum}
|
||||
set {_uniqueStorage()._channelNum = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// If true, duty cycle limits will be exceeded and thus you're possibly not following
|
||||
/// the local regulations if you're not a HAM.
|
||||
/// Has no effect if the duty cycle of the used region is 100%.
|
||||
public var overrideDutyCycle: Bool = false
|
||||
public var overrideDutyCycle: Bool {
|
||||
get {return _storage._overrideDutyCycle}
|
||||
set {_uniqueStorage()._overrideDutyCycle = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// If true, sets RX boosted gain mode on SX126X based radios
|
||||
public var sx126XRxBoostedGain: Bool = false
|
||||
public var sx126XRxBoostedGain: Bool {
|
||||
get {return _storage._sx126XRxBoostedGain}
|
||||
set {_uniqueStorage()._sx126XRxBoostedGain = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// This parameter is for advanced users and licensed HAM radio operators.
|
||||
|
|
@ -1167,17 +1206,33 @@ public struct Config {
|
|||
/// will still be applied. This will allow you to use out-of-band frequencies.
|
||||
/// Please respect your local laws and regulations. If you are a HAM, make sure you
|
||||
/// enable HAM mode and turn off encryption.
|
||||
public var overrideFrequency: Float = 0
|
||||
public var overrideFrequency: Float {
|
||||
get {return _storage._overrideFrequency}
|
||||
set {_uniqueStorage()._overrideFrequency = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// If true, disable the build-in PA FAN using pin define in RF95_FAN_EN.
|
||||
public var paFanDisabled: Bool {
|
||||
get {return _storage._paFanDisabled}
|
||||
set {_uniqueStorage()._paFanDisabled = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// For testing it is useful sometimes to force a node to never listen to
|
||||
/// particular other nodes (simulating radio out of range). All nodenums listed
|
||||
/// in ignore_incoming will have packets they send dropped on receive (by router.cpp)
|
||||
public var ignoreIncoming: [UInt32] = []
|
||||
public var ignoreIncoming: [UInt32] {
|
||||
get {return _storage._ignoreIncoming}
|
||||
set {_uniqueStorage()._ignoreIncoming = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// If true, the device will not process any packets received via LoRa that passed via MQTT anywhere on the path towards it.
|
||||
public var ignoreMqtt: Bool = false
|
||||
public var ignoreMqtt: Bool {
|
||||
get {return _storage._ignoreMqtt}
|
||||
set {_uniqueStorage()._ignoreMqtt = newValue}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
|
|
@ -1391,6 +1446,8 @@ public struct Config {
|
|||
}
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
public struct BluetoothConfig {
|
||||
|
|
@ -2443,106 +2500,184 @@ extension Config.LoRaConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplem
|
|||
12: .standard(proto: "override_duty_cycle"),
|
||||
13: .standard(proto: "sx126x_rx_boosted_gain"),
|
||||
14: .standard(proto: "override_frequency"),
|
||||
15: .standard(proto: "pa_fan_disabled"),
|
||||
103: .standard(proto: "ignore_incoming"),
|
||||
104: .standard(proto: "ignore_mqtt"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _usePreset: Bool = false
|
||||
var _modemPreset: Config.LoRaConfig.ModemPreset = .longFast
|
||||
var _bandwidth: UInt32 = 0
|
||||
var _spreadFactor: UInt32 = 0
|
||||
var _codingRate: UInt32 = 0
|
||||
var _frequencyOffset: Float = 0
|
||||
var _region: Config.LoRaConfig.RegionCode = .unset
|
||||
var _hopLimit: UInt32 = 0
|
||||
var _txEnabled: Bool = false
|
||||
var _txPower: Int32 = 0
|
||||
var _channelNum: UInt32 = 0
|
||||
var _overrideDutyCycle: Bool = false
|
||||
var _sx126XRxBoostedGain: Bool = false
|
||||
var _overrideFrequency: Float = 0
|
||||
var _paFanDisabled: Bool = false
|
||||
var _ignoreIncoming: [UInt32] = []
|
||||
var _ignoreMqtt: Bool = false
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
// The type itself is protecting the reference to its storage via CoW semantics.
|
||||
// This will force a copy to be made of this reference when the first mutation occurs;
|
||||
// hence, it is safe to mark this as `nonisolated(unsafe)`.
|
||||
static nonisolated(unsafe) let defaultInstance = _StorageClass()
|
||||
#else
|
||||
static let defaultInstance = _StorageClass()
|
||||
#endif
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_usePreset = source._usePreset
|
||||
_modemPreset = source._modemPreset
|
||||
_bandwidth = source._bandwidth
|
||||
_spreadFactor = source._spreadFactor
|
||||
_codingRate = source._codingRate
|
||||
_frequencyOffset = source._frequencyOffset
|
||||
_region = source._region
|
||||
_hopLimit = source._hopLimit
|
||||
_txEnabled = source._txEnabled
|
||||
_txPower = source._txPower
|
||||
_channelNum = source._channelNum
|
||||
_overrideDutyCycle = source._overrideDutyCycle
|
||||
_sx126XRxBoostedGain = source._sx126XRxBoostedGain
|
||||
_overrideFrequency = source._overrideFrequency
|
||||
_paFanDisabled = source._paFanDisabled
|
||||
_ignoreIncoming = source._ignoreIncoming
|
||||
_ignoreMqtt = source._ignoreMqtt
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &self.usePreset) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &self.modemPreset) }()
|
||||
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.bandwidth) }()
|
||||
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.spreadFactor) }()
|
||||
case 5: try { try decoder.decodeSingularUInt32Field(value: &self.codingRate) }()
|
||||
case 6: try { try decoder.decodeSingularFloatField(value: &self.frequencyOffset) }()
|
||||
case 7: try { try decoder.decodeSingularEnumField(value: &self.region) }()
|
||||
case 8: try { try decoder.decodeSingularUInt32Field(value: &self.hopLimit) }()
|
||||
case 9: try { try decoder.decodeSingularBoolField(value: &self.txEnabled) }()
|
||||
case 10: try { try decoder.decodeSingularInt32Field(value: &self.txPower) }()
|
||||
case 11: try { try decoder.decodeSingularUInt32Field(value: &self.channelNum) }()
|
||||
case 12: try { try decoder.decodeSingularBoolField(value: &self.overrideDutyCycle) }()
|
||||
case 13: try { try decoder.decodeSingularBoolField(value: &self.sx126XRxBoostedGain) }()
|
||||
case 14: try { try decoder.decodeSingularFloatField(value: &self.overrideFrequency) }()
|
||||
case 103: try { try decoder.decodeRepeatedUInt32Field(value: &self.ignoreIncoming) }()
|
||||
case 104: try { try decoder.decodeSingularBoolField(value: &self.ignoreMqtt) }()
|
||||
default: break
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &_storage._usePreset) }()
|
||||
case 2: try { try decoder.decodeSingularEnumField(value: &_storage._modemPreset) }()
|
||||
case 3: try { try decoder.decodeSingularUInt32Field(value: &_storage._bandwidth) }()
|
||||
case 4: try { try decoder.decodeSingularUInt32Field(value: &_storage._spreadFactor) }()
|
||||
case 5: try { try decoder.decodeSingularUInt32Field(value: &_storage._codingRate) }()
|
||||
case 6: try { try decoder.decodeSingularFloatField(value: &_storage._frequencyOffset) }()
|
||||
case 7: try { try decoder.decodeSingularEnumField(value: &_storage._region) }()
|
||||
case 8: try { try decoder.decodeSingularUInt32Field(value: &_storage._hopLimit) }()
|
||||
case 9: try { try decoder.decodeSingularBoolField(value: &_storage._txEnabled) }()
|
||||
case 10: try { try decoder.decodeSingularInt32Field(value: &_storage._txPower) }()
|
||||
case 11: try { try decoder.decodeSingularUInt32Field(value: &_storage._channelNum) }()
|
||||
case 12: try { try decoder.decodeSingularBoolField(value: &_storage._overrideDutyCycle) }()
|
||||
case 13: try { try decoder.decodeSingularBoolField(value: &_storage._sx126XRxBoostedGain) }()
|
||||
case 14: try { try decoder.decodeSingularFloatField(value: &_storage._overrideFrequency) }()
|
||||
case 15: try { try decoder.decodeSingularBoolField(value: &_storage._paFanDisabled) }()
|
||||
case 103: try { try decoder.decodeRepeatedUInt32Field(value: &_storage._ignoreIncoming) }()
|
||||
case 104: try { try decoder.decodeSingularBoolField(value: &_storage._ignoreMqtt) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.usePreset != false {
|
||||
try visitor.visitSingularBoolField(value: self.usePreset, fieldNumber: 1)
|
||||
}
|
||||
if self.modemPreset != .longFast {
|
||||
try visitor.visitSingularEnumField(value: self.modemPreset, fieldNumber: 2)
|
||||
}
|
||||
if self.bandwidth != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.bandwidth, fieldNumber: 3)
|
||||
}
|
||||
if self.spreadFactor != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.spreadFactor, fieldNumber: 4)
|
||||
}
|
||||
if self.codingRate != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.codingRate, fieldNumber: 5)
|
||||
}
|
||||
if self.frequencyOffset != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.frequencyOffset, fieldNumber: 6)
|
||||
}
|
||||
if self.region != .unset {
|
||||
try visitor.visitSingularEnumField(value: self.region, fieldNumber: 7)
|
||||
}
|
||||
if self.hopLimit != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.hopLimit, fieldNumber: 8)
|
||||
}
|
||||
if self.txEnabled != false {
|
||||
try visitor.visitSingularBoolField(value: self.txEnabled, fieldNumber: 9)
|
||||
}
|
||||
if self.txPower != 0 {
|
||||
try visitor.visitSingularInt32Field(value: self.txPower, fieldNumber: 10)
|
||||
}
|
||||
if self.channelNum != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.channelNum, fieldNumber: 11)
|
||||
}
|
||||
if self.overrideDutyCycle != false {
|
||||
try visitor.visitSingularBoolField(value: self.overrideDutyCycle, fieldNumber: 12)
|
||||
}
|
||||
if self.sx126XRxBoostedGain != false {
|
||||
try visitor.visitSingularBoolField(value: self.sx126XRxBoostedGain, fieldNumber: 13)
|
||||
}
|
||||
if self.overrideFrequency != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.overrideFrequency, fieldNumber: 14)
|
||||
}
|
||||
if !self.ignoreIncoming.isEmpty {
|
||||
try visitor.visitPackedUInt32Field(value: self.ignoreIncoming, fieldNumber: 103)
|
||||
}
|
||||
if self.ignoreMqtt != false {
|
||||
try visitor.visitSingularBoolField(value: self.ignoreMqtt, fieldNumber: 104)
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if _storage._usePreset != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._usePreset, fieldNumber: 1)
|
||||
}
|
||||
if _storage._modemPreset != .longFast {
|
||||
try visitor.visitSingularEnumField(value: _storage._modemPreset, fieldNumber: 2)
|
||||
}
|
||||
if _storage._bandwidth != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._bandwidth, fieldNumber: 3)
|
||||
}
|
||||
if _storage._spreadFactor != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._spreadFactor, fieldNumber: 4)
|
||||
}
|
||||
if _storage._codingRate != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._codingRate, fieldNumber: 5)
|
||||
}
|
||||
if _storage._frequencyOffset != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._frequencyOffset, fieldNumber: 6)
|
||||
}
|
||||
if _storage._region != .unset {
|
||||
try visitor.visitSingularEnumField(value: _storage._region, fieldNumber: 7)
|
||||
}
|
||||
if _storage._hopLimit != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._hopLimit, fieldNumber: 8)
|
||||
}
|
||||
if _storage._txEnabled != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._txEnabled, fieldNumber: 9)
|
||||
}
|
||||
if _storage._txPower != 0 {
|
||||
try visitor.visitSingularInt32Field(value: _storage._txPower, fieldNumber: 10)
|
||||
}
|
||||
if _storage._channelNum != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._channelNum, fieldNumber: 11)
|
||||
}
|
||||
if _storage._overrideDutyCycle != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._overrideDutyCycle, fieldNumber: 12)
|
||||
}
|
||||
if _storage._sx126XRxBoostedGain != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._sx126XRxBoostedGain, fieldNumber: 13)
|
||||
}
|
||||
if _storage._overrideFrequency != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._overrideFrequency, fieldNumber: 14)
|
||||
}
|
||||
if _storage._paFanDisabled != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._paFanDisabled, fieldNumber: 15)
|
||||
}
|
||||
if !_storage._ignoreIncoming.isEmpty {
|
||||
try visitor.visitPackedUInt32Field(value: _storage._ignoreIncoming, fieldNumber: 103)
|
||||
}
|
||||
if _storage._ignoreMqtt != false {
|
||||
try visitor.visitSingularBoolField(value: _storage._ignoreMqtt, fieldNumber: 104)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: Config.LoRaConfig, rhs: Config.LoRaConfig) -> Bool {
|
||||
if lhs.usePreset != rhs.usePreset {return false}
|
||||
if lhs.modemPreset != rhs.modemPreset {return false}
|
||||
if lhs.bandwidth != rhs.bandwidth {return false}
|
||||
if lhs.spreadFactor != rhs.spreadFactor {return false}
|
||||
if lhs.codingRate != rhs.codingRate {return false}
|
||||
if lhs.frequencyOffset != rhs.frequencyOffset {return false}
|
||||
if lhs.region != rhs.region {return false}
|
||||
if lhs.hopLimit != rhs.hopLimit {return false}
|
||||
if lhs.txEnabled != rhs.txEnabled {return false}
|
||||
if lhs.txPower != rhs.txPower {return false}
|
||||
if lhs.channelNum != rhs.channelNum {return false}
|
||||
if lhs.overrideDutyCycle != rhs.overrideDutyCycle {return false}
|
||||
if lhs.sx126XRxBoostedGain != rhs.sx126XRxBoostedGain {return false}
|
||||
if lhs.overrideFrequency != rhs.overrideFrequency {return false}
|
||||
if lhs.ignoreIncoming != rhs.ignoreIncoming {return false}
|
||||
if lhs.ignoreMqtt != rhs.ignoreMqtt {return false}
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._usePreset != rhs_storage._usePreset {return false}
|
||||
if _storage._modemPreset != rhs_storage._modemPreset {return false}
|
||||
if _storage._bandwidth != rhs_storage._bandwidth {return false}
|
||||
if _storage._spreadFactor != rhs_storage._spreadFactor {return false}
|
||||
if _storage._codingRate != rhs_storage._codingRate {return false}
|
||||
if _storage._frequencyOffset != rhs_storage._frequencyOffset {return false}
|
||||
if _storage._region != rhs_storage._region {return false}
|
||||
if _storage._hopLimit != rhs_storage._hopLimit {return false}
|
||||
if _storage._txEnabled != rhs_storage._txEnabled {return false}
|
||||
if _storage._txPower != rhs_storage._txPower {return false}
|
||||
if _storage._channelNum != rhs_storage._channelNum {return false}
|
||||
if _storage._overrideDutyCycle != rhs_storage._overrideDutyCycle {return false}
|
||||
if _storage._sx126XRxBoostedGain != rhs_storage._sx126XRxBoostedGain {return false}
|
||||
if _storage._overrideFrequency != rhs_storage._overrideFrequency {return false}
|
||||
if _storage._paFanDisabled != rhs_storage._paFanDisabled {return false}
|
||||
if _storage._ignoreIncoming != rhs_storage._ignoreIncoming {return false}
|
||||
if _storage._ignoreMqtt != rhs_storage._ignoreMqtt {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2165,26 +2165,20 @@ public struct FromRadio {
|
|||
///
|
||||
/// The packet id, used to allow the phone to request missing read packets from the FIFO,
|
||||
/// see our bluetooth docs
|
||||
public var id: UInt32 {
|
||||
get {return _storage._id}
|
||||
set {_uniqueStorage()._id = newValue}
|
||||
}
|
||||
public var id: UInt32 = 0
|
||||
|
||||
///
|
||||
/// Log levels, chosen to match python logging conventions.
|
||||
public var payloadVariant: OneOf_PayloadVariant? {
|
||||
get {return _storage._payloadVariant}
|
||||
set {_uniqueStorage()._payloadVariant = newValue}
|
||||
}
|
||||
public var payloadVariant: FromRadio.OneOf_PayloadVariant? = nil
|
||||
|
||||
///
|
||||
/// Log levels, chosen to match python logging conventions.
|
||||
public var packet: MeshPacket {
|
||||
get {
|
||||
if case .packet(let v)? = _storage._payloadVariant {return v}
|
||||
if case .packet(let v)? = payloadVariant {return v}
|
||||
return MeshPacket()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .packet(newValue)}
|
||||
set {payloadVariant = .packet(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -2192,10 +2186,10 @@ public struct FromRadio {
|
|||
/// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps.
|
||||
public var myInfo: MyNodeInfo {
|
||||
get {
|
||||
if case .myInfo(let v)? = _storage._payloadVariant {return v}
|
||||
if case .myInfo(let v)? = payloadVariant {return v}
|
||||
return MyNodeInfo()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .myInfo(newValue)}
|
||||
set {payloadVariant = .myInfo(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -2203,30 +2197,30 @@ public struct FromRadio {
|
|||
/// starts over with the first node in our DB
|
||||
public var nodeInfo: NodeInfo {
|
||||
get {
|
||||
if case .nodeInfo(let v)? = _storage._payloadVariant {return v}
|
||||
if case .nodeInfo(let v)? = payloadVariant {return v}
|
||||
return NodeInfo()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .nodeInfo(newValue)}
|
||||
set {payloadVariant = .nodeInfo(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Include a part of the config (was: RadioConfig radio)
|
||||
public var config: Config {
|
||||
get {
|
||||
if case .config(let v)? = _storage._payloadVariant {return v}
|
||||
if case .config(let v)? = payloadVariant {return v}
|
||||
return Config()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .config(newValue)}
|
||||
set {payloadVariant = .config(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set to send debug console output over our protobuf stream
|
||||
public var logRecord: LogRecord {
|
||||
get {
|
||||
if case .logRecord(let v)? = _storage._payloadVariant {return v}
|
||||
if case .logRecord(let v)? = payloadVariant {return v}
|
||||
return LogRecord()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .logRecord(newValue)}
|
||||
set {payloadVariant = .logRecord(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -2236,10 +2230,10 @@ public struct FromRadio {
|
|||
/// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps.
|
||||
public var configCompleteID: UInt32 {
|
||||
get {
|
||||
if case .configCompleteID(let v)? = _storage._payloadVariant {return v}
|
||||
if case .configCompleteID(let v)? = payloadVariant {return v}
|
||||
return 0
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .configCompleteID(newValue)}
|
||||
set {payloadVariant = .configCompleteID(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -2249,80 +2243,80 @@ public struct FromRadio {
|
|||
/// NOTE: This ID must not change - to keep (minimal) compatibility with <1.2 version of android apps.
|
||||
public var rebooted: Bool {
|
||||
get {
|
||||
if case .rebooted(let v)? = _storage._payloadVariant {return v}
|
||||
if case .rebooted(let v)? = payloadVariant {return v}
|
||||
return false
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .rebooted(newValue)}
|
||||
set {payloadVariant = .rebooted(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Include module config
|
||||
public var moduleConfig: ModuleConfig {
|
||||
get {
|
||||
if case .moduleConfig(let v)? = _storage._payloadVariant {return v}
|
||||
if case .moduleConfig(let v)? = payloadVariant {return v}
|
||||
return ModuleConfig()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .moduleConfig(newValue)}
|
||||
set {payloadVariant = .moduleConfig(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// One packet is sent for each channel
|
||||
public var channel: Channel {
|
||||
get {
|
||||
if case .channel(let v)? = _storage._payloadVariant {return v}
|
||||
if case .channel(let v)? = payloadVariant {return v}
|
||||
return Channel()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .channel(newValue)}
|
||||
set {payloadVariant = .channel(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Queue status info
|
||||
public var queueStatus: QueueStatus {
|
||||
get {
|
||||
if case .queueStatus(let v)? = _storage._payloadVariant {return v}
|
||||
if case .queueStatus(let v)? = payloadVariant {return v}
|
||||
return QueueStatus()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .queueStatus(newValue)}
|
||||
set {payloadVariant = .queueStatus(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// File Transfer Chunk
|
||||
public var xmodemPacket: XModem {
|
||||
get {
|
||||
if case .xmodemPacket(let v)? = _storage._payloadVariant {return v}
|
||||
if case .xmodemPacket(let v)? = payloadVariant {return v}
|
||||
return XModem()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .xmodemPacket(newValue)}
|
||||
set {payloadVariant = .xmodemPacket(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// Device metadata message
|
||||
public var metadata: DeviceMetadata {
|
||||
get {
|
||||
if case .metadata(let v)? = _storage._payloadVariant {return v}
|
||||
if case .metadata(let v)? = payloadVariant {return v}
|
||||
return DeviceMetadata()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .metadata(newValue)}
|
||||
set {payloadVariant = .metadata(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT)
|
||||
public var mqttClientProxyMessage: MqttClientProxyMessage {
|
||||
get {
|
||||
if case .mqttClientProxyMessage(let v)? = _storage._payloadVariant {return v}
|
||||
if case .mqttClientProxyMessage(let v)? = payloadVariant {return v}
|
||||
return MqttClientProxyMessage()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .mqttClientProxyMessage(newValue)}
|
||||
set {payloadVariant = .mqttClientProxyMessage(newValue)}
|
||||
}
|
||||
|
||||
///
|
||||
/// File system manifest messages
|
||||
public var fileInfo: FileInfo {
|
||||
get {
|
||||
if case .fileInfo(let v)? = _storage._payloadVariant {return v}
|
||||
if case .fileInfo(let v)? = payloadVariant {return v}
|
||||
return FileInfo()
|
||||
}
|
||||
set {_uniqueStorage()._payloadVariant = .fileInfo(newValue)}
|
||||
set {payloadVariant = .fileInfo(newValue)}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
|
@ -2450,8 +2444,6 @@ public struct FromRadio {
|
|||
}
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -4303,305 +4295,263 @@ extension FromRadio: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
|
|||
15: .same(proto: "fileInfo"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _id: UInt32 = 0
|
||||
var _payloadVariant: FromRadio.OneOf_PayloadVariant?
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
// The type itself is protecting the reference to its storage via CoW semantics.
|
||||
// This will force a copy to be made of this reference when the first mutation occurs;
|
||||
// hence, it is safe to mark this as `nonisolated(unsafe)`.
|
||||
static nonisolated(unsafe) let defaultInstance = _StorageClass()
|
||||
#else
|
||||
static let defaultInstance = _StorageClass()
|
||||
#endif
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_id = source._id
|
||||
_payloadVariant = source._payloadVariant
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularUInt32Field(value: &_storage._id) }()
|
||||
case 2: try {
|
||||
var v: MeshPacket?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .packet(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .packet(v)
|
||||
}
|
||||
}()
|
||||
case 3: try {
|
||||
var v: MyNodeInfo?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .myInfo(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .myInfo(v)
|
||||
}
|
||||
}()
|
||||
case 4: try {
|
||||
var v: NodeInfo?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .nodeInfo(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .nodeInfo(v)
|
||||
}
|
||||
}()
|
||||
case 5: try {
|
||||
var v: Config?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .config(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .config(v)
|
||||
}
|
||||
}()
|
||||
case 6: try {
|
||||
var v: LogRecord?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .logRecord(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .logRecord(v)
|
||||
}
|
||||
}()
|
||||
case 7: try {
|
||||
var v: UInt32?
|
||||
try decoder.decodeSingularUInt32Field(value: &v)
|
||||
if let v = v {
|
||||
if _storage._payloadVariant != nil {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .configCompleteID(v)
|
||||
}
|
||||
}()
|
||||
case 8: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if _storage._payloadVariant != nil {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .rebooted(v)
|
||||
}
|
||||
}()
|
||||
case 9: try {
|
||||
var v: ModuleConfig?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .moduleConfig(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .moduleConfig(v)
|
||||
}
|
||||
}()
|
||||
case 10: try {
|
||||
var v: Channel?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .channel(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .channel(v)
|
||||
}
|
||||
}()
|
||||
case 11: try {
|
||||
var v: QueueStatus?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .queueStatus(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .queueStatus(v)
|
||||
}
|
||||
}()
|
||||
case 12: try {
|
||||
var v: XModem?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .xmodemPacket(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .xmodemPacket(v)
|
||||
}
|
||||
}()
|
||||
case 13: try {
|
||||
var v: DeviceMetadata?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .metadata(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .metadata(v)
|
||||
}
|
||||
}()
|
||||
case 14: try {
|
||||
var v: MqttClientProxyMessage?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .mqttClientProxyMessage(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .mqttClientProxyMessage(v)
|
||||
}
|
||||
}()
|
||||
case 15: try {
|
||||
var v: FileInfo?
|
||||
var hadOneofValue = false
|
||||
if let current = _storage._payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .fileInfo(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
_storage._payloadVariant = .fileInfo(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularUInt32Field(value: &self.id) }()
|
||||
case 2: try {
|
||||
var v: MeshPacket?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .packet(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .packet(v)
|
||||
}
|
||||
}()
|
||||
case 3: try {
|
||||
var v: MyNodeInfo?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .myInfo(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .myInfo(v)
|
||||
}
|
||||
}()
|
||||
case 4: try {
|
||||
var v: NodeInfo?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .nodeInfo(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .nodeInfo(v)
|
||||
}
|
||||
}()
|
||||
case 5: try {
|
||||
var v: Config?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .config(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .config(v)
|
||||
}
|
||||
}()
|
||||
case 6: try {
|
||||
var v: LogRecord?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .logRecord(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .logRecord(v)
|
||||
}
|
||||
}()
|
||||
case 7: try {
|
||||
var v: UInt32?
|
||||
try decoder.decodeSingularUInt32Field(value: &v)
|
||||
if let v = v {
|
||||
if self.payloadVariant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .configCompleteID(v)
|
||||
}
|
||||
}()
|
||||
case 8: try {
|
||||
var v: Bool?
|
||||
try decoder.decodeSingularBoolField(value: &v)
|
||||
if let v = v {
|
||||
if self.payloadVariant != nil {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .rebooted(v)
|
||||
}
|
||||
}()
|
||||
case 9: try {
|
||||
var v: ModuleConfig?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .moduleConfig(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .moduleConfig(v)
|
||||
}
|
||||
}()
|
||||
case 10: try {
|
||||
var v: Channel?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .channel(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .channel(v)
|
||||
}
|
||||
}()
|
||||
case 11: try {
|
||||
var v: QueueStatus?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .queueStatus(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .queueStatus(v)
|
||||
}
|
||||
}()
|
||||
case 12: try {
|
||||
var v: XModem?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .xmodemPacket(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .xmodemPacket(v)
|
||||
}
|
||||
}()
|
||||
case 13: try {
|
||||
var v: DeviceMetadata?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .metadata(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .metadata(v)
|
||||
}
|
||||
}()
|
||||
case 14: try {
|
||||
var v: MqttClientProxyMessage?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .mqttClientProxyMessage(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .mqttClientProxyMessage(v)
|
||||
}
|
||||
}()
|
||||
case 15: try {
|
||||
var v: FileInfo?
|
||||
var hadOneofValue = false
|
||||
if let current = self.payloadVariant {
|
||||
hadOneofValue = true
|
||||
if case .fileInfo(let m) = current {v = m}
|
||||
}
|
||||
try decoder.decodeSingularMessageField(value: &v)
|
||||
if let v = v {
|
||||
if hadOneofValue {try decoder.handleConflictingOneOf()}
|
||||
self.payloadVariant = .fileInfo(v)
|
||||
}
|
||||
}()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if _storage._id != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._id, fieldNumber: 1)
|
||||
}
|
||||
switch _storage._payloadVariant {
|
||||
case .packet?: try {
|
||||
guard case .packet(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
}()
|
||||
case .myInfo?: try {
|
||||
guard case .myInfo(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}()
|
||||
case .nodeInfo?: try {
|
||||
guard case .nodeInfo(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
}()
|
||||
case .config?: try {
|
||||
guard case .config(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}()
|
||||
case .logRecord?: try {
|
||||
guard case .logRecord(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}()
|
||||
case .configCompleteID?: try {
|
||||
guard case .configCompleteID(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 7)
|
||||
}()
|
||||
case .rebooted?: try {
|
||||
guard case .rebooted(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 8)
|
||||
}()
|
||||
case .moduleConfig?: try {
|
||||
guard case .moduleConfig(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 9)
|
||||
}()
|
||||
case .channel?: try {
|
||||
guard case .channel(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 10)
|
||||
}()
|
||||
case .queueStatus?: try {
|
||||
guard case .queueStatus(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 11)
|
||||
}()
|
||||
case .xmodemPacket?: try {
|
||||
guard case .xmodemPacket(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 12)
|
||||
}()
|
||||
case .metadata?: try {
|
||||
guard case .metadata(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 13)
|
||||
}()
|
||||
case .mqttClientProxyMessage?: try {
|
||||
guard case .mqttClientProxyMessage(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 14)
|
||||
}()
|
||||
case .fileInfo?: try {
|
||||
guard case .fileInfo(let v)? = _storage._payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 15)
|
||||
}()
|
||||
case nil: break
|
||||
}
|
||||
// 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.id != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.id, fieldNumber: 1)
|
||||
}
|
||||
switch self.payloadVariant {
|
||||
case .packet?: try {
|
||||
guard case .packet(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
}()
|
||||
case .myInfo?: try {
|
||||
guard case .myInfo(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}()
|
||||
case .nodeInfo?: try {
|
||||
guard case .nodeInfo(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
}()
|
||||
case .config?: try {
|
||||
guard case .config(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}()
|
||||
case .logRecord?: try {
|
||||
guard case .logRecord(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}()
|
||||
case .configCompleteID?: try {
|
||||
guard case .configCompleteID(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 7)
|
||||
}()
|
||||
case .rebooted?: try {
|
||||
guard case .rebooted(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 8)
|
||||
}()
|
||||
case .moduleConfig?: try {
|
||||
guard case .moduleConfig(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 9)
|
||||
}()
|
||||
case .channel?: try {
|
||||
guard case .channel(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 10)
|
||||
}()
|
||||
case .queueStatus?: try {
|
||||
guard case .queueStatus(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 11)
|
||||
}()
|
||||
case .xmodemPacket?: try {
|
||||
guard case .xmodemPacket(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 12)
|
||||
}()
|
||||
case .metadata?: try {
|
||||
guard case .metadata(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 13)
|
||||
}()
|
||||
case .mqttClientProxyMessage?: try {
|
||||
guard case .mqttClientProxyMessage(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 14)
|
||||
}()
|
||||
case .fileInfo?: try {
|
||||
guard case .fileInfo(let v)? = self.payloadVariant else { preconditionFailure() }
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 15)
|
||||
}()
|
||||
case nil: break
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: FromRadio, rhs: FromRadio) -> Bool {
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._id != rhs_storage._id {return false}
|
||||
if _storage._payloadVariant != rhs_storage._payloadVariant {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.id != rhs.id {return false}
|
||||
if lhs.payloadVariant != rhs.payloadVariant {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -758,6 +758,9 @@ public struct ModuleConfig {
|
|||
|
||||
/// NMEA messages specifically tailored for CalTopo
|
||||
case caltopo // = 5
|
||||
|
||||
/// Ecowitt WS85 weather station
|
||||
case ws85 // = 6
|
||||
case UNRECOGNIZED(Int)
|
||||
|
||||
public init() {
|
||||
|
|
@ -772,6 +775,7 @@ public struct ModuleConfig {
|
|||
case 3: self = .textmsg
|
||||
case 4: self = .nmea
|
||||
case 5: self = .caltopo
|
||||
case 6: self = .ws85
|
||||
default: self = .UNRECOGNIZED(rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -784,6 +788,7 @@ public struct ModuleConfig {
|
|||
case .textmsg: return 3
|
||||
case .nmea: return 4
|
||||
case .caltopo: return 5
|
||||
case .ws85: return 6
|
||||
case .UNRECOGNIZED(let i): return i
|
||||
}
|
||||
}
|
||||
|
|
@ -1208,6 +1213,7 @@ extension ModuleConfig.SerialConfig.Serial_Mode: CaseIterable {
|
|||
.textmsg,
|
||||
.nmea,
|
||||
.caltopo,
|
||||
.ws85,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -2081,6 +2087,7 @@ extension ModuleConfig.SerialConfig.Serial_Mode: SwiftProtobuf._ProtoNameProvidi
|
|||
3: .same(proto: "TEXTMSG"),
|
||||
4: .same(proto: "NMEA"),
|
||||
5: .same(proto: "CALTOPO"),
|
||||
6: .same(proto: "WS85"),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,69 +277,130 @@ public struct EnvironmentMetrics {
|
|||
|
||||
///
|
||||
/// Temperature measured
|
||||
public var temperature: Float = 0
|
||||
public var temperature: Float {
|
||||
get {return _storage._temperature}
|
||||
set {_uniqueStorage()._temperature = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Relative humidity percent measured
|
||||
public var relativeHumidity: Float = 0
|
||||
public var relativeHumidity: Float {
|
||||
get {return _storage._relativeHumidity}
|
||||
set {_uniqueStorage()._relativeHumidity = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Barometric pressure in hPA measured
|
||||
public var barometricPressure: Float = 0
|
||||
public var barometricPressure: Float {
|
||||
get {return _storage._barometricPressure}
|
||||
set {_uniqueStorage()._barometricPressure = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Gas resistance in MOhm measured
|
||||
public var gasResistance: Float = 0
|
||||
public var gasResistance: Float {
|
||||
get {return _storage._gasResistance}
|
||||
set {_uniqueStorage()._gasResistance = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Voltage measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x)
|
||||
public var voltage: Float = 0
|
||||
public var voltage: Float {
|
||||
get {return _storage._voltage}
|
||||
set {_uniqueStorage()._voltage = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Current measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x)
|
||||
public var current: Float = 0
|
||||
public var current: Float {
|
||||
get {return _storage._current}
|
||||
set {_uniqueStorage()._current = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// relative scale IAQ value as measured by Bosch BME680 . value 0-500.
|
||||
/// Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here.
|
||||
public var iaq: UInt32 = 0
|
||||
public var iaq: UInt32 {
|
||||
get {return _storage._iaq}
|
||||
set {_uniqueStorage()._iaq = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm.
|
||||
public var distance: Float = 0
|
||||
public var distance: Float {
|
||||
get {return _storage._distance}
|
||||
set {_uniqueStorage()._distance = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// VEML7700 high accuracy ambient light(Lux) digital 16-bit resolution sensor.
|
||||
public var lux: Float = 0
|
||||
public var lux: Float {
|
||||
get {return _storage._lux}
|
||||
set {_uniqueStorage()._lux = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// VEML7700 high accuracy white light(irradiance) not calibrated digital 16-bit resolution sensor.
|
||||
public var whiteLux: Float = 0
|
||||
public var whiteLux: Float {
|
||||
get {return _storage._whiteLux}
|
||||
set {_uniqueStorage()._whiteLux = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Infrared lux
|
||||
public var irLux: Float = 0
|
||||
public var irLux: Float {
|
||||
get {return _storage._irLux}
|
||||
set {_uniqueStorage()._irLux = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Ultraviolet lux
|
||||
public var uvLux: Float = 0
|
||||
public var uvLux: Float {
|
||||
get {return _storage._uvLux}
|
||||
set {_uniqueStorage()._uvLux = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Wind direction in degrees
|
||||
/// 0 degrees = North, 90 = East, etc...
|
||||
public var windDirection: UInt32 = 0
|
||||
public var windDirection: UInt32 {
|
||||
get {return _storage._windDirection}
|
||||
set {_uniqueStorage()._windDirection = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Wind speed in m/s
|
||||
public var windSpeed: Float = 0
|
||||
public var windSpeed: Float {
|
||||
get {return _storage._windSpeed}
|
||||
set {_uniqueStorage()._windSpeed = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Weight in KG
|
||||
public var weight: Float = 0
|
||||
public var weight: Float {
|
||||
get {return _storage._weight}
|
||||
set {_uniqueStorage()._weight = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Wind gust in m/s
|
||||
public var windGust: Float {
|
||||
get {return _storage._windGust}
|
||||
set {_uniqueStorage()._windGust = newValue}
|
||||
}
|
||||
|
||||
///
|
||||
/// Wind lull in m/s
|
||||
public var windLull: Float {
|
||||
get {return _storage._windLull}
|
||||
set {_uniqueStorage()._windLull = newValue}
|
||||
}
|
||||
|
||||
public var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
public init() {}
|
||||
|
||||
fileprivate var _storage = _StorageClass.defaultInstance
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -678,99 +739,183 @@ extension EnvironmentMetrics: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
|
|||
13: .standard(proto: "wind_direction"),
|
||||
14: .standard(proto: "wind_speed"),
|
||||
15: .same(proto: "weight"),
|
||||
16: .standard(proto: "wind_gust"),
|
||||
17: .standard(proto: "wind_lull"),
|
||||
]
|
||||
|
||||
fileprivate class _StorageClass {
|
||||
var _temperature: Float = 0
|
||||
var _relativeHumidity: Float = 0
|
||||
var _barometricPressure: Float = 0
|
||||
var _gasResistance: Float = 0
|
||||
var _voltage: Float = 0
|
||||
var _current: Float = 0
|
||||
var _iaq: UInt32 = 0
|
||||
var _distance: Float = 0
|
||||
var _lux: Float = 0
|
||||
var _whiteLux: Float = 0
|
||||
var _irLux: Float = 0
|
||||
var _uvLux: Float = 0
|
||||
var _windDirection: UInt32 = 0
|
||||
var _windSpeed: Float = 0
|
||||
var _weight: Float = 0
|
||||
var _windGust: Float = 0
|
||||
var _windLull: Float = 0
|
||||
|
||||
#if swift(>=5.10)
|
||||
// This property is used as the initial default value for new instances of the type.
|
||||
// The type itself is protecting the reference to its storage via CoW semantics.
|
||||
// This will force a copy to be made of this reference when the first mutation occurs;
|
||||
// hence, it is safe to mark this as `nonisolated(unsafe)`.
|
||||
static nonisolated(unsafe) let defaultInstance = _StorageClass()
|
||||
#else
|
||||
static let defaultInstance = _StorageClass()
|
||||
#endif
|
||||
|
||||
private init() {}
|
||||
|
||||
init(copying source: _StorageClass) {
|
||||
_temperature = source._temperature
|
||||
_relativeHumidity = source._relativeHumidity
|
||||
_barometricPressure = source._barometricPressure
|
||||
_gasResistance = source._gasResistance
|
||||
_voltage = source._voltage
|
||||
_current = source._current
|
||||
_iaq = source._iaq
|
||||
_distance = source._distance
|
||||
_lux = source._lux
|
||||
_whiteLux = source._whiteLux
|
||||
_irLux = source._irLux
|
||||
_uvLux = source._uvLux
|
||||
_windDirection = source._windDirection
|
||||
_windSpeed = source._windSpeed
|
||||
_weight = source._weight
|
||||
_windGust = source._windGust
|
||||
_windLull = source._windLull
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate mutating func _uniqueStorage() -> _StorageClass {
|
||||
if !isKnownUniquelyReferenced(&_storage) {
|
||||
_storage = _StorageClass(copying: _storage)
|
||||
}
|
||||
return _storage
|
||||
}
|
||||
|
||||
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularFloatField(value: &self.temperature) }()
|
||||
case 2: try { try decoder.decodeSingularFloatField(value: &self.relativeHumidity) }()
|
||||
case 3: try { try decoder.decodeSingularFloatField(value: &self.barometricPressure) }()
|
||||
case 4: try { try decoder.decodeSingularFloatField(value: &self.gasResistance) }()
|
||||
case 5: try { try decoder.decodeSingularFloatField(value: &self.voltage) }()
|
||||
case 6: try { try decoder.decodeSingularFloatField(value: &self.current) }()
|
||||
case 7: try { try decoder.decodeSingularUInt32Field(value: &self.iaq) }()
|
||||
case 8: try { try decoder.decodeSingularFloatField(value: &self.distance) }()
|
||||
case 9: try { try decoder.decodeSingularFloatField(value: &self.lux) }()
|
||||
case 10: try { try decoder.decodeSingularFloatField(value: &self.whiteLux) }()
|
||||
case 11: try { try decoder.decodeSingularFloatField(value: &self.irLux) }()
|
||||
case 12: try { try decoder.decodeSingularFloatField(value: &self.uvLux) }()
|
||||
case 13: try { try decoder.decodeSingularUInt32Field(value: &self.windDirection) }()
|
||||
case 14: try { try decoder.decodeSingularFloatField(value: &self.windSpeed) }()
|
||||
case 15: try { try decoder.decodeSingularFloatField(value: &self.weight) }()
|
||||
default: break
|
||||
_ = _uniqueStorage()
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularFloatField(value: &_storage._temperature) }()
|
||||
case 2: try { try decoder.decodeSingularFloatField(value: &_storage._relativeHumidity) }()
|
||||
case 3: try { try decoder.decodeSingularFloatField(value: &_storage._barometricPressure) }()
|
||||
case 4: try { try decoder.decodeSingularFloatField(value: &_storage._gasResistance) }()
|
||||
case 5: try { try decoder.decodeSingularFloatField(value: &_storage._voltage) }()
|
||||
case 6: try { try decoder.decodeSingularFloatField(value: &_storage._current) }()
|
||||
case 7: try { try decoder.decodeSingularUInt32Field(value: &_storage._iaq) }()
|
||||
case 8: try { try decoder.decodeSingularFloatField(value: &_storage._distance) }()
|
||||
case 9: try { try decoder.decodeSingularFloatField(value: &_storage._lux) }()
|
||||
case 10: try { try decoder.decodeSingularFloatField(value: &_storage._whiteLux) }()
|
||||
case 11: try { try decoder.decodeSingularFloatField(value: &_storage._irLux) }()
|
||||
case 12: try { try decoder.decodeSingularFloatField(value: &_storage._uvLux) }()
|
||||
case 13: try { try decoder.decodeSingularUInt32Field(value: &_storage._windDirection) }()
|
||||
case 14: try { try decoder.decodeSingularFloatField(value: &_storage._windSpeed) }()
|
||||
case 15: try { try decoder.decodeSingularFloatField(value: &_storage._weight) }()
|
||||
case 16: try { try decoder.decodeSingularFloatField(value: &_storage._windGust) }()
|
||||
case 17: try { try decoder.decodeSingularFloatField(value: &_storage._windLull) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if self.temperature != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.temperature, fieldNumber: 1)
|
||||
}
|
||||
if self.relativeHumidity != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.relativeHumidity, fieldNumber: 2)
|
||||
}
|
||||
if self.barometricPressure != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.barometricPressure, fieldNumber: 3)
|
||||
}
|
||||
if self.gasResistance != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.gasResistance, fieldNumber: 4)
|
||||
}
|
||||
if self.voltage != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.voltage, fieldNumber: 5)
|
||||
}
|
||||
if self.current != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.current, fieldNumber: 6)
|
||||
}
|
||||
if self.iaq != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.iaq, fieldNumber: 7)
|
||||
}
|
||||
if self.distance != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.distance, fieldNumber: 8)
|
||||
}
|
||||
if self.lux != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.lux, fieldNumber: 9)
|
||||
}
|
||||
if self.whiteLux != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.whiteLux, fieldNumber: 10)
|
||||
}
|
||||
if self.irLux != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.irLux, fieldNumber: 11)
|
||||
}
|
||||
if self.uvLux != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.uvLux, fieldNumber: 12)
|
||||
}
|
||||
if self.windDirection != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: self.windDirection, fieldNumber: 13)
|
||||
}
|
||||
if self.windSpeed != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.windSpeed, fieldNumber: 14)
|
||||
}
|
||||
if self.weight != 0 {
|
||||
try visitor.visitSingularFloatField(value: self.weight, fieldNumber: 15)
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if _storage._temperature != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._temperature, fieldNumber: 1)
|
||||
}
|
||||
if _storage._relativeHumidity != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._relativeHumidity, fieldNumber: 2)
|
||||
}
|
||||
if _storage._barometricPressure != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._barometricPressure, fieldNumber: 3)
|
||||
}
|
||||
if _storage._gasResistance != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._gasResistance, fieldNumber: 4)
|
||||
}
|
||||
if _storage._voltage != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._voltage, fieldNumber: 5)
|
||||
}
|
||||
if _storage._current != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._current, fieldNumber: 6)
|
||||
}
|
||||
if _storage._iaq != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._iaq, fieldNumber: 7)
|
||||
}
|
||||
if _storage._distance != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._distance, fieldNumber: 8)
|
||||
}
|
||||
if _storage._lux != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._lux, fieldNumber: 9)
|
||||
}
|
||||
if _storage._whiteLux != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._whiteLux, fieldNumber: 10)
|
||||
}
|
||||
if _storage._irLux != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._irLux, fieldNumber: 11)
|
||||
}
|
||||
if _storage._uvLux != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._uvLux, fieldNumber: 12)
|
||||
}
|
||||
if _storage._windDirection != 0 {
|
||||
try visitor.visitSingularUInt32Field(value: _storage._windDirection, fieldNumber: 13)
|
||||
}
|
||||
if _storage._windSpeed != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._windSpeed, fieldNumber: 14)
|
||||
}
|
||||
if _storage._weight != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._weight, fieldNumber: 15)
|
||||
}
|
||||
if _storage._windGust != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._windGust, fieldNumber: 16)
|
||||
}
|
||||
if _storage._windLull != 0 {
|
||||
try visitor.visitSingularFloatField(value: _storage._windLull, fieldNumber: 17)
|
||||
}
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
public static func ==(lhs: EnvironmentMetrics, rhs: EnvironmentMetrics) -> Bool {
|
||||
if lhs.temperature != rhs.temperature {return false}
|
||||
if lhs.relativeHumidity != rhs.relativeHumidity {return false}
|
||||
if lhs.barometricPressure != rhs.barometricPressure {return false}
|
||||
if lhs.gasResistance != rhs.gasResistance {return false}
|
||||
if lhs.voltage != rhs.voltage {return false}
|
||||
if lhs.current != rhs.current {return false}
|
||||
if lhs.iaq != rhs.iaq {return false}
|
||||
if lhs.distance != rhs.distance {return false}
|
||||
if lhs.lux != rhs.lux {return false}
|
||||
if lhs.whiteLux != rhs.whiteLux {return false}
|
||||
if lhs.irLux != rhs.irLux {return false}
|
||||
if lhs.uvLux != rhs.uvLux {return false}
|
||||
if lhs.windDirection != rhs.windDirection {return false}
|
||||
if lhs.windSpeed != rhs.windSpeed {return false}
|
||||
if lhs.weight != rhs.weight {return false}
|
||||
if lhs._storage !== rhs._storage {
|
||||
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
|
||||
let _storage = _args.0
|
||||
let rhs_storage = _args.1
|
||||
if _storage._temperature != rhs_storage._temperature {return false}
|
||||
if _storage._relativeHumidity != rhs_storage._relativeHumidity {return false}
|
||||
if _storage._barometricPressure != rhs_storage._barometricPressure {return false}
|
||||
if _storage._gasResistance != rhs_storage._gasResistance {return false}
|
||||
if _storage._voltage != rhs_storage._voltage {return false}
|
||||
if _storage._current != rhs_storage._current {return false}
|
||||
if _storage._iaq != rhs_storage._iaq {return false}
|
||||
if _storage._distance != rhs_storage._distance {return false}
|
||||
if _storage._lux != rhs_storage._lux {return false}
|
||||
if _storage._whiteLux != rhs_storage._whiteLux {return false}
|
||||
if _storage._irLux != rhs_storage._irLux {return false}
|
||||
if _storage._uvLux != rhs_storage._uvLux {return false}
|
||||
if _storage._windDirection != rhs_storage._windDirection {return false}
|
||||
if _storage._windSpeed != rhs_storage._windSpeed {return false}
|
||||
if _storage._weight != rhs_storage._weight {return false}
|
||||
if _storage._windGust != rhs_storage._windGust {return false}
|
||||
if _storage._windLull != rhs_storage._windLull {return false}
|
||||
return true
|
||||
}
|
||||
if !storagesAreEqual {return false}
|
||||
}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit d191975ebc572527c6d9eec48d5b0a1e3331999f
|
||||
Subproject commit 10494bf328ac051fc4add9ddeb677eebf337b531
|
||||
Loading…
Add table
Add a link
Reference in a new issue