-
Notifications
You must be signed in to change notification settings - Fork 0
Version history
What each release actually changed, newest first. APKs are on the releases page and the package host.
The app and the server version independently — the app feature-detects what a server offers — so nothing here requires upgrading both at once.
| 2.2.7 | 21 Aug 2026 | the sleep timer, cat facts while loading, native licences |
| 2.2.6 | 16 Aug 2026 | the outdoor sensor, finally used: indoor/outdoor/target bar |
| 2.2.5 | 16 Aug 2026 | multiple servers, and the Nerd screen |
| 2.2.1 | 15 Aug 2026 | Android Auto actually appears in the car |
| 2.2.0 | 15 Aug 2026 | haptics that exist, generated device names, a welcome screen that welcomes |
| 2.1.2 | 14 Aug 2026 | the car app was invisible: IOT is Automotive-only |
| 2.1.1 | 13 Aug 2026 | the bug that locked people out, and Android Auto |
| 2.0.1 | 23 Jul 2026 | first stable 2.0; last-viewed unit, full diagnostics |
| 2.0.0 | 21–22 Jul 2026 | ground-up redesign: one unit per screen, Ed25519, SSE |
| 1.3.0 | 6 Jul 2026 | optimistic control + haptics, batched state, °C/°F, themes |
| 1.2.0 | 5 Jul 2026 | home-screen widgets |
| 1.1.0 | 5 Jul 2026 | add units by IP, rename them |
| 1.0.1 | 4 Jul 2026 | the first build |
- A sleep timer. An hourglass beside the power switch: pick how long the unit stays on and the server turns it off, so it works with the phone away. Asks for minutes rather than a time of day and counts down from the server's own figure, so a phone in another timezone — or with a wrong clock — still gets the right result. See the control screen.
- The refresh indicator moved next to the status dot, into a fixed-width slot. It used to sit where the hourglass now goes, and appearing mid-command shifted the unit's name sideways.
- Cat facts while waiting on the server, bundled rather than fetched.
- The native dependencies' licences are registered. Flutter's licence page only walks Dart packages, so the AndroidX Car App Library behind Android Auto had no attribution in the app at all.
The outdoor sensor, finally used. The units report an outdoor temperature —
diagnostics had been printing it all along — and the app was throwing it away. The
control screen now reads I: 27.0 °C / O: 33.0 °C with a slim bar showing how
indoor, outdoor and target relate.
The bar could have been described as three separate behaviours, which is how such things drift apart, so it is one rule: the warmest of the three sets the top of the scale, and the other two are drawn from the floor as overlapping fills, the warmer of them lighter. Cooling, heating and indoor-below-target all fall out of that without special cases.
Every way a sensor can lie is covered by a test: a missing outdoor probe reporting a sentinel like 255, NaN and infinities, below-zero outdoors extending the floor instead of clamping, fewer than two real readings showing numbers but no bar, and identical readings still getting a 1 °C span. Geometry is computed in Celsius whatever the display unit. See the temperature bar.
Multiple servers. Save as many as you like and switch instantly; each keeps its own credential in the Keystore, so coming back to one needs no re-pairing — which would otherwise mean getting an admin onto that server's LAN. An existing install migrates into a profile on first launch, writing the new keys before deleting the old ones so an interrupted migration retries rather than losing the credential.
The Nerd screen. Tap the
version seven times: the app's own dependency versions read from the shipped
pubspec.lock, the measured round-trip latency and how the server sees you, and
everything GET /api/system knows about the server, its units and every enrolled
device. One button copies the lot as JSON. Needs Breeze Core ≥ 3.0.5; against
anything older it says womp womp update your server.
Also a Licences page, and Gradle's heap capped at 2 GB with a 10-minute idle timeout — a build used to leave a ~5 GB JVM resident long after it finished.
The Android Auto surface now actually appears in the car. It never had: on a phone with Auto's developer mode and unknown sources enabled, Breeze was simply absent from the launcher with nothing in any log.
Through 2.2.0 the service declared its two categories as two separate
<intent-filter> blocks. Both resolve fine in PackageManager — either category
query returns the service — but the host reads the categories off the first
ResolveInfo it gets and sees only one. One filter carrying both, and Auto picked
it up immediately. Android Auto has the whole story.
Haptics, which were effectively absent. There were exactly two haptic calls in
the app: one selectionClick — the faintest constant Android offers — fired
after a control had already committed, plus one in diagnostics. Steppers, mode,
fan, flap, power and page swipes were silent, and the VIBRATE permission was not
even declared, so the stronger paths did nothing regardless. Feedback is now named
by meaning — tick, select, toggle, success/failure — so it stays consistent as
things get added.
Generated device names. Every install proposed "Breeze", so a household ended
up with several identically-named rows in the server's device list and no way to
tell which phone to revoke. Names are now a climate word plus seven digits —
Sirocco-4820937 — with a dice button to re-roll.
A welcome screen that welcomes. It was an icon and three bare fields followed by an abrupt jump to a pairing code nobody had been warned about. It now states the three steps before they happen — including that a person has to approve the pairing on your home network, which is the genuinely surprising one.
Fixes the car app not appearing at all. The surface was registered under
androidx.car.app.category.IOT, the semantically right home for "control a device
at my house" and what Google's own IoT guide pairs with the template used here.
But IOT is an Android Automotive OS category: Android Auto does not list an app
that only declares it. Nothing on the phone side could have helped. The service
now also declares POI, the only Auto-supported templated category that permits
these templates without the navigation permission.
The bug that locked users out, and the client half of Breeze Core 3.0.2.
The app treated any 401 as "my credential is dead": it deleted the stored
Ed25519 private key and demanded re-pairing. Re-pairing needs an admin on the LAN,
so a user away from home could not recover — and when the immediate re-enrolment
also failed, the app fell through to onboarding having forgotten the server
entirely. The trigger did not have to be real: a phone whose clock had drifted past
the server's 60-second window fails every signed request, which looks identical to
a revoked credential.
Now transient failures are retried once transparently; a clock_skew rejection
teaches the app the server's offset so a drifted clock self-heals in one
round-trip; re-pairing only happens when the server says the credential is finished
(or after three unexplained 401s); and a kept-credential 401 drops to the offline
state instead of polling every 5 seconds — that hammering is what tripped the
server's fail2ban and, behind NAT, banned everyone's shared address at once.
Diagnostics also stopped probing the LAN-only /api/auth/devices when you are
remote, since a single 403 there could get your address banned, and started
reporting the device clock offset — which would have identified all of this in one
tap. Full reasoning: Security.
Also in the 2.1 line: the Android Auto surface, the widget's bold ON/OFF/OFFLINE badge going colourless when a unit is off, power as a big red/green switch, and the flap as one pill split in two.
First stable of the 2.0 line. Reopens on the unit you last viewed, remembered
by unit rather than position so it survives adding, removing or reordering. And
full in-app diagnostics, mirroring the server's diag: connectivity, build and
features, auth posture, this device's credential and expiry, secret sanitisation,
input validation, batch state, a live-stream check, and per-unit health and
hardware capabilities.
A ground-up redesign, shipped stable as 2.0.1.
- One unit per screen, swipe to switch, replacing a scrolling list of cards. Each unit fills the screen, tinted to its mode.
- Modern controls — a 0.5° stepped temperature slider with ± buttons, a Low→High fan slider that detaches to Auto, a flap control, huge eco/turbo switches, a colourful segmented mode picker.
- No more flicker on refresh: state updates in place, and controls never jump while you are dragging them.
-
Live updates over SSE (pre2) — the app opens
/api/units/streamand applies pushed changes in place, so the phone stops polling and changes from schedules or other clients appear instantly. - Ed25519 request signing, scan-to-add, and a beep toggle, riding on Breeze Core 3.0.0.
Optimistic control with haptics — taps update instantly and reconcile on the reply, so the round-trip wait is gone. Faster, quieter loading: one batched state request (Breeze Core ≥ 2.4.0, falling back to per-unit), an offline banner, and poll backoff 5s → 20s instead of error-snackbar spam. Plus °C/°F, a light/dark/system override, periodic widget refresh via WorkManager, and remove unit.
Home-screen widgets: a resizable widget per unit with temperature, mode and power, and buttons that control the unit without opening the app — each tap runs a headless background task reusing the app's API client and Keystore-held credentials. Material You themed on Android 12+.
Add units by IP — the app asks the server to discover and add a unit by its LAN address — and rename units. Both need Breeze Core ≥ 2.2.0.
The first build. Its release notes read, in full: mrrp.
-
1.4.0 and 2.0.2 were never released. Both existed in
pubspec.yamlon the way to the next version. - 2.1.0 shipped as 2.1.1. The Android Auto surface was built under 2.1.0, and 2.1.1's lockout fix landed before anything was published.
- 2.2.2 to 2.2.4 do not exist. 2.2.1 was followed by 2.2.5.
Breeze · Breeze Core (the server) · APKs · AGPL-3.0
Start here
Using it
- The control screen
- Home-screen widgets
- Android Auto
- Programs
- Diagnostics and the Nerd screen
- Multiple servers
- Settings and theming
Under the hood
The server