134 lines
9.2 KiB
Markdown
134 lines
9.2 KiB
Markdown
# Car
|
|
|
|
차량 상태 조회, TCP 명령 전송, 모니터링, 데이터 사용량 표시를 제공하는 PHP 기반 차량 서비스입니다.
|
|
|
|
## 프로젝트 성격
|
|
|
|
Car는 차량 모뎀/게이트웨이에서 받은 상태를 수집해 DB에 저장하고, 웹 화면과 API에서 최신 상태와 명령 실행 결과를 제공하는 내부 차량 관리 서비스입니다.
|
|
|
|
모뎀에서 제공되는 값의 한계가 있으므로 도어 잠김, 경계, 시동, 공조 상태는 여러 필드를 조합해 해석합니다. 통신사 사용량은 DB 수집값과 T world 기준 보정값을 함께 사용합니다.
|
|
|
|
## 주요 기능
|
|
|
|
- 차량 상태 수집과 저장
|
|
- 차량 상태 API
|
|
- 허용된 차량 명령 TCP 전송
|
|
- monitor 화면과 AJAX 상태 갱신
|
|
- monitor 화면 WakeLock, 언어, 테마 토글
|
|
- monitor 좌측 상단 블로그 복귀 링크
|
|
- 모바일 및 좁은 카드 폭에 맞춘 사용량 2줄 배치, 로그 가로 스크롤, 시간 문구 축약
|
|
- 사용량/요금 표시와 보정 metadata
|
|
- 4.95초 UI timeout과 60초 사용량 정산 분리
|
|
- TCP 실패 reason과 마지막 수신 지연 표시
|
|
- 수집 공백을 반영한 차량 상태 경과 시간 표시
|
|
- 도어/경계/시동/공조 상태 해석
|
|
- 실시간 차량 도어/트렁크 열림 표시
|
|
- service worker와 PWA icon 제공
|
|
|
|
## 주요 API
|
|
|
|
- `api.php?action=status`: 차량 상태 조회
|
|
- `api.php?action=command`: 차량 명령 전송
|
|
- `monitor.php?mode=ajax`: monitor 상태 AJAX
|
|
- `monitor.php?mode=usage`: 데이터 사용량 AJAX
|
|
|
|
## Monitor 경과 시간
|
|
|
|
`monitor.php?mode=ajax`의 `meta.state_duration`은 현재 시동 상태가 연속으로 유지된 시간입니다. 화면의 시동 카드 문장은 이 값을 사용해 시동 켜짐/꺼짐 경과를 표시합니다.
|
|
|
|
`meta.engine_state_duration`도 같은 기준의 값을 함께 내려주어 내부 확인과 호환성을 유지합니다.
|
|
|
|
상태 기록 섹션의 경과는 각 로그가 기록된 시각부터 현재까지 흐른 시간입니다. 각 행의 `age_seconds`는 서버 현재시각과 로그 timestamp의 차이로 계산해 내려주며, 화면 갱신마다 상단 조회 주기 경과처럼 계속 증가합니다.
|
|
|
|
모바일처럼 화면이나 상태 카드 폭이 좁을 때는 조회 경과와 시동 유지 시간이 한 줄로 유지되도록 초, 필요 시 분 단위를 생략해 표시합니다. 사용량 지표는 3열 2줄로 카드 안에 배치하고, 상태 기록 테이블은 카드 내부 좌우 스크롤로 분리해 전체 페이지 레이아웃이 밀리지 않게 합니다.
|
|
|
|
실시간 차량 그림의 도어/트렁크 열림 표시선은 열림 애니메이션 중에도 차량 기준 위치를 유지합니다. 트렁크 표시선은 중앙 정렬 기준을 유지한 상태에서 확대되어 PC와 모바일 모두에서 차체 하단과 맞도록 표시됩니다.
|
|
|
|
## Monitor 화면 제어
|
|
|
|
헤더 우측 컨트롤은 WakeLock, 언어, 테마 순서입니다. WakeLock은 Screen Wake Lock API를 지원하는 브라우저에서 화면 꺼짐을 방지하며, 활성 상태는 초록색 아이콘 버튼으로 표시합니다. 사용자의 선택은 `localStorage`에 저장하고, 새로고침이나 탭 복귀 후에는 브라우저 정책에 맞춰 다시 획득을 시도합니다.
|
|
|
|
## 구성
|
|
|
|
- `api.php`: 차량 상태/제어 API
|
|
- `monitor.php`: 모니터링 화면과 AJAX 응답
|
|
- `common.php`: 외부 secret 로드와 공통 DB/API 함수
|
|
- `collector_se.php`: 상태 수집 CLI/cron
|
|
- `tcp_worker.php`: TCP 큐 처리와 늦은 사용량 정산 worker
|
|
- `car-tcp-worker.service`: systemd service 예시
|
|
- `sw.js`: service worker
|
|
- `assets/`: 아이콘과 정적 자산
|
|
|
|
## 데이터/저장소
|
|
|
|
- Car DB tables: 차량 상태, 로그, 차트용 기록, TCP 요청 큐
|
|
- 사용량 수집값과 월별 보정 기준
|
|
- `/home/seo/secret/car.php`: TCP, DB, token, 허용 IP 설정
|
|
|
|
## 처리 흐름
|
|
|
|
1. `collector_se.php`가 차량 상태를 수집해 DB에 저장합니다.
|
|
2. `monitor.php`는 상태 AJAX와 사용량 AJAX를 분리해 갱신합니다.
|
|
3. 제어 요청은 token/IP 정책을 검증합니다.
|
|
4. 명령 코드를 허용 목록과 대조합니다.
|
|
5. 요청을 `car_tcp_request_queue`에 저장합니다.
|
|
6. `car-tcp-worker.service`가 큐를 처리하며 TCP 게이트웨이로 전송합니다.
|
|
7. API는 큐 상태를 4.95초까지만 기다린 뒤 결과 또는 timeout을 반환합니다.
|
|
|
|
## TCP timeout과 사용량 정산
|
|
|
|
차량 명령 성공/실패 판단은 UI 안정성을 위해 `TCP_TOTAL_TIMEOUT` 기본값인 4.95초를 사용합니다. 이 시간 안에 정상 응답이 없으면 API는 기존처럼 실패를 반환하므로 자동화와 UI는 즉시 재시도 여부를 판단할 수 있습니다.
|
|
|
|
단, 실제 모뎀이 4.95초 이후에 늦게 응답할 수 있으므로 사용량 기록은 별도로 정산합니다. API는 요청을 DB 큐에 넣고 4.95초까지만 기다립니다. `car-tcp-worker.service`는 해당 요청의 TCP 연결을 직접 열고, UI timeout 이후에도 같은 소켓을 최대 `TCP_USAGE_SETTLEMENT_TIMEOUT` 기본 60초까지 더 관찰합니다.
|
|
|
|
- 60초 안에 정상 응답이 완성되면 `late_response_after_ui_timeout`으로 송신량과 수신량을 함께 기록합니다.
|
|
- 60초까지 응답이 없으면 `late_total_timeout_60s_sent_only`로 송신 패킷만 사용량에 반영합니다.
|
|
- 60초 안에 일부 데이터만 오고 정상 포맷이 아니면 `late_invalid_or_partial_response`로 실제 수신된 바이트까지 기록합니다.
|
|
- 늦은 정상 응답이 차량 상태 포맷이면 상태 DB에도 저장합니다.
|
|
|
|
이 구조에서 `request_id`는 UI 응답과 늦은 사용량 정산 기록을 연결하는 기준입니다. 즉 명령 재시도 로직은 4.95초 기준을 유지하고, 데이터 사용량은 최대 60초까지 늦은 수신 패킷을 반영합니다.
|
|
|
|
## systemd worker
|
|
|
|
설치 파일은 `car-tcp-worker.service`입니다.
|
|
|
|
```bash
|
|
cp /var/www/seoul/car/car-tcp-worker.service /etc/systemd/system/car-tcp-worker.service
|
|
systemctl daemon-reload
|
|
systemctl enable --now car-tcp-worker.service
|
|
systemctl status car-tcp-worker.service
|
|
```
|
|
|
|
큐 테이블은 코드에서 자동 생성합니다. Worker가 중지되면 API 요청은 큐에 쌓이지만 4.95초 안에 처리되지 않아 실패로 반환될 수 있습니다. 안전을 위해 worker가 뒤늦게 오래된 queued 요청을 발견하면 실제 TCP 송신 없이 `queue_expired_before_send`로 만료 처리합니다.
|
|
|
|
Worker 교체나 예외 종료로 `processing`, `ui_timeout_pending` 상태가 남으면 다음 claim 전에 stale queue를 복구합니다. 전송 전이면 `expired_before_send`, 이미 TCP payload를 보낸 상태면 `settled_sent_only`로 정산해 사용량 누락을 막습니다.
|
|
|
|
## 주요 함수/모듈
|
|
|
|
- `common.php`: secret 로드와 공통 DB/API 함수
|
|
- `api.php`: 상태 조회와 명령 전송
|
|
- `monitor.php`: 화면 렌더링과 AJAX 응답
|
|
- `collector_se.php`: 상태 수집과 중복 실행 방지
|
|
- `tcp_worker.php`: TCP 요청 큐 처리와 60초 사용량 정산
|
|
|
|
## 보안
|
|
|
|
- 차량 API는 API token 또는 허용 IP 정책을 사용합니다.
|
|
- 차량 모니터 화면과 `monitor.php?mode=ajax`, `monitor.php?mode=usage`는 런처 공통 인증 쿠키 또는 사이트 관리자 세션이 유효할 때만 응답합니다.
|
|
- 공통 암호로 로그인한 일반 인증은 30분 유지하고, 사이트 관리자 세션이 확인되면 관리자 장기 쿠키를 발급해 PWA에서 반복 인증이 뜨는 일을 줄입니다.
|
|
- 런처 공통 인증은 우선 공통 인증 모듈로 직접 확인합니다. 공통 모듈을 사용할 수 없는 경우에만 `https://chaegeon.com/custom/launcher/api.php?session=1` 응답으로 확인합니다.
|
|
- 차량 모니터의 브라우저 화면 인증은 런처/나의 찾기와 같은 공통 쿠키를 사용하지만, 차량 단말이 호출하는 `api.php` 인증은 API token과 허용 IP 정책을 사용하는 별도 경로입니다.
|
|
- 차량 제어 명령은 허용된 명령 코드로 제한합니다.
|
|
- Secret 파일은 저장소 밖에서 제한된 권한으로 유지합니다.
|
|
- 실제 제어 명령은 최신 상태 조회와 명령 검증 이후에만 전송합니다.
|
|
|
|
## 운영 체크포인트
|
|
|
|
- 차량 TCP 실패 reason과 마지막 수신 지연을 확인합니다.
|
|
- 명령별 rate limit과 감사 로그를 유지합니다.
|
|
- 통신사 기준 데이터 사용량 보정값을 주기적으로 확인합니다. 2026-06-26 01:10 T world 실측 102.4MB(104,834KB) 기준 2026-06 보정값은 통신사 누적 107,350,016 bytes, 로컬 보정 전 누적 54,104,011 bytes, 배율 1.984142입니다.
|
|
- 직전 배율 1.984648 기준 현재값은 107,377,429 bytes로 계산되어 T world보다 27,413 bytes(약 0.026MB) 높았고, 새 배율은 직전보다 0.000507 낮아졌습니다.
|
|
- 데이터 사용량 집계는 성공 응답 평균을 SQL로 먼저 구하고, 월간/일간 행은 PHP에서 한 줄씩 스트리밍 처리합니다. 기존 보정 조건은 유지하면서 `fetchAll()` 메모리 사용을 제거해 PHP-FPM `memory_limit=128M`에서도 동작하도록 합니다.
|
|
- 4.95초 timeout 직후에는 사용량 기록이 즉시 생기지 않을 수 있으며, 최대 60초 뒤 늦은 정산 행이 추가될 수 있습니다.
|
|
- `systemctl status car-tcp-worker.service`와 `journalctl -u car-tcp-worker.service`로 worker 상태를 확인합니다.
|