fix: HA toggles — real-time ha_entities table, optimistic update, renderHATable extracted

This commit is contained in:
2026-05-31 16:34:01 +00:00
parent 795411387c
commit aa622e97a5
2 changed files with 66 additions and 25 deletions
+44 -21
View File
@@ -52,26 +52,49 @@ if ($method === 'POST' && $action === 'service') {
exit;
}
// Serve entities from cache (populated by stats_cache.php cron, every 5 min)
$cached = JarvisDB::query(
'SELECT data, UNIX_TIMESTAMP(updated_at) as updated_ts FROM api_cache WHERE cache_key=? LIMIT 1',
['ha_entities']
);
// Serve entities from ha_entities table (real-time agent push data)
$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',
'adguard_','folding_home','music_assistant','get_hacs','mealie',
'mosquitto','social_to','motion_detection',
'front_yard_record','down_hill_record','camera1_record',
'back_yard_record','nvr_','assist_microphone'];
if ($cached && !empty($cached[0]['data'])) {
$row = $cached[0];
$data_out = json_decode($row['data'], true);
$data_out['cache_age_s'] = (int)(time() - (int)$row['updated_ts']);
echo json_encode($data_out);
} else {
echo json_encode([
'configured' => true,
'ha_version' => 'unknown',
'location' => 'Home',
'entity_count' => 0,
'entities' => [],
'cached_at' => null,
'cache_age_s' => -1,
'message' => 'Cache warming up — first update in under 5 minutes.',
]);
$rows = JarvisDB::query(
"SELECT entity_id, entity_name, domain, state, UNIX_TIMESTAMP(updated_at) as updated_ts
FROM ha_entities
WHERE state NOT IN ('unavailable','unknown')
ORDER BY domain, entity_name"
) ?? [];
$grouped = [];
$latestTs = 0;
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 ((int)$e['updated_ts'] > $latestTs) $latestTs = (int)$e['updated_ts'];
$grouped[$dom][] = [
'entity_id' => $e['entity_id'],
'name' => $e['entity_name'],
'state' => $e['state'],
];
}
echo json_encode([
'configured' => true,
'entities' => $grouped,
'cache_age_s' => $latestTs > 0 ? (int)(time() - $latestTs) : -1,
'cached_at' => $latestTs > 0 ? date('c', $latestTs) : null,
]);