-
Notifications
You must be signed in to change notification settings - Fork 0
JSON Schemas
Prakhar Yadav edited this page Sep 16, 2026
·
1 revision
All schemas are versioned; breaking changes bump the v1. Additive booleans
(monitor_only, auto_restore_pending, polls) did not change the ids.
{
"schema": "afanctl.status.v1",
"daemon": { "running": true, "mode": "curve", "monitor_only": false, "auto_restore_pending": false, "watchdog_armed": true, "uptime_s": 981 },
"sensors": [ { "label": "Core 0", "temp_c": 53.0 } ],
"effective": { "temp_c": 53.0, "method": "max" },
"fan": { "rpm": 1203, "min_rpm": 1200, "max_rpm": 7200, "target_rpm": 1200, "manual": false },
"config": { "high_c": 66, "max_c": 86, "min_rpm": 1200, "max_rpm": 6200, "interval_s": 1,
"source": "/etc/afanctl/afanctl.toml" },
"recent_errors": [ { "ts": "2026-09-14T15:02:11+05:30", "msg": "…" } ]
}| Field | Type | Source |
|---|---|---|
daemon.running |
bool |
state.json exists |
daemon.mode |
observe|curve|hold
|
state.json, default observe
|
daemon.monitor_only |
bool |
state.json (degraded latch) |
daemon.auto_restore_pending |
bool |
state.json (unverified release) |
daemon.watchdog_armed |
bool | notify socket reachable |
daemon.uptime_s |
int |
polls × interval_s (legacy fallback watchdog_pings × interval_s) |
sensors[].label / temp_c
|
string / float|null | live sysfs reads (null = failed read) |
effective.temp_c / method
|
float|null / max
|
max over valid sensors |
fan.rpm/min_rpm/max_rpm/manual |
int/int/int/bool | live sysfs reads |
fan.target_rpm |
int|null |
state.json (null when daemon down) |
config.* |
ints | loaded config |
config.source |
string | config path, or defaults
|
recent_errors[] |
{ts, msg} |
state.json (last 5), else []
|
{ "schema": "afanctl.cmd.v1", "mode": "hold", "rpm": 3000 }| Field | Type | Notes |
|---|---|---|
schema |
string | always afanctl.cmd.v1
|
mode |
observe|curve|hold
|
unknown → logged + ignored |
rpm |
u32 | hold only; out-of-range → logged + ignored |
Atomic tmp+rename write. Freshness-gated on read (byte-identical re-issues ignored).
{ "schema": "afanctl.state.v1", "ts": "…", "mode": "curve", "t_eff_c": 71.2,
"target_rpm": 3400, "last_written_rpm": 3350, "actual_rpm": 3390,
"verified": true, "monitor_only": false, "auto_restore_pending": false, "polls": 981,
"watchdog_pings": 1962, "recent_errors": [ { "ts": "…", "msg": "…" } ] }| Field | Type | Notes |
|---|---|---|
schema |
string | always afanctl.state.v1
|
ts |
string | UTC YYYY-MM-DDTHH:MM:SSZ
|
mode |
string |
observe|curve|hold (commanded mode, kept during degradation) |
t_eff_c |
float|null | effective temp °C |
target_rpm |
int|null | decision target, clamped to hw band |
last_written_rpm |
int|null | applied.or(last_written) |
actual_rpm |
int|null | last observed tach |
verified |
bool | !monitor_only && l1_ok |
monitor_only |
bool | degraded latch (additive) |
auto_restore_pending |
bool | unverified release (additive) |
polls |
int | completed polls, 1/poll — uptime source (additive) |
watchdog_pings |
int | L3 audit, 2/poll — never uptime |
recent_errors |
array | ring, last 5 {ts, msg}
|
Atomic tmp+rename write, every poll. Serialize/write failures are logged and never abort control.
{
"schema": "afanctl.doctor.v1",
"checks": [ { "name": "…", "status": "PASS", "detail": "…" } ],
"compare": {
"samples": 600, "lost": 0, "mean_delta_rpm": 191.0, "max_abs_delta_rpm": 2260,
"quieter": 198, "louder": 392, "equal": 10,
"rows": [ { "t_eff_c": 63.0, "smc_rpm": 1200, "our_rpm": 1200, "delta_rpm": 0 } ],
"verdict": "…"
}
}compare is present only when --compare N ran. status is one of
PASS/FAIL/WARN per check (same fields as the human output).
- Home
- Installation
- CLI Reference
- Configuration
- Control Policy
- Supervisor and Run Modes
- Safety Model
- Hardware Interface
- Diagnostics (doctor)
- Plugin Surface (omafan)
- JSON Schemas
- systemd and Packaging
- Development and Testing
- Architecture and Internals
- Troubleshooting and FAQ
- Background and Verification
- afanctl-vs-mbpfan