Skip to content

Commit 5dd7ace

Browse files
committed
fix: database suspend now persists across HA restarts — saved to settings store, restored on startup
1 parent 8db7203 commit 5dd7ace

9 files changed

Lines changed: 45 additions & 12 deletions

File tree

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
padspanHA package version: 0.20.52
1+
padspanHA package version: 0.20.53

custom_components/padspan_ha/build_info.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html
55
"""Generated at build time. Used to prove what version is actually installed."""
66

7-
BUILD_VERSION = "0.20.52"
8-
BUILD_ID = "20260422T033758Z"
7+
BUILD_VERSION = "0.20.53"
8+
BUILD_ID = "20260422T034144Z"
99
CHANNEL = "beta"
1010

1111
# Backwards/for convenience

custom_components/padspan_ha/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
DOMAIN = "padspan_ha"
2121
NAME = "PadSpan HA"
22-
VERSION = "0.20.52"
22+
VERSION = "0.20.53"
2323

2424
# ── Config-flow option keys ───────────────────────────────────────────────────
2525
CONF_ENABLE_CLOUD = "enable_cloud"

custom_components/padspan_ha/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020
"issue_tracker": "https://github.com/gbroeckling/padspanHA/issues",
2121
"requirements": [],
2222
"single_config_entry": true,
23-
"version": "0.20.52"
23+
"version": "0.20.53"
2424
}

custom_components/padspan_ha/presence_coordinator.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,23 +320,44 @@ def __init__(self, hass: HomeAssistant) -> None:
320320

321321
# Suspend: when set, use only raw radio + spatial centroid (no k-NN, no adaptive)
322322
self._suspend_until: float = 0.0 # monotonic timestamp when suspend ends
323+
self._suspend_permanent: bool = False # persisted via settings store
324+
325+
# Restore persistent suspend from settings
326+
try:
327+
_st_init = self.hass.data.get(DOMAIN, {}).get(DATA_SETTINGS)
328+
if _st_init and _st_init.data.get("databases_suspended"):
329+
self._suspend_permanent = True
330+
_LOGGER.info("Databases suspended (restored from settings)")
331+
except Exception:
332+
pass
323333

324334
# ── Suspend / reset smoothing state ─────────────────────────────────────
325335

326336
@property
327337
def suspended(self) -> bool:
328338
"""True when databases are suspended — raw radio + spatial only."""
329-
return time.monotonic() < self._suspend_until
339+
return self._suspend_permanent or time.monotonic() < self._suspend_until
330340

331341
def suspend_databases(self, minutes: int = 60) -> None:
332342
"""Suspend all learned/cached databases for N minutes.
333343
334344
Clears all smoothing state and disables k-NN, adaptive learning,
335345
and scanner reliability for the duration. Only raw radio RSSI +
336346
spatial weighted centroid is used for positioning.
347+
348+
Also persists the flag so it survives HA restarts.
337349
"""
338350
self.clear_smoothing_state()
351+
self._suspend_permanent = True
339352
self._suspend_until = time.monotonic() + minutes * 60
353+
# Persist so it survives restarts
354+
try:
355+
_st = self.hass.data.get(DOMAIN, {}).get(DATA_SETTINGS)
356+
if _st:
357+
_st.data["databases_suspended"] = True
358+
self.hass.async_create_task(_st.store.async_save(_st.data))
359+
except Exception:
360+
pass
340361
_LOGGER.info(
341362
"Databases suspended for %d minutes — raw radio + spatial centroid only",
342363
minutes,
@@ -345,7 +366,16 @@ def suspend_databases(self, minutes: int = 60) -> None:
345366
def unsuspend_databases(self) -> None:
346367
"""End suspension early — resume normal pipeline."""
347368
self._suspend_until = 0.0
369+
self._suspend_permanent = False
348370
self.clear_smoothing_state() # start fresh when resuming too
371+
# Persist
372+
try:
373+
_st = self.hass.data.get(DOMAIN, {}).get(DATA_SETTINGS)
374+
if _st:
375+
_st.data.pop("databases_suspended", None)
376+
self.hass.async_create_task(_st.store.async_save(_st.data))
377+
except Exception:
378+
pass
349379
_LOGGER.info("Database suspension ended — full pipeline resumed")
350380

351381
def clear_smoothing_state(self) -> None:

custom_components/padspan_ha/websocket.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,8 +3210,11 @@ async def ws_live_snapshot(hass: HomeAssistant, connection, msg) -> None:
32103210
snap["suspended"] = _pc_sus.suspended
32113211
if _pc_sus.suspended:
32123212
import time as _time_mod
3213-
_remaining = max(0, _pc_sus._suspend_until - _time_mod.monotonic())
3214-
snap["suspend_remaining_s"] = round(_remaining)
3213+
if _pc_sus._suspend_permanent:
3214+
snap["suspend_remaining_s"] = 0 # permanent until unsuspended
3215+
else:
3216+
_remaining = max(0, _pc_sus._suspend_until - _time_mod.monotonic())
3217+
snap["suspend_remaining_s"] = round(_remaining)
32153218
except Exception:
32163219
pass
32173220

custom_components/padspan_ha/www/padspan-ha/lights_panel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
BUILD_ID / APP_VERSION updated automatically by scripts/release.py.
1313
*/
1414

15-
const APP_VERSION = "0.20.52";
16-
const BUILD_ID = "20260422T033758Z";
15+
const APP_VERSION = "0.20.53";
16+
const BUILD_ID = "20260422T034144Z";
1717

1818
// ── DOM helpers ──────────────────────────────────────────────────────────────
1919
function el(tag, attrs={}, children=[]){

custom_components/padspan_ha/www/padspan-ha/panel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ If UI changes don't show:
2222
// BUILD_ID (YYYYMMDDTHHMMSSZ) is appended to all JS import URLs as a cache-buster
2323
// so browsers always load the latest code after a release.
2424
// CHANNEL controls the sidebar badge and maps to GitHub release types (beta=pre-release).
25-
const APP_VERSION = "0.20.52";
26-
const BUILD_ID = "20260422T033758Z";
25+
const APP_VERSION = "0.20.53";
26+
const BUILD_ID = "20260422T034144Z";
2727
const CHANNEL = "beta";
2828

2929
// ── Dynamic view imports ─────────────────────────────────────────────────────

dist/padspan_ha.zip

267 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)