-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.go
138 lines (118 loc) · 3.45 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package utils
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"strconv"
"strings"
)
const SensorPath = "/sys/class/hwmon"
// Returns the sensor value in its raw form as exposed by the /sys file system.
// For example, with the Intel Core i9-12900k, the temperature will be returned
// as an integer value in degrees Celcius. Fractional parts of the temperature
// (if supported by the CPU) will require conversion. Simply put, if the
// temperature is 20.5 degrees Celcius, the value returned by this function will
// be 20500.
//
// The sensor string must be a valid full path to the sensor:
//
// - /sys/class/hwmon/hwmon1/temp1_input
//
// Any error that prevents reading the value will be returned.
func GetSensorValue(sensor string) (int64, error) {
sensorValueRaw, err := os.ReadFile(sensor)
if err != nil {
return 0, err
}
sensorValueTrimmed := strings.TrimSuffix(string(sensorValueRaw), "\n")
sensorValue, err := strconv.ParseInt(sensorValueTrimmed, 10, 32)
if err != nil {
return 0, err
}
return sensorValue, nil
}
// Converts a value returned by GetSensorValue into a float64 temperature
// in degrees Celcius.
func ReadSensorValue(value int64) float64 {
return float64(value) / 1000.0
}
// Returns true if the mode has the symbolic link flag set.
func symbolicLink(mode fs.FileMode) bool {
return mode&fs.ModeSymlink != 0
}
// Searches all directories under SensorPath, following symbolic links, for
// an hwmonX/name file whose contents matches name and a *_input file whose
// corresponding *_label file matches label. Returns the full path to the
// matching *_input file containing the sensor data, or an error if no match
// was was found.
func FindSensorPath(name, label string) (string, error) {
sensorPath := ""
entries, err := os.ReadDir(SensorPath)
if err != nil {
return sensorPath, err
}
for _, entry := range entries {
info, err := entry.Info()
if err != nil {
return sensorPath, err
}
if !symbolicLink(info.Mode()) {
err := errors.New("Expected " + entry.Name() + " to be a symbolic link.")
return sensorPath, err
}
fp := filepath.Join(SensorPath, entry.Name())
link, err := os.Readlink(fp)
if err != nil {
return sensorPath, err
}
path := filepath.Join(SensorPath, link)
entries, err := os.ReadDir(path)
if err != nil {
return sensorPath, err
}
nameFound := false
labelFound := false
for _, entry := range entries {
if strings.HasSuffix(entry.Name(), "name") {
fp := filepath.Join(path, entry.Name())
raw, err := os.ReadFile(fp)
if err != nil {
return sensorPath, err
}
data := string(raw)
data = strings.TrimSpace(data)
if data == name {
nameFound = true
}
} else if strings.HasSuffix(entry.Name(), "label") { // e.g. temp1_label
fp := filepath.Join(path, entry.Name())
raw, err := os.ReadFile(fp)
if err != nil {
return sensorPath, err
}
data := string(raw)
data = strings.TrimSpace(data)
data = strings.ToLower(data)
if !strings.HasPrefix(data, label) {
continue
}
prefix := strings.TrimSuffix(entry.Name(), "label")
filename := fmt.Sprintf("%s%s", prefix, "input")
fp = filepath.Join(path, filename)
_, err = os.ReadFile(fp)
if err != nil {
return sensorPath, err
}
labelFound = true
sensorPath = fp
}
if nameFound && labelFound {
return sensorPath, nil
}
}
}
err = errors.New("No sensor data found for " + name + "/" + label)
return sensorPath, err
}