diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dda1552..b1ceff5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [Unreleased] + +### Fixed +- Smart Home rules: rule-limit (409) now shows only the banner instead of banner + alert (double signal) +- Smart Home rules: rule-name field enforces the 20-char cap client-side (`maxlength`) across all three themes +- Smart Home rules: `limitWarn` now derives from `deconzCapabilities.ruleLimit.warnAtGcRules` (single source) instead of a duplicated magic threshold; corrected a stale comment on cancel-condition inversion + +### Tests +- Added coverage for the daylight trigger translation, the unknown-button-action rejection, and `deconzClient.deleteSchedule` + +--- + ## [1.113.1] — 2026-07-01 ### Fixes diff --git a/public/js/smarthome-rules.js b/public/js/smarthome-rules.js index 7e5ff793..21c01caf 100644 --- a/public/js/smarthome-rules.js +++ b/public/js/smarthome-rules.js @@ -299,7 +299,7 @@ else await api('/rules', { method: 'POST', body: JSON.stringify({ gateway_id: gatewayId, name, definition }) }); closeBuilder(); await loadRules(); } catch (e) { - if (e.status === 409) showLimit(e.message); // rule-limit / no-api-key + if (e.status === 409) { showLimit(e.message); return; } // rule-limit / no-api-key → banner only alert(e.message); // 400 = validation detail from the server } } diff --git a/src/services/smarthome/rulesTranslate.js b/src/services/smarthome/rulesTranslate.js index 0ce8ce7a..dba7dbe4 100644 --- a/src/services/smarthome/rulesTranslate.js +++ b/src/services/smarthome/rulesTranslate.js @@ -83,8 +83,8 @@ function relTime(mins) { } // Cancel-condition = trigger back to its inverse binary state. -// Only eq-conditions with 'true'/'false' values are binary-invertible. -// button (numeric code) and daylight (non-eq) are excluded. +// Only eq-conditions with 'true'/'false' values are binary-invertible (presence/open/water/daylight). +// button conditions (numeric buttonevent code) are excluded — not invertible. function cancelConditionsFrom(conditions) { return conditions .filter((c) => c.operator === 'eq' && (c.value === 'true' || c.value === 'false')) diff --git a/src/services/smarthome/smarthomeRules.js b/src/services/smarthome/smarthomeRules.js index ba690345..22bd084a 100644 --- a/src/services/smarthome/smarthomeRules.js +++ b/src/services/smarthome/smarthomeRules.js @@ -9,7 +9,7 @@ const caps = require('./deconzCapabilities'); const LIMIT_CODES = new Set(caps.ruleLimit.errorCodes); // deckt HTTP-Status UND 200-Body-Error-Codes ab (Spike Step 6) function isLimit(e) { return !!(e && LIMIT_CODES.has(e.code)); } function ruleLimitError() { const e = new Error('deconz rule limit reached'); e.code = 'DECONZ_RULE_LIMIT_REACHED'; return e; } -function limitWarn(gcRuleCount) { return gcRuleCount * 4 > 150; } // Worst-Case-Slot-Multiplikator (§8/§10) +function limitWarn(gcRuleCount) { return gcRuleCount >= caps.ruleLimit.warnAtGcRules; } // §8/§10: gc rules × Worst-Case-4-Slots > 150 ⇒ ≥ warnAtGcRules (=38) // Default-Factory: lokaler Gateway-Client wie index.js' privates clientForGateway (kein index-Import → kein Zirkularbezug). function defaultClientFactory(gatewayId) { diff --git a/templates/aurora/partials/modals/smarthome-rule-builder.njk b/templates/aurora/partials/modals/smarthome-rule-builder.njk index 014b6134..24831335 100644 --- a/templates/aurora/partials/modals/smarthome-rule-builder.njk +++ b/templates/aurora/partials/modals/smarthome-rule-builder.njk @@ -9,7 +9,7 @@