mirror of
https://github.com/myronblair/jarvis
synced 2026-06-30 17:50:23 -05:00
fix: HA voice control — domain preference scoring, exact match priority, skip unavailable, fresh entity_map
This commit is contained in:
+33
-9
@@ -136,7 +136,8 @@ if (!$reply) {
|
|||||||
// ── Tier 0: Home Assistant Control ───────────────────────────────────────
|
// ── Tier 0: Home Assistant Control ───────────────────────────────────────
|
||||||
// Uses entity_map stored by facts_collector to resolve natural language → entity
|
// Uses entity_map stored by facts_collector to resolve natural language → entity
|
||||||
$haEntityMapRow = JarvisDB::query(
|
$haEntityMapRow = JarvisDB::query(
|
||||||
'SELECT fact_value FROM kb_facts WHERE category=? AND fact_key=? LIMIT 1',
|
'SELECT fact_value FROM kb_facts WHERE category=? AND fact_key=?
|
||||||
|
AND (expires_at IS NULL OR expires_at > NOW()) ORDER BY updated_at DESC LIMIT 1',
|
||||||
['ha', 'entity_map']
|
['ha', 'entity_map']
|
||||||
);
|
);
|
||||||
$haEntityMap = ($haEntityMapRow && !empty($haEntityMapRow[0]['fact_value']))
|
$haEntityMap = ($haEntityMapRow && !empty($haEntityMapRow[0]['fact_value']))
|
||||||
@@ -213,22 +214,45 @@ if (!$reply && preg_match('/(turn|switch|put|set)\s+(on|off)/i', $message, $acti
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$bestEid) {
|
if (!$bestEid) {
|
||||||
// Build search terms from message (remove control words with word boundaries)
|
// Detect preferred domain from message
|
||||||
$searchMsg = preg_replace('/\b(turn|switch|put|set|the|my|all|please|jarvis|on|off|lights?|lamps?)\b/i', ' ', $msgLower);
|
$preferLight = (bool) preg_match('/\blight(s)?\b/i', $message);
|
||||||
|
$preferSwitch = (bool) preg_match('/\b(switch|plug|outlet|strip)\b/i', $message);
|
||||||
|
|
||||||
|
// Strip control words — keep device/room name
|
||||||
|
$searchMsg = preg_replace('/\b(turn|switch|put|set|the|my|all|please|jarvis|on|off|lights?|lamps?|plugs?|strips?)\b/i', ' ', $msgLower);
|
||||||
$searchMsg = trim(preg_replace('/\s+/', ' ', $searchMsg));
|
$searchMsg = trim(preg_replace('/\s+/', ' ', $searchMsg));
|
||||||
|
|
||||||
foreach ($haEntityMap as $eid => $info) {
|
foreach ($haEntityMap as $eid => $info) {
|
||||||
|
if (($info['state'] ?? '') === 'unavailable') continue;
|
||||||
$nameLower = strtolower($info['name']);
|
$nameLower = strtolower($info['name']);
|
||||||
// Score: exact substring match = 10, word overlap = words matched
|
$domain = $info['domain'] ?? '';
|
||||||
if ($searchMsg && strpos($nameLower, $searchMsg) !== false) {
|
|
||||||
$score = 10;
|
|
||||||
} else {
|
|
||||||
$words = array_filter(explode(' ', $searchMsg));
|
|
||||||
$score = 0;
|
$score = 0;
|
||||||
|
|
||||||
|
// Exact name match = highest priority
|
||||||
|
if ($nameLower === $searchMsg) {
|
||||||
|
$score = 100;
|
||||||
|
// Search is substring of name
|
||||||
|
} elseif ($searchMsg && strpos($nameLower, $searchMsg) !== false) {
|
||||||
|
$score = 40;
|
||||||
|
// Name is substring of search (e.g. search="living room light", name="Living Room")
|
||||||
|
} elseif ($searchMsg && strpos($searchMsg, $nameLower) !== false) {
|
||||||
|
$score = 30;
|
||||||
|
} else {
|
||||||
|
// Word overlap scoring
|
||||||
|
$words = array_filter(explode(' ', $searchMsg));
|
||||||
foreach ($words as $w) {
|
foreach ($words as $w) {
|
||||||
if (strlen($w) > 2 && strpos($nameLower, $w) !== false) $score++;
|
if (strlen($w) > 2 && strpos($nameLower, $w) !== false) $score += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($score <= 0) continue;
|
||||||
|
|
||||||
|
// Domain preference bonus
|
||||||
|
if ($preferLight && $domain === 'light') $score += 20;
|
||||||
|
if ($preferSwitch && $domain === 'switch') $score += 20;
|
||||||
|
// Penalty for clearly wrong domain when user specified one
|
||||||
|
if ($preferLight && in_array($domain, ['media_player','sensor','climate'])) $score -= 15;
|
||||||
|
|
||||||
if ($score > $bestScore) {
|
if ($score > $bestScore) {
|
||||||
$bestScore = $score;
|
$bestScore = $score;
|
||||||
$bestEid = $eid;
|
$bestEid = $eid;
|
||||||
|
|||||||
Reference in New Issue
Block a user