diff options
author | Jakob P. Liljenberg <admin@qvantnet.com> | 2024-02-11 16:45:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-11 16:45:40 +0100 |
commit | 77c758c3492c0435aa2427aaef3e6b6139c6c9f6 (patch) | |
tree | b490d32fe335c4f1d6756f6a0a9cae14a2fa89a1 | |
parent | 338aa72f6fb2beda1305bf524b9a450a0f6a3762 (diff) | |
parent | f1f37ad6af7e05b3a82133e55c4aa1381bef530c (diff) |
Merge pull request #689 from vsey/battery-power-2
-rw-r--r-- | src/btop_config.cpp | 3 | ||||
-rw-r--r-- | src/btop_draw.cpp | 12 | ||||
-rw-r--r-- | src/btop_menu.cpp | 5 | ||||
-rw-r--r-- | src/btop_shared.hpp | 4 | ||||
-rw-r--r-- | src/freebsd/btop_collect.cpp | 13 | ||||
-rw-r--r-- | src/linux/btop_collect.cpp | 90 | ||||
-rw-r--r-- | src/openbsd/btop_collect.cpp | 8 | ||||
-rw-r--r-- | src/osx/btop_collect.cpp | 8 |
8 files changed, 103 insertions, 40 deletions
diff --git a/src/btop_config.cpp b/src/btop_config.cpp index 18e60ae..0b44630 100644 --- a/src/btop_config.cpp +++ b/src/btop_config.cpp @@ -199,6 +199,8 @@ namespace Config { {"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."}, + {"show_battery_watts", "#* Show power stats of battery next to charge indicator."}, + {"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."}, #ifdef GPU_SUPPORT @@ -293,6 +295,7 @@ namespace Config { {"net_auto", true}, {"net_sync", true}, {"show_battery", true}, + {"show_battery_watts", true}, {"vim_keys", false}, {"tty_mode", false}, {"disk_free_priv", false}, diff --git a/src/btop_draw.cpp b/src/btop_draw.cpp index 5e3cc5b..bfd12ce 100644 --- a/src/btop_draw.cpp +++ b/src/btop_draw.cpp @@ -706,6 +706,7 @@ namespace Cpu { if (Config::getB("show_battery") and has_battery) { static int old_percent{}; // defaults to = 0 static long old_seconds{}; // defaults to = 0 + static float old_watts{}; // defaults to = 0 static string old_status; static Draw::Meter bat_meter {10, "cpu", true}; static const std::unordered_map<string, string> bat_symbols = { @@ -715,16 +716,18 @@ namespace Cpu { {"unknown", "○"} }; - const auto& [percent, seconds, status] = current_bat; + const auto& [percent, watts, seconds, status] = current_bat; - if (redraw or percent != old_percent or seconds != old_seconds or status != old_status) { + if (redraw or percent != old_percent or (watts != old_watts and Config::getB("show_battery_watts")) or seconds != old_seconds or status != old_status) { old_percent = percent; + old_watts = watts; old_seconds = seconds; old_status = status; const string str_time = (seconds > 0 ? sec_to_dhms(seconds, true, true) : ""); const string str_percent = to_string(percent) + '%'; + const string str_watts = (watts != -1 and Config::getB("show_battery_watts") ? fmt::format("{:.2f}", watts) + 'W' : ""); const auto& bat_symbol = bat_symbols.at((bat_symbols.contains(status) ? status : "unknown")); - const int current_len = (Term::width >= 100 ? 11 : 0) + str_time.size() + str_percent.size() + to_string(Config::getI("update_ms")).size(); + const int current_len = (Term::width >= 100 ? 11 : 0) + str_time.size() + str_percent.size() + str_watts.size() + to_string(Config::getI("update_ms")).size(); const int current_pos = Term::width - current_len - 17; if ((bat_pos != current_pos or bat_len != current_len) and bat_pos > 0 and not redraw) @@ -734,7 +737,7 @@ namespace Cpu { out += Mv::to(y, bat_pos) + title_left + Theme::c("title") + Fx::b + "BAT" + bat_symbol + ' ' + str_percent + (Term::width >= 100 ? Fx::ub + ' ' + bat_meter(percent) + Fx::b : "") - + (not str_time.empty() ? ' ' + Theme::c("title") + str_time : " ") + Fx::ub + title_right; + + (not str_time.empty() ? ' ' + Theme::c("title") + str_time : "") + (not str_watts.empty() ? " " + Theme::c("title") + Fx::b + str_watts : "") + Fx::ub + title_right; } } else if (bat_pos > 0) { @@ -2239,3 +2242,4 @@ namespace Draw { } } } + diff --git a/src/btop_menu.cpp b/src/btop_menu.cpp index fb119aa..b1da526 100644 --- a/src/btop_menu.cpp +++ b/src/btop_menu.cpp @@ -353,6 +353,11 @@ namespace Menu { "Can be both batteries and UPS.", "", "\"Auto\" for auto detection."}, + {"show_battery_watts", + "Show battery power.", + "", + "Show discharge power when discharging.", + "Show charging power when charging."}, {"log_level", "Set loglevel for error.log", "", diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index 69566c6..c543d9e 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -178,7 +178,7 @@ namespace Cpu { extern string cpuName, cpuHz; extern vector<string> available_fields; extern vector<string> available_sensors; - extern tuple<int, long, string> current_bat; + extern tuple<int, float, long, string> current_bat; struct cpu_info { std::unordered_map<string, deque<long long>> cpu_percent = { @@ -213,7 +213,7 @@ namespace Cpu { auto get_cpuHz() -> string; //* Get battery info from /sys - auto get_battery() -> tuple<int, long, string>; + auto get_battery() -> tuple<int, float, long, string>; } namespace Mem { diff --git a/src/freebsd/btop_collect.cpp b/src/freebsd/btop_collect.cpp index 2db49a2..38f4368 100644 --- a/src/freebsd/btop_collect.cpp +++ b/src/freebsd/btop_collect.cpp @@ -207,7 +207,7 @@ namespace Cpu { string cpuName; string cpuHz; bool has_battery = true; - tuple<int, long, string> current_bat; + tuple<int, float, long, string> current_bat; const array<string, 10> time_names = {"user", "nice", "system", "idle"}; @@ -373,10 +373,11 @@ namespace Cpu { return core_map; } - auto get_battery() -> tuple<int, long, string> { - if (not has_battery) return {0, 0, ""}; + auto get_battery() -> tuple<int, float, long, string> { + if (not has_battery) return {0, 0, 0, ""}; long seconds = -1; + float watts = -1; uint32_t percent = -1; size_t size = sizeof(percent); string status = "discharging"; @@ -388,6 +389,10 @@ namespace Cpu { if (sysctlbyname("hw.acpi.battery.time", &seconds, &size, nullptr, 0) < 0) { seconds = 0; } + size = sizeof(watts); + if (sysctlbyname("hw.acpi.battery.rate", &watts, &size, nullptr, 0) < 0) { + watts = -1; + } int state; size = sizeof(state); if (sysctlbyname("hw.acpi.battery.state", &state, &size, nullptr, 0) < 0) { @@ -402,7 +407,7 @@ namespace Cpu { } } - return {percent, seconds, status}; + return {percent, watts, seconds, status}; } auto collect(bool no_update) -> cpu_info & { diff --git a/src/linux/btop_collect.cpp b/src/linux/btop_collect.cpp index 3a11e7e..739d587 100644 --- a/src/linux/btop_collect.cpp +++ b/src/linux/btop_collect.cpp @@ -301,7 +301,7 @@ namespace Cpu { string cpuName; string cpuHz; bool has_battery = true; - tuple<int, long, string> current_bat; + tuple<int, float, long, string> current_bat; const array time_names { "user"s, "nice"s, "system"s, "idle"s, "iowait"s, @@ -671,13 +671,14 @@ namespace Cpu { } struct battery { - fs::path base_dir, energy_now, energy_full, power_now, status, online; + fs::path base_dir, energy_now, charge_now, energy_full, charge_full, power_now, current_now, voltage_now, status, online; string device_type; - bool use_energy = true; + bool use_energy_or_charge = true; + bool use_power = true; }; - auto get_battery() -> tuple<int, long, string> { - if (not has_battery) return {0, 0, ""}; + auto get_battery() -> tuple<int, float, long, string> { + if (not has_battery) return {0, 0, 0, ""}; static string auto_sel; static std::unordered_map<string, battery> batteries; @@ -709,19 +710,27 @@ namespace Cpu { } 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; + else if (fs::exists(bat_dir / "charge_now")) new_bat.charge_now = bat_dir / "charge_now"; + else new_bat.use_energy_or_charge = 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; + else if (fs::exists(bat_dir / "charge_full")) new_bat.charge_full = bat_dir / "charge_full"; + else new_bat.use_energy_or_charge = false; - if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { + if (not new_bat.use_energy_or_charge 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 / "power_now")) { + new_bat.power_now = bat_dir / "power_now"; + } + else if ((fs::exists(bat_dir / "current_now")) and (fs::exists(bat_dir / "current_now"))) { + new_bat.current_now = bat_dir / "current_now"; + new_bat.voltage_now = bat_dir / "voltage_now"; + } + else { + new_bat.use_power = false; + } 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"; @@ -736,7 +745,7 @@ namespace Cpu { } if (batteries.empty()) { has_battery = false; - return {0, 0, ""}; + return {0, 0, 0, ""}; } } @@ -756,25 +765,33 @@ namespace Cpu { int percent = -1; long seconds = -1; + float watts = -1; //? Try to get battery percentage - if (b.use_energy) { + if (percent < 0) { + try { + percent = stoll(readfile(b.base_dir / "capacity", "-1")); + } + catch (const std::invalid_argument&) { } + catch (const std::out_of_range&) { } + } + if (b.use_energy_or_charge and percent < 0) { try { 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) { + if (b.use_energy_or_charge and percent < 0) { try { - percent = stoll(readfile(b.base_dir / "capacity", "-1")); + percent = round(100.0 * stoll(readfile(b.charge_now, "-1")) / stoll(readfile(b.charge_full, "1"))); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } if (percent < 0) { has_battery = false; - return {0, 0, ""}; + return {0, 0, 0, ""}; } //? Get charging/discharging status @@ -788,23 +805,52 @@ namespace Cpu { //? Get seconds to empty if (not is_in(status, "charging", "full")) { - if (b.use_energy and not b.power_now.empty()) { + if (b.use_energy_or_charge ) { + if (not b.power_now.empty()) { + try { + 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&) { } + } + else if (not b.current_now.empty()) { + try { + seconds = round((double)stoll(readfile(b.charge_now, "0")) / (double)stoll(readfile(b.current_now, "1")) * 3600); + } + catch (const std::invalid_argument&) { } + catch (const std::out_of_range&) { } + } + } + + if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) { try { - seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600); + seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60; } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } - if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) { + } + + //? Get power draw + if (b.use_power) { + if (not b.power_now.empty()) { try { - seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60; + watts = (float)stoll(readfile(b.energy_now, "-1")) / 1000000.0; } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } + else if (not b.voltage_now.empty() and not b.current_now.empty()) { + try { + watts = (float)stoll(readfile(b.current_now, "-1")) / 1000000.0 * stoll(readfile(b.voltage_now, "1")) / 1000000.0; + } + catch (const std::invalid_argument&) { } + catch (const std::out_of_range&) { } + } + } - return {percent, seconds, status}; + return {percent, watts, seconds, status}; } auto collect(bool no_update) -> cpu_info& { diff --git a/src/openbsd/btop_collect.cpp b/src/openbsd/btop_collect.cpp index df35662..3784ea9 100644 --- a/src/openbsd/btop_collect.cpp +++ b/src/openbsd/btop_collect.cpp @@ -202,7 +202,7 @@ namespace Cpu { string cpuName; string cpuHz; bool has_battery = true; - tuple<int, long, string> current_bat; + tuple<int, float, long, string> current_bat; const array<string, 10> time_names = {"user", "nice", "system", "idle"}; @@ -385,8 +385,8 @@ namespace Cpu { return core_map; } - auto get_battery() -> tuple<int, long, string> { - if (not has_battery) return {0, 0, ""}; + auto get_battery() -> tuple<int, float, long, string> { + if (not has_battery) return {0, 0, 0, ""}; long seconds = -1; uint32_t percent = -1; @@ -417,7 +417,7 @@ namespace Cpu { } } - return {percent, seconds, status}; + return {percent, -1, seconds, status}; } auto collect(bool no_update) -> cpu_info & { diff --git a/src/osx/btop_collect.cpp b/src/osx/btop_collect.cpp index 860e457..acafedb 100644 --- a/src/osx/btop_collect.cpp +++ b/src/osx/btop_collect.cpp @@ -191,7 +191,7 @@ namespace Cpu { string cpuHz; bool has_battery = true; bool macM1 = false; - tuple<int, long, string> current_bat; + tuple<int, float, long, string> current_bat; const array<string, 10> time_names = {"user", "nice", "system", "idle"}; @@ -407,8 +407,8 @@ namespace Cpu { ~IOPSList_Wrap() { CFRelease(data); } }; - auto get_battery() -> tuple<int, long, string> { - if (not has_battery) return {0, 0, ""}; + auto get_battery() -> tuple<int, float, long, string> { + if (not has_battery) return {0, 0, 0, ""}; uint32_t percent = -1; long seconds = -1; @@ -447,7 +447,7 @@ namespace Cpu { has_battery = false; } } - return {percent, seconds, status}; + return {percent, -1, seconds, status}; } auto collect(bool no_update) -> cpu_info & { |