2 Commits
v1.3 ... v1.4

Author SHA1 Message Date
eleksir
757fb5e57e Add sysfs method to get battery charge for linux 2025-04-24 20:42:32 +03:00
eleksir
6b81991ebb Add small delay in spawner 2025-04-24 18:38:19 +03:00
4 changed files with 115 additions and 15 deletions

View File

@@ -518,6 +518,15 @@
"battery": {
"enabled": false,
// Valid only on linux, where we have mounted sysfs and /sys/class/power_supply/BAT0/capacity available
"use_sysfs": false,
// it is possible to set files here, if none set, /sys/class/power_supply/BAT0/capacity will be taken.
"sysfs_files": [
"/sys/class/power_supply/BAT0/capacity",
"/sys/class/power_supply/HIDP0/capacity"
],
// If omitted set to default color defined up here.
"color": "#3e78fd",

View File

@@ -2,7 +2,12 @@ package lib
import (
"fmt"
"log"
"math"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/distatus/battery"
@@ -11,9 +16,6 @@ import (
// UpdateBatteryInfo updates info about battery charge.
func (c *MyConfig) UpdateBatteryInfo() {
var (
ch int
status string
Batts string
InitialDelay = 100 * time.Millisecond
LoopIterationDelay = 5 * time.Second
Delay = InitialDelay
@@ -26,9 +28,82 @@ func (c *MyConfig) UpdateBatteryInfo() {
ticker.Reset(Delay)
}
batteries, _ := battery.GetAll()
var (
batteries []*battery.Battery = []*battery.Battery{}
Batts string
ch int
status string
)
if c.Battery.UseSysfs {
for _, file := range c.Battery.SysfsFiles {
var batt battery.Battery
_, err := os.Stat(file)
// If file exists.
if !os.IsNotExist(err) {
var (
myCharge string
myStatus string
)
b, err := os.ReadFile(file)
if err != nil {
log.Printf("Unable to read file %s: %s", file, err)
continue
}
myCharge = strings.Trim(string(b), "\n")
statusFile := filepath.Dir(file) + "/status"
// If file exists.
if !os.IsNotExist(err) {
b, err := os.ReadFile(statusFile)
if err != nil {
log.Printf("Unable to read file %s: %s", statusFile, err)
continue
}
myStatus = strings.Trim(string(b), "\n")
} else {
continue
}
// Make stub battery class :) .
switch myStatus {
case "Charging":
batt.State.Raw = battery.Charging
case "Discharging":
batt.State.Raw = battery.Discharging
case "Empty":
batt.State.Raw = battery.Empty
case "Full":
batt.State.Raw = battery.Full
default:
batt.State.Raw = battery.Unknown
}
ch, err := strconv.Atoi(myCharge)
if err != nil {
log.Printf("Unable to convert string from file %s to integer", file)
continue
}
batt.Current = float64(ch)
batteries = append(batteries, &batt)
}
}
} else {
batteries, _ = battery.GetAll()
// In theory, this module should give for each entry its separate err, but in practice it gives
// one single err for all entries, so we cannot detemine whist exatly entry errored.
}
var (
battsInfo string
@@ -49,7 +124,11 @@ func (c *MyConfig) UpdateBatteryInfo() {
// N.B. there can be case when battery is overcharged and shows >100%. It also can indicate that
// calibration data is out of date and battery should be re-calibrated.
if c.Battery.UseSysfs {
ch = int(b.Current)
} else {
ch = int(math.Round((b.Full - (b.Full - b.Current)) * (100 / b.Full)))
}
switch {
case ch <= 500 && ch >= 84:

View File

@@ -135,6 +135,8 @@ type MyConfig struct {
Battery struct {
Enabled bool `json:"enabled,omitempty"`
UseSysfs bool `json:"use_sysfs,omitempty"`
SysfsFiles []string `json:"sysfs_files,omitempty"`
Color string `json:"color,omitempty"`
Background string `json:"background,omitempty"`
Font string `json:"font,omitempty"`
@@ -778,6 +780,15 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
}
// sampleConfig.Battery.Enabled will be false if not set in config
// sampleConfig.Battery.UseSysfs will be false if not set in config
if len(sampleConfig.Battery.SysfsFiles) == 0 {
sampleConfig.Battery.SysfsFiles = append(
sampleConfig.Battery.SysfsFiles,
"/sys/class/power_supply/BAT0/capacity",
)
}
if sampleConfig.Battery.Color == "" {
sampleConfig.Battery.Color = sampleConfig.Color
}

View File

@@ -11,6 +11,7 @@ import (
// Spawner forks and execs given program, and also detaches form its control tty.
func (c *MyConfig) Spawner() {
for prg := range c.Channels.RunChan {
<-time.After(25 * time.Millisecond)
devnullR, _ := os.Open(os.DevNull)
devnullW, _ := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644)