diff --git a/src/common/common.go b/src/common/common.go new file mode 100644 index 0000000..50d5200 --- /dev/null +++ b/src/common/common.go @@ -0,0 +1,61 @@ +package common + +import ( + "log" + "os" + "strconv" + "syscall" + "time" + "fmt" +) + +var ( + CPU_FAN_PIN = 12 + DISK_FAN_PIN = 13 + BUTTON_PIN = 17 + OLED_RESET_PIN = 23 + TEMP = GetEnv("TEMP_SENSOR", "/sys/class/thermal/thermal_zone0/temp") + DU_PATH = GetEnv("OLED_DU_PATH", "/") +) + +func Clamp (x, min, max uint32) uint32 { + if x > max { + return max + } + if x < min { + return min + } + return x +} + +func GetEnv(key string, default_value string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + return default_value +} + +func ReadTemp() float64 { + dat, err:= os.ReadFile(TEMP) + if err != nil { + log.Fatal(err) + } + + var temperature, _ = strconv.ParseFloat(string(dat[:3]), 64) + return temperature / 10.0 +} + +func DiskUsage() float64 { + var stat syscall.Statfs_t + syscall.Statfs(DU_PATH, &stat) + return 100.0 * float64(stat.Blocks - stat.Bavail) / float64(stat.Blocks) +} + +func GetLines() []string { + lines := []string { + time.Now().Format("Time: 15:04:05"), + fmt.Sprintf("Temp: %.1f°C", ReadTemp()), + fmt.Sprintf("Disk: %02.0f%%", DiskUsage()), + } + return lines +} diff --git a/src/fan-control/main.go b/src/fan-control/main.go index f35838d..e262ac4 100644 --- a/src/fan-control/main.go +++ b/src/fan-control/main.go @@ -1,61 +1,37 @@ package main import ( - "time" + "github.com/baierjan/go-sata-hat/src/common" + "fmt" - "github.com/stianeikeland/go-rpio/v4" + "log" "os" "os/signal" "strconv" -) + "syscall" + "time" -func getEnv(key string, default_value string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - return default_value -} + "github.com/stianeikeland/go-rpio/v4" +) var ( - fans = [2] rpio.Pin {rpio.Pin(12), rpio.Pin(13)} + fans = [2] rpio.Pin {rpio.Pin(common.CPU_FAN_PIN), rpio.Pin(common.DISK_FAN_PIN)} current_level uint32 - TEMP = getEnv("TEMP_SENSOR", "/sys/class/thermal/thermal_zone0/temp") - MIN, _ = strconv.ParseFloat(getEnv("TEMP_MIN", "35.0"), 64) - MED, _ = strconv.ParseFloat(getEnv("TEMP_MED", "50.0"), 64) - MAX, _ = strconv.ParseFloat(getEnv("TEMP_MAX", "55.0"), 64) + MIN, _ = strconv.ParseFloat(common.GetEnv("TEMP_MIN", "35.0"), 64) + MED, _ = strconv.ParseFloat(common.GetEnv("TEMP_MED", "50.0"), 64) + MAX, _ = strconv.ParseFloat(common.GetEnv("TEMP_MAX", "55.0"), 64) ) -func Clamp (x, min, max uint32) uint32 { - if x > max { - return max - } - if x < min { - return min - } - return x -} - func setFan(fan int, level uint32) { - fmt.Fprintf(os.Stdout, "Setting fan %d to level %d\n", fan, level) + log.Print(fmt.Sprintf("Setting fan %d to level %d\n", fan, level)) fans[fan].Mode(rpio.Pwm) fans[fan].Freq(100000) fans[fan].DutyCycle(level, 4) } -func readTemp() float64 { - dat, err:= os.ReadFile(TEMP) - if err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(3) - } - - var temperature, _ = strconv.ParseFloat(string(dat[:3]), 64) - return temperature / 10.0 -} - func setLevel() { var level uint32 = 2 - var temperature = readTemp() + var temperature = common.ReadTemp() if temperature >= MAX { level = 4 } @@ -69,7 +45,7 @@ func setLevel() { level = 1 } if current_level != level { - fmt.Fprintf(os.Stdout, "Current temperature is %.0f°C\n", temperature) + log.Print(fmt.Sprintf("Current temperature is %.0f°C\n", temperature)) setFan(0, level) setFan(1, level) current_level = level @@ -83,28 +59,32 @@ func main() { } if err := rpio.Open(); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(2) + log.Fatal(err) } - defer rpio.Close() + // Install signal handler signal_chan := make(chan os.Signal, 1) - signal.Notify(signal_chan, os.Interrupt, os.Kill) + signal.Notify(signal_chan, os.Interrupt, os.Kill, syscall.SIGTERM) go func() { for { s := <-signal_chan switch s { - case os.Interrupt, os.Kill: - fmt.Fprintf(os.Stdout, "Exiting...\n") + case os.Interrupt, os.Kill, syscall.SIGTERM: + log.Print("Exiting...") + rpio.Close() os.Exit(0) } } }() - var input, _ = strconv.ParseUint(os.Args[2], 10, 64) - var level = Clamp(uint32(input), 0, 4) + var input, err = strconv.ParseUint(os.Args[2], 10, 64) + if err != nil { + log.Fatal(err) + } + + var level = common.Clamp(uint32(input), 0, 4) switch os.Args[1] { case "cpu": @@ -115,10 +95,10 @@ func main() { setFan(0, level) setFan(1, level) case "auto": + log.Print("Starting automatic fan control...") for { setLevel() time.Sleep(time.Second) } } - } diff --git a/src/oled/main.go b/src/oled/main.go index 6c9e36e..7b8ac0c 100644 --- a/src/oled/main.go +++ b/src/oled/main.go @@ -1,67 +1,32 @@ package main import ( - "fmt" - "github.com/stianeikeland/go-rpio/v4" - "golang.org/x/image/font" - "golang.org/x/image/font/inconsolata" - "golang.org/x/image/math/fixed" + "github.com/baierjan/go-sata-hat/src/common" + "image" "log" "os" "os/signal" + "strconv" + "syscall" + "time" + + "github.com/stianeikeland/go-rpio/v4" + "golang.org/x/image/font" + "golang.org/x/image/font/inconsolata" + "golang.org/x/image/math/fixed" "periph.io/x/conn/v3/i2c/i2creg" "periph.io/x/devices/v3/ssd1306" "periph.io/x/devices/v3/ssd1306/image1bit" "periph.io/x/host/v3" - "strconv" - "syscall" - "time" ) -func getEnv(key string, default_value string) string { - if value, ok := os.LookupEnv(key); ok { - return value - } - return default_value -} - var ( - OLED_RESET_PIN = 23 - BUTTON_PIN = 17 - TEMP = getEnv("TEMP_SENSOR", "/sys/class/thermal/thermal_zone0/temp") - ROTATE, _ = strconv.ParseBool(getEnv("OLED_ROTATE", "true")) - DU_PATH = getEnv("OLED_DU_PATH", "/") + ROTATE, _ = strconv.ParseBool(common.GetEnv("OLED_ROTATE", "true")) ) -func Clamp (x, min, max uint32) uint32 { - if x > max { - return max - } - if x < min { - return min - } - return x -} - -func readTemp() float64 { - dat, err:= os.ReadFile(TEMP) - if err != nil { - log.Fatal(err) - } - - var temperature, _ = strconv.ParseFloat(string(dat[:3]), 64) - return temperature / 10.0 -} - -func diskUsage() float64 { - var stat syscall.Statfs_t - syscall.Statfs(DU_PATH, &stat) - return 100.0 * float64(stat.Blocks - stat.Bavail) / float64(stat.Blocks) -} - func resetOled() { - pin := rpio.Pin(OLED_RESET_PIN) + pin := rpio.Pin(common.OLED_RESET_PIN) pin.Mode(rpio.Output) pin.Low() time.Sleep(200 * time.Millisecond) @@ -69,14 +34,13 @@ func resetOled() { } func setupButton() rpio.Pin { - pin := rpio.Pin(BUTTON_PIN) + pin := rpio.Pin(common.BUTTON_PIN) pin.Input() pin.PullUp() pin.Detect(rpio.FallEdge) return pin } - func draw(dev *ssd1306.Dev) { f := inconsolata.Bold8x16 pin := setupButton() @@ -94,11 +58,7 @@ func draw(dev *ssd1306.Dev) { } } if show { - lines := [3]string{ - time.Now().Format("Time: 15:04:05"), - fmt.Sprintf("Temp: %.1f°C", readTemp()), - fmt.Sprintf("Disk: %02.0f%%", diskUsage()), - } + lines := common.GetLines() img := image1bit.NewVerticalLSB(dev.Bounds()) drawer := font.Drawer{ Dst: img,