feat: HA scene control via voice

- ha.php: GET scenes action returns live scene list from HA; POST scene_activate triggers by entity_id
- chat.php: ha_scene intent fetches all scenes live, fuzzy token-matches against message, calls scene.turn_on; falls back to listing available scenes if no match
- KB intents: 14 patterns covering good night/morning/goodbye/kitchen lights/ocean dawn/porch + generic activate/run/trigger/set scene

Scenes available: Good Night, Good Morning, Good Morning Work, Goodbye, Kitchen Lights On/Off, Front Porch Lights, Office Ocean Dawn, Master Bedroom

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 02:34:29 +00:00
parent c29d1bf4c7
commit b024e51f3d
2 changed files with 79 additions and 0 deletions
+28
View File
@@ -38,6 +38,34 @@ if (!$configured) {
exit;
}
// Scene list
if ($method === 'GET' && $action === 'scenes') {
$states = haRequest('/states') ?? [];
$scenes = [];
foreach ($states as $s) {
if (str_starts_with($s['entity_id'] ?? '', 'scene.')) {
$scenes[] = [
'entity_id' => $s['entity_id'],
'name' => $s['attributes']['friendly_name'] ?? $s['entity_id'],
];
}
}
echo json_encode(['scenes' => $scenes]);
exit;
}
// Scene activate
if ($method === 'POST' && $action === 'scene_activate') {
$entity_id = $data['entity_id'] ?? '';
if ($entity_id && str_starts_with($entity_id, 'scene.')) {
$result = haRequest('/services/scene/turn_on', 'POST', ['entity_id' => $entity_id]);
echo json_encode(['success' => true, 'entity_id' => $entity_id]);
} else {
echo json_encode(['error' => 'Invalid scene entity_id']);
}
exit;
}
// Live service call (toggle device) — always direct to HA, never cached
if ($method === 'POST' && $action === 'service') {
$domain = $data['domain'] ?? '';