Repository navigation
Releases: BobMcGlobus/ha-vanmoof
Release list
v0.16.2 — fix "closes the Home Assistant aiohttp session" warning
Fixes the warning introduced in v0.16.1:
Detected that custom integration 'vanmoof' closes the Home Assistant aiohttp session
v0.16.1 created a dedicated HTTP session for the account login and closed it afterwards. Home Assistant wraps close() on such sessions in a warning because they share HA's connector (detach() is the documented call). That dedicated session only existed to rule out shared cookie state as a cause of the stale account bike list (#1) — and that hypothesis has since been disproven, since the same stale list appears with plain curl outside Home Assistant. So it's back to the shared session; the debug logging of the returned bikes stays.
Thanks @asys3 for spotting it. Please update to v0.16.2.
v0.16.1 — cloud login diagnostics (#1)
Groundwork for #1 (account bike list appears stale).
- The account login now uses a dedicated HTTP session with its own cookie jar instead of Home Assistant's shared one, so a one-shot login can't pick up or leave session state from other integrations.
- The bikes returned by the VanMoof API (names + frame numbers) are now logged at debug level, and the manifest declares its logger so debug logging can be switched on from the UI. This makes it possible to tell a stale API response apart from a UI problem.
No functional change if your account list was already correct.
v0.16.0 — sane decimals + "Last update" diagnostic sensor
Display precision. The bike reports whole numbers, so battery, speed, gear and module battery now show no decimals (no more 0,00 km/h, and no more 95.000000000000010 axis labels in history). Distance declares one decimal, which is its actual resolution.
New "Last update" diagnostic sensor. Shows when the bike was last read successfully, so you can tell at a glance whether polling still works — without digging through logs. It stays available even while polls are failing (a sensor that reports failure is useless if it disappears then) and it survives restarts, so "last seen 14 hours ago" is still there after a reboot.
Find it under Diagnostics on the device page. Update in HACS to v0.16.0 and restart HA.
v0.15.0 — steady presence + pick what matters more
Why the "In range" sensor had dropouts: reading the bike requires a connection, and while it is connected the bike stops advertising — which Home Assistant can read as "gone". So the more often we poll for battery, the more presence flaps. Two changes:
- Presence now ignores our own connection. While the integration holds a BLE session, an "unavailable" signal is no longer treated as the bike leaving. This is simply correct, regardless of settings.
- New option: what matters more? Under Configure:
- Battery and sensor readings (default) — brief dropouts are waited out with a 5 minute grace period and re-checked before presence turns off. Departure is detected a few minutes later.
- Fast departure detection — presence reacts immediately, at the cost of occasional short dropouts.
Update in HACS to v0.15.0 and restart HA, then set your preference under Configure.
v0.14.0 — no more false reauth prompts, cloud login on reauth, backoff
Three fixes from real-world use.
1. No more false "authentication failed" prompts. Your key hadn't changed — the prompt was wrong. Every observed error was at handle=50, the CHALLENGE read inside the handshake, which happens before the key is used for anything; a failure there is a transport problem (stale GATT table, flaky proxy, wedged module), never a bad key. Handshake failures are now kept separate from post-handshake read failures and never trigger re-authentication.
2. Re-authentication now offers the VanMoof account login. Previously it only accepted a manually typed key, so getting the key from the cloud meant deleting and re-adding the integration. Reauth now shows the same menu as setup, and the cloud path matches this bike automatically by frame number (with a picker as fallback), refreshing key, frame number and model.
3. Backoff instead of hammering. A bike could stay unreachable for many hours while being polled every 5 minutes — which tends to keep a wedged module wedged. After 3 consecutive failures the interval now doubles, up to 60 minutes; a successful poll restores your configured interval, and the Refresh button always forces an immediate attempt.
Update in HACS to v0.14.0 and restart HA.
v0.13.0 — entities load even when the bike is away; faster recovery
Setup no longer blocks on reaching the bike. Previously, if the bike was out of range or asleep when Home Assistant started, the whole entry stayed in "retrying" and no entities loaded — including the passive presence sensor and the Refresh button, which are exactly what you want when the bike isn't there. Now the entry loads, entities show unavailable, and they recover on a later poll. Presence and Refresh work immediately.
Faster self-healing. After clearing a stale GATT cache (the error=14 Unlikely error case), the integration now reconnects and retries once right away instead of staying broken until the next poll. Cache-clear success is logged for debugging.
Docs: dropped a stale note claiming reauth was unimplemented (it shipped in 0.4.0/0.11.1), and documented the single-connection behaviour plus ESP32-S3 active-proxy flakiness.
Note this doesn't make an unreachable bike reachable — if every poll fails with error=14/133, the bike's module is likely stuck (wake/ride it or power-cycle) or the connection path is unstable.
v0.12.0 — keep last battery/gear for 2h, frame number always
Sensors now hold their last value for a bounded time when the bike is out of range, instead of dropping to unavailable immediately:
- Frame number — kept always (it's static, from your account).
- Odometer — kept always (unchanged).
- Battery, Gear — kept for 2 hours after the last successful read, then unavailable.
- Speed and the rest — unchanged (unavailable on a failed poll; a stale speed would be misleading).
Update in HACS to v0.12.0 and restart HA.
v0.11.4 — serialise BLE sessions (one connection at a time)
The bike accepts only one BLE connection at a time. The poll and every one-off action (lock/unlock, bell, selects, Refresh) open their own short session, so triggering a control during a poll could open two connections at once — which the bike rejects with GATT "Unlikely error" / 133. A lock now serialises all BLE sessions so only one is ever open.
Good hygiene for a single-connection device; reduces spurious errors when you interact with the bike while it's polling.
v0.11.3 — handle incomplete GATT discovery gracefully
Fixes a crash ('NoneType' object has no attribute 'get_characteristic') that showed up on flaky connections — e.g. right after restarting an ESPHome proxy.
On an unstable (proxy) connection the GATT table can enumerate incompletely, so the service/characteristic lookup returns None. The code now raises a proper BleakError instead of crashing, which routes into the cache-clear + retry path and self-heals on the next poll once discovery completes.
Also raised the re-auth escalation threshold (2 → 5) so a flaky connection during setup isn't mistaken for a wrong key and doesn't trigger a false "authentication expired" prompt.
If a bike is stuck: update to 0.11.3, then give it a couple of poll cycles (or press Refresh). GATT error 133 / incomplete discovery is usually connection contention or an ESP proxy at the edge of range — a proxy restart and/or fewer simultaneous BLE connections helps.
v0.11.2 — self-heal stale GATT cache ("Unlikely error")
Fixes a bike getting stuck unavailable with a repeating Bluetooth GATT Error … error=14 Unlikely error while still shown in range — and the Refresh button not helping.
Cause: Home Assistant caches the device's GATT service table on disk. When the bike's smart module reboots, the cached handles go stale and every read (starting with the auth nonce) fails with ATT "Unlikely error"; a retry/reload keeps reusing the bad cache. Now a post-connect error clears the service cache (clear_cache()), so the next poll rediscovers the services and recovers on its own.
Update to 0.11.2. If a bike is stuck right now, it should self-heal within a poll cycle after the update; if not, toggling the bike's Bluetooth (or waking it) forces a fresh advertisement.