diff --git a/public_html/admin/index.php b/public_html/admin/index.php index 68be20d..d19b1fc 100644 --- a/public_html/admin/index.php +++ b/public_html/admin/index.php @@ -234,22 +234,44 @@ if ($action) { // ── HOME ASSISTANT ENTITIES ─────────────────────────────────────────── case 'ha_list': - $raw = JarvisDB::single("SELECT data, UNIX_TIMESTAMP(updated_at) ts FROM api_cache WHERE cache_key='ha_entities'"); - if (!$raw) j(['entities'=>[],'domains'=>[],'ts'=>null]); - $cache = json_decode($raw['data'], true) ?? []; + // Read from ha_entities table (real-time pushes from jarvis_agent custom component) $domain = $_GET['domain'] ?? ''; $search = strtolower(trim($_GET['search'] ?? '')); - $all = []; - foreach ($cache['entities'] ?? [] as $dom => $ents) { - if ($domain && $dom !== $domain) continue; - foreach ($ents as $e) { - if ($search && strpos(strtolower($e['name']??''),$search)===false && strpos(strtolower($e['entity_id']??''),$search)===false) continue; - $e['domain'] = $dom; - $all[] = $e; + $skipDomains = ['sensor','binary_sensor','button','update','select','number', + 'device_tracker','event','image','person','zone','tts','conversation', + 'assist_satellite','input_button']; + $skipKeywords = ['pre_release','_record','_ftp_','_push_','_hub_ringtone', + '_siren_on','_email_on','_manual_record','_infrared_', + 'do_not_disturb','matter_server','zerotier','mariadb', + 'spotify_connect','file_editor','ssh_web','uptime_kuma', + 'folding_home','music_assistant','get_hacs','mealie', + 'mosquitto','social_to','esphome_device','motion_detection', + 'front_yard_record','down_hill_record','camera1_record', + 'back_yard_record','nvr_','assist_microphone','cec_scanner']; + $where = "state NOT IN ('unavailable','unknown')"; + $params = []; + if ($domain) { $where .= " AND domain=?"; $params[] = $domain; } + $rows = JarvisDB::query( + "SELECT entity_id, entity_name name, domain, state, updated_at + FROM ha_entities WHERE $where ORDER BY domain, entity_name LIMIT 500", + $params + ) ?? []; + $all = []; $domains = []; + foreach ($rows as $e) { + $dom = $e['domain']; + if (in_array($dom, $skipDomains)) continue; + $skip = false; + if ($dom === 'switch') { + foreach ($skipKeywords as $kw) { + if (strpos($e['entity_id'], $kw) !== false) { $skip = true; break; } + } } + if ($skip) continue; + if ($search && strpos(strtolower($e['name']??''), $search) === false) continue; + $all[] = $e; + $domains[$dom] = true; } - usort($all, fn($a,$b) => strcmp($a['name']??'',$b['name']??'')); - j(['entities'=>array_slice($all,0,500),'domains'=>array_keys($cache['entities']??[]),'total'=>count($all),'ts'=>$raw['ts']]); + j(['entities'=>$all,'domains'=>array_keys($domains),'total'=>count($all),'ts'=>time()]); case 'ha_toggle': $eid = trim($_POST['entity_id'] ?? ''); if (!$eid) bad('Missing entity_id'); @@ -1334,8 +1356,8 @@ function haToggle(entityId, currentState, el) { ent.state = wasOn ? 'off' : 'on'; filterHATable(); } - // Also sync from HA after 3s (actual state confirmation) - setTimeout(loadHA, 3000); + // Sync from ha_entities (real-time agent data) after 5s — enough time for HA to execute + push + setTimeout(loadHA, 5000); } else { toast('Toggle failed (code ' + (res.code||'?') + ')', 'err'); }