Files
josh 9bb4b09a04
CI / Lint + build + test (push) Has been cancelled
Initial commit: full Phases 1-6 implementation
Post-repair hardware validation pipeline for Proxmox cluster hosts.
Go orchestrator + in-image agent + mkosi live image + bundled dnsmasq
PXE + SQLite + HTMX/SSE UI + notify registry + janitor + full docs.
2026-04-17 21:32:10 -04:00

68 lines
1.7 KiB
Go

package probes
import (
"os"
"path/filepath"
"strconv"
"strings"
)
// ThermalSample is one reading from /sys/class/hwmon. Kind is "temp",
// Key is the label (or chip-relative name) and Value is degrees C.
type ThermalSample struct {
Kind string
Key string
Value float64
Unit string
}
// Thermals walks /sys/class/hwmon looking for temp*_input files. The
// kernel reports millidegrees C; we divide by 1000. Labels come from
// temp*_label (preferred) or a chip-relative fallback.
//
// This is also used by the thermal sidecar; it re-reads on each tick
// rather than holding open handles so hot-plugged sensors (e.g. a PCIe
// card enumerating late) get picked up.
func Thermals() []ThermalSample {
root := "/sys/class/hwmon"
chips, err := os.ReadDir(root)
if err != nil {
return nil
}
var out []ThermalSample
for _, c := range chips {
base := filepath.Join(root, c.Name())
chipName := strings.TrimSpace(readFileStr(filepath.Join(base, "name")))
files, err := os.ReadDir(base)
if err != nil {
continue
}
for _, f := range files {
name := f.Name()
if !strings.HasPrefix(name, "temp") || !strings.HasSuffix(name, "_input") {
continue
}
idx := strings.TrimSuffix(strings.TrimPrefix(name, "temp"), "_input")
label := strings.TrimSpace(readFileStr(filepath.Join(base, "temp"+idx+"_label")))
if label == "" {
label = chipName + "/temp" + idx
}
raw := strings.TrimSpace(readFileStr(filepath.Join(base, name)))
milli, err := strconv.Atoi(raw)
if err != nil {
continue
}
out = append(out, ThermalSample{Kind: "temp", Key: label, Value: float64(milli) / 1000, Unit: "C"})
}
}
return out
}
func readFileStr(p string) string {
b, err := os.ReadFile(p)
if err != nil {
return ""
}
return string(b)
}