feat: Begins more work on async integration

This commit is contained in:
2024-11-07 17:10:21 -05:00
parent 19b2eb42c5
commit 408e0484cd
9 changed files with 177 additions and 97 deletions

7
.editorconfig Normal file
View File

@@ -0,0 +1,7 @@
root = true
[*.swift]
indent_style = space
indent_size = 2
tab_width = 2
trim_trailing_whitespace = true

1
.swiftformat Normal file
View File

@@ -0,0 +1 @@
--self init-only

View File

@@ -36,7 +36,7 @@ public struct Client {
}
public enum SensorPublishRequest {
case mixed(State.Sensors.TemperatureHumiditySensor<State.Sensors.Mixed>)
case mixed(State.Sensors.TemperatureHumiditySensor<State.Sensors.MixedAir>)
case postCoil(State.Sensors.TemperatureHumiditySensor<State.Sensors.PostCoil>)
case `return`(State.Sensors.TemperatureHumiditySensor<State.Sensors.Return>)
case supply(State.Sensors.TemperatureHumiditySensor<State.Sensors.Supply>)

View File

@@ -61,7 +61,7 @@ public class AsyncClient {
tlsConfiguration: nil,
webSocketURLPath: nil
)
self.client = .init(
self.client = MQTTClient(
host: envVars.host,
identifier: envVars.identifier,
eventLoopGroupProvider: .shared(Self.eventLoopGroup),

View File

@@ -24,13 +24,13 @@ public final class State {
public struct Sensors: Equatable {
public var mixedAirSensor: TemperatureHumiditySensor<Mixed>
public var mixedAirSensor: TemperatureHumiditySensor<MixedAir>
public var postCoilSensor: TemperatureHumiditySensor<PostCoil>
public var returnAirSensor: TemperatureHumiditySensor<Return>
public var supplyAirSensor: TemperatureHumiditySensor<Supply>
public init(
mixedAirSensor: TemperatureHumiditySensor<Mixed> = .init(),
mixedAirSensor: TemperatureHumiditySensor<MixedAir> = .init(),
postCoilSensor: TemperatureHumiditySensor<PostCoil> = .init(),
returnAirSensor: TemperatureHumiditySensor<Return> = .init(),
supplyAirSensor: TemperatureHumiditySensor<Supply> = .init()
@@ -97,7 +97,7 @@ extension State.Sensors {
}
// MARK: - Temperature / Humidity Sensor Location Namespaces
public enum Mixed { }
public enum MixedAir { }
public enum PostCoil { }
public enum Return { }
public enum Supply { }

View File

@@ -0,0 +1,65 @@
import Psychrometrics
public struct TemperatureAndHumiditySensor: Equatable, Identifiable {
/// The identifier of the sensor, same as the location.
public var id: Location { location }
public let altitude: Length
/// The location identifier of the sensor
public let location: Location
/// The current temperature value of the sensor.
@TrackedChanges
public var temperature: Temperature?
/// The current humidity value of the sensor.
@TrackedChanges
public var humidity: RelativeHumidity?
/// The psychrometric units of the sensor.
public let units: PsychrometricEnvironment.Units
public init(
location: Location,
altitude: Length = .feet(800.0),
temperature: Temperature? = nil,
humidity: RelativeHumidity? = nil,
needsProcessed: Bool = false,
units: PsychrometricEnvironment.Units = .imperial
) {
self.altitude = altitude
self.location = location
self._temperature = .init(wrappedValue: temperature, needsProcessed: needsProcessed)
self._humidity = .init(wrappedValue: humidity, needsProcessed: needsProcessed)
self.units = units
}
/// The calculated dew-point temperature of the sensor.
public var dewPoint: DewPoint? {
guard let temperature = temperature,
let humidity = humidity,
!temperature.rawValue.isNaN,
!humidity.rawValue.isNaN
else { return nil }
return .init(dryBulb: temperature, humidity: humidity, units: units)
}
/// Check whether any of the sensor values have changed and need processed.
public var needsProcessed: Bool {
get { $temperature.needsProcessed || $humidity.needsProcessed }
set {
$temperature.needsProcessed = newValue
$humidity.needsProcessed = newValue
}
}
/// Represents the different locations of a temperature and humidity sensor, which can
/// be used to derive the topic to both listen and publish new values to.
public enum Location: String, Equatable, Hashable {
case mixedAir = "mixed-air"
case postCoil = "post-coil"
case `return`
case supply
}
}

View File

@@ -1,5 +1,5 @@
/// A container for all the different topics that are needed by the application.
/// A container for all the different MQTT topics that are needed by the application.
public struct Topics: Codable, Equatable {
/// The command topics the application can publish to.
@@ -36,13 +36,13 @@ public struct Topics: Codable, Equatable {
/// Represents the sensor topics.
public struct Sensors: Codable, Equatable {
public var mixedAirSensor: TemperatureAndHumiditySensor<State.Sensors.Mixed>
public var mixedAirSensor: TemperatureAndHumiditySensor<State.Sensors.MixedAir>
public var postCoilSensor: TemperatureAndHumiditySensor<State.Sensors.PostCoil>
public var returnAirSensor: TemperatureAndHumiditySensor<State.Sensors.Return>
public var supplyAirSensor: TemperatureAndHumiditySensor<State.Sensors.Supply>
public init(
mixedAirSensor: TemperatureAndHumiditySensor<State.Sensors.Mixed> = .default(location: "mixed=air"),
mixedAirSensor: TemperatureAndHumiditySensor<State.Sensors.MixedAir> = .default(location: "mixed-air"),
postCoilSensor: TemperatureAndHumiditySensor<State.Sensors.PostCoil> = .default(location: "post-coil"),
returnAirSensor: TemperatureAndHumiditySensor<State.Sensors.Return> = .default(location: "return"),
supplyAirSensor: TemperatureAndHumiditySensor<State.Sensors.Supply> = .default(location: "supply")

View File

@@ -1,11 +1,20 @@
/// A property wrapper that tracks changes of a property.
///
/// This allows values to only publish changes if they have changed since the
/// last time they were recieved.
@propertyWrapper
public struct TrackedChanges<Value> {
/// The current tracking state.
private var tracking: TrackingState
/// The current wrapped value.
private var value: Value
/// Used to check if a new value is equal to an old value.
private var isEqual: (Value, Value) -> Bool
/// Access to the underlying property that we are wrapping.
public var wrappedValue: Value {
get { value }
set {
@@ -17,6 +26,12 @@ public struct TrackedChanges<Value> {
}
}
/// Create a new property that tracks it's changes.
///
/// - Parameters:
/// - wrappedValue: The value that we are wrapping.
/// - needsProcessed: Whether this value needs processed (default = false).
/// - isEqual: Method to compare old values against new values.
public init(
wrappedValue: Value,
needsProcessed: Bool = false,
@@ -27,11 +42,17 @@ public struct TrackedChanges<Value> {
self.isEqual = isEqual
}
/// Represents whether a wrapped value has changed and needs processed or not.
enum TrackingState {
/// The state when nothing has changed and we've already processed the current value.
case hasProcessed
/// The state when the value has changed and has not been processed yet.
case needsProcessed
}
/// Check whether the value needs processed.
public var needsProcessed: Bool {
get { tracking == .needsProcessed }
set {
@@ -55,6 +76,11 @@ extension TrackedChanges: Equatable where Value: Equatable {
&& lhs.needsProcessed == rhs.needsProcessed
}
/// Create a new property that tracks it's changes, using the default equality check.
///
/// - Parameters:
/// - wrappedValue: The value that we are wrapping.
/// - needsProcessed: Whether this value needs processed (default = false).
public init(
wrappedValue: Value,
needsProcessed: Bool = false

View File

@@ -1,19 +0,0 @@
{
"name": "xcode build server",
"version": "0.2",
"bspVersion": "2.0",
"languages": [
"c",
"cpp",
"objective-c",
"objective-cpp",
"swift"
],
"argv": [
"/opt/homebrew/bin/xcode-build-server"
],
"workspace": "/Volumes/michael/Repos/github.com/hvac-iot/swift-mqtt-dewPoint/.swiftpm/xcode/package.xcworkspace",
"build_root": "/Volumes/michael/Repos/github.com",
"scheme": "dewPoint-controller-Package",
"kind": "xcode"
}