Skip to content

Commit eddabf2

Browse files
tim-irelandclaude
andcommitted
fix: EWT/LWT anomaly rule fires on large delta, not small
The original rule warned when delta < 2°F, labelling it a flow restriction. This is backwards: Q = flow_gpm × 500 × ΔT, so a *large* delta at a given load means low flow (pump not moving enough water). A small delta is normal — low compressor load or high flow. Changed threshold to > 10°F (normal range is 5–10°F). Added two unit tests — one for the real 7-series case that triggered the false positive (1.9°F, now silent) and one for the alert case (11°F). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e78dadf commit eddabf2

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

crates/flux-api/src/routes/intel.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -645,18 +645,21 @@ async fn build_anomalies(state: &AppState) -> Vec<Anomaly> {
645645
}
646646
}
647647

648-
// Warn if EWT and LWT are very close (< 2°F delta) while system runs —
649-
// suggests poor ground loop heat exchange.
648+
// Warn if EWT/LWT delta is large (> 10°F) while the system is running.
649+
// Q = flow_gpm × 500 × ΔT, so a large ΔT at a given load means low flow —
650+
// the pump isn't moving enough water through the ground loop. Normal operating
651+
// range is 5–10°F; > 10°F suggests a flow restriction or failing loop pump.
652+
// (A *small* ΔT is normal — it just means low compressor load or high flow.)
650653
for entry in &hvac_entries {
651654
let ewt = field_f64(&entry.event.fields, "ewt_f");
652655
let lwt = field_f64(&entry.event.fields, "lwt_f");
653656
let power = field_f64(&entry.event.fields, "total_power_w");
654-
if power > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() < 2.0 {
657+
if power > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() > 10.0 {
655658
anomalies.push(Anomaly {
656659
severity: "WARN",
657660
domain: "HVAC",
658661
message: format!(
659-
"{}: EWT/LWT delta is only {:.1}°F — possible loop flow restriction",
662+
"{}: EWT/LWT delta {:.1}°F exceeds normal range — possible loop flow restriction or failing pump",
660663
entry.event.source,
661664
(ewt - lwt).abs()
662665
),
@@ -847,4 +850,23 @@ mod tests {
847850
let power_w = 500.0_f64;
848851
assert!(power_w > 200.0 && cop > 0.0 && cop < 2.0);
849852
}
853+
854+
#[test]
855+
fn loop_flow_restriction_fires_on_large_delta() {
856+
// Large EWT/LWT delta → restricted flow (loop not moving enough water)
857+
let ewt = 55.0_f64;
858+
let lwt = 44.0_f64; // delta = 11°F — exceeds 10°F threshold
859+
let power_w = 1500.0_f64;
860+
assert!(power_w > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() > 10.0);
861+
}
862+
863+
#[test]
864+
fn loop_flow_restriction_silent_on_normal_delta() {
865+
// 1.9°F delta (like the real 7-series case that prompted this fix) must not warn.
866+
// Small delta = low load or high flow rate — both normal.
867+
let ewt = 43.3_f64;
868+
let lwt = 41.4_f64; // delta = 1.9°F
869+
let power_w = 800.0_f64;
870+
assert!(!(power_w > 200.0 && ewt > 0.0 && lwt > 0.0 && (ewt - lwt).abs() > 10.0));
871+
}
850872
}

0 commit comments

Comments
 (0)