mirror of
https://github.com/aristocratos/btop.git
synced 2024-09-28 22:21:35 +02:00
Added: Displayed battery selectable in options menu
This commit is contained in:
parent
dfef4fdcc8
commit
4cacdf28fe
@ -170,6 +170,8 @@ namespace Config {
|
||||
|
||||
{"show_battery", "#* Show battery stats in top right if battery is present."},
|
||||
|
||||
{"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."},
|
||||
|
||||
{"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n"
|
||||
"#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."}
|
||||
};
|
||||
@ -187,6 +189,7 @@ namespace Config {
|
||||
{"cpu_graph_upper", "total"},
|
||||
{"cpu_graph_lower", "total"},
|
||||
{"cpu_sensor", "Auto"},
|
||||
{"selected_battery", "Auto"},
|
||||
{"cpu_core_map", ""},
|
||||
{"temp_scale", "celsius"},
|
||||
{"clock_format", "%X"},
|
||||
@ -265,6 +268,8 @@ namespace Config {
|
||||
fs::path conf_dir;
|
||||
fs::path conf_file;
|
||||
|
||||
vector<string> available_batteries = {"Auto"};
|
||||
|
||||
vector<string> current_boxes;
|
||||
vector<string> preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"};
|
||||
int current_preset = -1;
|
||||
|
@ -45,6 +45,7 @@ namespace Config {
|
||||
|
||||
extern vector<string> current_boxes;
|
||||
extern vector<string> preset_list;
|
||||
extern vector<string> available_batteries;
|
||||
extern int current_preset;
|
||||
|
||||
//* Check if string only contains space seperated valid names for boxes
|
||||
|
@ -270,6 +270,13 @@ namespace Menu {
|
||||
"",
|
||||
"Show battery stats in the top right corner",
|
||||
"if a battery is present."},
|
||||
{"selected_battery",
|
||||
"Select battery.",
|
||||
"",
|
||||
"Which battery to use if multiple are present.",
|
||||
"Can be both batteries and UPS.",
|
||||
"",
|
||||
"\"Auto\" for auto detection."},
|
||||
{"log_level",
|
||||
"Set loglevel for error.log",
|
||||
"",
|
||||
@ -962,7 +969,8 @@ namespace Menu {
|
||||
{"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)},
|
||||
{"cpu_graph_upper", std::cref(Cpu::available_fields)},
|
||||
{"cpu_graph_lower", std::cref(Cpu::available_fields)},
|
||||
{"cpu_sensor", std::cref(Cpu::available_sensors)}
|
||||
{"cpu_sensor", std::cref(Cpu::available_sensors)},
|
||||
{"selected_battery", std::cref(Config::available_batteries)},
|
||||
};
|
||||
auto& tty_mode = Config::getB("tty_mode");
|
||||
auto& vim_keys = Config::getB("vim_keys");
|
||||
|
@ -468,75 +468,99 @@ namespace Cpu {
|
||||
return core_map;
|
||||
}
|
||||
|
||||
struct battery {
|
||||
fs::path base_dir, energy_now, energy_full, power_now, status, online;
|
||||
string device_type;
|
||||
bool use_energy = true;
|
||||
};
|
||||
|
||||
auto get_battery() -> tuple<int, long, string> {
|
||||
if (not has_battery) return {0, 0, ""};
|
||||
static fs::path bat_dir, energy_now_path, energy_full_path, power_now_path, status_path, online_path;
|
||||
static bool use_energy = true;
|
||||
static string auto_sel;
|
||||
static unordered_flat_map<string, battery> batteries;
|
||||
|
||||
//? Get paths to needed files and check for valid values on first run
|
||||
if (bat_dir.empty() and has_battery) {
|
||||
if (batteries.empty() and has_battery) {
|
||||
if (fs::exists("/sys/class/power_supply")) {
|
||||
for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) {
|
||||
//? Only consider online power supplies of type Battery or UPS
|
||||
//? see kernel docs for details on the file structure and contents
|
||||
//? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
||||
battery new_bat;
|
||||
fs::path bat_dir;
|
||||
try {
|
||||
if (not d.is_directory()
|
||||
or not fs::exists(d.path() / "type")
|
||||
or not fs::exists(d.path() / "type")
|
||||
or not fs::exists(d.path() / "present")
|
||||
or stoi(readfile(d.path() / "present")) != 1)
|
||||
continue;
|
||||
string type = readfile(d.path() / "type");
|
||||
if (type == "Battery" or type == "UPS") {
|
||||
string dev_type = readfile(d.path() / "type");
|
||||
if (is_in(dev_type, "Battery", "UPS")) {
|
||||
bat_dir = d.path();
|
||||
break;
|
||||
new_bat.base_dir = d.path();
|
||||
new_bat.device_type = dev_type;
|
||||
}
|
||||
} catch (...) {
|
||||
//? skip power supplies not conforming to the kernel standard
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now";
|
||||
else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now";
|
||||
else new_bat.use_energy = false;
|
||||
|
||||
if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full";
|
||||
else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full";
|
||||
else new_bat.use_energy = false;
|
||||
|
||||
if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now";
|
||||
else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now";
|
||||
|
||||
if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online";
|
||||
else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online";
|
||||
|
||||
batteries[bat_dir.filename()] = new_bat;
|
||||
Config::available_batteries.push_back(bat_dir.filename());
|
||||
}
|
||||
}
|
||||
if (bat_dir.empty()) {
|
||||
if (batteries.empty()) {
|
||||
has_battery = false;
|
||||
return {0, 0, ""};
|
||||
}
|
||||
else {
|
||||
if (fs::exists(bat_dir / "energy_now")) energy_now_path = bat_dir / "energy_now";
|
||||
else if (fs::exists(bat_dir / "charge_now")) energy_now_path = bat_dir / "charge_now";
|
||||
else use_energy = false;
|
||||
|
||||
if (fs::exists(bat_dir / "energy_full")) energy_full_path = bat_dir / "energy_full";
|
||||
else if (fs::exists(bat_dir / "charge_full")) energy_full_path = bat_dir / "charge_full";
|
||||
else use_energy = false;
|
||||
|
||||
if (not use_energy and not fs::exists(bat_dir / "capacity")) {
|
||||
has_battery = false;
|
||||
return {0, 0, ""};
|
||||
}
|
||||
|
||||
if (fs::exists(bat_dir / "power_now")) power_now_path = bat_dir / "power_now";
|
||||
else if (fs::exists(bat_dir / "current_now")) power_now_path = bat_dir / "current_now";
|
||||
|
||||
if (fs::exists(bat_dir / "AC0/online")) online_path = bat_dir / "AC0/online";
|
||||
else if (fs::exists(bat_dir / "AC/online")) online_path = bat_dir / "AC/online";
|
||||
}
|
||||
}
|
||||
|
||||
auto& battery_sel = Config::getS("selected_battery");
|
||||
|
||||
if ((battery_sel == "Auto" and auto_sel.empty())) {
|
||||
for (auto& [name, bat] : batteries) {
|
||||
if (bat.device_type == "Battery") {
|
||||
auto_sel = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (auto_sel.empty()) auto_sel = batteries.begin()->first;
|
||||
}
|
||||
|
||||
auto& b = (battery_sel != "Auto" and batteries.contains(battery_sel) ? batteries.at(battery_sel) : batteries.at(auto_sel));
|
||||
|
||||
int percent = -1;
|
||||
long seconds = -1;
|
||||
|
||||
//? Try to get battery percentage
|
||||
if (use_energy) {
|
||||
if (b.use_energy) {
|
||||
try {
|
||||
percent = round(100.0 * stoll(readfile(energy_now_path, "-1")) / stoll(readfile(energy_full_path, "1")));
|
||||
percent = round(100.0 * stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1")));
|
||||
}
|
||||
catch (const std::invalid_argument&) { }
|
||||
catch (const std::out_of_range&) { }
|
||||
}
|
||||
if (percent < 0) {
|
||||
try {
|
||||
percent = stoll(readfile(bat_dir / "capacity", "-1"));
|
||||
percent = stoll(readfile(b.base_dir / "capacity", "-1"));
|
||||
}
|
||||
catch (const std::invalid_argument&) { }
|
||||
catch (const std::out_of_range&) { }
|
||||
@ -547,9 +571,9 @@ namespace Cpu {
|
||||
}
|
||||
|
||||
//? Get charging/discharging status
|
||||
string status = str_to_lower(readfile(bat_dir / "status", "unknown"));
|
||||
if (status == "unknown" and not online_path.empty()) {
|
||||
const auto online = readfile(online_path, "0");
|
||||
string status = str_to_lower(readfile(b.base_dir / "status", "unknown"));
|
||||
if (status == "unknown" and not b.online.empty()) {
|
||||
const auto online = readfile(b.online, "0");
|
||||
if (online == "1" and percent < 100) status = "charging";
|
||||
else if (online == "1") status = "full";
|
||||
else status = "discharging";
|
||||
@ -557,16 +581,16 @@ namespace Cpu {
|
||||
|
||||
//? Get seconds to empty
|
||||
if (not is_in(status, "charging", "full")) {
|
||||
if (use_energy and not power_now_path.empty()) {
|
||||
if (b.use_energy and not b.power_now.empty()) {
|
||||
try {
|
||||
seconds = round((double)stoll(readfile(energy_now_path, "0")) / stoll(readfile(power_now_path, "1")) * 3600);
|
||||
seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600);
|
||||
}
|
||||
catch (const std::invalid_argument&) { }
|
||||
catch (const std::out_of_range&) { }
|
||||
}
|
||||
if (seconds < 0 and fs::exists(bat_dir / "time_to_empty")) {
|
||||
if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) {
|
||||
try {
|
||||
seconds = stoll(readfile(bat_dir / "time_to_empty", "0")) * 60;
|
||||
seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60;
|
||||
}
|
||||
catch (const std::invalid_argument&) { }
|
||||
catch (const std::out_of_range&) { }
|
||||
|
Loading…
Reference in New Issue
Block a user