UI-003: show prediction evaluation feedback

This commit is contained in:
2026-06-14 15:38:11 +02:00
parent 87ae051238
commit 1c5eab14b6
4 changed files with 26 additions and 5 deletions

View File

@@ -1,5 +1,11 @@
# Changelog # Changelog
## 0.6.1 - 2026-06-14
- Manuelle Prüfung als `Aktuelle Situation auswerten` eindeutig von Simulation
oder Aktorschaltung abgegrenzt
- Sichtbare Rückmeldung mit Prüfzeitpunkt, vorhergesagtem Zustand und Sicherheit
oder klarem Hinweis auf einen fehlenden frischen Sensorwechsel
## 0.6.0 - 2026-06-14 ## 0.6.0 - 2026-06-14
- Kausales Shadow-Lernen erkennt frische Kontextwechsel unmittelbar vor einer - Kausales Shadow-Lernen erkennt frische Kontextwechsel unmittelbar vor einer
Aktorhandlung, etwa `Tür geschlossen → offen` vor `Licht aus → an` Aktorhandlung, etwa `Tür geschlossen → offen` vor `Licht aus → an`

View File

@@ -1,5 +1,5 @@
name: SillyHome Next name: SillyHome Next
version: "0.6.0" version: "0.6.1"
slug: sillyhome_next slug: sillyhome_next
description: Lernt automatisch aus deinem Verhalten und steuert freigegebene Aktoren description: Lernt automatisch aus deinem Verhalten und steuert freigegebene Aktoren
url: http://192.168.6.31:3000/pino/sillyhome-next url: http://192.168.6.31:3000/pino/sillyhome-next

View File

@@ -225,7 +225,7 @@ async function loadConfiguredActuators() {
} }
} }
async function showActuator(actuatorId) { async function showActuator(actuatorId, evaluationMessage = "") {
currentActuatorId = actuatorId; currentActuatorId = actuatorId;
const box = document.getElementById("actuator-detail"); const box = document.getElementById("actuator-detail");
try { try {
@@ -273,7 +273,9 @@ async function showActuator(actuatorId) {
<p><strong>Letztes Training:</strong> ${escapeHtml(record.behavior.last_trained_at || "noch nicht")}</p> <p><strong>Letztes Training:</strong> ${escapeHtml(record.behavior.last_trained_at || "noch nicht")}</p>
<p><strong>Was noch passiert:</strong> ${escapeHtml(record.behavior.reason)}</p> <p><strong>Was noch passiert:</strong> ${escapeHtml(record.behavior.reason)}</p>
${activationButton} ${activationButton}
<button class="secondary" onclick="evaluateActuator('${escapeHtml(record.actuator_entity_id)}')">Vorhersage jetzt prüfen</button> <button class="secondary" onclick="evaluateActuator('${escapeHtml(record.actuator_entity_id)}')">Aktuelle Situation auswerten</button>
<p class="muted">Die Prüfung simuliert keinen Sensorwechsel und schaltet keinen Aktor.</p>
${evaluationMessage ? `<p class="ok">${escapeHtml(evaluationMessage)}</p>` : ""}
</div> </div>
</div> </div>
<h3>Was SillyHome aktuell vorhersagt</h3> <h3>Was SillyHome aktuell vorhersagt</h3>
@@ -290,9 +292,18 @@ async function showActuator(actuatorId) {
async function evaluateActuator(actuatorId) { async function evaluateActuator(actuatorId) {
try { try {
await api(`v1/actuators/${encodeURIComponent(actuatorId)}/evaluate`, {method: "POST"}); const record = await api(
`v1/actuators/${encodeURIComponent(actuatorId)}/evaluate`,
{method: "POST"},
);
const checkedAt = new Date(
record.behavior.last_evaluated_at || Date.now(),
).toLocaleString("de-DE");
const message = record.behavior.prediction
? `Prüfung ${checkedAt}: ${record.behavior.prediction.target_state} mit ${Math.round(record.behavior.prediction.confidence * 100)} % vorhergesagt.`
: `Prüfung ${checkedAt}: Kein frischer passender Sensorwechsel erkannt; aktuell ist keine Aktion fällig.`;
await loadConfiguredActuators(); await loadConfiguredActuators();
await showActuator(actuatorId); await showActuator(actuatorId, message);
} catch (error) { } catch (error) {
alert(error.message); alert(error.message);
} }

View File

@@ -17,6 +17,10 @@ def test_dashboard_is_served_at_root() -> None:
assert "Freigabe noch gesperrt" in response.text assert "Freigabe noch gesperrt" in response.text
assert "Bediene das Licht dafür direkt über Home Assistant" in response.text assert "Bediene das Licht dafür direkt über Home Assistant" in response.text
assert "Davon erkannte HA-Automationen" in response.text assert "Davon erkannte HA-Automationen" in response.text
assert "Aktuelle Situation auswerten" in response.text
assert "Die Prüfung simuliert keinen Sensorwechsel" in response.text
assert "Kein frischer passender Sensorwechsel erkannt" in response.text
assert "Vorhersage jetzt prüfen" not in response.text
assert 'record.behavior.status === "trained" && missingUserActions === 0' in response.text assert 'record.behavior.status === "trained" && missingUserActions === 0' in response.text
assert "Automation-Entwurf" not in response.text assert "Automation-Entwurf" not in response.text
assert "Manuelle Overrides" not in response.text assert "Manuelle Overrides" not in response.text