Files
pika/pkg/agent/collector/temperature.go
T
2026-08-12 18:59:29 +08:00

167 lines
5.0 KiB
Go

package collector
import (
"context"
"runtime"
"strings"
"unicode/utf8"
"github.com/pika-monitor/pika/internal/protocol"
"github.com/shirou/gopsutil/v4/sensors"
)
// TemperatureCollector 温度监控采集器
type TemperatureCollector struct{}
// NewTemperatureCollector 创建温度采集器
func NewTemperatureCollector() *TemperatureCollector {
return &TemperatureCollector{}
}
// Collect 采集温度数据(某些系统可能不支持)
func (t *TemperatureCollector) Collect() ([]*protocol.TemperatureData, error) {
// 使用 gopsutil 的 sensors 包采集温度数据
temps, err := sensors.TemperaturesWithContext(context.Background())
if err != nil && len(temps) == 0 {
// 如果获取失败,返回空数组(某些系统可能不支持)
return []*protocol.TemperatureData{}, nil
}
// 按类型聚合温度数据(同类型取最大值)
typeMaxTemp := make(map[string]*protocol.TemperatureData)
for _, temp := range temps {
// 跳过温度值为 0 的传感器(可能是未激活或不支持的传感器)
if temp.Temperature == 0 {
continue
}
// https://github.com/shirou/gopsutil/issues/1832
if runtime.GOOS == "darwin" && !utf8.ValidString(temp.SensorKey) {
continue
}
// 识别传感器类型
sensorType := guessSensorType(temp.SensorKey)
if sensorType == "OTHER" {
continue
}
// 对于同一类型的传感器,取温度最大值
if existing, ok := typeMaxTemp[sensorType]; !ok || temp.Temperature > existing.Temperature {
typeMaxTemp[sensorType] = &protocol.TemperatureData{
SensorKey: temp.SensorKey,
Temperature: temp.Temperature,
Type: sensorType,
}
}
}
// 将聚合后的数据转换为列表
var tempDataList []*protocol.TemperatureData
for _, tempData := range typeMaxTemp {
tempDataList = append(tempDataList, tempData)
}
return tempDataList, nil
}
// guessSensorType 根据操作系统和传感器名称推断类型
func guessSensorType(key string) string {
keyLower := strings.ToLower(key)
// ---------------- Linux 常见规则 ----------------
if runtime.GOOS == "linux" {
// CPU 温度传感器
if strings.Contains(keyLower, "coretemp") || // Intel Core 系列
strings.Contains(keyLower, "k10temp") || // AMD Ryzen/EPYC
strings.Contains(keyLower, "zenpower") || // AMD Zen 架构
strings.Contains(keyLower, "cpu_thermal") || // 通用 CPU 热传感器
strings.Contains(keyLower, "soc_thermal") || // ARM SoC
strings.Contains(keyLower, "tctl") || // AMD Tctl (控制温度)
strings.Contains(keyLower, "tdie") || // AMD Tdie (芯片温度)
strings.Contains(keyLower, "package id") || // Intel 封装温度
strings.Contains(keyLower, "core ") || // CPU 核心温度
strings.Contains(keyLower, "scpi_sensors") || // ARM SCPI 温度传感器
strings.Contains(keyLower, "aml_thermal") { // Amlogic SoC 温度
return "CPU"
}
// GPU 温度传感器
if strings.Contains(keyLower, "amdgpu") || // AMD GPU
strings.Contains(keyLower, "radeon") || // AMD Radeon
strings.Contains(keyLower, "nvidia") || // NVIDIA GPU
strings.Contains(keyLower, "nouveau") || // NVIDIA 开源驱动
strings.Contains(keyLower, "gpu") { // 通用 GPU
return "GPU"
}
// NPU 温度传感器
if strings.Contains(keyLower, "npu") {
return "NPU"
}
// 硬盘/SSD 温度传感器
if strings.Contains(keyLower, "nvme") || // NVMe SSD
strings.Contains(keyLower, "drivetemp") || // 硬盘温度
strings.Contains(keyLower, "sata") || // SATA 设备
strings.Contains(keyLower, "scsi") || // SCSI 设备
strings.Contains(keyLower, "composite") { // NVMe Composite 温度
return "DISK"
}
// 主板芯片组温度
if strings.Contains(keyLower, "pch") || // Platform Controller Hub
strings.Contains(keyLower, "chipset") {
return "CHIPSET"
}
// ACPI 温度区域 (通常是主板/系统温度)
if strings.Contains(keyLower, "acpitz") || // ACPI Thermal Zone
strings.Contains(keyLower, "thermal_zone") {
return "SYSTEM"
}
// 电源温度
if strings.Contains(keyLower, "psu") ||
strings.Contains(keyLower, "power supply") {
return "PSU"
}
}
// ---------------- macOS 常见规则 ----------------
if runtime.GOOS == "darwin" {
// 电池温度传感器
if strings.Contains(keyLower, "battery") || strings.Contains(keyLower, "gas gauge") {
return "BATTERY"
}
// 存储设备温度传感器
if strings.Contains(keyLower, "nand") || strings.Contains(keyLower, "disk") {
return "DISK"
}
// GPU 温度传感器
if strings.Contains(keyLower, "gpu") {
return "GPU"
}
// PMU tdie* 系列是 CPU 核心温度 (die temperature)
// PMU tdev* 系列是设备/外围温度 (device temperature)
// PMU tcal 是校准温度
if strings.HasPrefix(keyLower, "pmu") {
if strings.Contains(keyLower, "tdie") {
return "CPU"
}
// tdev 和 tcal 等其他 PMU 传感器归类为 OTHER
return "OTHER"
}
// 其他包含 die 的可能是 CPU
if strings.Contains(keyLower, "die") || strings.Contains(keyLower, "cpu") {
return "CPU"
}
}
return "OTHER"
}