10 Commits
0.2.0 ... dev

Author SHA1 Message Date
061785d77b feat: Updates tracking state of sensors 2024-11-20 22:45:20 -05:00
c4c4fed4bc feat: Updates tracking state of sensors 2024-11-20 22:43:05 -05:00
e44c1c24c5 feat: Update ci workflow to only work on pushes to main branch and pull requests.
All checks were successful
CI / Run Tests (pull_request) Successful in 4m18s
CI / Run Tests (push) Successful in 4m17s
Create and publish a Docker image / build-and-push-image (push) Successful in 8m4s
2024-11-20 15:10:23 -05:00
df05898a65 fix: Fixes dewpoint and enthalpy not converting to imperial units.
Some checks failed
CI / Run Tests (push) Has been cancelled
2024-11-20 15:07:33 -05:00
916fcb3584 fix: Update to release workflow
All checks were successful
Create and publish a Docker image / build-and-push-image (push) Successful in 8m12s
CI / Run Tests (pull_request) Successful in 4m28s
CI / Run Tests (push) Successful in 5m5s
2024-11-19 15:08:07 -05:00
d9af0b8b30 fix: Update to release workflow
Some checks failed
CI / Run Tests (push) Has been cancelled
Create and publish a Docker image / build-and-push-image (push) Failing after 7m15s
2024-11-19 14:52:37 -05:00
aa666d799a fix: Update to release workflow
Some checks failed
CI / Run Tests (push) Has been cancelled
Create and publish a Docker image / build-and-push-image (push) Failing after 7m42s
2024-11-19 14:24:43 -05:00
3825517dae fix: Update to release workflow
Some checks failed
CI / Run Tests (push) Has been cancelled
Create and publish a Docker image / build-and-push-image (push) Failing after 13s
2024-11-19 14:22:21 -05:00
c21695a37e fix: Update to release workflow
Some checks failed
CI / Run Tests (push) Has been cancelled
Create and publish a Docker image / build-and-push-image (push) Failing after 8s
2024-11-19 14:18:50 -05:00
3743eefa69 fix: Update to release workflow
Some checks failed
CI / Run Tests (push) Has been cancelled
Create and publish a Docker image / build-and-push-image (push) Failing after 6s
2024-11-19 14:02:10 -05:00
5 changed files with 58 additions and 48 deletions

View File

@@ -2,6 +2,7 @@
name: CI
on:
push:
branches: ["main"]
pull_request:
jobs:

View File

@@ -12,7 +12,7 @@ on:
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: git.housh.dev
IMAGE_NAME: ${{ github.repository }}
IMAGE_NAME: ${{ gitea.repository }}
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
@@ -33,8 +33,8 @@ jobs:
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
username: ${{ gitea.actor }}
password: ${{ secrets.CONTAINER_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
@@ -53,15 +53,16 @@ jobs:
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
file: docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
# - name: Generate artifact attestation
# uses: actions/attest-build-provenance@v1
# with:
# subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
# subject-digest: ${{ steps.push.outputs.digest }}
# push-to-registry: true
# github-token: ${{ secrets.CONTAINER_TOKEN }}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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)
}
}