Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
05df4f3
docs: add strategy config validation design
raman325 Mar 11, 2026
ff3ffd4
docs: add strategy config validation implementation plan
raman325 Mar 11, 2026
8c355c8
Merge remote-tracking branch 'upstream/main'
raman325 Apr 3, 2026
8d8416d
fix: start autolock timer when lock is already unlocked
raman325 Apr 11, 2026
ec4bdf7
refactor: persist autolock timer to HA Store for restart recovery
raman325 Apr 11, 2026
83c78f9
refactor: use UTC times in autolock timer via homeassistant.util.dt
raman325 Apr 11, 2026
6588a2e
fix: replace dual timer callbacks with single fire-then-cleanup callback
raman325 Apr 11, 2026
c94b4cf
refactor: make timer properties pure by delegating to is_running
raman325 Apr 11, 2026
24c64c0
style: apply ruff formatting
raman325 Apr 11, 2026
bf36e79
fix: cancel autolock timer when disabling autolock switch
raman325 Apr 11, 2026
786c171
fix: reset complementary throttle on lock/door state transitions
raman325 Apr 11, 2026
b8507c9
chore: remove docs/plans directory
raman325 Apr 11, 2026
10734d0
fix: address review feedback for timer setup and tests
raman325 Apr 11, 2026
18a58e6
refactor: rename duration to total_duration for clarity
raman325 Apr 11, 2026
7ef9749
Revert "refactor: rename duration to total_duration for clarity"
raman325 Apr 11, 2026
f6c5dee
fix: guard against corrupted timer store data on recovery
raman325 Apr 11, 2026
316b741
refactor: add TimerStoreEntry TypedDict for precise store typing
raman325 Apr 11, 2026
72ee58a
refactor: inline timer_id in _setup_timer
raman325 Apr 11, 2026
12281cf
test: add coverage for timer persistence edge cases, throttle resets,…
raman325 Apr 15, 2026
15ddb40
style: apply ruff formatting to test_helpers.py
raman325 Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions custom_components/keymaster/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,13 @@ async def _setup_timer(self, kmlock: KeymasterLock) -> None:
call_action=functools.partial(self._timer_triggered, kmlock),
)

if (
kmlock.autolock_enabled
and kmlock.lock_state == LockState.UNLOCKED
and not kmlock.autolock_timer.is_running
):
await kmlock.autolock_timer.start()
Comment thread
raman325 marked this conversation as resolved.
Outdated

async def _timer_triggered(self, kmlock: KeymasterLock, _: dt) -> None:
_LOGGER.debug("[timer_triggered] %s", kmlock.lock_name)
if kmlock.retry_lock and kmlock.door_state == STATE_OPEN:
Expand Down
10 changes: 10 additions & 0 deletions custom_components/keymaster/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
from typing import Any

from homeassistant.components.lock.const import LockState
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
Expand Down Expand Up @@ -292,6 +293,15 @@ async def async_turn_on(self, **_: Any) -> None:
self._kmlock.autolock_min_day = DEFAULT_AUTOLOCK_MIN_DAY
if self._kmlock.autolock_min_night is None:
self._kmlock.autolock_min_night = DEFAULT_AUTOLOCK_MIN_NIGHT
if (
self._kmlock.lock_state == LockState.UNLOCKED
and self._kmlock.autolock_timer
and not self._kmlock.autolock_timer.is_running
):
await self._kmlock.autolock_timer.start()
self.coordinator.async_set_updated_data(
dict(self.coordinator.kmlocks)
)
if (
self._property.endswith(".enabled")
and self._kmlock
Expand Down
65 changes: 65 additions & 0 deletions docs/plans/2026-03-10-strategy-config-validation-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Strategy Config Validation Design

## Problem

The dashboard, view, and section Lovelace strategies accept config objects but lack
full schema validation. The view and section strategies have some inline checks
(e.g., requiring one of `config_entry_id`/`lock_name`), but:

- The dashboard strategy does no validation at all.
- No strategy rejects unknown keys (typos pass silently).
- Type validation is missing (e.g., `slot_num` could be a string).
- Validation logic is scattered and inconsistent.
Comment thread
raman325 marked this conversation as resolved.
Outdated

## Design

### New module: `validation.ts`

A centralized validation module with three exported functions:

```ts
validateDashboardConfig(config): ValidationResult
validateViewConfig(config): ValidationResult
validateSectionConfig(config): ValidationResult
```

**Return type:**
```ts
type ValidationResult = { valid: true } | { valid: false; error: string };
```

#### Dashboard validation rules
- `type` must be `'custom:keymaster'`
- No other keys allowed

#### View validation rules
- `type` required, must be `'custom:keymaster'`
- Exactly one of `config_entry_id` or `lock_name` (not both, not neither)
- Allowed optional keys: `icon`, `path`, `theme`, `title`, `visible`
- All provided values must match expected types
- Unknown keys rejected

#### Section validation rules
- `type` required, must be `'custom:keymaster'`
- `slot_num` required, must be a number
- Exactly one of `config_entry_id` or `lock_name`
- No other keys allowed
- All provided values must match expected types

### Strategy changes

Each strategy's `generate()` calls its validator first. On failure, returns an
error card/section using the existing `createErrorView`/`createErrorSection`
pattern. Existing inline validation in view and section strategies is replaced
by the centralized validators.

### Error behavior

Validation failures return error cards (markdown cards with error messages),
consistent with the existing pattern. No thrown errors.

### Tests

- `validation.test.ts`: Unit tests for each validator covering valid configs,
missing required fields, unknown keys, wrong types, and edge cases.
- Existing strategy tests updated to verify validation integration.
Loading
Loading