The PHP app runs on Cafe24 shared web hosting -- calling it 'cloud' was misleading. Renames the directory, the edge client module, and every doc/script/identifier that used the term. - cloud/ -> server/ (incl. server/deploy/build_cafe24_package.sh paths) - edge/cloudclient.py -> edge/serverclient.py, CloudClient -> ServerClient - cloud/docs/cloud-deploy.md -> server/docs/server-deploy.md - CLOUD_* env/config keys -> SERVER_* - tests renamed to match Tests: PHP 109 pass (4 skipped), pytest 167 pass. dist/ regenerated.
6.4 KiB
P1 파일럿 런북 (노트북 웹캠 엔드투엔드)
이 문서는 노트북 웹캠 하나로 엣지 → 서버 → 관리자 응답의 최소 경로를 돌리는 절차다. 실장비(Hailo·Pi5)·폐쇄망 전체 번들·드릴 게이트·SMS 연동은 후속(범위 밖, §6).
- 엣지:
python -m edge(또는move-detect-edge) — CPU MoveNet pose → 감지 → HMAC 서명 POST. - 서버: 기존
server/PHP 앱 — ingest + 대시보드 + 사고 상세 + 데스크 Web Audio 알림.
1. 빌드 머신 준비 (모델 · onnxruntime)
폐쇄망 원칙: onnxruntime 휠과
.onnx모델은 빌드 머신에서 받아 번들한다. 타깃(폐쇄망)에서 인터넷을 받지 않는다. 노트북 파일럿은 빌드=타깃이 같은 머신이라 아래를 그대로 실행하면 된다.
pip install onnxruntime # CPU 추론 런타임 (에어갭 타깃엔 오프라인 휠로 번들)
python -m edge.tools.fetch_movenet # MoveNet SinglePose Lightning ONNX -> models/movenet_lightning.onnx
fetch_movenet.py의 URL은 빌드 편의용이다. 실제 내려받은 모델의 입력 크기/자료형과 출력 레이아웃
[1,1,17,3](y,x,score)를 어댑터 기대값과 대조하라(다르면 MoveNetPoseAdapter(input_size=...) 조정;
COCO-17 remap 로직은 그대로). 어댑터 remap은 tests/test_movenet_pose.py(fake session)로 고정돼 있고,
실모델 경로는 tests/hardware/test_movenet_smoke.py가 모델이 번들됐을 때만 게이트로 검증한다.
2. 서버 로컬 기동
로컬 MySQL 8(스키마 CHECK 제약은 8.0.16+)과 PHP 8.2+ 필요. 상세 배포·전제조건(gd/argon2/HTTPS 등)은 server/docs/server-deploy.md 참조 — 여기선 로컬 최소 절차만.
- DB 생성 후 스키마 임포트:
mysql <db> < server/schema.sql(10개 테이블). server/config.php를server/config.example.php에서 복사, 로컬 DB DSN/계정 기입 (snapshot_dir는 쓰기 가능 경로로).- 관리자 계정 · 디바이스 시크릿 등록 — 앱에 셀프 가입 흐름이 없으므로 직접 넣는다.
CLI 스니펫과 SQL은 server-deploy.md §6(디바이스 시크릿) · §7(첫 관리자) 그대로 사용:
- 시크릿 생성:
php -r "echo bin2hex(random_bytes(32)), \"\n\";" INSERT INTO devices (device_id, name, secret, config_version) VALUES ('pi-01','노트북','<시크릿>',1);- 관리자 해시:
php -r "echo password_hash('바꿀-암구호', PASSWORD_ARGON2ID), \"\n\";" INSERT INTO users (username, password_hash, role, ...) VALUES ('admin','<해시>','admin',NULL,0,0);
- 시크릿 생성:
- 기동:
php -S localhost:8000 -t server/public- 세션 쿠키가
cookie_secure라 순수 HTTP에선 로그인 쿠키가 안 붙을 수 있다. 로컬은 대개localhost가 secure-context로 취급돼 동작하지만, 안 되면 server-deploy.md §8(HTTPS) 참조.
- 세션 쿠키가
3. 엣지 환경변수
edge/config.py(load_config) + edge/daemon.py(main)가 읽는 실제 키:
| env | 의미 | 예시 |
|---|---|---|
DEVICE_ID |
devices.device_id와 일치 |
pi-01 |
DEVICE_SECRET |
devices.secret와 일치(HMAC) |
<§2에서 생성한 값> |
CAFE24_URL |
서버 베이스 URL | http://localhost:8000 |
CAMERA_ID |
이벤트/구역의 camera_id | cam-01 |
MOVENET_ONNX |
모델 경로 (필수, 없으면 즉시 KeyError) | models/movenet_lightning.onnx |
UVC_DEVICE |
OpenCV 캡처 인덱스 | 0 |
TARGET_FPS |
프레임 간격 = 1/fps | 12 |
QUEUE_DB |
오프라인 큐 sqlite 경로 | queue.db |
감지 임계값(선택, 데모 단축용): FALL_PRONE_S(기본 3.0), FALL_NO_MOTION_S(10.0),
IMMOBILE_S(120.0), GHOST_REAPPEAR_S(10.0), ZONE_DEBOUNCE_S(0.75), COOLDOWN_S(30.0).
export DEVICE_ID=pi-01 DEVICE_SECRET='<시크릿>' CAFE24_URL=http://localhost:8000 \
CAMERA_ID=cam-01 MOVENET_ONNX=models/movenet_lightning.onnx UVC_DEVICE=0 TARGET_FPS=12
python -m edge # 또는 move-detect-edge
4. 데모 시나리오
- 낙상: 웹캠 앞에서 눕는다 →
FALL_PRONE_S(기본 3초) 후fall(high) 이벤트. - 위급 상승: 계속 안 움직이면
FALL_NO_MOTION_S(기본 10초) 후no_motion(critical) → 대시보드에서 데스크 비프 반복(첫 클릭으로 오디오 언락 필요). - 가시화: 목록의 이벤트 유형(링크) 클릭 →
/events/{id}/view상세 → 스냅샷 이미지 확인. - 응답: 상세/목록에서 확인 → 미확인 critical이 사라지면 비프 정지.
- 역루프(구역): 대시보드
구역 설정에서 폴리곤 저장 → 발끝 진입 →zone_*이벤트. 구역 변경은 엣지의 다음 config 폴링 때 적용된다 — 기본 cadencesync_every=150프레임 ≈ 12fps에서 약 12초. 저장 후 ~15초 기다렸다가 진입할 것. - 오프라인 큐: 네트워크(또는
php -S) 중단 상태에서 이벤트 발생 → 큐에 적재 → 복구 후flush_every=300프레임(≈25초)마다 flush로 밀린 이벤트 전송. - 하트비트:
heartbeat_every=900프레임(≈75초)마다POST /api/heartbeat(서명).
cadence(
sync_every/heartbeat_every/flush_every)는daemon.main()기본값이며 env로 노출돼 있지 않다. 데모에서 더 빠른 주기가 필요하면run_loop(...)호출 인자를 임시 조정한다.
5. 검증(테스트)
pytest -q # 엣지 유닛(하드웨어 스모크는 모델 없으면 skip)
cd server && ./vendor/bin/phpunit --display-warnings --display-deprecations # 서버(0 warnings)
모델을 번들한 뒤 실추론 경로까지 확인하려면 models/movenet_lightning.onnx 존재 상태로 pytest -q —
tests/hardware/test_movenet_smoke.py가 skip 해제돼 실행된다.
6. 파일럿 한계 (명시)
- 단일 카메라 · CPU pose(저 fps) — 실장비 Hailo 가속은 후속.
- 단일 프레임 스냅샷 — 前中後 링버퍼 다중 프레임은 P2.
- 알림 1채널(데스크 Web Audio) — critical SMS/webhook 실연동은 후속(게이트 정보 필요).
- 폐쇄망 전체 번들 아님 — onnxruntime/모델 fetch만 제공. 오프라인 휠·차단 설치·
docker save패키징은 별도 후속 태스크. - 드릴 게이트 · F14 컴플라이언스 · 감사 해시체인 — 범위 밖(P1-C/P3).