Fix monitor duration semantics
This commit is contained in:
@@ -17,6 +17,7 @@ Car는 차량 모뎀/게이트웨이에서 받은 상태를 수집해 DB에 저
|
||||
- 사용량/요금 표시와 보정 metadata
|
||||
- 4.95초 UI timeout과 60초 사용량 정산 분리
|
||||
- TCP 실패 reason과 마지막 수신 지연 표시
|
||||
- 수집 공백을 반영한 차량 상태 경과 시간 표시
|
||||
- 도어/경계/시동/공조 상태 해석
|
||||
- service worker와 PWA icon 제공
|
||||
|
||||
@@ -27,6 +28,14 @@ Car는 차량 모뎀/게이트웨이에서 받은 상태를 수집해 DB에 저
|
||||
- `monitor.php?mode=ajax`: monitor 상태 AJAX
|
||||
- `monitor.php?mode=usage`: 데이터 사용량 AJAX
|
||||
|
||||
## Monitor 경과 시간
|
||||
|
||||
`monitor.php?mode=ajax`의 `meta.state_duration`은 현재 화면에 표시되는 차량 상태가 연속으로 유지된 시간입니다. 시동 값만 보지 않고 주행, 시동, 원격시동 준비/실행 상태를 함께 비교하며, 중간 수집 공백이 `RECEIVE_GAP_LIMIT_SEC`를 넘으면 같은 상태로 이어진 것으로 보지 않습니다.
|
||||
|
||||
기존 시동 상태 기준 경과는 `meta.engine_state_duration`으로 분리했습니다. 시동이 꺼진 지 하루 이상 지난 상황에서도 화면 경과가 하루 단위로 튀지 않고, 실제 모니터링 데이터가 연속으로 유지된 시간만 보여주기 위한 구조입니다.
|
||||
|
||||
로그 테이블의 경과 계산은 `YYYY-MM-DD HH:MM:SS` 값을 브라우저 기본 파서에 맡기지 않고 로컬 시간으로 직접 파싱합니다. 브라우저별 UTC/로컬 해석 차이로 로그 경과가 흔들리는 문제를 줄입니다.
|
||||
|
||||
## 구성
|
||||
|
||||
- `api.php`: 차량 상태/제어 API
|
||||
|
||||
+17
-2
@@ -572,7 +572,8 @@ if (isset($_GET['mode']) && $_GET['mode'] === 'ajax') {
|
||||
'stale' => $isStale,
|
||||
'stale_reason' => $staleReason,
|
||||
'latest_tcp' => $latestTcp,
|
||||
'state_duration' => current_engine_state_duration($pdo, $latest),
|
||||
'state_duration' => current_state_duration($pdo, $latest),
|
||||
'engine_state_duration' => current_engine_state_duration($pdo, $latest),
|
||||
'poll_interval' => $isFastPollState ? 5 : 10,
|
||||
'log_count' => count($logs),
|
||||
'chart_count' => count($chart),
|
||||
@@ -1775,13 +1776,27 @@ if (isset($_GET['mode']) && $_GET['mode'] === 'usage') {
|
||||
});
|
||||
}
|
||||
|
||||
function parseLocalTimestamp(value) {
|
||||
const match = String(value || '').match(/^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})/);
|
||||
if (!match) return null;
|
||||
return new Date(
|
||||
Number(match[1]),
|
||||
Number(match[2]) - 1,
|
||||
Number(match[3]),
|
||||
Number(match[4]),
|
||||
Number(match[5]),
|
||||
Number(match[6])
|
||||
).getTime();
|
||||
}
|
||||
|
||||
function updateLogs(logs) {
|
||||
const tbody = document.getElementById('log-table-body');
|
||||
const html = logs.map(log => {
|
||||
const cmdCode = String(log.cmd || '').toLowerCase();
|
||||
const cmd = CMD_MAP[cmdCode] || { label: '', icon: 'fa-terminal', bg: 'rgba(128,128,128,0.1)', color: 'var(--text-secondary)' };
|
||||
const cmdText = cmd.label ? t(cmd.label) : (cmdCode.toUpperCase() || '-');
|
||||
const ageSec = Math.max(0, Math.floor((Date.now() - new Date(log.ts).getTime()) / 1000));
|
||||
const logMs = parseLocalTimestamp(log.ts);
|
||||
const ageSec = logMs === null ? 0 : Math.max(0, Math.floor((Date.now() - logMs) / 1000));
|
||||
const doors = doorSummary(log);
|
||||
const remote = remoteSummary(log);
|
||||
const trim = escapeHtml(log.raw_trim || '-');
|
||||
|
||||
Reference in New Issue
Block a user