Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions crates/flux-api/src/routes/intel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,18 +645,21 @@ async fn build_anomalies(state: &AppState) -> Vec<Anomaly> {
}
}

// Warn if EWT and LWT are very close (< 2°F delta) while system runs —
// suggests poor ground loop heat exchange.
// Warn if EWT/LWT delta is large (> 10°F) while the system is running.
// Q = flow_gpm × 500 × ΔT, so a large ΔT at a given load means low flow —
// the pump isn't moving enough water through the ground loop. Normal operating
// range is 5–10°F; > 10°F suggests a flow restriction or failing loop pump.
// (A *small* ΔT is normal — it just means low compressor load or high flow.)
for entry in &hvac_entries {
let ewt = field_f64(&entry.event.fields, "ewt_f");
let lwt = field_f64(&entry.event.fields, "lwt_f");
let power = field_f64(&entry.event.fields, "total_power_w");
if power > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() < 2.0 {
if power > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() > 10.0 {
anomalies.push(Anomaly {
severity: "WARN",
domain: "HVAC",
message: format!(
"{}: EWT/LWT delta is only {:.1}°F — possible loop flow restriction",
"{}: EWT/LWT delta {:.1}°F exceeds normal range — possible loop flow restriction or failing pump",
entry.event.source,
(ewt - lwt).abs()
),
Expand Down Expand Up @@ -847,4 +850,23 @@ mod tests {
let power_w = 500.0_f64;
assert!(power_w > 200.0 && cop > 0.0 && cop < 2.0);
}

#[test]
fn loop_flow_restriction_fires_on_large_delta() {
// Large EWT/LWT delta → restricted flow (loop not moving enough water)
let ewt = 55.0_f64;
let lwt = 44.0_f64; // delta = 11°F — exceeds 10°F threshold
let power_w = 1500.0_f64;
assert!(power_w > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() > 10.0);
}

#[test]
fn loop_flow_restriction_silent_on_normal_delta() {
// 1.9°F delta (like the real 7-series case that prompted this fix) must not warn.
// Small delta = low load or high flow rate — both normal.
let ewt = 43.3_f64;
let lwt = 41.4_f64; // delta = 1.9°F
let power_w = 800.0_f64;
assert!(!(power_w > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() > 10.0));
}
}
Loading