Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
061785d77b
|
|||
|
c4c4fed4bc
|
|||
|
e44c1c24c5
|
|||
|
df05898a65
|
@@ -2,6 +2,7 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -60,7 +60,10 @@ public struct TemperatureAndHumiditySensor: Identifiable, Sendable {
|
||||
!temperature.value.isNaN,
|
||||
!humidity.value.isNaN
|
||||
else { return nil }
|
||||
return try? await psychrometrics.dewPoint(.dryBulb(temperature, relativeHumidity: humidity))
|
||||
return try? await psychrometrics.dewPoint(.dryBulb(
|
||||
.fahrenheit(temperature.fahrenheit),
|
||||
relativeHumidity: humidity
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +76,7 @@ public struct TemperatureAndHumiditySensor: Identifiable, Sendable {
|
||||
!humidity.value.isNaN
|
||||
else { return nil }
|
||||
return try? await psychrometrics.enthalpy.moistAir(
|
||||
.dryBulb(temperature, relativeHumidity: humidity, altitude: altitude)
|
||||
.dryBulb(.fahrenheit(temperature.fahrenheit), relativeHumidity: humidity, altitude: altitude, units: .imperial)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -81,12 +84,11 @@ public struct TemperatureAndHumiditySensor: Identifiable, Sendable {
|
||||
/// Check whether any of the sensor values have changed and need processed.
|
||||
///
|
||||
/// - Note: Setting a value will set to both the temperature and humidity properties.
|
||||
public var needsProcessed: Bool {
|
||||
get { $temperature.needsProcessed || $humidity.needsProcessed }
|
||||
set {
|
||||
$temperature.needsProcessed = newValue
|
||||
$humidity.needsProcessed = newValue
|
||||
}
|
||||
public var needsProcessed: Bool { $temperature.needsProcessed || $humidity.needsProcessed }
|
||||
|
||||
public mutating func setHasProcessed() {
|
||||
$temperature.setHasProcessed()
|
||||
$humidity.setHasProcessed()
|
||||
}
|
||||
|
||||
/// Represents the different locations of a temperature and humidity sensor, which can
|
||||
|
||||
@@ -5,24 +5,20 @@
|
||||
@propertyWrapper
|
||||
public struct TrackedChanges<Value: Sendable>: Sendable {
|
||||
|
||||
/// The current tracking state.
|
||||
private var tracking: TrackingState
|
||||
|
||||
/// The current wrapped value.
|
||||
private var value: Value
|
||||
/// The current value wrapped in a tracking state.
|
||||
private var value: TrackingState
|
||||
|
||||
/// Used to check if a new value is equal to an old value.
|
||||
private var isEqual: @Sendable (Value, Value) -> Bool
|
||||
|
||||
/// Access to the underlying property that we are wrapping.
|
||||
public var wrappedValue: Value {
|
||||
get { value }
|
||||
get { value.currentValue }
|
||||
set {
|
||||
// Check if the new value is equal to the old value.
|
||||
guard !isEqual(newValue, value) else { return }
|
||||
guard !isEqual(newValue, value.currentValue) else { return }
|
||||
// If it's not equal then set it, as well as set the tracking to `.needsProcessed`.
|
||||
value = newValue
|
||||
tracking = .needsProcessed
|
||||
value = .needsProcessed(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,31 +33,42 @@ public struct TrackedChanges<Value: Sendable>: Sendable {
|
||||
needsProcessed: Bool = false,
|
||||
isEqual: @escaping @Sendable (Value, Value) -> Bool
|
||||
) {
|
||||
self.value = wrappedValue
|
||||
self.tracking = needsProcessed ? .needsProcessed : .hasProcessed
|
||||
self.value = .init(wrappedValue, needsProcessed: needsProcessed)
|
||||
self.isEqual = isEqual
|
||||
}
|
||||
|
||||
/// Represents whether a wrapped value has changed and needs processed or not.
|
||||
enum TrackingState {
|
||||
fileprivate enum TrackingState {
|
||||
case hasProcessed(Value)
|
||||
case needsProcessed(Value)
|
||||
|
||||
/// The state when nothing has changed and we've already processed the current value.
|
||||
case hasProcessed
|
||||
init(_ value: Value, needsProcessed: Bool) {
|
||||
if needsProcessed {
|
||||
self = .needsProcessed(value)
|
||||
} else {
|
||||
self = .hasProcessed(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// The state when the value has changed and has not been processed yet.
|
||||
case needsProcessed
|
||||
var currentValue: Value {
|
||||
switch self {
|
||||
case let .hasProcessed(value):
|
||||
return value
|
||||
case let .needsProcessed(value):
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
var needsProcessed: Bool {
|
||||
guard case .needsProcessed = self else { return false }
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the value needs processed.
|
||||
public var needsProcessed: Bool {
|
||||
get { tracking == .needsProcessed }
|
||||
set {
|
||||
if newValue {
|
||||
tracking = .needsProcessed
|
||||
} else {
|
||||
tracking = .hasProcessed
|
||||
}
|
||||
}
|
||||
var needsProcessed: Bool { value.needsProcessed }
|
||||
|
||||
mutating func setHasProcessed() {
|
||||
value = .hasProcessed(value.currentValue)
|
||||
}
|
||||
|
||||
public var projectedValue: Self {
|
||||
@@ -95,6 +102,5 @@ extension TrackedChanges: Hashable where Value: Hashable {
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(wrappedValue)
|
||||
hasher.combine(needsProcessed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public actor SensorsService: Service {
|
||||
|
||||
private func publishUpdates() async throws {
|
||||
for sensor in sensors.filter(\.needsProcessed) {
|
||||
try await publish(sensor.dewPoint?.value, to: sensor.topics.dewPoint)
|
||||
try await publish(sensor.dewPoint?.fahrenheit, to: sensor.topics.dewPoint)
|
||||
try await publish(sensor.enthalpy?.value, to: sensor.topics.enthalpy)
|
||||
try sensors.hasProcessed(sensor)
|
||||
}
|
||||
@@ -172,7 +172,7 @@ private extension Array where Element == TemperatureAndHumiditySensor {
|
||||
guard let index = firstIndex(where: { $0.id == sensor.id }) else {
|
||||
throw SensorNotFoundError()
|
||||
}
|
||||
self[index].needsProcessed = false
|
||||
self[index].setHasProcessed()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +207,6 @@ extension Humidity<Relative>: BufferInitalizable {
|
||||
extension Temperature<DryAir>: BufferInitalizable {
|
||||
init?(buffer: ByteBuffer) {
|
||||
guard let value = Double(buffer: buffer) else { return nil }
|
||||
self.init(value)
|
||||
self.init(value, units: .celsius)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user