commit a7af00864d8d49263b68b2c4338001d13c96ee72 Author: datalore Date: Fri Feb 16 20:58:14 2024 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1be241e --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +build/batstat:src/*.cc + g++ -o build/batstat src/*.cc -Iinclude +clean: + rm build/batstat diff --git a/include/batteryinfo.h b/include/batteryinfo.h new file mode 100644 index 0000000..dd795c3 --- /dev/null +++ b/include/batteryinfo.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +namespace dlore +{ + struct + { + std::string Manufacturer; + std::string Model; + std::string Technology; + unsigned int CellSeriesCount; + unsigned int Capacity; + float Vnow; + float Vmin; + unsigned int ChargeNow; + unsigned int ChargeFull; + unsigned int ChargeFullDesign; + } typedef BatteryInfo; + + BatteryInfo GetBatteryInfo(std::filesystem::path classPath); +} diff --git a/src/batteryinfo.cc b/src/batteryinfo.cc new file mode 100644 index 0000000..125ef4b --- /dev/null +++ b/src/batteryinfo.cc @@ -0,0 +1,41 @@ +#include +#include +#include + +namespace dlore +{ + std::string readData(std::filesystem::path path) + { + std::ifstream file(path, std::ios::in); + if(!file) return ""; + std::string ret; + std::getline(file, ret); + file.close(); + return ret; + } + + BatteryInfo GetBatteryInfo(std::filesystem::path classPath) + { + BatteryInfo info; + info.Manufacturer = readData(classPath / "manufacturer"); + info.Model = readData(classPath / "model_name"); + info.Technology = readData(classPath / "technology"); + + info.Capacity = std::stoi(readData(classPath / "capacity")); + info.ChargeNow = std::stoi(readData(classPath / "charge_now")) / 1000; + info.ChargeFull = std::stoi(readData(classPath / "charge_full")) / 1000; + info.ChargeFullDesign = std::stoi(readData(classPath / "charge_full_design")) / 1000; + + int Vnow = std::stoi(readData(classPath / "voltage_now")) / 1000; + int Vmin = std::stoi(readData(classPath / "voltage_min_design")) / 1000; + + info.Vnow = Vnow / 1000.0f; + info.Vmin = Vmin / 1000.0f; + + info.CellSeriesCount = std::ceil(info.Vmin / 3.7f); + // LiPo and Li-Ion cells operate at 3.7V (with the exception of LiFePO4 cells, which operate + // at 3.3V but are not used in laptops due to low voltage and charge) + + return info; + } +} diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..ceec6c9 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +#include + +void printBattery(std::filesystem::path classPath) +{ + dlore::BatteryInfo bat = dlore::GetBatteryInfo(classPath); + + std::cout << std::fixed << std::setprecision(2); + + std::cout << "Battery " << bat.Manufacturer << bat.Model; // manufacturer has a trailing whitespace, so no additional space necessary + std::cout << std::endl << "\tTechnology: " << bat.Technology; + std::cout << std::endl << "\tCell series count: " << bat.CellSeriesCount << 's' << std::endl; + std::cout << std::endl << "\tCapacity: " << bat.Capacity << '%'; + std::cout << std::endl << "\tVmin: " << bat.Vmin << 'V'; + std::cout << " Per cell: " << bat.Vmin / bat.CellSeriesCount << 'V'; + std::cout << std::endl << "\tVnow: " << bat.Vnow << 'V'; + std::cout << " Per cell: " << bat.Vnow / bat.CellSeriesCount << 'V'; + std::cout << std::endl << "\tCharge now: " << bat.ChargeNow << "mAh"; + std::cout << std::endl << "\tCharge full: " << bat.ChargeFull << "mAh"; + std::cout << std::endl << "\tCharge full (design): " << bat.ChargeFullDesign << "mAh" << std::endl; +} + +int main(int argc, const char** argv) +{ + for(const std::filesystem::directory_entry& entry : std::filesystem::directory_iterator("/sys/class/power_supply")) + { + std::filesystem::path path = entry.path(); + if(path.filename().string().find("BAT") == std::string::npos) continue; // filename does not contain BAT, continue + printBattery(path); + } + return 0; +}