Updated logic in battery module
parent
4deb6d812d
commit
120c68e014
|
@ -157,122 +157,227 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uint32_t total_power = 0; // μW
|
uint32_t total_power = 0; // μW
|
||||||
|
bool total_power_exists = false;
|
||||||
uint32_t total_energy = 0; // μWh
|
uint32_t total_energy = 0; // μWh
|
||||||
|
bool total_energy_exists = false;
|
||||||
uint32_t total_energy_full = 0;
|
uint32_t total_energy_full = 0;
|
||||||
|
bool total_energy_full_exists = false;
|
||||||
uint32_t total_energy_full_design = 0;
|
uint32_t total_energy_full_design = 0;
|
||||||
|
bool total_energy_full_design_exists = false;
|
||||||
uint32_t total_capacity{0};
|
uint32_t total_capacity{0};
|
||||||
|
bool total_capacity_exists = false;
|
||||||
|
|
||||||
std::string status = "Unknown";
|
std::string status = "Unknown";
|
||||||
for (auto const& item : batteries_) {
|
for (auto const& item : batteries_) {
|
||||||
auto bat = item.first;
|
auto bat = item.first;
|
||||||
uint32_t power_now;
|
|
||||||
uint32_t energy_full;
|
|
||||||
uint32_t energy_now;
|
|
||||||
uint32_t energy_full_design;
|
|
||||||
uint32_t capacity{0};
|
|
||||||
std::string _status;
|
std::string _status;
|
||||||
std::getline(std::ifstream(bat / "status"), _status);
|
std::getline(std::ifstream(bat / "status"), _status);
|
||||||
|
|
||||||
// Some battery will report current and charge in μA/μAh.
|
// Some battery will report current and charge in μA/μAh.
|
||||||
// Scale these by the voltage to get μW/μWh.
|
// Scale these by the voltage to get μW/μWh.
|
||||||
if (fs::exists(bat / "current_now") || fs::exists(bat / "current_avg")) {
|
|
||||||
uint32_t voltage_now;
|
uint32_t capacity;
|
||||||
uint32_t current_now;
|
bool capacity_exists;
|
||||||
uint32_t charge_now;
|
if (fs::exists(bat / "capacity")) {
|
||||||
uint32_t charge_full;
|
capacity_exists = true;
|
||||||
uint32_t charge_full_design;
|
|
||||||
// Some batteries have only *_avg, not *_now
|
|
||||||
if (fs::exists(bat / "voltage_now"))
|
|
||||||
std::ifstream(bat / "voltage_now") >> voltage_now;
|
|
||||||
else
|
|
||||||
std::ifstream(bat / "voltage_avg") >> voltage_now;
|
|
||||||
if (fs::exists(bat / "current_now"))
|
|
||||||
std::ifstream(bat / "current_now") >> current_now;
|
|
||||||
else
|
|
||||||
std::ifstream(bat / "current_avg") >> current_now;
|
|
||||||
std::ifstream(bat / "charge_full") >> charge_full;
|
|
||||||
std::ifstream(bat / "charge_full_design") >> charge_full_design;
|
|
||||||
if (fs::exists(bat / "charge_now"))
|
|
||||||
std::ifstream(bat / "charge_now") >> charge_now;
|
|
||||||
else {
|
|
||||||
// charge_now is missing on some systems, estimate using capacity.
|
|
||||||
uint32_t capacity;
|
|
||||||
std::ifstream(bat / "capacity") >> capacity;
|
|
||||||
charge_now = (capacity * charge_full) / 100;
|
|
||||||
}
|
|
||||||
power_now = ((uint64_t)current_now * (uint64_t)voltage_now) / 1000000;
|
|
||||||
energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000;
|
|
||||||
energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000;
|
|
||||||
energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000;
|
|
||||||
} // Gamepads such as PS Dualshock provide the only capacity
|
|
||||||
else if (fs::exists(bat / "energy_now") && fs::exists(bat / "energy_full")) {
|
|
||||||
std::ifstream(bat / "power_now") >> power_now;
|
|
||||||
std::ifstream(bat / "energy_now") >> energy_now;
|
|
||||||
std::ifstream(bat / "energy_full") >> energy_full;
|
|
||||||
std::ifstream(bat / "energy_full_design") >> energy_full_design;
|
|
||||||
} else {
|
|
||||||
std::ifstream(bat / "capacity") >> capacity;
|
std::ifstream(bat / "capacity") >> capacity;
|
||||||
|
} else {
|
||||||
|
capacity_exists = false;
|
||||||
|
capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t current_now;
|
||||||
|
bool current_now_exists;
|
||||||
|
if (fs::exists(bat / "current_now")) {
|
||||||
|
current_now_exists = true;
|
||||||
|
std::ifstream(bat / "current_now") >> current_now;
|
||||||
|
} else if (fs::exists(bat / "current_avg")) {
|
||||||
|
current_now_exists = true;
|
||||||
|
std::ifstream(bat / "current_avg") >> current_now;
|
||||||
|
} else {
|
||||||
|
current_now_exists = false;
|
||||||
|
current_now = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t voltage_now;
|
||||||
|
bool voltage_now_exists;
|
||||||
|
if (fs::exists(bat / "voltage_now")) {
|
||||||
|
voltage_now_exists = true;
|
||||||
|
std::ifstream(bat / "voltage_now") >> voltage_now;
|
||||||
|
} else if (fs::exists(bat / "voltage_avg")) {
|
||||||
|
voltage_now_exists = true;
|
||||||
|
std::ifstream(bat / "voltage_avg") >> voltage_now;
|
||||||
|
} else {
|
||||||
|
voltage_now_exists = false;
|
||||||
|
voltage_now = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t charge_full;
|
||||||
|
bool charge_full_exists;
|
||||||
|
if (fs::exists(bat / "charge_full")) {
|
||||||
|
charge_full_exists = true;
|
||||||
|
std::ifstream(bat / "charge_full") >> charge_full;
|
||||||
|
} else {
|
||||||
|
charge_full_exists = false;
|
||||||
|
charge_full = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t charge_full_design;
|
||||||
|
bool charge_full_design_exists;
|
||||||
|
if (fs::exists(bat / "charge_full_design")) {
|
||||||
|
charge_full_design_exists = true;
|
||||||
|
std::ifstream(bat / "charge_full_design") >> charge_full_design;
|
||||||
|
} else {
|
||||||
|
charge_full_design_exists = false;
|
||||||
|
charge_full_design = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t charge_now;
|
||||||
|
bool charge_now_exists;
|
||||||
|
if (fs::exists(bat / "charge_now")) {
|
||||||
|
charge_now_exists = true;
|
||||||
|
std::ifstream(bat / "charge_now") >> charge_now;
|
||||||
|
} else if (capacity_exists && charge_full_exists) {
|
||||||
|
// charge_now is missing on some systems, estimate using capacity and charge_full.
|
||||||
|
charge_now_exists = true; // this could be debatably set to false (same for all properties below)
|
||||||
|
charge_now = (capacity * charge_full) / 100;
|
||||||
|
} else {
|
||||||
|
charge_now_exists = false;
|
||||||
|
charge_now = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t power_now;
|
||||||
|
bool power_now_exists;
|
||||||
|
if (fs::exists(bat / "power_now")) {
|
||||||
|
power_now_exists = true;
|
||||||
|
std::ifstream(bat / "power_now") >> power_now;
|
||||||
|
} else if (current_now_exists && voltage_now_exists) {
|
||||||
|
power_now_exists = true;
|
||||||
|
power_now = ((uint64_t)current_now * (uint64_t)voltage_now) / 1000000;
|
||||||
|
} else {
|
||||||
|
power_now_exists = false;
|
||||||
power_now = 0;
|
power_now = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t energy_now;
|
||||||
|
bool energy_now_exists;
|
||||||
|
if (fs::exists(bat / "energy_now")) {
|
||||||
|
energy_now_exists = true;
|
||||||
|
std::ifstream(bat / "energy_now") >> energy_now;
|
||||||
|
} else if (charge_now_exists && voltage_now_exists) {
|
||||||
|
energy_now_exists = true;
|
||||||
|
energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000;
|
||||||
|
} else {
|
||||||
|
energy_now_exists = false;
|
||||||
energy_now = 0;
|
energy_now = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t energy_full;
|
||||||
|
bool energy_full_exists;
|
||||||
|
if (fs::exists(bat / "energy_full")) {
|
||||||
|
energy_full_exists = true;
|
||||||
|
std::ifstream(bat / "energy_full") >> energy_full;
|
||||||
|
} else if (charge_full_exists && voltage_now_exists) {
|
||||||
|
energy_full_exists = true;
|
||||||
|
energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000;
|
||||||
|
} else {
|
||||||
|
energy_full_exists = false;
|
||||||
energy_full = 0;
|
energy_full = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t energy_full_design;
|
||||||
|
bool energy_full_design_exists;
|
||||||
|
if (fs::exists(bat / "energy_full_design")) {
|
||||||
|
energy_full_design_exists = true;
|
||||||
|
std::ifstream(bat / "energy_full_design") >> energy_full_design;
|
||||||
|
} else if (charge_full_design_exists && voltage_now_exists) {
|
||||||
|
energy_full_design_exists = true;
|
||||||
|
energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000;
|
||||||
|
} else {
|
||||||
|
energy_full_design_exists = false;
|
||||||
energy_full_design = 0;
|
energy_full_design = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the "smallest" status among all batteries
|
// Show the "smallest" status among all batteries
|
||||||
if (status_gt(status, _status)) {
|
if (status_gt(status, _status))
|
||||||
status = _status;
|
status = _status;
|
||||||
|
|
||||||
|
if (power_now_exists) {
|
||||||
|
total_power_exists = true;
|
||||||
|
total_power += power_now;
|
||||||
|
}
|
||||||
|
if (energy_now_exists) {
|
||||||
|
total_energy_exists = true;
|
||||||
|
total_energy += energy_now;
|
||||||
|
}
|
||||||
|
if (energy_full_exists) {
|
||||||
|
total_energy_full_exists = true;
|
||||||
|
total_energy_full += energy_full;
|
||||||
|
}
|
||||||
|
if (energy_full_design_exists) {
|
||||||
|
total_energy_full_design_exists = true;
|
||||||
|
total_energy_full_design += energy_full_design;
|
||||||
|
}
|
||||||
|
if (capacity_exists) {
|
||||||
|
total_capacity_exists = true;
|
||||||
|
total_capacity += capacity;
|
||||||
}
|
}
|
||||||
total_power += power_now;
|
|
||||||
total_energy += energy_now;
|
|
||||||
total_energy_full += energy_full;
|
|
||||||
total_energy_full_design += energy_full_design;
|
|
||||||
total_capacity += capacity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!adapter_.empty() && status == "Discharging") {
|
if (!adapter_.empty() && status == "Discharging") {
|
||||||
bool online;
|
bool online;
|
||||||
std::ifstream(adapter_ / "online") >> online;
|
if (fs::exists(adapter_ / "online"))
|
||||||
if (online) {
|
std::ifstream(adapter_ / "online") >> online;
|
||||||
|
else
|
||||||
|
online = false;
|
||||||
|
if (online)
|
||||||
status = "Plugged";
|
status = "Plugged";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
float time_remaining = 0;
|
|
||||||
if (status == "Discharging" && total_power != 0) {
|
float time_remaining{0.0f};
|
||||||
time_remaining = (float)total_energy / total_power;
|
if (status == "Discharging" && total_power_exists && total_energy_exists) {
|
||||||
} else if (status == "Charging" && total_power != 0) {
|
if (total_power != 0)
|
||||||
time_remaining = -(float)(total_energy_full - total_energy) / total_power;
|
time_remaining = (float)total_energy / total_power;
|
||||||
if (time_remaining > 0.0f) {
|
} else if (status == "Charging" && total_energy_exists && total_energy_full_exists && total_power_exists) {
|
||||||
// If we've turned positive it means the battery is past 100% and so
|
if (total_power != 0)
|
||||||
// just report that as no time remaining
|
time_remaining = -(float)(total_energy_full - total_energy) / total_power;
|
||||||
|
// If we've turned positive it means the battery is past 100% and so just report that as no time remaining
|
||||||
|
if (time_remaining > 0.0f)
|
||||||
time_remaining = 0.0f;
|
time_remaining = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float calculated_capacity{0.0f};
|
||||||
|
if (total_capacity_exists) {
|
||||||
|
if (total_capacity > 0.0f)
|
||||||
|
calculated_capacity = (float)total_capacity;
|
||||||
|
else if (total_energy_full_exists && total_energy_exists) {
|
||||||
|
if (total_energy_full > 0.0f)
|
||||||
|
calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float capacity{0.0f};
|
|
||||||
if (total_energy_full > 0.0f) {
|
|
||||||
capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
|
|
||||||
} else {
|
|
||||||
capacity = (float)total_capacity;
|
|
||||||
}
|
|
||||||
// Handle design-capacity
|
// Handle design-capacity
|
||||||
if (config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) {
|
if ((config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) && total_energy_exists && total_energy_full_design_exists) {
|
||||||
capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design);
|
if (total_energy_full_design > 0.0f)
|
||||||
|
calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle full-at
|
// Handle full-at
|
||||||
if (config_["full-at"].isUInt()) {
|
if (config_["full-at"].isUInt()) {
|
||||||
auto full_at = config_["full-at"].asUInt();
|
auto full_at = config_["full-at"].asUInt();
|
||||||
if (full_at < 100) {
|
if (full_at < 100)
|
||||||
capacity = 100.f * capacity / full_at;
|
calculated_capacity = 100.f * calculated_capacity / full_at;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (capacity > 100.f) {
|
|
||||||
// This can happen when the battery is calibrating and goes above 100%
|
// Handle it gracefully by clamping at 100%
|
||||||
// Handle it gracefully by clamping at 100%
|
// This can happen when the battery is calibrating and goes above 100%
|
||||||
capacity = 100.f;
|
if (calculated_capacity > 100.f)
|
||||||
}
|
calculated_capacity = 100.f;
|
||||||
uint8_t cap = round(capacity);
|
|
||||||
if (cap == 100 && status == "Charging") {
|
uint8_t cap = round(calculated_capacity);
|
||||||
// If we've reached 100% just mark as full as some batteries can stay
|
// If we've reached 100% just mark as full as some batteries can stay stuck reporting they're still charging but not yet done
|
||||||
// stuck reporting they're still charging but not yet done
|
if (cap == 100 && status == "Charging")
|
||||||
status = "Full";
|
status = "Full";
|
||||||
}
|
|
||||||
|
|
||||||
return {cap, time_remaining, status, total_power / 1e6};
|
return {cap, time_remaining, status, total_power / 1e6};
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
|
|
Loading…
Reference in New Issue