From 82fc0429899d1c5563026a0107b44200f3b2946d Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Sat, 18 Oct 2025 16:45:10 -0400 Subject: [PATCH] Initial code commit --- .gitignore | 1 + go.mod | 8 +++++++ go.sum | 4 ++++ main.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 .gitignore create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e7c5768 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/unifi-shutd diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f8c3913 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module unifi-shutd + +go 1.25.2 + +require ( + github.com/rwinkhart/go-boilerplate v0.1.0 + github.com/rwinkhart/uni-nut v1.1.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9ffab6a --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/rwinkhart/go-boilerplate v0.1.0 h1:EzlVj6R7Bxtl79Nl7R5zRcg6s+Cf2FAqGIzR4giWTQg= +github.com/rwinkhart/go-boilerplate v0.1.0/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY= +github.com/rwinkhart/uni-nut v1.1.0 h1:oVq6pQj/2oAx18tcuXRDLXy0ebhgbynEABn+tH/MS3Q= +github.com/rwinkhart/uni-nut v1.1.0/go.mod h1:H5s8llqTO0UnerDqZHn+30bJVY07OLSoR1PaZa4yzPk= diff --git a/main.go b/main.go new file mode 100644 index 0000000..ccbd1b5 --- /dev/null +++ b/main.go @@ -0,0 +1,63 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/exec" + "strconv" + "time" + + "github.com/rwinkhart/go-boilerplate/other" + nut "github.com/rwinkhart/uni-nut" +) + +func main() { + if len(os.Args) != 5 { + printUsageInfo() + } + intervalInt, err := strconv.Atoi(os.Args[3]) + if err != nil { + other.PrintError("Failed to parse scan interval as integer: "+err.Error(), 2) + } + intervalDur := time.Duration(intervalInt) * time.Second + shutdownMultiplier, err := strconv.Atoi(os.Args[4]) + if err != nil { + other.PrintError("Failed to parse bad scan limit as integer: "+err.Error(), 3) + } + client, err := nut.Dial(os.Args[1]) + if err != nil { + other.PrintError("Failed to dial NUT server ("+os.Args[1]+"): "+err.Error(), 4) + } + log.Println("Starting NUT monitoring loop...") + cmd := exec.Command("/sbin/poweroff") + var value string + var badCycles int + for { + time.Sleep(intervalDur) + value, err = client.GetVar(os.Args[2], "ups.status") + if err != nil { + other.PrintError("Failed to get status from \""+os.Args[2]+"\": "+err.Error(), 5) + } + + switch value { + case "OB DISCHRG": + badCycles++ + log.Printf("BAD cycle: %d", badCycles) + default: + badCycles = 0 + } + if badCycles >= shutdownMultiplier { + log.Println("Bad scan limit reached; initiating shutdown...") + err := cmd.Run() + if err != nil { + other.PrintError("Failed to execute shutdown command: "+err.Error(), 6) + } + } + } +} + +func printUsageInfo() { + fmt.Print("\nUsage: unifi-shutd \n\n") + os.Exit(0) +}