
Server-Room Dynamic Thermal Management — System Design
Goal: Home Assistant continuously finds and holds the sweet-spot setpoint for the
server-room minisplit — on a rolling basis — while absorbing on-demand HPC gear
(rented / brought up for big jobs), using calendar lookahead to pre-cool, and
preferentially spending excess solar instead of grid watts.
Status: Design v1 (2026-09-03) · Tracking:
#614 (implementation) ·
#629 (Carrier dongle, Friday 2026-09-04) ·
#760 (SolArk solar) ·
#344 (HA platform)
· First calibration dataset captured 2026-09-03 (see §4).
1.
The problem, stated precisely
The server room is a thermal system with three forcing inputs and one actuator:
| Input | Nature | Known to HA? |
|---|---|---|
| watts → BTU (1 W = 3.412 BTU/h), step changes when rental/HPC gear energizes | Yes — that’s the design’s core bet | |
| heat ingress from ambient + sun (weather-driven, forecastable) | Yes (met.no + room sensors) | |
| grid $/kWh vs free excess solar | Yes (smart meter + SolArk #760) | |
| minisplit setpoint (BTU capacity follows ΔT) | Yes after dongle pairing (#629) |
Sweet spot = the setpoint that minimizes energy_cost × cooling_energy subject to
hard equipment-thermal constraints — recomputed on a rolling basis as load, weather,
and solar change. Not a fixed number; a policy.
2.
Architecture
flowchart TB
subgraph SENSE[📡 Sensing]
T[Thermal fleet<br/>7 hosts silicon + rack + ambient<br/>+ minisplit coil/return via dongle]
P[Power<br/>whole-house meter · node watts<br/>RENTAL BANK metering NEW]
SOL[SolArk #760<br/>production · battery SOC · grid flow]
W[Weather/met.no<br/>ambient + forecast]
CAL[📅 Job calendar<br/>rental/HPC schedule]
end
subgraph BRAIN[🧠 Home Assistant — pfv-bms]
LOAD[Load model<br/>watts→BTU timeline<br/>calendar lookahead]
THERM[Thermal model<br/>rolling learned response<br/>setpoint→cooling-rate curves]
ECON[Cost model<br/>$/kWh · solar excess windows]
OPT[🎯 Setpoint policy engine<br/>optimize subject to guardrails]
ADMIT[⚡ Load admission<br/>gear on/off interlocks]
end
subgraph ACT[⚙️ Actuation]
AC[❄️ Minisplit setpoint<br/>via dongle · rate-limited]
GEAR[🔌 Rental gear banks<br/>metered PDU / relays]
ALERT[📱 Alerts + logbook rationale<br/>companion apps]
end
T & P & SOL & W & CAL --> BRAIN
LOAD & THERM & ECON --> OPT
OPT --> AC
OPT --> ADMIT --> GEAR
BRAIN --> ALERT
3.
Components (what exists / what’s new)
Exists today 
- Full thermal sensor fleet (plant_snmp: 7 hosts, rack temp, ambients, iDRAC ΔT)
- tiered alert thresholds (drives/DIMM 140°F, NVMe 150°F, PCH 160°F, GPU 185°F, ambient 104°F).
- Whole-house kWh (Smart Meter Texas), tsys6/7 node watts, garage PDU amps, UPS runtime.
- Weather + forecast (met.no, verified live).
- Calendar platform (HA) — ready to ingest a job calendar.
- Alerting + arm-switch pattern (doorman’s founder-level control idiom, reusable).
- First calibration dataset (see §4).
Lands Friday (#629) 
- Carrier dongle → HA climate entity for the minisplit. Design assumption:
setpoint read and write. If write is unavailable, the system degrades
gracefully to Advisory mode (§6) until hardware allows write.
New hardware/decisions 
- Rental-bank power metering (per bank or per circuit):
metered PDU (APC pattern) or CT-clamp energy monitor (Shelly EM class).
Required: per-bank watts so HA can turn “rental coming online” into exact BTU. - Rental-bank control (optional per bank): relay/PDU outlet switching —
enables admission control (§5.3). Manual-energize banks still work with
metering-only (HA reacts instead of gates). - SolArk RS485 integration (#760) for production/battery/SOC.
4.
The thermal model — “rolling sweet spot” mechanics
Calibration data point #1 (2026-09-03, manual): setpoint 80→70°F produced
intake −9°F, rack −4.9°F, hottest drive −1.8°F over ~6 h. Drives are
airflow-bound (known tsys4 cage issue) — room air alone doesn’t fix them;
the optimizer must learn per-sensor response, not just room average.
Model per sensor class (room air, rack, drives, silicon):
T_sensor(t+1) = T_sensor(t) + (P_gear·k1 + P_envelope(ambient,sun)·k2
− P_cool(setpoint, T_room)·k3) · dt / C_sensor
- Coefficients learned by rolling regression over the last N days
(recomputed nightly; HAutility_meter+ recorder history feed it). - Cool-down/heating rates per setpoint per ambient band → pre-cool lead time
is computed, not guessed:lead = ΔT_needed / learned_rate.
Optimizer (v2, closed loop): every 15–30 min, pick setpoint ∈ allowed band
minimizing predicted cost, subject to: P95(sensor temps) under thresholds,
minisplit duty-cycle sanity, solar-excess window schedule. Hysteresis: max
2°F step, 20-min dwell minimum (minisplits hate churn).
5.
On-demand gear: watts/BTU admission + pre-cool
- Calendar ingestion (
hpc-jobscalendar, any CalDAV source): job entries
carry bank IDs + expected watts (or HA looks up per-bank draw from history). - Pre-cool trigger: at
job_start − lead, cool toward pre-cool target
(computed so room hits job-optimal at start). - Solar preference: if SolArk reports excess production (or forecast high),
schedule pre-cool INTO the surplus window — “store cold” in the room’s thermal
mass instead of exporting/curtailing. Battery SOC arbitrates: surplus-first,
battery-second, grid-last (policy knob). - Admission control (v3): a bank may be energized only if
cooling_capacity ≥ bank_BTU + existing_loadwithin the alert thresholds —
else HA alerts with the wait/lead-time estimate. Founder override always wins
(revenue gear never silently blocked; policy = warn-and-allow by default).
6.
Phased rollout
| Phase | What | Gate |
|---|---|---|
| 0 — Baseline (Fri) | Dongle paired; climate entity live; HA dashboards show setpoint + full thermal fleet; data collection ON | #629 UAT |
| 1 — Advisory | Policy engine computes recommended setpoint + pre-cool advice; displays + notifies; no actuation; thermal model training begins | 1 week clean data |
| 2 — Closed loop | Auto setpoint within conservative band (68–80°F), hysteresis + dwell, manual-override detection (housemate turns dial → respected N hours, then advisory nudge) | Founder acceptance of advisory accuracy |
| 3 — Full orchestration | Calendar pre-cool + solar-aware scheduling + bank admission control + rolling optimizer widening the band | Solar live (#760) + rental metering installed |
7.
Guardrails (non-negotiable)
- Arm switch (doorman idiom):
Off / Advisory / Auto— founder-level control. - Alert tiers remain the hard ceiling — the optimizer may never trade
equipment safety for cost. - Every setpoint change logged to logbook with rationale (predicted load,
solar window, model confidence). - Manual override (physical dial) detected via setpoint deltas → policy:
respect 4 h, notify, then resume advisory. - UPS-on-battery → max-cooling bias + load-shed advisory (cooling is the
priority consumer of runtime). - All config in KNEL/pfv-bms repo (deploy pipeline with
ha core checkgate).
8.
Open questions (founder)
- Job calendar source — which system holds the rental/HPC schedule
(Google/CalDAV/gitea/HA-local)? Who writes entries? - Rental banks — how many circuits/banks, typical wattage, metered-PDU vs
CT-clamp preference, and should banks be relay-controllable or metering-only? - Setpoint band + override policy — OK with 68–80°F working band and the
4-hour manual-override respect window? - Electricity plan — flat or time-of-use? (Pre-cool economics change.)
- Minisplit nameplate (Friday #629): model + BTU rating — confirms capacity
ceiling for admission math; and does the dongle expose setpoint WRITE?
— Design v1 by the HA/plant lane, 2026-09-03. Implementation tracked on [#614];
discussion in this topic.