close
Skip to content

ptcodes/BatteryScope

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BatteryScope

Screenshot

CI

A GTK4/libadwaita desktop application for Linux that monitors laptop battery health, usage patterns, and long-term degradation trends. Unlike a one-shot query (upower -d), BatteryScope continuously collects data over time and surfaces insights that are only visible across days and weeks of usage.


Why continuous data collection?

A single measurement of your battery tells you almost nothing useful. Battery behavior is contextual: power draw varies with workload, health degrades slowly over months, and time-to-empty estimates are only accurate when averaged over realistic usage rather than a momentary spike. BatteryScope solves this by recording battery state every minute to a local SQLite database, then using that history to answer questions that a one-shot tool cannot.

With continuous data you can:

  • Estimate remaining runtime based on your actual average power draw over the last 15 minutes, not a kernel heuristic
  • Track health degradation over weeks and months as the battery's maximum charge capacity shrinks
  • Spot anomalies — a sudden spike in power draw, an unusually fast drain, or a charge session that stopped short
  • Project the future — model when your battery will cross the 80% health threshold that most manufacturers define as end-of-useful-life

The cost is minimal: a small bash script run by a systemd timer writes a single SQLite row per minute. The database grows by roughly 500 KB per year.


Architecture

systemd timer (every 1 min)
    └── battery-logger.sh
            reads /sys/class/power_supply/BAT0/*
            writes one row to ~/.local/share/battery-logger.db

BatteryScope (GTK4 app)
    ├── reads DB every 30 seconds  →  Status panel, Health panel, Capacity chart
    ├── reads /sys directly every 1 second  →  real-time power draw chart
    └── reads /sys at launch  →  Battery info panel

Installation

cargo build --release
./target/release/BatteryScope

Requirements: Linux, GTK 4.12+, libadwaita 1.4+, SQLite, systemd (user session), Rust 2024 edition toolchain.

On first launch, open the Settings tab and enable background monitoring. The app will install the logger script and systemd timer automatically. Data collection begins within one minute.

BatteryScope is Linux-only. The data logger relies on sysfs (/sys/class/power_supply/) and systemd, and the app reads battery hardware directly from the same sysfs interface. macOS and Windows expose battery data through different platform APIs and would require separate implementations.

Uninstallation

Disable background monitoring in the Settings tab before removing the binary. This stops the systemd timer and removes the logger script and unit files from ~/.local/bin/ and ~/.config/systemd/user/.

Your collected data at ~/.local/share/battery-logger.db is intentionally left intact. Delete it manually if you no longer need it.


Interface

Status panel

Displays the current operating state of the battery, refreshed every 30 seconds.

Field Explanation
Temperature Battery cell temperature in °C. Sourced from /sys/class/power_supply/BAT0/temp if available, otherwise falls back to the ACPI thermal zone (/sys/class/thermal/thermal_zone0/temp). Tagged Cool below 30°C, Normal up to 45°C, Hot above that. High sustained temperatures accelerate chemical degradation inside the cell.
Power now Instantaneous power flowing in or out of the battery in watts. Tagged Idle below 8 W, Normal up to 15 W, Heavy above. This is the raw kernel value from /sys/class/power_supply/BAT0/power_now (reported in microwatts).
Estimated time left When discharging: remaining energy divided by your average power draw over the last 15 minutes. Calculated as energy_now / avg(power_now, last 15 min). Because it uses a rolling average rather than the instantaneous reading, it is stable under short workload spikes. Switches to Est. full charge time when plugged in.
Est. full charge time When charging: energy still needed divided by the current charge power, (energy_full − energy_now) / power_now. Both values are in microwatt-hours and microwatts, so the units cancel to hours — no conversion needed.
Current draw Amperage derived from power_now / voltage_now, expressed in milliamps. Useful for comparing against the rated discharge current of the battery.
Voltage Current battery terminal voltage in volts. A fully charged Li-ion cell sits around 4.2 V per cell; at the bottom of its discharge curve it approaches 3.0 V. The total pack voltage is the number of cells in series multiplied by the per-cell voltage.

Health panel

Displays the long-term state of the battery's electrochemical capacity.

Field Explanation
Capacity energy_full / energy_full_design × 100%. This is what the kernel reports as the battery's current maximum charge relative to the manufacturer's original design capacity. A brand-new battery is typically 100–105% (cells are often spec'd conservatively). Tagged Excellent above 90%, Good above 80%, Worn above 70%, Poor below. The Info tab also shows an action-oriented rating: Optimal (100%–85%) means no action needed; Monitor (85%–80%) means the battery is beginning to age and replacement should be planned if you rely on battery use; Replace (below 80%) means the battery is considered consumed by most manufacturers and unexpected shutdowns may occur.
Degradation rate The rate at which capacity is shrinking, expressed as percentage points per month. Computed by fitting a linear regression over daily peak energy_full readings (one data point per calendar day, using the daily maximum to filter out partial charge readings). A healthy battery typically degrades 0.1–0.5% per month under normal use. Rates above 1% per month suggest heavy use, frequent high-temperature charging, or a battery approaching end of life.
Projected to 80% Using the regression slope, estimates how many months (or years and months) remain until the battery's capacity crosses the 80% threshold. If the battery is already below 80%, this reports Already below 80%. If no meaningful degradation trend is detected, it reports Not degrading.

Battery panel

Static information read from sysfs at launch. Does not change during a session.

Field Source
Manufacturer /sys/class/power_supply/BAT0/manufacturer
Model /sys/class/power_supply/BAT0/model_name
Technology Chemistry type, e.g. Li-ion or Li-poly. Li-poly is more flexible in physical shape; both degrade by the same electrochemical mechanisms.
Cycle count Number of full charge-discharge cycles recorded by the battery management chip. One "cycle" is 100% of total capacity discharged, not necessarily one plug-in/plug-out. Draining from 100% to 50% twice counts as one cycle. Tagged Like new (0–100), Light use (101–300), Moderate (301–600), Heavy (601–900), Very heavy (900+). Most laptop batteries are rated for 300–500 full cycles before reaching 80% capacity.
Serial Manufacturer serial number of the cell pack.

Settings tab

Contains a toggle to enable or disable background monitoring. Enabling installs the logger script to ~/.local/bin/battery-logger.sh and the systemd service and timer to ~/.config/systemd/user/, then starts the timer. Disabling reverses this. If monitoring is off when the app launches, a banner at the top of the window links directly to this tab.


Charts

Power draw (W) — last 2 min Updated every second by reading /sys/class/power_supply/BAT0/power_now directly, bypassing the database. Maintains a 120-sample rolling window. Useful for correlating power spikes with specific applications or system events in real time. Colored green when below 8 W (idle), amber up to 15 W, red above.

Capacity (%) — last 2 hours Updated every 30 seconds from the database, showing the last 120 logged readings. Reveals how fast the battery is draining under current conditions and makes charging sessions clearly visible as rising slopes.


Battery degradation explained

What is degradation?

Lithium-ion batteries lose capacity through irreversible chemical changes inside the cell. The two primary mechanisms are:

  1. SEI layer growth. Each charge cycle deposits a thin layer of lithium compounds on the graphite anode (the solid-electrolyte interphase). This layer consumes lithium that can no longer participate in the charge-discharge reaction, permanently reducing capacity.

  2. Cathode degradation. Repeated expansion and contraction of cathode material (typically lithium cobalt oxide or similar) during cycling causes microscopic cracking and structural changes, reducing how much lithium the cathode can hold.

Both processes are gradual and irreversible. They are accelerated by heat, by charging to 100% frequently, by discharging to 0% frequently, and by high charge rates.

Why does 80% matter?

The 80% capacity threshold is the industry standard definition of end-of-useful-life for a laptop battery, used by Apple, Lenovo, Dell, and most others. It is also the threshold at which:

  • Many laptop warranty programs cover battery replacement
  • macOS marks the battery as needing service
  • The difference in real-world runtime becomes practically noticeable — a battery that once lasted 8 hours now lasts about 6.4 hours at equivalent workload

Crossing 80% does not mean the battery stops working. It will continue to discharge and charge normally. But the decline tends to accelerate below 80% because the internal resistance of a degraded cell is higher, which generates more heat during use, which accelerates further degradation.

Why do the degradation metrics require ~14 days of data?

The degradation rate is estimated by linear regression over daily peak energy_full readings. There are two reasons 14 days is the minimum:

  1. Day-to-day noise. The kernel's energy_full reading is not perfectly stable — it fluctuates by a small amount between measurements depending on temperature, recent charge history, and measurement timing. With fewer than two weeks of daily data points, this noise can produce a regression slope that is meaningless or even inverted.

  2. Statistical significance. Battery degradation over a two-week period is genuinely tiny — typically 0.05–0.25% of design capacity. Detecting a signal that small requires enough data points that the regression line is not dominated by individual noisy readings.

With 14+ days of data, the regression becomes stable enough to produce a slope accurate to within roughly ±0.1% per month. With 30–60 days the projection becomes reliable enough to plan around.


Battery care recommendations

The following practices meaningfully extend battery lifespan:

Keep charge between 20% and 80%. The chemical stress on the electrodes is highest at the extremes of the charge range. Charging to 80% instead of 100% and plugging in before 20% can roughly double the number of cycles to 80% capacity. Many laptops now offer a "battery limit" mode in firmware for exactly this reason.

Avoid sustained high temperatures. Heat is the single biggest accelerant of battery aging. A battery stored or operated at 40°C degrades roughly twice as fast as one kept at 25°C. Keep vents clear, avoid soft surfaces that block airflow, and avoid leaving the laptop in a hot car.

Avoid frequent full discharges. Li-ion does not have a "memory effect" (that was NiMH). Deep discharges are more stressful than shallow ones. Topping up from 50% is better for the battery than running it flat.

Charge slowly when possible. Fast charging generates more heat inside the cell. If time permits, using a lower-wattage charger (or a USB-C charger below the laptop's rated input) charges the battery more gently. This is why your 45 W rated charger may deliver 27 W — the battery management system accepts less than the maximum to balance speed against heat.

Charge rate vs. rated wattage. Your charger's rated wattage is the maximum it can deliver. What the battery actually receives is negotiated between the charger, the USB-C power delivery controller, and the battery management IC in real time. The BMS limits charge current based on temperature, current state of charge (charge rate always slows near 100%), and the health of the cell. A lower actual wattage than the charger's rating is normal and does not indicate a problem.


Data stored

All data is stored locally in ~/.local/share/battery-logger.db. Nothing is sent anywhere. The schema:

CREATE TABLE stats (
    timestamp           TEXT    NOT NULL,   -- YYYY-MM-DD HH:MM:SS (local time)
    capacity            INTEGER NOT NULL,   -- 0–100 %
    status              TEXT    NOT NULL,   -- Charging / Discharging / Full / Unknown
    energy_now          INTEGER,            -- µWh, current stored energy
    energy_full         INTEGER,            -- µWh, current maximum capacity
    energy_full_design  INTEGER,            -- µWh, factory design capacity
    power_now           INTEGER,            -- µW, instantaneous power flow
    voltage_now         INTEGER             -- µV, terminal voltage
);

Energy values are in microwatt-hours (µWh) and power in microwatts (µW) — these are the raw kernel units. BatteryScope converts them to watts and watt-hours for display by dividing by 1,000,000.

About

🔋BatteryScope is a Linux desktop app that tracks laptop battery health, logs per-minute stats to a local SQLite database, and visualizes capacity trends and degradation over time.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors