mirror of
https://codeberg.org/frosty/modbot.git
synced 2024-09-19 11:46:34 -04:00
172 lines
4.5 KiB
Go
172 lines
4.5 KiB
Go
|
// modbot is a system information agregator
|
||
|
// Copyright (C) 2024 frosty <inthishouseofcards@gmail.com>
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as published
|
||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
|
||
|
package readers
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"strconv"
|
||
|
)
|
||
|
|
||
|
type BatteryStatus int
|
||
|
type BatteryTechnology int
|
||
|
|
||
|
const (
|
||
|
StatusUnknown BatteryStatus = iota
|
||
|
StatusCharging
|
||
|
StatusDischarging
|
||
|
StatusNotCharging
|
||
|
StatusFull
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
TechnologyUnknown BatteryTechnology = iota
|
||
|
TechnologyNimh
|
||
|
TechnologyLiion
|
||
|
TechnologyLipoly
|
||
|
TechnologyLife
|
||
|
TechnologyNicd
|
||
|
TechnologyLimn
|
||
|
)
|
||
|
|
||
|
type BatteryInfo struct {
|
||
|
Capacity uint8
|
||
|
Status BatteryStatus
|
||
|
Technology BatteryTechnology
|
||
|
}
|
||
|
|
||
|
func (bs BatteryStatus) String() string {
|
||
|
switch bs {
|
||
|
case StatusCharging:
|
||
|
return "Charging"
|
||
|
case StatusDischarging:
|
||
|
return "Discharging"
|
||
|
case StatusNotCharging:
|
||
|
return "Not charging"
|
||
|
case StatusFull:
|
||
|
return "Full"
|
||
|
default:
|
||
|
return "Unknown"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (bt BatteryTechnology) String() string {
|
||
|
switch bt {
|
||
|
case TechnologyNimh:
|
||
|
return "NiMH"
|
||
|
case TechnologyLiion:
|
||
|
return "Li-ion"
|
||
|
case TechnologyLipoly:
|
||
|
return "Li-poly"
|
||
|
case TechnologyLife:
|
||
|
return "LiFe"
|
||
|
case TechnologyNicd:
|
||
|
return "NiCd"
|
||
|
case TechnologyLimn:
|
||
|
return "LiMn"
|
||
|
default:
|
||
|
return "Unknown"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var batteryStatusMap = map[string]BatteryStatus{
|
||
|
"Unknown": StatusUnknown,
|
||
|
"Charging": StatusCharging,
|
||
|
"Discharging": StatusDischarging,
|
||
|
"Not charging": StatusNotCharging,
|
||
|
"Full": StatusFull,
|
||
|
}
|
||
|
|
||
|
var batteryTechnologyMap = map[string]BatteryTechnology{
|
||
|
"Unknown": TechnologyUnknown,
|
||
|
"NiMH": TechnologyNimh,
|
||
|
"Li-ion": TechnologyLiion,
|
||
|
"Li-poly": TechnologyLipoly,
|
||
|
"LiFe": TechnologyLife,
|
||
|
"NiCd": TechnologyNicd,
|
||
|
"LiMn": TechnologyLimn,
|
||
|
}
|
||
|
|
||
|
func BatteryStatusFromStr(statusStr string) BatteryStatus {
|
||
|
if status, exists := batteryStatusMap[statusStr]; exists {
|
||
|
return status
|
||
|
}
|
||
|
return StatusUnknown
|
||
|
}
|
||
|
|
||
|
func BatteryTechnologyFromStr(technologyStr string) BatteryTechnology {
|
||
|
if technology, exists := batteryTechnologyMap[technologyStr]; exists {
|
||
|
return technology
|
||
|
}
|
||
|
return TechnologyUnknown
|
||
|
}
|
||
|
|
||
|
func ReadBattery(batteryName string) (BatteryInfo, error) {
|
||
|
capacityPath := fmt.Sprintf("/sys/class/power_supply/%s/capacity", batteryName)
|
||
|
statusPath := fmt.Sprintf("/sys/class/power_supply/%s/status", batteryName)
|
||
|
technologyPath := fmt.Sprintf("/sys/class/power_supply/%s/technology", batteryName)
|
||
|
|
||
|
capacityFile, err := os.Open(capacityPath)
|
||
|
if err != nil {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to open %s: %w", capacityPath, err)
|
||
|
}
|
||
|
defer capacityFile.Close()
|
||
|
|
||
|
capacityScanner := bufio.NewScanner(capacityFile)
|
||
|
if !capacityScanner.Scan() {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to read from %s: %w", capacityPath, capacityScanner.Err())
|
||
|
}
|
||
|
|
||
|
statusFile, err := os.Open(statusPath)
|
||
|
if err != nil {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to open %s: %w", statusPath, err)
|
||
|
}
|
||
|
defer statusFile.Close()
|
||
|
|
||
|
statusScanner := bufio.NewScanner(statusFile)
|
||
|
if !statusScanner.Scan() {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to read from %s: %w", statusPath, statusScanner.Err())
|
||
|
}
|
||
|
|
||
|
technologyFile, err := os.Open(technologyPath)
|
||
|
if err != nil {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to open %s: %w", technologyPath, err)
|
||
|
}
|
||
|
defer technologyFile.Close()
|
||
|
|
||
|
technologyScanner := bufio.NewScanner(technologyFile)
|
||
|
if !technologyScanner.Scan() {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to read from %s: %w", technologyPath, technologyScanner.Err())
|
||
|
}
|
||
|
|
||
|
batteryCapacityStr := capacityScanner.Text()
|
||
|
batteryStatus := statusScanner.Text()
|
||
|
batteryTechnology := technologyScanner.Text()
|
||
|
|
||
|
batteryCapacity, err := strconv.ParseUint(batteryCapacityStr, 10, 8)
|
||
|
if err != nil {
|
||
|
return BatteryInfo{}, fmt.Errorf("failed to parse capacity from %s: %w", capacityPath, err)
|
||
|
}
|
||
|
|
||
|
return BatteryInfo{
|
||
|
Capacity: uint8(batteryCapacity),
|
||
|
Status: BatteryStatusFromStr(batteryStatus),
|
||
|
Technology: BatteryTechnologyFromStr(batteryTechnology),
|
||
|
}, nil
|
||
|
}
|