The file is the macroplan (plus per-version scope), so rename it to match and retitle to "Macroplan"; update all inbound links and friendly labels across the docs. Refresh the plan while here: v0.2 gutter built, :gl pull recorded (v0.7), command-line editing (v0.4), and the format_on_save pref (v0.5).
5.8 KiB
Wi-Fi energy vs auto-sync interval
Decision:
auto_syncdefaults to 10 min, and is an opportunistic, rate-limited push — not a wall-clock timer that wakes the device. See Policy. Backs the.typoena.tomlauto_synckey in../macroplan.md(v0.5), whose runtime timer lands in v0.7 and must respect sleep (v0.8).Tradeoff-curves index:
README.md. Docs index:../README.md.
The model
For a text commit the git payload is a few KB — negligible. Almost all the energy of one sync is a fixed radio burst that costs the same no matter how little changed:
radio wake → AP association → TLS handshake → tiny push → teardown
So energy per unit time scales as (fixed cost per sync) × (syncs per hour):
E(T) = K / T T = interval in minutes, K = one burst's worth of energy
A hyperbola. Doubling the frequency doubles the cost; the words you actually wrote barely move it.
Placeholder constants (pending the v0.8 bench measurement — "measure idle /
typing / push current draw"): an ~8 s radio burst at ~150 mA average ⇒
0.33 mAh per sync, so K ≈ 20 mAh·min/hr. The vertical scale below moves
with the real measurement; the shape and the knee do not.
One assumption is baked into that burst: the radio is fully off between
syncs, not parked in modem-sleep. Holding the association awake to skip the
per-sync handshake costs ~15–20 mAh/hr on the WROOM — more than a 1-min interval
and ~10× the 10-min default — and only pays back above ~150 syncs/hr (one sync
every ~24 s), which a writing appliance never reaches. So each sync legitimately
pays a full fresh wake → associate → handshake burst, and "off" everywhere
below means radio de-init, not beacon-listening. Tear the connection down
immediately after each push, too: with syncs ≥2 min apart a keep-alive window
saves nothing, and Typoena only ever pushes — there's no inbound traffic that
would justify staying reachable.
Status (v0.1) — the shipped firmware does not cycle the radio yet. It brings Wi-Fi up lazily on the first
:syncand then keeps it up for the rest of the session:run_git_servicein../../firmware/src/git_sync.rsholds thewifihandle across its whole request loop and never stops, disconnects, or drops it (grep the module forstop/disconnect/drop— zero hits). So today's device runs the stay-associated strategy this section argues against, at ~15–20 mAh/hr after the first push. The off-between-syncs assumption above is the target, not current behaviour: the modem is.take()n exactly once, so per-sync teardown is a v0.8 refactor of that ownership, not a config flip — and a prerequisite before any sleep mode ships.
The curve
Wi-Fi energy vs auto-sync interval E(T) ≈ K / T
mAh/hr
20 | * each sync ≈ one fixed radio burst,
| * independent of how much text changed
| *
15 | * ← STEEP: every extra sync/min costs a full burst
| * for zero payload benefit
| *
| *
10 | *
| *
| *
| * ← knee
5 | *·.___ (5 min)
| `·-·__ ______
| `·-·__·--·______ (15) diminishing returns:
0 | `·--·----·----·----·----·--- the tail is ~flat
+----+----+----+----+----+----+----+----+----+----+----+----+
0 5 10 15 20 25 30 35 40 45 50 55 min
└── knee: 5–10 min. Left of here you pay a lot;
right of here you save almost nothing.
| interval | syncs/hr | Wi-Fi mAh/hr | vs 5-min | per 8 h day |
|---|---|---|---|---|
| 1 min | 60 | 20.0 | 5.0× | 160 mAh |
| 2 min | 30 | 10.0 | 2.5× | 80 mAh |
| 5 min | 12 | 4.0 | 1.0× | 32 mAh |
| 10 min | 6 | 2.0 | 0.5× | 16 mAh |
| 15 min | 4 | 1.33 | 0.33× | 10.7 mAh |
| 30 min | 2 | 0.67 | 0.17× | 5.3 mAh |
| 60 min | 1 | 0.33 | 0.08× | 2.7 mAh |
Two things that move where "best" sits
save_on_idle already prevents data loss — auto-sync is only remote-mirror
freshness. The durable local copy is the SD write on the idle pause. A longer
sync interval never risks losing work; it only means the GitHub mirror is a
few minutes staler. That's a weak cost, and it pushes the optimum toward
longer intervals.
The real battery risk is the sleep interaction, not the awake case. While you're typing, the CPU/e-ink baseline dwarfs the sync cost — 5 vs 15 min is noise. The damage happens when the device is idle or asleep and a wall-clock timer wakes it just to push: each wake pays the radio burst plus the wake/boot cost and blocks the low-power state. That turns "closed on the desk overnight" from weeks of standby into dead-by-morning.
Policy
Ship auto_sync as an opportunistic, rate-limited push, with the config value
read as a max-staleness cap rather than a timer period:
- Push when already awake + dirty, coalesced into the existing idle-pause,
rate-limited to at most once per
auto_sync— so a fast typist pausing every 20 s doesn't sync 100×/hr. - Push once on the way into sleep (idle → light sleep, and especially lid-close → deep sleep) if dirty. This is the highest-value sync: nearly free (the device is spinning up anyway) and it's the freshness guarantee.
- Never wake from deep sleep purely to sync. The one behavior that wrecks standby life.
On the single number: 10 min halves the sync energy versus a 5-min default
for essentially no real cost, because save_on_idle already owns data safety.
Clamp the minimum to ~2 min so a palette command (> auto sync: 10s) can't
quietly drain the battery.