mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Additional fixes
This commit is contained in:
parent
add5d3f9e5
commit
f78f6ed20e
8 changed files with 100 additions and 226 deletions
|
|
@ -49,7 +49,6 @@
|
|||
233E99C52D84A0B600CC3A77 /* CompactWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233E99C42D84A0B600CC3A77 /* CompactWidget.swift */; };
|
||||
233E99C72D84A70900CC3A77 /* SoilCompactWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233E99C62D84A70900CC3A77 /* SoilCompactWidgets.swift */; };
|
||||
233E99CB2D85AAA900CC3A77 /* RainfallCompactWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233E99CA2D85AAA900CC3A77 /* RainfallCompactWidget.swift */; };
|
||||
2344A2AB2D66974300170A77 /* ManagedAttributePropertyWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2344A2AA2D66973D00170A77 /* ManagedAttributePropertyWrapper.swift */; };
|
||||
2344A2B12D68DFF800170A77 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25C49D8F2C471AEA0024FBD1 /* Constants.swift */; };
|
||||
2346A7192E2FB9A300CB9239 /* SerialConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2346A7182E2FB9A300CB9239 /* SerialConnection.swift */; };
|
||||
2346A71D2E2FB9C500CB9239 /* SerialTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2346A71C2E2FB9C500CB9239 /* SerialTransport.swift */; };
|
||||
|
|
@ -407,9 +406,6 @@
|
|||
233E99C42D84A0B600CC3A77 /* CompactWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactWidget.swift; sourceTree = "<group>"; };
|
||||
233E99C62D84A70900CC3A77 /* SoilCompactWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoilCompactWidgets.swift; sourceTree = "<group>"; };
|
||||
233E99CA2D85AAA900CC3A77 /* RainfallCompactWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RainfallCompactWidget.swift; sourceTree = "<group>"; };
|
||||
2344A2AA2D66973D00170A77 /* ManagedAttributePropertyWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedAttributePropertyWrapper.swift; sourceTree = "<group>"; };
|
||||
2344A2AD2D6697A700170A77 /* TelemetryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TelemetryEntity+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
2344A2AE2D6697A700170A77 /* TelemetryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TelemetryEntity+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
2346A7182E2FB9A300CB9239 /* SerialConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerialConnection.swift; sourceTree = "<group>"; };
|
||||
2346A71C2E2FB9C500CB9239 /* SerialTransport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerialTransport.swift; sourceTree = "<group>"; };
|
||||
2349A0492EAE4DA30060A581 /* ManualConnectionList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualConnectionList.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -822,15 +818,6 @@
|
|||
path = "Compact Widgets";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2344A2AC2D66978000170A77 /* CoreData */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2344A2AD2D6697A700170A77 /* TelemetryEntity+CoreDataClass.swift */,
|
||||
2344A2AE2D6697A700170A77 /* TelemetryEntity+CoreDataProperties.swift */,
|
||||
);
|
||||
path = CoreData;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
237AEB8D2E1FE120003B7CE3 /* Accessory */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1013,7 +1000,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
108FFECC2DD4005600BFAA81 /* NodeInfoEntityToNodeInfo.swift */,
|
||||
2344A2AA2D66973D00170A77 /* ManagedAttributePropertyWrapper.swift */,
|
||||
DD58C5F12919AD3C00D5BEFB /* ChannelEntityExtension.swift */,
|
||||
6DEDA55B2A9592F900321D2E /* MessageEntityExtension.swift */,
|
||||
DD007BAD2AA4E91200F5FA12 /* MyInfoEntityExtension.swift */,
|
||||
|
|
@ -1337,7 +1323,6 @@
|
|||
D8D66A4063FE4E868CD30D3C /* TraceRouteModels.swift */,
|
||||
918722D2C1474B2D99ED01DC /* UserEntity.swift */,
|
||||
E98797BFD67F449B9ACCEDA7 /* WaypointEntity.swift */,
|
||||
2344A2AC2D66978000170A77 /* CoreData */,
|
||||
231B3F1E2D0879BC0069A07D /* Metrics Visualization */,
|
||||
DD23A50E26FD1B4400D9B90C /* PeripheralModel.swift */,
|
||||
);
|
||||
|
|
@ -1987,7 +1972,6 @@
|
|||
DD6F657B2C6EC2900053C113 /* LockLegend.swift in Sources */,
|
||||
DD97E96628EFD9820056DDA4 /* MeshtasticLogo.swift in Sources */,
|
||||
DDAB580D2B0DAA9E00147258 /* Routes.swift in Sources */,
|
||||
2344A2AB2D66974300170A77 /* ManagedAttributePropertyWrapper.swift in Sources */,
|
||||
BCB613832C672A2600485544 /* MessageChannelIntent.swift in Sources */,
|
||||
D93068D52B812B700066FBC8 /* MessageDestination.swift in Sources */,
|
||||
BC10380F2DD4334400B00BFA /* AddContactIntent.swift in Sources */,
|
||||
|
|
@ -1996,9 +1980,7 @@
|
|||
2346A71D2E2FB9C500CB9239 /* SerialTransport.swift in Sources */,
|
||||
BCDDFA9A2DBB180D0065189C /* ScrollToBottomButton.swift in Sources */,
|
||||
DDC4C9FF2A8D982900CE201C /* DetectionSensorConfig.swift in Sources */,
|
||||
2344A2AF2D6697A700170A77 /* TelemetryEntity+CoreDataClass.swift in Sources */,
|
||||
2349A04A2EAE4DA30060A581 /* ManualConnectionList.swift in Sources */,
|
||||
2344A2B02D6697A700170A77 /* TelemetryEntity+CoreDataProperties.swift in Sources */,
|
||||
D9C983A22B79D1A600BDBE6A /* RequestPositionButton.swift in Sources */,
|
||||
237AEB8F2E1FE457003B7CE3 /* Transport.swift in Sources */,
|
||||
DDDB26442AAC0206003AFCB7 /* NodeDetail.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -661,6 +661,7 @@ extension AccessoryManager {
|
|||
|
||||
let traceRoute = TraceRouteEntity()
|
||||
context.insert(traceRoute)
|
||||
traceRoute.sent = true
|
||||
// TODO: Not sure what's going on here. We always have a fromNodeNum
|
||||
let nodes = FetchDescriptor<NodeInfoEntity>(predicate: #Predicate { $0.num == destNum || $0.num == fromNodeNum })
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
//
|
||||
// ManagedAttributePropertyWrapper.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Jake Bordens on 12/26/24.
|
||||
//
|
||||
import CoreData
|
||||
|
||||
@propertyWrapper
|
||||
public struct ManagedAttribute<Value: Numeric> {
|
||||
private let attributeName: String
|
||||
private let converter: (NSNumber) -> Value?
|
||||
|
||||
public init(attributeName: String) {
|
||||
self.attributeName = attributeName
|
||||
|
||||
// Define the converter closure based on the generic type Value
|
||||
if Value.self == Float.self {
|
||||
converter = { $0.floatValue as? Value }
|
||||
} else if Value.self == Double.self {
|
||||
converter = { $0.doubleValue as? Value }
|
||||
} else if Value.self == Int.self {
|
||||
converter = { $0.intValue as? Value }
|
||||
} else if Value.self == Int8.self {
|
||||
converter = { $0.int8Value as? Value }
|
||||
} else if Value.self == Int16.self {
|
||||
converter = { $0.int16Value as? Value }
|
||||
} else if Value.self == Int32.self {
|
||||
converter = { $0.int32Value as? Value }
|
||||
} else if Value.self == Int64.self {
|
||||
converter = { $0.int64Value as? Value }
|
||||
} else if Value.self == UInt32.self {
|
||||
converter = { $0.uint32Value as? Value }
|
||||
} else {
|
||||
fatalError("Unsupported type: \(Value.self)")
|
||||
}
|
||||
}
|
||||
|
||||
public var wrappedValue: Value? {
|
||||
get { fatalError("Access via enclosing instance required.") }
|
||||
set { fatalError("Access via enclosing instance required.") }
|
||||
}
|
||||
|
||||
public static subscript<EnclosingSelf: NSManagedObject>(
|
||||
_enclosingInstance observed: EnclosingSelf,
|
||||
wrapped wrappedKeyPath: KeyPath<EnclosingSelf, Value?>,
|
||||
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, ManagedAttribute<Value>>
|
||||
) -> Value? {
|
||||
get {
|
||||
let wrapper = observed[keyPath: storageKeyPath]
|
||||
let number = observed.primitiveValue(forKey: wrapper.attributeName) as? NSNumber
|
||||
return number.flatMap { wrapper.converter($0) }
|
||||
}
|
||||
set {
|
||||
let wrapper = observed[keyPath: storageKeyPath]
|
||||
if let newValue = newValue {
|
||||
observed.setPrimitiveValue(NSNumber(value: Double("\(newValue)")!), forKey: wrapper.attributeName)
|
||||
} else {
|
||||
observed.setPrimitiveValue(nil, forKey: wrapper.attributeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -177,8 +177,15 @@ actor MeshPackets {
|
|||
do {
|
||||
let fetchedMyInfo = try modelContext.fetch(fetchDescriptor)
|
||||
if fetchedMyInfo.count == 1 {
|
||||
let newChannel = ChannelEntity()
|
||||
modelContext.insert(newChannel)
|
||||
let existing = fetchedMyInfo[0].channels.first(where: { $0.index == Int32(channel.index) })
|
||||
let newChannel: ChannelEntity
|
||||
if let existing {
|
||||
newChannel = existing
|
||||
} else {
|
||||
newChannel = ChannelEntity()
|
||||
modelContext.insert(newChannel)
|
||||
fetchedMyInfo[0].channels.append(newChannel)
|
||||
}
|
||||
newChannel.id = Int32(channel.index)
|
||||
newChannel.index = Int32(channel.index)
|
||||
newChannel.uplinkEnabled = channel.settings.uplinkEnabled
|
||||
|
|
@ -190,11 +197,6 @@ actor MeshPackets {
|
|||
newChannel.positionPrecision = Int32(truncatingIfNeeded: channel.settings.moduleSettings.positionPrecision)
|
||||
newChannel.mute = channel.settings.moduleSettings.isMuted
|
||||
}
|
||||
if let oldIndex = fetchedMyInfo[0].channels.firstIndex(where: { $0.index == newChannel.index }) {
|
||||
fetchedMyInfo[0].channels[oldIndex] = newChannel
|
||||
} else {
|
||||
fetchedMyInfo[0].channels.append(newChannel)
|
||||
}
|
||||
do {
|
||||
try modelContext.save()
|
||||
} catch {
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// TelemetryEntity+CoreDataClass.swift
|
||||
//
|
||||
//
|
||||
// Created by Jake Bordens on 12/26/24.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
// Manual implementation of the TelemetryEntry object for CoreData.
|
||||
// Add optional scalar types here using the @ManagedAttribute property wrapper.
|
||||
// CoreData is based on Objective-C, which doesn't have optional scalars.
|
||||
// The @ManagedAttribute property wrapper handles the conversion to optional scalars.
|
||||
|
||||
@objc(TelemetryEntity)
|
||||
public class TelemetryEntity: NSManagedObject, Identifiable {
|
||||
|
||||
@ManagedAttribute<Float>(attributeName: "airUtilTx") public var airUtilTx: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "barometricPressure") public var barometricPressure: Float?
|
||||
@ManagedAttribute<Int32>(attributeName: "batteryLevel") public var batteryLevel: Int32?
|
||||
@ManagedAttribute<Float>(attributeName: "channelUtilization") public var channelUtilization: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "current") public var current: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "distance") public var distance: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "gasResistance") public var gasResistance: Float?
|
||||
@ManagedAttribute<Int32>(attributeName: "iaq") public var iaq: Int32?
|
||||
@ManagedAttribute<Float>(attributeName: "powerCh1Current") var powerCh1Current: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "powerCh1Voltage") var powerCh1Voltage: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "powerCh2Current") var powerCh2Current: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "powerCh2Voltage") var powerCh2Voltage: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "powerCh3Current") var powerCh3Current: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "powerCh3Voltage") var powerCh3Voltage: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "relativeHumidity") public var relativeHumidity: Float?
|
||||
@ManagedAttribute<Int32>(attributeName: "rssi") public var rssi: Int32?
|
||||
@ManagedAttribute<Float>(attributeName: "snr") public var snr: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "temperature") public var temperature: Float?
|
||||
@ManagedAttribute<Int32>(attributeName: "uptimeSeconds") public var uptimeSeconds: Int32?
|
||||
@ManagedAttribute<Float>(attributeName: "voltage") public var voltage: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "weight") public var weight: Float?
|
||||
@ManagedAttribute<Int32>(attributeName: "windDirection") public var windDirection: Int32?
|
||||
@ManagedAttribute<Float>(attributeName: "windGust") public var windGust: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "windLull") public var windLull: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "windSpeed") public var windSpeed: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "irLux") public var irLux: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "lux") public var lux: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "uvLux") public var uvLux: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "whiteLux") public var whiteLux: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "radiation") public var radiation: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "rainfall1H") public var rainfall1H: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "rainfall24H") public var rainfall24H: Float?
|
||||
@ManagedAttribute<Float>(attributeName: "soilTemperature") public var soilTemperature: Float?
|
||||
@ManagedAttribute<UInt32>(attributeName: "soilMoisture") public var soilMoisture: UInt32?
|
||||
|
||||
public var dewPoint: Float? {
|
||||
guard let temp = self.temperature, let rh = self.relativeHumidity else {
|
||||
return nil
|
||||
}
|
||||
return Float(calculateDewPoint(temp: temp, relativeHumidity: rh, convertToLocale: false))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
//
|
||||
// TelemetryEntity+CoreDataProperties.swift
|
||||
//
|
||||
//
|
||||
// Created by Jake Bordens on 12/26/24.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
// Manual implementation of the TelemetryEntry object for CoreData.
|
||||
// Add non-optional scalar types here using the standard @NSManaged proprty wrapper
|
||||
// Add optional/non-optional object types here using the standard @NSManaged proprty wrapper
|
||||
// CoreData is based on Objective-C which natively supports optionals for class types and
|
||||
// non-optional scalars.
|
||||
|
||||
extension TelemetryEntity {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<TelemetryEntity> {
|
||||
return NSFetchRequest<TelemetryEntity>(entityName: "TelemetryEntity")
|
||||
}
|
||||
|
||||
@NSManaged public var time: Date?
|
||||
@NSManaged public var metricsType: Int32
|
||||
@NSManaged public var numOnlineNodes: Int32
|
||||
@NSManaged public var numPacketsRx: Int32
|
||||
@NSManaged public var numPacketsRxBad: Int32
|
||||
@NSManaged public var numPacketsTx: Int32
|
||||
@NSManaged public var numRxDupe: Int32
|
||||
@NSManaged public var numTotalNodes: Int32
|
||||
@NSManaged public var numTxRelay: Int32
|
||||
@NSManaged public var numTxRelayCanceled: Int32
|
||||
@NSManaged public var nodeTelemetry: NodeInfoEntity?
|
||||
|
||||
}
|
||||
|
|
@ -239,51 +239,13 @@ struct Channels: View {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
if node?.myInfo?.channels.count ?? 0 < 8 && node != nil {
|
||||
|
||||
Button {
|
||||
let channelIndexes = node?.myInfo?.channels.map { Int($0.index) }
|
||||
let firstChannelIndex = firstMissingChannelIndex(channelIndexes ?? [])
|
||||
channelKeySize = 16
|
||||
let key = generateChannelKey(size: channelKeySize)
|
||||
channelName = ""
|
||||
channelIndex = Int32(firstChannelIndex)
|
||||
channelRole = 2
|
||||
channelKey = key
|
||||
positionsEnabled = false
|
||||
preciseLocation = false
|
||||
positionPrecision = 0
|
||||
uplink = false
|
||||
downlink = false
|
||||
|
||||
let newChannel = ChannelEntity()
|
||||
context.insert(newChannel)
|
||||
newChannel.id = channelIndex
|
||||
newChannel.index = channelIndex
|
||||
newChannel.uplinkEnabled = uplink
|
||||
newChannel.downlinkEnabled = downlink
|
||||
newChannel.name = channelName
|
||||
newChannel.role = Int32(channelRole)
|
||||
newChannel.psk = Data(base64Encoded: channelKey) ?? Data()
|
||||
newChannel.positionPrecision = Int32(positionPrecision)
|
||||
selectedChannel = newChannel
|
||||
hasChanges = true
|
||||
|
||||
} label: {
|
||||
Label("Add Channel", systemImage: "plus.square")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingHelp) {
|
||||
ChannelsHelp()
|
||||
.presentationDetents([.large])
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
||||
.safeAreaInset(edge: .bottom) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
|
|
@ -296,9 +258,46 @@ struct Channels: View {
|
|||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
.controlSize(.regular)
|
||||
Spacer()
|
||||
if node?.myInfo?.channels.count ?? 0 < 8 && node != nil {
|
||||
Button {
|
||||
let channelIndexes = node?.myInfo?.channels.map { Int($0.index) }
|
||||
let firstChannelIndex = firstMissingChannelIndex(channelIndexes ?? [])
|
||||
channelKeySize = 16
|
||||
let key = generateChannelKey(size: channelKeySize)
|
||||
channelName = ""
|
||||
channelIndex = Int32(firstChannelIndex)
|
||||
channelRole = 2
|
||||
channelKey = key
|
||||
positionsEnabled = false
|
||||
preciseLocation = false
|
||||
positionPrecision = 0
|
||||
uplink = false
|
||||
downlink = false
|
||||
|
||||
let newChannel = ChannelEntity()
|
||||
context.insert(newChannel)
|
||||
newChannel.id = channelIndex
|
||||
newChannel.index = channelIndex
|
||||
newChannel.uplinkEnabled = uplink
|
||||
newChannel.downlinkEnabled = downlink
|
||||
newChannel.name = channelName
|
||||
newChannel.role = Int32(channelRole)
|
||||
newChannel.psk = Data(base64Encoded: channelKey) ?? Data()
|
||||
newChannel.positionPrecision = Int32(positionPrecision)
|
||||
selectedChannel = newChannel
|
||||
hasChanges = true
|
||||
} label: {
|
||||
Label("Add Channel", systemImage: "plus.square")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
}
|
||||
}
|
||||
.controlSize(.regular)
|
||||
.padding(5)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.navigationTitle("Channels")
|
||||
|
|
|
|||
50
MeshtasticTests/ChannelEntityTests.swift
Normal file
50
MeshtasticTests/ChannelEntityTests.swift
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import XCTest
|
||||
import SwiftData
|
||||
@testable import Meshtastic
|
||||
|
||||
final class ChannelEntityTests: XCTestCase {
|
||||
var modelContainer: ModelContainer!
|
||||
var context: ModelContext!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
let schema = Schema([ChannelEntity.self])
|
||||
modelContainer = try! ModelContainer(for: schema, configurations: [])
|
||||
context = ModelContext(modelContainer)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
modelContainer = nil
|
||||
context = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testChannelEntityDefaultInit() {
|
||||
let channel = ChannelEntity()
|
||||
XCTAssertFalse(channel.downlinkEnabled)
|
||||
XCTAssertEqual(channel.id, 0)
|
||||
XCTAssertEqual(channel.index, 0)
|
||||
XCTAssertFalse(channel.mute)
|
||||
XCTAssertNil(channel.name)
|
||||
XCTAssertEqual(channel.positionPrecision, 32)
|
||||
XCTAssertNil(channel.psk)
|
||||
XCTAssertEqual(channel.role, 0)
|
||||
XCTAssertFalse(channel.uplinkEnabled)
|
||||
XCTAssertNil(channel.myInfoChannel)
|
||||
}
|
||||
|
||||
func testChannelEntityInsertAndFetch() throws {
|
||||
let channel = ChannelEntity()
|
||||
channel.id = 42
|
||||
channel.name = "Test Channel"
|
||||
channel.uplinkEnabled = true
|
||||
context.insert(channel)
|
||||
try context.save()
|
||||
|
||||
let descriptor = FetchDescriptor<ChannelEntity>(predicate: #Predicate { $0.id == 42 })
|
||||
let fetched = try context.fetch(descriptor)
|
||||
XCTAssertEqual(fetched.count, 1)
|
||||
XCTAssertEqual(fetched.first?.name, "Test Channel")
|
||||
XCTAssertTrue(fetched.first?.uplinkEnabled ?? false)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue