Battery Usage — Last 7 Days

Battery level from OwnTracks GPS data via PostgreSQL. Red = heavy drain (>30%), orange = moderate, green = light. Dashed lines at 20% and 80%.

import psycopg2, datetime
BST = datetime.timezone(datetime.timedelta(hours=1))
conn = psycopg2.connect(host='/home/john/tmp', port=5432, dbname='owntracks', user='owntracks_ro')
cur = conn.cursor()
cur.execute("""
    WITH day_batt AS (
        SELECT (to_timestamp(tst) AT TIME ZONE 'Europe/London')::date AS day,
               batt, tst, bs
        FROM locations
        WHERE tst >= extract(epoch FROM now() - interval '7 days')
          AND batt IS NOT NULL
    )
    SELECT day,
           (array_agg(batt ORDER BY tst ASC))[1]  AS first_batt,
           (array_agg(batt ORDER BY tst DESC))[1] AS last_batt,
           MIN(batt), MAX(batt),
           COUNT(*) FILTER (WHERE bs IN (2,3)),
           COUNT(*),
           array_agg(batt ORDER BY tst),
           array_agg(tst  ORDER BY tst)
    FROM day_batt GROUP BY day ORDER BY day
""")
rows = cur.fetchall()
conn.close()
print(f"Fetched {len(rows)} days")
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns

def plot_day(row):
    day, first_b, last_b, min_b, max_b, chrg_fixes, total_fixes, batt_series, tst_series = row
    times = [datetime.datetime.fromtimestamp(t, tz=BST) for t in tst_series]
    charging = chrg_fixes > total_fixes * 0.1
    drop = first_b - last_b
    colour = '#e05050' if drop > 30 else '#e09030' if drop > 10 else '#50a050'

    sns.set_theme(style='whitegrid')
    fig, ax = plt.subplots(figsize=(14, 2.5))
    ax.plot(times, batt_series, color=colour, linewidth=1.5)
    ax.fill_between(times, batt_series, alpha=0.2, color=colour)
    ax.set_ylim(0, 105)
    ax.set_ylabel('%', fontsize=9)
    ax.set_title(
        f"start={first_b}%  end={last_b}%  min={min_b}%  drop={drop:+d}%"
        + ('  [charging]' if charging else ''),
        fontsize=9, loc='right'
    )
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
    ax.xaxis.set_major_locator(mdates.AutoDateLocator())
    ax.axhline(20, color='#bbb', linewidth=0.6, linestyle='--')
    ax.axhline(80, color='#bbb', linewidth=0.6, linestyle='--')
    fig.tight_layout()
    show(fig)
    plt.close(fig)

print("plot_day() defined")

Tuesday 07 Jul — iPhone battery

plot_day(rows[0])

Wednesday 08 Jul — iPhone battery

plot_day(rows[1])

Thursday 09 Jul — iPhone battery

plot_day(rows[2])

Friday 10 Jul — iPhone battery

plot_day(rows[3])

Saturday 11 Jul — iPhone battery

plot_day(rows[4])

Sunday 12 Jul — iPhone battery

plot_day(rows[5])

Monday 13 Jul — iPhone battery

plot_day(rows[6])

Tuesday 14 Jul — iPhone battery

plot_day(rows[7])
version 2