diff --git a/api/endpoints/stats_cache.php b/api/endpoints/stats_cache.php index f8c37b4..deb85f4 100644 --- a/api/endpoints/stats_cache.php +++ b/api/endpoints/stats_cache.php @@ -133,13 +133,30 @@ if (HA_TOKEN !== 'YOUR_HA_TOKEN_HERE' && strpos(HA_URL, '10.48.200.X') === false $states = $statesRaw ? json_decode($statesRaw, true) : []; $config = $configRaw ? json_decode($configRaw, true) : []; - $interesting = ['light','switch','sensor','climate','binary_sensor','cover', - 'media_player','camera','alarm_control_panel','lock','fan','input_boolean']; + // Controllable domains only — skip read-only sensors to keep list manageable + $interesting = ['light','switch','scene','media_player','alarm_control_panel', + 'lawn_mower','water_heater','fan','lock','cover','climate','input_boolean']; + // Switches that are HA internals / camera settings, not physical devices + $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', + 'kiosker','hacs_pre','adguard']; $grouped = []; foreach (($states ?? []) as $entity) { $domain = explode('.', $entity['entity_id'])[0]; if (!in_array($domain, $interesting)) continue; - if (strpos($entity['entity_id'], 'adguard') !== false) continue; + if ($domain === 'switch') { + $skip = false; + foreach ($skipKeywords as $kw) { + if (strpos($entity['entity_id'], $kw) !== false) { $skip = true; break; } + } + if ($skip) continue; + } if (!isset($grouped[$domain])) $grouped[$domain] = []; $grouped[$domain][] = [ 'entity_id' => $entity['entity_id'], diff --git a/public_html/index.html b/public_html/index.html index 3cf74b3..796a750 100644 --- a/public_html/index.html +++ b/public_html/index.html @@ -493,16 +493,36 @@ body::after{ /* HA DEVICES ────────────────────────────────────────────────────────── */ .ha-entity{ - display:flex;align-items:center;justify-content:space-between; - padding:5px 0;border-bottom:1px solid rgba(0,212,255,0.06); + display:flex;align-items:center;gap:6px; + padding:4px 2px;border-bottom:1px solid rgba(0,212,255,0.06); font-family:var(--font-mono);font-size:0.72rem; - cursor:pointer;transition:background 0.15s;border-radius:4px; + transition:background 0.15s;border-radius:4px; } .ha-entity:hover{background:rgba(0,212,255,0.06)} -.ha-name{color:var(--text);flex:1} -.ha-state{font-weight:600} +.ha-name{color:var(--text);flex:1;cursor:pointer} +.ha-state{font-weight:600;font-size:0.65rem;min-width:32px;text-align:right} .ha-state.on{color:var(--green)} .ha-state.off{color:var(--text-dim)} +.ha-state.unavailable{color:var(--text-dim);opacity:0.4} +/* toggle switch */ +.ha-toggle{ + position:relative;width:32px;height:16px;flex-shrink:0;cursor:pointer; +} +.ha-toggle input{opacity:0;width:0;height:0;position:absolute} +.ha-slider{ + position:absolute;inset:0;border-radius:8px; + background:rgba(255,255,255,0.1);border:1px solid rgba(255,255,255,0.15); + transition:background 0.2s,border-color 0.2s; +} +.ha-slider::before{ + content:'';position:absolute;left:2px;top:2px; + width:10px;height:10px;border-radius:50%; + background:var(--text-dim);transition:transform 0.2s,background 0.2s; +} +.ha-toggle input:checked + .ha-slider{background:rgba(0,255,100,0.25);border-color:var(--green)} +.ha-toggle input:checked + .ha-slider::before{transform:translateX(16px);background:var(--green)} +.ha-toggle.scene .ha-slider{background:rgba(0,212,255,0.15);border-color:var(--cyan)} +.ha-toggle.scene .ha-slider::before{background:var(--cyan)} /* ALERTS BADGE ─────────────────────────────────────────────────────── */ .alert-item{ @@ -1396,19 +1416,31 @@ async function loadHA() { return; } + const domainIcon = {light:'💡',switch:'🔌',scene:'🎬',media_player:'📺', + alarm_control_panel:'🔒',lawn_mower:'🌿',water_heater:'🌡',fan:'💨', + lock:'🔑',cover:'🪟',climate:'❄',input_boolean:'⚙'}; let html = ''; for (const [domain, items] of Object.entries(entities)) { if (!items.length) continue; - html += `