diff --git a/CHANGELOG.md b/CHANGELOG.md index 71c9458..786fba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.5.4 - 2026-06-14 +- Tür-, Bewegungs- und andere belastbare Kontextsensoren werden auch ohne + numerischen Sensor als vollständige automatische Kontextzuordnung angezeigt +- Status und Zuordnungssicherheit bilden das aktive Verhaltenslernen ab statt + eines optionalen numerischen Modells +- Ausführungsfreigabe erscheint erst, wenn genügend eindeutig manuelle + Bedienungen vorliegen; bis dahin nennt die Oberfläche die noch fehlende Anzahl + ## 0.5.3 - 2026-06-14 - Verhindert fachlich falsche Sensorzuordnungen nur aufgrund generischer Namen wie `Licht` oder `Lichtschalter` diff --git a/addon/config.yaml b/addon/config.yaml index 0339bd9..5d1f8a0 100644 --- a/addon/config.yaml +++ b/addon/config.yaml @@ -1,5 +1,5 @@ name: SillyHome Next -version: "0.5.3" +version: "0.5.4" slug: sillyhome_next description: Lernt automatisch aus deinem Verhalten und steuert freigegebene Aktoren url: http://192.168.6.31:3000/pino/sillyhome-next diff --git a/app/actuators/lifecycle.py b/app/actuators/lifecycle.py index 05ae1de..f6c3a8d 100644 --- a/app/actuators/lifecycle.py +++ b/app/actuators/lifecycle.py @@ -239,12 +239,25 @@ class ActuatorReconciliationService: (candidate for candidate in numeric_candidates if candidate.auto_accepted), None, ) - top_contexts = [ - candidate.entity_id + accepted_contexts = [ + candidate for candidate in context_candidates if candidate.auto_accepted ][: _MAX_CONTEXT_SELECTIONS] + top_contexts = [candidate.entity_id for candidate in accepted_contexts] if top_numeric is None: + if accepted_contexts: + return AssignmentSelection( + selected_numeric_entity_id=None, + selected_context_entity_ids=top_contexts, + source=AssignmentSource.AUTOMATIC, + confidence=max(candidate.confidence for candidate in accepted_contexts), + review_required=False, + reason=( + "Passender Schaltkontext automatisch erkannt. Für diese " + "Verhaltensvorhersage ist kein numerischer Sensor erforderlich." + ), + ) return AssignmentSelection( selected_numeric_entity_id=None, selected_context_entity_ids=top_contexts, diff --git a/app/static/index.html b/app/static/index.html index 65bb8a6..790039c 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -112,6 +112,7 @@ async function api(path, options = {}) { } function lifecycleLabel(record) { + if (record.behavior.status === "trained") return "Kontext erkannt"; const labels = { trained: "lernt", pending_history: "sammelt Historie", @@ -124,6 +125,7 @@ function lifecycleLabel(record) { } function statusClass(record) { + if (record.behavior.status === "trained") return "ok"; if (record.lifecycle.status === "trained") return "ok"; if (["pending_history", "pending_assignment", "archived"].includes(record.lifecycle.status)) return "warn"; return "bad"; @@ -237,11 +239,18 @@ async function showActuator(actuatorId) { .map(candidate => `
Freigabe wird möglich, sobald genügend Handlungen gelernt wurden.
"; + : record.behavior.status === "trained" + ? `Freigabe noch gesperrt: ${missingUserActions} eindeutig manuelle Bedienung${missingUserActions === 1 ? "" : "en"} fehlen. Bediene das Licht dafür direkt über Home Assistant.
` + : "Freigabe wird möglich, sobald genügend Handlungen gelernt wurden.
"; box.innerHTML = `