Go service (nasmon/) plus nfpm packaging (packaging/), carried over from the home_nas monorepo. Adds rpm packaging alongside the existing deb build (Fedora/RHEL/Rocky dependency names via nfpm overrides, per-format systemd unit path, dpkg+rpm-compatible maintainer scripts) and a Gitea Actions workflow that builds both formats on every push. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
90 lines
2.2 KiB
Go
90 lines
2.2 KiB
Go
package collect
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Temp struct {
|
|
Chip string `json:"chip"`
|
|
Label string `json:"label"`
|
|
C float64 `json:"c"`
|
|
}
|
|
|
|
// ReadTemps lists every hwmon temperature input; falls back to thermal zones.
|
|
func ReadTemps() []Temp {
|
|
temps := readHwmon("/sys/class/hwmon")
|
|
if len(temps) == 0 {
|
|
temps = readThermalZones("/sys/class/thermal")
|
|
}
|
|
sort.Slice(temps, func(i, j int) bool {
|
|
if temps[i].Chip != temps[j].Chip {
|
|
return temps[i].Chip < temps[j].Chip
|
|
}
|
|
return temps[i].Label < temps[j].Label
|
|
})
|
|
return temps
|
|
}
|
|
|
|
func readHwmon(root string) []Temp {
|
|
var out []Temp
|
|
chips, _ := filepath.Glob(filepath.Join(root, "hwmon*"))
|
|
for _, chip := range chips {
|
|
name := readTrim(filepath.Join(chip, "name"))
|
|
inputs, _ := filepath.Glob(filepath.Join(chip, "temp*_input"))
|
|
for _, in := range inputs {
|
|
v, err := strconv.ParseFloat(readTrim(in), 64)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
base := strings.TrimSuffix(in, "_input")
|
|
label := readTrim(base + "_label")
|
|
if label == "" {
|
|
label = filepath.Base(base)
|
|
}
|
|
out = append(out, Temp{Chip: name, Label: label, C: v / 1000})
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func readThermalZones(root string) []Temp {
|
|
var out []Temp
|
|
zones, _ := filepath.Glob(filepath.Join(root, "thermal_zone*"))
|
|
for _, z := range zones {
|
|
v, err := strconv.ParseFloat(readTrim(filepath.Join(z, "temp")), 64)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
out = append(out, Temp{Chip: "thermal", Label: readTrim(filepath.Join(z, "type")), C: v / 1000})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// CPUTemp picks the most plausible CPU package temperature from the list.
|
|
func CPUTemp(temps []Temp) (float64, bool) {
|
|
best, found := 0.0, false
|
|
for _, t := range temps {
|
|
chip := strings.ToLower(t.Chip)
|
|
lbl := strings.ToLower(t.Label)
|
|
isCPU := chip == "coretemp" || chip == "k10temp" || chip == "zenpower" ||
|
|
strings.Contains(lbl, "package") || strings.Contains(lbl, "tctl") || strings.Contains(lbl, "tdie") ||
|
|
strings.Contains(lbl, "x86_pkg_temp") || strings.Contains(lbl, "cpu")
|
|
if isCPU && (!found || t.C > best) {
|
|
best, found = t.C, true
|
|
}
|
|
}
|
|
return best, found
|
|
}
|
|
|
|
func readTrim(p string) string {
|
|
b, err := os.ReadFile(p)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(string(b))
|
|
}
|