Skip to content

Commit

Permalink
handle errors better
Browse files Browse the repository at this point in the history
  • Loading branch information
snhilde committed Aug 23, 2020
1 parent d40d8e3 commit 398ef7f
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 159 deletions.
39 changes: 18 additions & 21 deletions sbbattery/battery.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ var colorEnd = "^d^"

// These are the possible charging states of the battery.
const (
UNKNOWN = -1
CHARGING = iota
DISCHARGING
FULL
statusUnknown = 0
statusCharging = iota
statusDischarging
statusFull
)

// Routine is the main type for this package.
Expand Down Expand Up @@ -73,15 +73,15 @@ func New(colors ...[3]string) *Routine {

// Update reads the current battery capacity left and calculates a percentage based on it.
func (r *Routine) Update() (bool, error) {
// Handle error reading max capacity.
if r.max < 0 {
// Handle error in New or error reading max capacity.
if r.max <= 0 {
return false, r.err
}

// Get current charge and calculate a percentage.
now, err := readCharge("/sys/class/power_supply/BAT0/charge_now")
if err != nil {
r.err = err
r.err = errors.New("Error reading charge")
return true, err
}

Expand All @@ -95,19 +95,19 @@ func (r *Routine) Update() (bool, error) {
// Get charging status.
status, err := ioutil.ReadFile("/sys/class/power_supply/BAT0/status")
if err != nil {
r.err = err
r.err = errors.New("Error reading status")
return true, err
}

switch strings.TrimSpace(string(status)) {
case "Charging":
r.status = CHARGING
r.status = statusCharging
case "Discharging":
r.status = DISCHARGING
r.status = statusDischarging
case "Full":
r.status = FULL
r.status = statusFull
default:
r.status = UNKNOWN
r.status = statusUnknown
}

return true, nil
Expand All @@ -116,8 +116,6 @@ func (r *Routine) Update() (bool, error) {
// String formats the percentage of battery left.
func (r *Routine) String() string {
var c string
var s string

if r.perc > 25 {
c = r.colors.normal
} else if r.perc > 10 {
Expand All @@ -126,14 +124,13 @@ func (r *Routine) String() string {
c = r.colors.error
}

if r.status == CHARGING {
s = fmt.Sprintf("+%v%%", r.perc)
} else if r.status == DISCHARGING {
s = fmt.Sprintf("-%v%%", r.perc)
} else if r.status == FULL {
s := fmt.Sprintf("%v%%", r.perc)
if r.status == statusCharging {
s = "+" + s
} else if r.status == statusDischarging {
s = "-" + s
} else if r.status == statusFull {
s = "Full"
} else {
s = fmt.Sprintf("%v%%", r.perc)
}

return fmt.Sprintf("%s%s BAT%s", c, s, colorEnd)
Expand Down
44 changes: 22 additions & 22 deletions sbcputemp/cputemp.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
)
Expand All @@ -21,11 +21,8 @@ type Routine struct {
// Error encountered along the way, if any.
err error

// Path to the device directory, as discovered in findDir().
path string

// Slice of files that contain temperature readings.
files []os.FileInfo
files []string

// Average temperature across all sensors, in degrees Celsius.
temp int
Expand Down Expand Up @@ -62,38 +59,41 @@ func New(colors ...[3]string) *Routine {
colorEnd = ""
}

// Error will be handled in Update() and String().
r.path, r.err = findDir()
if r.err != nil {
path, err := findDir()
if err != nil {
r.err = err
return &r
}

// Error will be handled in Update() and String().
r.files, r.err = findFiles(r.path)
files, err := findFiles(path)
if err != nil {
r.err = err
return &r
}

r.files = files
return &r
}

// Update reads out the value of each sensor, gets an average of all temperatures, and converts it from milliCelsius to
// Celsius. If we have trouble reading a particular sensor, then we'll skip it on this pass.
func (r *Routine) Update() (bool, error) {
var n int

if r.path == "" || len(r.files) == 0 {
// Handle error in New.
if len(r.files) == 0 {
return false, r.err
}

r.temp = 0
for _, file := range r.files {
b, err := ioutil.ReadFile(r.path + file.Name())
b, err := ioutil.ReadFile(file)
if err != nil {
r.err = err
r.err = errors.New("Error reading " + filepath.Base(file))
return true, err
}

n, err = strconv.Atoi(strings.TrimSpace(string(b)))
n, err := strconv.Atoi(strings.TrimSpace(string(b)))
if err != nil {
r.err = err
r.err = errors.New("Error parsing " + filepath.Base(file))
return true, err
}

Expand All @@ -112,7 +112,6 @@ func (r *Routine) Update() (bool, error) {
// String prints a formatted temperature average in degrees Celsius.
func (r *Routine) String() string {
var c string

if r.temp < 75 {
c = r.colors.normal
} else if r.temp < 100 {
Expand Down Expand Up @@ -170,18 +169,19 @@ func findDir() (string, error) {

// findFiles goes through the given path and builds a list of files that contain a temperature reading. These files will
// begin with "temp" and end with "input".
func findFiles(path string) ([]os.FileInfo, error) {
var b []os.FileInfo
func findFiles(path string) ([]string, error) {
var b []string

files, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
}

for _, file := range files {
if strings.HasPrefix(file.Name(), "temp") && strings.HasSuffix(file.Name(), "input") {
filename := file.Name()
if strings.HasPrefix(filename, "temp") && strings.HasSuffix(filename, "input") {
// We found a temperature reading. Add it to the list.
b = append(b, file)
b = append(b, filepath.Join(path, filename))
}
}

Expand Down
58 changes: 33 additions & 25 deletions sbcpuusage/cpuusage.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type stats struct {
func New(colors ...[3]string) *Routine {
var r Routine

// Set this now so we can key off it in Update to determine whether or not New was successful.
r.threads = -1

// Do a minor sanity check on the color codes.
if len(colors) == 1 {
for _, color := range colors[0] {
Expand All @@ -67,12 +70,13 @@ func New(colors ...[3]string) *Routine {
colorEnd = ""
}

// Find out how many threads the CPU has.
r.threads, r.err = numThreads()
if r.err != nil {
return &r
}

err := readFile(&(r.oldStats))
err := readStats(&(r.oldStats))
if err != nil {
r.err = err
}
Expand All @@ -83,9 +87,13 @@ func New(colors ...[3]string) *Routine {
// Update gets the current CPU stats, compares them to the last-read stats, and calculates the percentage of CPU
// currently being used.
func (r *Routine) Update() (bool, error) {
var newStats stats
// Handle error in New.
if r.threads < 0 {
return false, r.err
}

err := readFile(&newStats)
var newStats stats
err := readStats(&newStats)
if err != nil {
r.err = err
return true, err
Expand Down Expand Up @@ -144,28 +152,6 @@ func (r *Routine) Name() string {
return "CPU Usage"
}

// readFile opens /proc/stat and reads out the CPU stats from the first line.
func readFile(newStats *stats) error {
// The first line of /proc/stat will look like this:
// "cpu userVal niceVal sysVal idleVal ..."
f, err := os.Open("/proc/stat")
if err != nil {
return err
}
defer f.Close()

reader := bufio.NewReader(f)

line, err := reader.ReadString('\n')
if err != nil {
return err
}

// Error will be handled in String().
_, err = fmt.Sscanf(line, "cpu %v %v %v %v", &(newStats.user), &(newStats.nice), &(newStats.sys), &(newStats.idle))
return err
}

// The shell command 'lscpu' will return a variety of CPU information, including the number of threads
// per CPU core. We don't care about the number of cores, because we're already reading in the
// averaged total. We only want to know if we need to be changing its range. To get this number, we're
Expand All @@ -191,3 +177,25 @@ func numThreads() (int, error) {
// If we made it this far, then we didn't find anything.
return -1, errors.New("Failed to find number of threads")
}

// readStats opens /proc/stat and reads out the CPU stats from the first line.
func readStats(newStats *stats) error {
// The first line of /proc/stat will look like this:
// "cpu userVal niceVal sysVal idleVal ..."
f, err := os.Open("/proc/stat")
if err != nil {
return err
}
defer f.Close()

reader := bufio.NewReader(f)

line, err := reader.ReadString('\n')
if err != nil {
return err
}

// Error will be handled in String().
_, err = fmt.Sscanf(line, "cpu %v %v %v %v", &(newStats.user), &(newStats.nice), &(newStats.sys), &(newStats.idle))
return err
}
25 changes: 17 additions & 8 deletions sbdisk/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ type fs struct {
func New(paths []string, colors ...[3]string) *Routine {
var r Routine

for _, path := range paths {
r.disks = append(r.disks, fs{path: path})
if len(paths) == 0 {
r.err = errors.New("No paths provided")
return &r
}

// Do a minor sanity check on the color codes.
Expand All @@ -76,18 +77,27 @@ func New(paths []string, colors ...[3]string) *Routine {
colorEnd = ""
}

// We want to do this after checking the colors so we can know in Update if New was successful or not.
for _, path := range paths {
r.disks = append(r.disks, fs{path: path})
}

return &r
}

// Update gets the amount of used and total disk space and converts them into a human-readable size for each provided
// filesystem.
func (r *Routine) Update() (bool, error) {
var b syscall.Statfs_t
// Handle error in New.
if len(r.disks) == 0 {
return false, r.err
}

for i, disk := range r.disks {
var b syscall.Statfs_t
err := syscall.Statfs(disk.path, &b)
if err != nil {
r.err = err
r.err = errors.New("Error checking stats")
return true, err
}

Expand All @@ -104,9 +114,8 @@ func (r *Routine) Update() (bool, error) {

// String formats and prints the amounts of disk space for each provided filesystem.
func (r *Routine) String() string {
var c string
var b strings.Builder

c := ""
b := new(strings.Builder)
for i, disk := range r.disks {
if disk.perc > 90 {
c = r.colors.error
Expand All @@ -120,7 +129,7 @@ func (r *Routine) String() string {
b.WriteString(", ")
}
b.WriteString(c)
fmt.Fprintf(&b, "%s: %v%c/%v%c", disk.path, disk.used, disk.usedUnit, disk.total, disk.totalUnit)
fmt.Fprintf(b, "%s: %v%c/%v%c", disk.path, disk.used, disk.usedUnit, disk.total, disk.totalUnit)
b.WriteString(colorEnd)
}

Expand Down
15 changes: 10 additions & 5 deletions sbfan/fan.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,17 @@ func New(colors ...[3]string) *Routine {
colorEnd = ""
}

// Find the max fan speed file and read its value.
// Find the files holding the values for the maximum fan speed and the current fan speed.
maxFile, outFile, err := findFiles()
if err != nil {
r.err = err
return &r
}

// Error will be handled later in Update() and String().
// Find the max fan speed file and read its value.
r.max, r.err = readSpeed(maxFile)
r.fanPath = outFile

r.fanPath = outFile
return &r
}

Expand All @@ -84,8 +83,14 @@ func (r *Routine) Update() (bool, error) {
return false, r.err
}

r.speed, r.err = readSpeed(r.fanPath)
return true, r.err
speed, err := readSpeed(r.fanPath)
if err != nil {
r.err = errors.New("Error reading speed")
return true, err
}

r.speed = speed
return true, nil
}

// String prints the current speed in RPM.
Expand Down
Loading

0 comments on commit 398ef7f

Please sign in to comment.