2026-03-02 15:22:47 +09:00
2026-03-02 15:22:47 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00
2026-02-28 12:45:29 +09:00

VasCURA589 코드 분석 (com/laseroptek/raman)

이 문서는 app/src/main/java/com/laseroptek/raman 폴더를 기준으로 구조와 동작을 요약한 분석 문서입니다.
요청 경로의 com/leaseroptek/raman는 오타로 보이며, 실제 패키지는 com/laseroptek/raman입니다.

1) 폴더 개요

  • 분석 대상 파일 수: 246개
  • 상위 패키지 구성
    • const (12): 프로토콜/테이블/상수
    • data (57): 모델, DB/Serial/Preference 데이터 소스
    • di (4): Hilt DI 모듈
    • navigation (5): 라우트/네비게이션 그래프
    • repository (3): 데이터 접근 추상화 계층
    • ui (123): Compose UI + ViewModel
    • utils (40): 확장 함수, 보조 유틸, 커스텀 컴포넌트

2) 아키텍처 요약

전체적으로 Compose + Hilt + Room + DataStore + Serial(NDK) 구조입니다.

  • Application
    • VasCURA589App: Hilt 진입점, Timber 로그 트리 설정
  • Activity
    • ui/MainActivity: 전체 초기화 오케스트레이션, 풀스크린/시스템바 제어, APK 선택 이벤트 처리
  • Presentation
    • ui/screens/...: Home, Info, Config, Lock, Engineer 화면
    • 공용 상태는 MainViewModel이 중심으로 보유
  • Domain/Data Access
    • repository/*Repository: Serial/Preference/DB 접근 래퍼
  • Data Source
    • data/source/serial/SerialPort: native serial_port 라이브러리 로딩 + FD 기반 통신
    • data/source/db/*: Room DB(SerialLog) 접근
    • PreferenceRepository: DataStore 기반 앱 설정/테이블/카운트 저장

3) 실행 흐름 (부팅~운영)

  1. MainActivity.onCreate()
  2. initialize()에서 MainViewModel.performFullInitialization() 실행
  3. 초기화 완료 후 UI 활성화(setInitialized(true))
  4. 시리얼 시작
    • txPacketOnce(): 초기 설정 패킷 송신
    • rxPacketLoop(): 수신 루프 + 패킷 파싱/상태 반영
    • txPacketLoop(): 주기적 heartbeat 성격 송신

핵심 포인트:

  • 초기화는 IO 스레드에서 병렬 로딩(launch + joinAll)로 처리
  • MainScreenisInitialized를 기준으로 로딩 화면 -> 본 화면 전환
  • 통신 타임아웃 감시(monitorConnectionTimeout)로 안정성 상태 추적

4) 주요 패키지별 역할

ui/screens/main

  • MainViewModel: 앱의 사실상 중앙 상태 저장소
    • 레이저 파라미터(펄스/플루언스/반복률), 카운터, 경고/에러, 온도, DCD, 에너지 디텍터 상태 관리
    • 시리얼 TX/RX 패킷 생성/파싱
    • Preference 로드/저장, DB 로그 적재/트리밍
    • 핸드피스 타입 변경 시 에너지/Hz 테이블 재적용

ui/screens/home (30개)

  • 실제 시술/운영 메인 UI
  • 슬라이더 기반 파라미터 조절, 스탠바이/발진, 카운트/프리셋/DCD 제어

ui/screens/info (6개)

  • 모니터링/차트 화면
  • InfoViewModel은 차트 라인 표시 상태(체크박스)만 관리
  • 실데이터(온도, 램프카운트 등)는 MainViewModel에서 수신

ui/screens/config (7개)

  • 볼륨, 가이드빔, 언어/시간 설정, 엔지니어 모드 진입 지점

ui/screens/engineer (38개)

  • 서비스/캘리브레이션/로그/버전/임계치/시리얼번호 등 유지보수 기능
  • Voltage Table/수명/온도 한계/Energy detect 기준값 조정

ui/screens/lock (3개)

  • PIN 기반 잠금/해제 플로우

5) 시리얼 통신 구조

  • 송신: MainViewModel.txPacket()
    • READ_WRITE + CMD로 패킷 조합
    • WRITE 시 CS(checksum) 포함
  • 수신: rxPacketLoop()
    • 버퍼 누적 후 findCompletePackets()로 STX(0x21)~ETX(0x0d) 패킷 분리
    • procRxPacket()에서 CMD별 모델 변환 및 상태 업데이트

처리 예:

  • CMD.LASER_STATUS: 발진 상태 반영, 카운트 증가, 알림음
  • CMD.HAND_PIECE: 타입 변경 감지 후 테이블/각도/상태 재초기화
  • CMD.TEMPERATURE: 차트 큐 갱신 + 임계값 비교
  • CMD.ENERGY_DETECT: 버전/마운트/측정 상태 처리 및 Good/Not Good 응답

6) 저장 전략

  • DataStore (PreferenceRepository)
    • 카운트, 볼륨, 가이드빔, 프리셋, Spray DCD, Voltage Table, 임계값, 시리얼 번호 리스트 등
  • Room (RamanDatabase, SerialLogDao)
    • 주요 시리얼 패킷 로그 저장
    • trimLogs(limit)로 로그 최대 개수 유지

7) 눈에 띄는 구현 특성

  • MainViewModel에 상태/로직이 집중된 구조(단일 허브)
  • 디버그 로그(Timber)와 패킷 헥사 덤프 활용
  • 미리보기/테스트를 위한 fake serial repository 제공
  • 패키지 네이밍이 일부 혼재:
    • 예: 파일 경로는 data/source/db인데 패키지 선언은 data.datasource.db인 클래스가 존재

8) 빠른 참고 파일

  • 앱 진입: VasCURA589App.kt, ui/MainActivity.kt
  • 내비게이션: navigation/Routes.kt, navigation/graphs/MainNavGraph.kt
  • 핵심 로직: ui/screens/main/MainViewModel.kt
  • 시리얼: data/source/serial/SerialPort.kt, repository/SerialPortRepository.kt
  • 설정 저장: repository/PreferenceRepository.kt
  • 로그 DB: data/source/db/*, repository/DatabaseRepository.kt

9) MainViewModel.kt 별도 분석

개요

  • 파일: app/src/main/java/com/laseroptek/raman/ui/screens/main/MainViewModel.kt
  • 규모: 약 2,288 라인
  • 역할: 앱 전체의 공용 상태 + 시리얼 프로토콜 처리 + 로컬 저장소 동기화를 한곳에서 담당하는 중앙 오케스트레이터

의존성 주입 구조

  • PreferenceRepository: DataStore 기반 영속값 로드/저장
  • SerialPortRepository: 시리얼 포트 open/write/close
  • DatabaseRepository: 시리얼 로그 조회/저장/트리밍
  • DispatcherProvider: 코루틴 디스패처 추상화
  • Context: 알림음 재생 및 시스템 리소스 접근

상태(State) 도메인 분류

  • UI/초기화 제어
    • isInitialized, 팝업 노출 플래그, apkUpdateEvent
  • 레이저 파라미터
    • pulseAngle, fluenceAngle, repetitionAngle
    • energyTable, hzTable, voltageTable, fluenceList, repetitionList
  • 프리셋/옵션
    • presetList, selectedPresetIndex
    • sprayDcdList, selectedSprayDcdIndex
  • 카운터/수명
    • laserCount, lampCount, dcdCount, hpCount, lifeTime, opTimeHour
  • 장비 상태 패킷
    • laserStatus, handPiece, warning, error, version
    • temperature, temperature_write, qSwitch, dcdGas, sprayDcd, oven, purgeBubble
  • 에너지 디텍션
    • energyVersion, energyHandpiece, energyControl, energyMeasured, energyMeasuredWrite, energyDetectRefer2
  • 모니터링/로그
    • chartDataQueue, serialLogList, isCommunicationStable

핵심 메서드 흐름

  • 초기화
    • performFullInitialization()
    • DB 정리/온도 이력 로딩 후, 다수의 preference 로딩을 launch + joinAll로 병렬 수행
  • 시리얼 송신
    • txPacketOnce(): 버전/QSwitch/GuideBeam/DCD/Spray 기본값 송신
    • txPacketLoop(): 주기적 명령(핸드피스, 샷카운트, 경고, 온도) 폴링
    • txPacket(): CMD/READ_WRITE에 따라 실제 프로토콜 패킷 생성
  • 시리얼 수신
    • rxPacketLoop(): 포트 수신 collect
    • findCompletePackets(): 버퍼에서 STX~ETX 완성 패킷 분리
    • procRxPacket(): CMD 별 디코딩/상태 반영/로그 저장
    • monitorConnectionTimeout(): 응답 지연 watchdog

비즈니스 로직 포인트

  • CMD.HAND_PIECE 수신 시
    • 핸드피스 변경 여부 확인 후 레이저 상태/카운트/테이블/슬라이더 초기화
    • handpiece type별 lifetime 카운트 누적
  • CMD.LASER_STATUS 수신 시
    • 레이저 ON 상태에서 샷/램프/HP/DCD 카운트 갱신
    • 조건에 따라 알림음 재생 및 스탠바이 전환 처리
  • CMD.TEMPERATURE 수신 시
    • 차트 큐에 타임스탬프 데이터 적재
    • 설정 임계값(temperature_write)과 비교해 경고/에러 조건 반영
  • CMD.ENERGY_DETECT 수신 시
    • measured 값과 refer2 기준 비교 후 Good(0x47)/Not Good(0x4E) 응답 송신

파라미터 계산 로직

  • txLaserStatusEntry(laserStatus: Int)
    • 현재 각도 -> step 변환
    • step -> pulse/fluence/repetition 매핑
    • (pulse, fluence)로 energy 조회
    • calculateInterpolatedC()로 목표 전압 계산(선형 보간)
    • 최종 LaserStatus 패킷 송신

저장소 동기화 패턴

  • 상태 변경 직후 save*ToPreference() 호출하는 즉시 반영형 패턴
  • 앱 시작 시 load*FromPreference()로 메모리 상태 복원
  • 시리얼 로그는 특정 CMD만 DB에 적재하고, trimSerialLog()로 최대 개수 유지

설계 관점 평가

  • 장점
    • 장비 프로토콜 처리, UI 상태, 저장소 동기화가 한 ViewModel에서 일관되게 연결됨
    • 초기화 병렬화로 부팅 지연 완화
    • 통신 watchdog/버퍼 파싱 등 실장비 대응 로직이 명확함
  • 트레이드오프
    • 단일 ViewModel 책임이 매우 큼(상태/함수 밀집)
    • 기능 분리(예: SerialHandler, PreferenceSync, LaserDomain) 여지가 큼

유지보수 시 우선 확인 포인트

  • 신규 CMD 추가 시
    • txPacket() 인코딩 + procRxPacket() 디코딩을 함께 확장
  • 파라미터 표 변경 시
    • loadFluenceTable(), loadHzTable(), calculateInterpolatedC() 영향 확인
  • 성능/안정성 이슈 시
    • txPacketLoop() 주기, RX_TIMEOUT_THRESHOLD, DB 로그 적재량 점검
Description
No description provided
Readme 30 MiB
Languages
Kotlin 99.7%
C 0.3%