mirror of
https://github.com/aristocratos/btop.git
synced 2024-06-27 18:40:57 +12: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."},
|
{"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"
|
{"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."}
|
"#* 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_upper", "total"},
|
||||||
{"cpu_graph_lower", "total"},
|
{"cpu_graph_lower", "total"},
|
||||||
{"cpu_sensor", "Auto"},
|
{"cpu_sensor", "Auto"},
|
||||||
|
{"selected_battery", "Auto"},
|
||||||
{"cpu_core_map", ""},
|
{"cpu_core_map", ""},
|
||||||
{"temp_scale", "celsius"},
|
{"temp_scale", "celsius"},
|
||||||
{"clock_format", "%X"},
|
{"clock_format", "%X"},
|
||||||
|
@ -265,6 +268,8 @@ namespace Config {
|
||||||
fs::path conf_dir;
|
fs::path conf_dir;
|
||||||
fs::path conf_file;
|
fs::path conf_file;
|
||||||
|
|
||||||
|
vector<string> available_batteries = {"Auto"};
|
||||||
|
|
||||||
vector<string> current_boxes;
|
vector<string> current_boxes;
|
||||||
vector<string> preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"};
|
vector<string> preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"};
|
||||||
int current_preset = -1;
|
int current_preset = -1;
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace Config {
|
||||||
|
|
||||||
extern vector<string> current_boxes;
|
extern vector<string> current_boxes;
|
||||||
extern vector<string> preset_list;
|
extern vector<string> preset_list;
|
||||||
|
extern vector<string> available_batteries;
|
||||||
extern int current_preset;
|
extern int current_preset;
|
||||||
|
|
||||||
//* Check if string only contains space seperated valid names for boxes
|
//* 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",
|
"Show battery stats in the top right corner",
|
||||||
"if a battery is present."},
|
"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",
|
{"log_level",
|
||||||
"Set loglevel for error.log",
|
"Set loglevel for error.log",
|
||||||
"",
|
"",
|
||||||
|
@ -962,7 +969,8 @@ namespace Menu {
|
||||||
{"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)},
|
{"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)},
|
||||||
{"cpu_graph_upper", std::cref(Cpu::available_fields)},
|
{"cpu_graph_upper", std::cref(Cpu::available_fields)},
|
||||||
{"cpu_graph_lower", 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& tty_mode = Config::getB("tty_mode");
|
||||||
auto& vim_keys = Config::getB("vim_keys");
|
auto& vim_keys = Config::getB("vim_keys");
|
||||||
|
|
|
@ -468,75 +468,99 @@ namespace Cpu {
|
||||||
return core_map;
|
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> {
|
auto get_battery() -> tuple<int, long, string> {
|
||||||
if (not has_battery) return {0, 0, ""};
|
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 string auto_sel;
|
||||||
static bool use_energy = true;
|
static unordered_flat_map<string, battery> batteries;
|
||||||
|
|
||||||
//? Get paths to needed files and check for valid values on first run
|
//? 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")) {
|
if (fs::exists("/sys/class/power_supply")) {
|
||||||
for (const auto& d : fs::directory_iterator("/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
|
//? Only consider online power supplies of type Battery or UPS
|
||||||
//? see kernel docs for details on the file structure and contents
|
//? see kernel docs for details on the file structure and contents
|
||||||
//? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
//? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
||||||
|
battery new_bat;
|
||||||
|
fs::path bat_dir;
|
||||||
try {
|
try {
|
||||||
if (not d.is_directory()
|
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 not fs::exists(d.path() / "present")
|
||||||
or stoi(readfile(d.path() / "present")) != 1)
|
or stoi(readfile(d.path() / "present")) != 1)
|
||||||
continue;
|
continue;
|
||||||
string type = readfile(d.path() / "type");
|
string dev_type = readfile(d.path() / "type");
|
||||||
if (type == "Battery" or type == "UPS") {
|
if (is_in(dev_type, "Battery", "UPS")) {
|
||||||
bat_dir = d.path();
|
bat_dir = d.path();
|
||||||
break;
|
new_bat.base_dir = d.path();
|
||||||
|
new_bat.device_type = dev_type;
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
//? skip power supplies not conforming to the kernel standard
|
//? skip power supplies not conforming to the kernel standard
|
||||||
continue;
|
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;
|
has_battery = false;
|
||||||
return {0, 0, ""};
|
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;
|
int percent = -1;
|
||||||
long seconds = -1;
|
long seconds = -1;
|
||||||
|
|
||||||
//? Try to get battery percentage
|
//? Try to get battery percentage
|
||||||
if (use_energy) {
|
if (b.use_energy) {
|
||||||
try {
|
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::invalid_argument&) { }
|
||||||
catch (const std::out_of_range&) { }
|
catch (const std::out_of_range&) { }
|
||||||
}
|
}
|
||||||
if (percent < 0) {
|
if (percent < 0) {
|
||||||
try {
|
try {
|
||||||
percent = stoll(readfile(bat_dir / "capacity", "-1"));
|
percent = stoll(readfile(b.base_dir / "capacity", "-1"));
|
||||||
}
|
}
|
||||||
catch (const std::invalid_argument&) { }
|
catch (const std::invalid_argument&) { }
|
||||||
catch (const std::out_of_range&) { }
|
catch (const std::out_of_range&) { }
|
||||||
|
@ -547,9 +571,9 @@ namespace Cpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
//? Get charging/discharging status
|
//? Get charging/discharging status
|
||||||
string status = str_to_lower(readfile(bat_dir / "status", "unknown"));
|
string status = str_to_lower(readfile(b.base_dir / "status", "unknown"));
|
||||||
if (status == "unknown" and not online_path.empty()) {
|
if (status == "unknown" and not b.online.empty()) {
|
||||||
const auto online = readfile(online_path, "0");
|
const auto online = readfile(b.online, "0");
|
||||||
if (online == "1" and percent < 100) status = "charging";
|
if (online == "1" and percent < 100) status = "charging";
|
||||||
else if (online == "1") status = "full";
|
else if (online == "1") status = "full";
|
||||||
else status = "discharging";
|
else status = "discharging";
|
||||||
|
@ -557,16 +581,16 @@ namespace Cpu {
|
||||||
|
|
||||||
//? Get seconds to empty
|
//? Get seconds to empty
|
||||||
if (not is_in(status, "charging", "full")) {
|
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 {
|
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::invalid_argument&) { }
|
||||||
catch (const std::out_of_range&) { }
|
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 {
|
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::invalid_argument&) { }
|
||||||
catch (const std::out_of_range&) { }
|
catch (const std::out_of_range&) { }
|
||||||
|
|
Loading…
Reference in a new issue