diff --git a/.devcontainer/ui-lovelace.yaml b/.devcontainer/ui-lovelace.yaml index a8c74f2..b6e8e56 100644 --- a/.devcontainer/ui-lovelace.yaml +++ b/.devcontainer/ui-lovelace.yaml @@ -11,7 +11,7 @@ views: - type: custom:restriction-card condition: entity: light.kitchen_lights - value: "on" + value: 'on' card: type: light entity: light.kitchen_lights @@ -73,7 +73,13 @@ views: entity: sensor.outside_humidity name: Throttle? graph: line - - type: "custom:restriction-card" + - type: 'custom:restriction-card' + restrictions: + pin: + code: 1234 + retry_delay: 10 + max_retries: 2 + max_retries_delay: 20 card: type: map entities: [] diff --git a/README.md b/README.md index d8f12f5..28bcadb 100644 --- a/README.md +++ b/README.md @@ -68,12 +68,15 @@ resources: ## Pin Options -| Name | Type | Requirement | Description | -| ---------- | ------ | ------------ | ------------------------------------------------------------------------------------------- | -| pin | string | **Required** | Pin code the user needs to enter to unlock | -| text | string | **Optional** | Text to display in prompt dialog | -| exemptions | list | **Optional** | List of exemption objects. See [Exemption Options](#exemption-options). | -| condition | map | **Optional** | Conditional object to make restriction active. See [Condition Options](#condition-options). | +| Name | Type | Requirement | Description | +| ----------------- | ------ | ------------ | ------------------------------------------------------------------------------------------------------------------------- | +| pin | string | **Required** | Pin code the user needs to enter to unlock | +| text | string | **Optional** | Text to display in prompt dialog | +| exemptions | list | **Optional** | List of exemption objects. See [Exemption Options](#exemption-options). | +| condition | map | **Optional** | Conditional object to make restriction active. See [Condition Options](#condition-options). | +| retry_delay | number | **Optional** | Number of seconds that you want to delay next attempt to unlock. Default is `0` | +| max_retries | number | **Optional** | Number of consecutive invalid retries allowed before blocking for the `max_retries_delay` seconds. Default is `unlimited` | +| max_retries_delay | number | **Optional** | Number of seconds to block attempts to unlock after the `max_retries` has been reached | ## Block Options diff --git a/package.json b/package.json index 6626018..8b90bf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "restriction-card", - "version": "1.2.1", + "version": "1.2.2", "description": "Lovelace restriction-card", "keywords": [ "home-assistant", diff --git a/src/const.ts b/src/const.ts index 6a82ac0..77a9572 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1 +1 @@ -export const CARD_VERSION = '1.2.1'; +export const CARD_VERSION = '1.2.2'; diff --git a/src/restriction-card.ts b/src/restriction-card.ts index f9267cb..202c58d 100644 --- a/src/restriction-card.ts +++ b/src/restriction-card.ts @@ -20,6 +20,9 @@ class RestrictionCard extends LitElement implements LovelaceCard { @property() protected _hass?: HomeAssistant; @property() private _helpers?: any; private _initialized = false; + private _delay = false; + private _maxed = false; + private _retries = 0; set hass(hass: HomeAssistant) { this._hass = hass; @@ -156,13 +159,13 @@ class RestrictionCard extends LitElement implements LovelaceCard { } private _handleAction(ev): void { - if (this._config && this._config.action === ev.detail.action) { + if (this._config?.action === ev.detail.action) { this._handleRestriction(); } } private _handleRestriction(): void { - if (!this._config || !this.shadowRoot) { + if (!this._config || !this.shadowRoot || this._delay || this._maxed) { return; } @@ -189,12 +192,43 @@ class RestrictionCard extends LitElement implements LovelaceCard { // tslint:disable-next-line: triple-equals if (pin != this._config.restrictions.pin.code) { lock.classList.add('invalid'); - window.setTimeout(() => { - if (lock) { - lock.classList.remove('invalid'); - } - }, 3000); + this._delay = Boolean(this._config.restrictions.pin.retry_delay); + if (this._config.restrictions.pin.max_retries) { + this._retries++; + } + + if (this._config.restrictions.pin.max_retries && this._retries >= this._config.restrictions.pin.max_retries) { + this._maxed = true; + + window.setTimeout( + () => { + if (lock) { + lock.classList.remove('invalid'); + } + this._retries = 0; + this._maxed = false; + this._delay = false; + }, + this._config.restrictions.pin.max_retries_delay + ? this._config.restrictions.pin.max_retries_delay * 1000 + : 5000, + ); + } else { + window.setTimeout( + () => { + this._delay = false; + + if (lock && !this._maxed) { + lock.classList.remove('invalid'); + } + }, + this._config.restrictions.pin.retry_delay ? this._config.restrictions.pin.retry_delay * 1000 : 3000, + ); + } + return; + } else { + this._retries = 0; } } diff --git a/src/types.ts b/src/types.ts index 2af088c..1581c6a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -39,6 +39,9 @@ export interface PinRestrictionConfig { text?: string; exemptions?: ExemptionConfig[]; condition?: ConditionConfig; + retry_delay?: number; + max_retries?: number; + max_retries_delay?: number; } export interface ExemptionConfig {