From 1a8439e52bbd7c541b6db42f1413cda6752b7a38 Mon Sep 17 00:00:00 2001 From: seo Date: Sun, 7 Jun 2026 18:13:34 +0900 Subject: [PATCH] Reset observed WiFi session when client disappears --- README.md | 2 +- public/api.php | 55 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index bba7c53..eb74ffc 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ control-push-healthcheck.service - 센서 수집 주기와 DB 증가량을 확인합니다. - 하드웨어 또는 OS 변경 후 fan sysfs 경로를 확인합니다. -- 5G WiFi 연결 시간은 외부 모듈이 값을 제공하지 않을 때 서버가 처음 감지한 시각 기준으로 계산되므로, 장치 재시작이나 DB 초기화 후에는 다시 0부터 누적됩니다. +- 5G WiFi 연결 시간은 외부 모듈이 값을 제공하지 않을 때 서버가 처음 감지한 시각 기준으로 계산합니다. 현재 5G 목록에서 MAC이 사라지면 관측 세션을 즉시 종료하므로 재연결 시 0부터 다시 누적됩니다. - WebSocket은 장기 실행 프로세스이므로 `public/api.php`, `config/config.php`, `bin/control_ws.php` 변경을 감지하면 15초 안에 종료되고 `control-websocket.service`가 새 프로세스로 재시작합니다. - WebSocket 장기 실행 중 DB 연결이 끊길 수 있으므로 reconnect 로그를 확인합니다. - Push 구독 자동 복구가 과도한 반복 등록을 만들지 않는지 확인합니다. diff --git a/public/api.php b/public/api.php index abd3b9a..1ab4dd6 100644 --- a/public/api.php +++ b/public/api.php @@ -1464,18 +1464,48 @@ function wifi_connected_time_missing(mixed $value): bool return $text === '' || $text === 'N/A' || $text === '-'; } +function wifi_valid_mac(string $mac): bool +{ + return preg_match('/^[0-9a-f]{2}(?::[0-9a-f]{2}){5}$/', strtolower($mac)) === 1; +} + +function prune_observed_wifi_sessions(PDO $pdo, array $visibleMacs): void +{ + $visibleMacs = array_values(array_unique(array_filter( + array_map(static fn($mac) => strtolower((string)$mac), $visibleMacs), + static fn($mac) => wifi_valid_mac($mac) + ))); + + if ($visibleMacs === []) { + $pdo->exec("DELETE FROM wifi_observed_sessions WHERE band = '5G'"); + return; + } + + $placeholders = implode(',', array_fill(0, count($visibleMacs), '?')); + $stmt = $pdo->prepare(" + DELETE FROM wifi_observed_sessions + WHERE band = '5G' + AND mac NOT IN ($placeholders) + "); + $stmt->execute($visibleMacs); +} + function observed_wifi_duration_seconds(array $clients): array { $targets = []; + $visible5gMacs = []; foreach ($clients as $client) { $band = (string)($client['band'] ?? ''); $mac = strtolower((string)($client['mac'] ?? '')); - if ($band !== '5G' - || !wifi_connected_time_missing($client['connected_time'] ?? null) - || !preg_match('/^[0-9a-f]{2}(?::[0-9a-f]{2}){5}$/', $mac) - ) { + if ($band !== '5G' || !wifi_valid_mac($mac)) { + continue; + } + + $visible5gMacs[] = $mac; + + if (!wifi_connected_time_missing($client['connected_time'] ?? null)) { continue; } @@ -1488,18 +1518,15 @@ function observed_wifi_duration_seconds(array $clients): array ]; } - if ($targets === []) { - try { - db()->exec("DELETE FROM wifi_observed_sessions WHERE last_seen_at < DATE_SUB(NOW(3), INTERVAL 2 MINUTE)"); - } catch (Throwable) { - } - - return []; - } - try { $pdo = db(); $pdo->beginTransaction(); + prune_observed_wifi_sessions($pdo, $visible5gMacs); + + if ($targets === []) { + $pdo->commit(); + return []; + } $upsert = $pdo->prepare(" INSERT INTO wifi_observed_sessions @@ -1524,8 +1551,6 @@ function observed_wifi_duration_seconds(array $clients): array ]); } - $pdo->exec("DELETE FROM wifi_observed_sessions WHERE last_seen_at < DATE_SUB(NOW(3), INTERVAL 2 MINUTE)"); - $placeholders = implode(',', array_fill(0, count($targets), '?')); $stmt = $pdo->prepare(" SELECT