# ๐ pfv-bms โ the house brain
> **Datacenter-grade monitoring and access control for a private residence + server room** โ
> 372 entities, ~260 sensors, and a badge-actuated door, all deployed by `git push`.





Production Home Assistant configuration for the Turnsys PFV โ
environmental monitoring (temperatures, power, UPS) across a seven-node
Proxmox fleet plus single-board computers, server-room badge access
control, and tiered alerting to mobile devices.
Work tracking: [Redmine](https://projects.knownelement.com)
([#344](https://projects.knownelement.com/issues/344) umbrella) ยท
Docs: [VP TechOps on Discourse](https://community.turnsys.com/c/vp-techops)
---
## ๐บ๏ธ System architecture
```mermaid
flowchart LR
subgraph FIELD[๐ก The field]
TS[๐ฅ๏ธ 7ร Proxmox hosts
lm-sensors + iDRAC extends]
BOARDS[๐ฅง SBCs
pfvsvrpi ยท jetson ยท 3ร subopi]
UPS[๐ UPS on tsys1
NUT server :3493]
PDU[๐ Garage PDU
SNMPv1 relay]
METER[โก Utility meter
Smart Meter Texas]
READER[๐ชช Badge readers
pfvsvrpi ยท ultix-field]
end
subgraph HA[๐ pfv-bms โ this repo]
INGEST[๐ฆ packages/plant_snmp.yaml
SNMP pollers โ raw sensors]
TEMPLATE[๐งฎ template sensors
raw โ ยฐF/units + thresholds]
DOOR[๐ช packages/doorman.yaml
scan ingest + decision engine]
ROSTER[๐ roster sensors
REST poll of private access-roster]
ENERGY[๐ utility_meter +
Riemann-sum energy]
AUTO[๐จ automations.yaml
tiered thermal + UPS alerts]
end
subgraph OUT[๐ฒ Outcomes]
ALERT[๐ฑ push alerts
companion apps]
LOG[๐ logbook + history
every scan, every degree]
DASH[๐ฅ๏ธ dashboards
server-room + plant]
RELAY[โก doorctl โ usbrelay
โ door strike]
end
READER -->|webhook| DOOR
DOOR -->|whitelist| ROSTER
DOOR -->|armed + valid| RELAY
TS & BOARDS -->|SNMP| INGEST
UPS -->|NUT| INGEST
PDU -->|SNMP relay| INGEST
METER -->|REST| INGEST
INGEST --> TEMPLATE --> AUTO
INGEST --> ENERGY
AUTO --> ALERT
TEMPLATE & DOOR --> LOG & DASH
```
### ๐ก๏ธ Badge access lane (server-room door)
| Component | Role | Lives |
|-----------|------|-------|
| USB HID readers | 13.56 MHz badge readers (keyboard-emulating) | door + dev bench |
| [`KNEL/doorman`](https://git.knownelement.com/KNEL/doorman) | pure-bash listener, decode, webhook, doorctl | `pfvsvrpi` (prod), `ultix-field` (dev) |
| `packages/doorman.yaml` | scan ingest, whitelist decision, alerts, unlock dispatch | **this repo** |
| [`KNEL/access-roster`](https://git.knownelement.com/KNEL/access-roster) ๐ | badge IDs + holders โ **private**, two-human PR gate | gitea (private) |
| `doorctl` + usbrelay | socket-activated, token + source-IP ACL, EXIT-trap secured | `pfvsvrpi` |
Fail-closed end to end: HA unreachable โ the door does not open.
Break-glass badges fire the relay locally (works with HA down) and
report `local_unlock` so HA never double-fires. Arm switch
(`input_boolean.doorman_unlock_enabled`) is founder-level control.
Verified end-to-end 2026-09-03: real armed scan โ dispatch โ relay.
---
## ๐ก๏ธ Environmental monitoring
Raw SNMP pollers (`packages/plant_snmp.yaml`) โ unit-normalized
template sensors โ tiered automations. Every host contributes
lm-sensors extends; iDRAC hosts add inlet/exhaust/CPU; NUT feeds UPS
electricals.
| Family | Coverage |
|--------|----------|
| ๐ฅ๏ธ Host silicon | CPU/drive/NVMe/PCH temps on 7 Proxmox hosts |
| ๐ก๏ธ Thermal zones | rack ambient, DIMM banks, GPU, tsys7 iDRAC inletโexhaust ฮT |
| ๐ฅง Boards | pfvsvrpi, jetson, 3ร subopi |
| ๐ UPS | tsys1 battery charge/voltage, on-battery + runtime alerts |
| โก Power | whole-house kWh (utility), tsys6/7 node watts + kWh integrals, garage PDU amps |
| ๐ Rooms | temp/humidity/battery sensors (Govee, cloud-fed) |
### ๐จ Alert tiers (automations.yaml)
| Trigger | Threshold |
|---------|-----------|
| Drive / DIMM temps | > 140 ยฐF |
| NVMe | > 150 ยฐF |
| PCH | > 160 ยฐF |
| GPU | > 185 ยฐF |
| Ambient | > 104 ยฐF |
| UPS | on-battery transitions + runtime |
| Watchdog | plant sensor freshness sweep every 30 min |
### ๐ Snapshot (2026-09-03)
372 entities ยท ~260 sensors ยท 45 temperature sensors ยท 21
electrical/energy sensors ยท 8 todo lists ยท 2-way alerting to companion
apps.
---
## ๐ Security model (read this before forking)
- **No secrets in git, ever.** Everything sensitive is `!secret`
indirection into an on-box `secrets.yaml` (gitignored). Verified by
full-history scans.
- **Badge IDs are NOT in this repo.** The roster lives in the *private*
[`KNEL/access-roster`](https://git.knownelement.com/KNEL/access-roster)
repo (two-human PR gate) and is fetched live at runtime.
- **Fail-closed access control** โ see the badge lane above.
- Battery room sensors and locks are cloud-fed; credentials also live
in `secrets.yaml`.
- **HomeKit is controller-only (founder ruling 2026-09-04).** HA pulls
*from* HomeKit accessories when one enters the fleet; HA entities are
NEVER exposed *to* Apple Home โ no `homekit` bridge integration, no
outward QR pairing.
## ๐ Deployment pipeline
**Branch model (2026-09-04):** `dev` = WIP integration โ the pipeline
IGNORES it. `release` = what the box runs โ pushing release IS the deploy.
`master` is frozen (pre-branch-model history). A PR process with AI +
human reviewers will gate dev โ release (founder, upcoming).
```mermaid
flowchart LR
PUSH[๐ push to dev] --> NOOP[๐ซ pipeline ignores dev]
REL[๐ merge dev โ release
and push] --> HOOK[gitea webhook
fast path]
REL --> SHA[sha-watch
release sha ยท 300 s poll]
HOOK & SHA --> CHECK{changed files?}
CHECK -->|configuration.yaml,
packages/**| RESTART[โป๏ธ core restart
webhook triggers need it]
CHECK -->|other YAML| RELOAD[โก reload only
~5 min to live]
```
Gate before pushing `release` (and after any `packages/**` change on
`dev`): `ha core check` must pass on-box.
Measured end-to-end: 4 m 52 s commit โ live.
## ๐บ๏ธ Repo map
| Path | What |
|------|------|
| `configuration.yaml` | entrypoint + package includes |
| `packages/doorman.yaml` | ๐ช badge scan ingest + decisions |
| `packages/plant_snmp.yaml` | ๐ก๏ธ SNMP pollers + templates |
| `automations.yaml` | ๐จ tiered alerts + watchdogs |
| `dashboards/` | Lovelace dashboards |
| `tools/` | operator tooling (websocket CLI) |
| `docs/reference-packs/` | historical YAML references โ NOT loaded |
## ๐ Related
- Badge listener + relay code: [`KNEL/doorman`](https://git.knownelement.com/KNEL/doorman)
- Wider fleet (Proxmox, DNS, monitoring): [`KNEL/PFVCluster`](https://git.knownelement.com/KNEL/PFVCluster)
- Badge roster (private): `KNEL/access-roster` ๐
## License
Copyright ยฉ 2026 Known Element Enterprises / Charles Wyble.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. See [LICENSE](LICENSE)
for the full text.