ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • FRD: blf & dbc --> mdf
    카테고리 없음 2026. 3. 9. 10:09

    나는 클로드를 이용하여 코딩할 때, 구현하고자 하는 기능을 (10줄 이내로) 간략하게 기술한다. 이를 FRD(Functional Requirement Document)라고 부른다. 클로드에게 FRD 검토와 피드백을 요청한다. 클로드의 피드백들 중에 내 마음에 드는 것을 선택하고 서브 기능에 관해  내 생각을 이야기하고 피드백을 요청한다. 이런 작업을 반복한다. 중간중간에 코드 작성을 요청하고 실행해 본다. 버그나 사용 방법 개선에 관해 클로드와 대화한다. 어느 정도 진척이 이뤄지면 클로드에게 FRD 업데이트를 요청한다.  

    BLF + DBC → MDF 변환 도구 기능 요구 조건 (FRD)

    문서 버전: 0.7 <-- 버전이 0.7인 것으로 미루어 프로젝트 중에 클로드에게 6번 FRD 정리를 요청했나보다. 첫 버전은 내가 작성한 것이다.  
    작성일: 2026-03-08
    파일명: blf_dbc_to_mdf_mp.py (PySide6 데스크톱 앱, 멀티프로세싱 버전)


    변경 이력

    버전 날짜 내용
    0.1 2026-03-06 초안 (Streamlit 기반)
    0.2 2026-03-06 프레임워크 변경: Streamlit → PySide6. FR-01 파일 입력 방식 변경 (text_input → 파일 다이얼로그). Streamlit 특화 표현 전반 수정.
    0.3 2026-03-07 FR-02에 파싱 트리거 버튼 추가(FR-02-8). FR-05-2 리샘플링 주기 단위 ms 고정. FR-06-2 변환 버튼 비활성화 조건 확장. FR-06-7 취소 버튼 추가. FR-07-2 차트 라이브러리 pyqtgraph 확정. OI-02 단일 채널 처리 방식 확정. OI-03 JSON 저장 범위 확정. 의존 라이브러리 목록 갱신.
    0.4 2026-03-07 UI 레이아웃을 4개 탭 구조로 변경 (파일 입력 / 신호 선택 / 변환 옵션 및 실행 / 미리보기). FR-08 탭 전환 규칙 추가.
    0.5 2026-03-07 탭 5 [설정] 추가. FR-09 다국어 지원(한국어 / English / 中文) 추가. NFR-07 i18n 문자열 관리 추가. FR-08-1 탭 수 4 → 5 변경.
    0.6 2026-03-07 FR-01-6 파일별 디렉터리 독립 기억으로 확장. FR-02-9 신호 선택 탭 트리 수준 버튼 추가. FR-03-5 BLF 파싱 크기 제한 추가. FR-09-6 설정 탭에 파싱 크기 항목 추가. FR-06-2 변환 버튼 재활성화 버그 수정 내용 반영. 설정 탭 UI 레이아웃 업데이트.
    0.7 2026-03-08 파일명 변경: blf_dbc_to_mdf.pyblf_dbc_to_mdf_mp.py. FR-06-4 진행 상태 표시 개선 (0% → 현재/전체 MB + 경과 시간). FR-06-8 신규: 변환 완료 효과음. FR-07 미리보기 탭 전면 개편: 수평 스플리터(4:1) 레이아웃, MDF 열기 버튼, 다중 신호 선택, 개별 그래프 체크박스. FR-02-9 신호 선택 툴바 버튼 순서 명시. FR-09-7/FR-09-8 신규: 병렬 프로세스 수·배치 크기 설정. FR-10 신규: 멀티프로세싱 변환 (ProcessPoolExecutor, 프레임 배치 분할). NFR-08 신규: 의존 라이브러리 multiprocessing 추가.

    1. 개요

    BLF(Binary Logging File) 형식의 CAN 데이터 로그와 DBC(Database CAN) 형식의 CAN 매트릭스를 입력으로 받아,
    사용자가 선택한 신호들을 MDF4(.mf4) 형식으로 변환·저장하는 PySide6 데스크톱 애플리케이션.

    1.1 배경

    • BLF는 Vector 장비 등에서 생성되는 CAN 로그 포맷이다.
    • DBC는 CAN 버스의 메시지·신호 정의 파일이다.
    • MDF4는 자동차 산업 표준 계측 데이터 포맷(ASAM MDF)으로, 채널마다 독립적인 타임스탬프를 지원하여 리샘플링 없이도 원본 데이터를 보존할 수 있다.

    1.2 처리 흐름

    BLF 파일 ──┐
                ├─→ [파싱] 버튼 → DBC 파싱 + BLF 스캔(앞 N MB) → 신호 선택 → [변환 실행] → (옵션: 리샘플링/정규화) → MDF4 저장
    DBC 파일 ──┘
    
    탭 흐름: [파일 입력] → [신호 선택] → [변환 옵션 및 실행] → [미리보기]

    2. 기능 요구 조건

    FR-01. 파일 경로 입력

    ID 요구 조건
    FR-01-1 BLF 파일 선택 버튼을 클릭하면 QFileDialog가 열리고, .blf 확장자 필터가 적용되어야 한다. 선택된 경로는 QLineEdit에 표시된다.
    FR-01-2 DBC 파일 선택 버튼을 클릭하면 QFileDialog가 열리고, .dbc 확장자 필터가 적용되어야 한다. 선택된 경로는 QLineEdit에 표시된다.
    FR-01-3 QLineEdit에 경로를 직접 타이핑하거나 붙여넣기(Ctrl+V)할 수도 있어야 한다. 경로가 변경될 때마다 파일 존재 여부를 즉시 검증하고, 존재하지 않으면 오류 아이콘 또는 메시지를 표시해야 한다.
    FR-01-4 파일 확장자가 올바른지 검증해야 한다 (BLF: .blf, DBC: .dbc).
    FR-01-5 파일 크기 정보를 경로 표시 아래에 표시해야 한다.
    FR-01-6 BLF, DBC, JSON 파일 다이얼로그는 각각 독립적으로 마지막 디렉터리를 기억하여 다음 실행 시 같은 디렉터리에서 시작해야 한다 (QSettings 키: last_dir_blf, last_dir_dbc, last_dir_json).

    FR-02. DBC 파싱 및 신호 목록 표시

    ID 요구 조건
    FR-02-1 DBC 파일이 유효한 경우 DBC 내의 모든 메시지와 신호를 파싱하여 표시해야 한다.
    FR-02-2 메시지 목록은 메시지 ID, 메시지 이름, 신호 수를 포함해야 한다.
    FR-02-3 메시지-신호 계층 구조를 QTreeWidget으로 표시해야 한다. 메시지는 최상위 항목, 신호는 자식 항목이다.
    FR-02-4 각 신호 항목에는 신호명, 단위(unit), 최솟값/최댓값(DBC 정의 기준)을 표시해야 한다.
    FR-02-5 각 신호 항목에 개별 체크박스(Qt.ItemIsUserCheckable)가 있어야 하며, 체크된 신호만 MDF로 추출되어야 한다.
    FR-02-6 각 메시지 항목에도 체크박스가 있어야 하며, 메시지 체크박스를 조작하면 하위 신호 전체가 선택/해제되어야 한다.
    FR-02-7 전체 메시지에 대한 전체 선택 / 전체 해제 버튼이 있어야 한다.
    FR-02-8 DBC 파싱과 BLF 스캔은 [파싱] 버튼을 클릭했을 때 시작된다 (파일 선택 시 자동 시작하지 않는다). [파싱] 버튼은 BLF와 DBC 파일이 모두 유효하게 선택된 경우에만 활성화된다.
    FR-02-9 신호 선택 탭 툴바의 버튼 배치 순서는 다음과 같다: [전체 선택][전체 해제][메시지 수준][신호 수준] → (여백) → [선택 저장][선택 로드] → (stretch) → BLF 발견 메시지 요약 → 선택된 신호 수. [메시지 수준] 버튼은 트리의 모든 메시지 항목을 접어(collapseAll) 메시지 목록만 보이게 하고, [신호 수준] 버튼은 모든 메시지 항목을 펼쳐(expandAll) 신호 목록까지 보이게 한다.

    FR-03. BLF 분석 — 실제 존재 메시지 검증

    ID 요구 조건
    FR-03-1 BLF 파일을 스캔하여 실제로 존재하는 CAN 메시지 ID 목록을 추출해야 한다.
    FR-03-2 DBC에 정의되어 있지만 BLF에 존재하지 않는 메시지의 항목은 체크박스를 비활성화(setDisabled(True))하고 시각적으로 구분(회색 표시 등)해야 한다.
    FR-03-3 BLF 스캔은 UI가 멈추지 않도록 별도 워커 스레드(QThread)에서 실행되어야 한다. 스캔 중 진행 상태를 상태 표시줄과 QProgressBar로 표시해야 한다. 스캔 중 [취소] 버튼을 클릭하면 스캔을 중단하고 트리를 초기 상태로 되돌려야 한다.
    FR-03-4 BLF에 존재하는 메시지 수와 DBC 전체 메시지 수를 비교하는 요약 정보를 표시해야 한다.
    FR-03-5 BLF 스캔은 파일 전체가 아닌 앞부분 N MB만 읽어 수행한다 (기본값: 5 MB). 스캔 크기는 [설정] 탭에서 MB 단위로 지정할 수 있으며 (FR-09-6), 파싱 단계에만 적용된다. 변환 실행 시에는 BLF 파일 전체를 읽는다.

    FR-04. 신호 선택 저장 및 로드

    ID 요구 조건
    FR-04-1 현재 신호 선택 상태를 JSON 파일로 저장하는 버튼이 있어야 한다.
    FR-04-2 저장 파일명은 자동으로 DBC 파일명 기반으로 생성되어야 한다 (예: venue_esc_selection.json).
    FR-04-3 저장 경로는 QFileDialog를 통해 사용자가 변경할 수 있어야 한다.
    FR-04-4 저장 파일이 존재하면 앱 시작 시 자동으로 로드하여 신호 선택 상태를 복원해야 한다.
    FR-04-5 저장 파일 로드 버튼이 있고, QFileDialog를 통해 경로를 직접 지정할 수 있어야 한다.
    FR-04-6 로드 시 현재 DBC에 없는 신호가 저장 파일에 있으면 경고 메시지를 표시하고 해당 신호는 무시해야 한다.
    FR-04-7 저장 파일에는 DBC 파일 경로, BLF 파일 경로, 저장 시각, 선택된 신호 목록이 포함되어야 한다. 변환 설정(리샘플링 여부, 주기 등)은 저장하지 않는다.

    FR-05. 변환 옵션 설정

    ID 요구 조건
    FR-05-1 리샘플링 여부QCheckBox로 선택할 수 있어야 한다.
    FR-05-2 리샘플링을 선택한 경우 리샘플링 주기를 QLineEdit으로 입력할 수 있어야 한다. 입력값은 숫자(정수 또는 소수)이며 단위는 ms로 고정한다 (기본값: 20). 리샘플링을 선택하지 않으면 입력 필드는 비활성화된다.
    FR-05-3 타임스탬프 정규화 여부QCheckBox로 선택할 수 있어야 한다 (0초 시작 여부).
    FR-05-4 리샘플링을 선택하지 않은 경우(MDF 기본 사용 방식), 각 신호가 독립적인 타임스탬프를 갖도록 저장해야 한다.
    FR-05-5 출력 MDF 파일 경로를 QFileDialog로 사용자가 지정할 수 있어야 한다.
    FR-05-6 출력 파일명은 BLF 파일명을 기반으로 자동 생성되어야 한다 (예: xxx_resampled_20ms.mf4 또는 xxx_raw.mf4).
    FR-05-7 MDF 버전을 QComboBox로 선택할 수 있어야 한다 (MDF4 .mf4 기본, MDF3 .mdf 옵션).

    FR-06. 변환 실행 및 진행 상태 표시

    ID 요구 조건
    FR-06-1 [변환 실행] 버튼(QPushButton)이 있어야 한다.
    FR-06-2 다음 조건 중 하나라도 해당하면 [변환 실행] 버튼이 비활성화되어야 한다: (1) BLF 또는 DBC 파일이 선택되지 않은 경우, (2) 파싱이 완료되지 않은 경우, (3) 선택된 신호가 없는 경우, (4) 변환이 실행 중인 경우. 변환이 완료되면 버튼은 즉시 다시 활성화되어야 한다.
    FR-06-3 변환은 UI가 멈추지 않도록 별도 워커 스레드(QThread)에서 실행되어야 한다.
    FR-06-4 변환 중 단계별 진행 상태를 QProgressBar와 상태 레이블로 표시해야 한다 (BLF 파싱 → NaN 처리 → (리샘플링) → MDF 저장). 상태 레이블의 진행 상세 정보는 (현재 처리 MB / 전체 MB, 경과 시간 초) 형식으로 표시한다 (예: 변환 중... BLF 파싱 (12.3 MB / 45.6 MB, 8 sec)).
    FR-06-5 변환 완료 후 결과 요약을 표시해야 한다: 총 신호 수, 총 데이터 포인트 수, 시간 범위, 저장 경로.
    FR-06-6 변환 중 오류 발생 시 QMessageBox로 오류 메시지를 명확하게 표시하고 앱이 중단되지 않아야 한다.
    FR-06-7 변환 실행 중 [취소] 버튼을 클릭하면 변환을 중단하고 미완성 출력 파일을 삭제해야 한다. [취소] 버튼은 변환 실행 중에만 활성화된다.
    FR-06-8 변환 완료 시 효과음을 재생한다. Windows에서는 winsound.Beep(1000, 300)을 사용하고, 그 외 플랫폼 또는 실패 시 QApplication.beep()으로 폴백한다. 다른 작업을 하다가도 완료 여부를 인지할 수 있도록 한다.

    FR-07. 결과 미리보기

    ID 요구 조건
    FR-07-1 미리보기 탭은 QSplitter(Horizontal)로 좌우 분리되며 비율은 4:1 (좌: 신호 선택 + 차트, 우: 테이블)이다.
    FR-07-2 좌측 패널 상단에 [MDF 열기] 버튼과 파일 경로 표시 QLineEdit(읽기 전용)이 있다. 변환 완료 시 출력 파일 경로가 자동으로 채워지며, [MDF 열기] 버튼을 클릭하면 QFileDialog로 임의의 .mf4/.mdf 파일을 열어 미리볼 수 있다.
    FR-07-3 파일 경로 아래에 신호 선택 QListWidget이 있다. 표시 방향은 수평 흐름(LeftToRight)이며 체크박스 형태로 복수 신호를 선택할 수 있다(ExtendedSelection). 최대 높이는 140 px로 제한하여 차트 영역을 최대화한다.
    FR-07-4 신호 선택 영역 우측에 [개별 그래프] 체크박스(QCheckBox)가 있다. 체크 시 선택된 신호들이 각각 별도 서브플롯으로 표시되고, 미체크 시 하나의 플롯에 겹쳐 표시된다.
    FR-07-5 차트 라이브러리는 pyqtgraph를 사용한다. 차트 배경은 흰색이다.
    FR-07-6 우측 패널에는 QTableWidget (컬럼: 타임스탬프(s), 값)이 있으며, 현재 선택된 신호(단일) 기준으로 첫 N 행을 표시한다.

    FR-08. 탭 구조 및 전환 규칙

    ID 요구 조건
    FR-08-1 앱은 QTabWidget으로 구성된 5개 탭을 가진다: [파일 입력], [신호 선택], [변환 옵션 및 실행], [미리보기], [설정].
    FR-08-2 파싱이 완료되면 자동으로 [신호 선택] 탭으로 전환한다.
    FR-08-3 변환이 완료되면 자동으로 [미리보기] 탭으로 전환한다.
    FR-08-4 탭은 사용자가 언제든지 자유롭게 클릭하여 이동할 수 있다.

    FR-09. 설정 탭

    ID 요구 조건
    FR-09-1 [설정] 탭에 언어 선택 QComboBox가 있어야 한다. 선택 가능한 언어는 한국어, English, 中文 세 가지이다.
    FR-09-2 언어를 변경하면 앱을 재시작하지 않고 즉시 모든 UI 텍스트(탭 이름, 버튼, 레이블, 메시지, 상태 표시줄 등)가 선택한 언어로 갱신되어야 한다.
    FR-09-3 모든 UI 문자열은 언어 키 딕셔너리(STRINGS)로 중앙 관리하며, 하드코딩 문자열을 UI 위젯에 직접 사용하지 않아야 한다.
    FR-09-4 선택된 언어는 QSettings에 저장되어 다음 실행 시 자동으로 복원되어야 한다.
    FR-09-5 앱 최초 실행 시 기본 언어는 한국어이다.
    FR-09-6 [설정] 탭에 BLF 파싱 크기 제한 입력 필드(QLineEdit)가 있어야 한다. 단위는 MB이며 기본값은 5이다. 입력된 값은 QSettings에 저장되어 다음 실행 시 자동으로 복원된다. 유효하지 않은 값(숫자가 아닌 경우)이 입력된 경우 기본값(5 MB)을 사용한다.
    FR-09-7 [설정] 탭에 병렬 프로세스 수 입력 필드(QLineEdit)가 있어야 한다. 기본값은 cpu_count - 1 (최소 1)이다. 입력된 값은 QSettings에 저장·복원된다. 유효하지 않은 값이 입력된 경우 기본값을 사용한다.
    FR-09-8 [설정] 탭에 배치 크기 (프레임) 입력 필드(QLineEdit)가 있어야 한다. BLF를 멀티프로세싱으로 변환할 때 한 번에 처리할 프레임 수를 지정한다. 기본값은 200,000 프레임이다. 입력된 값은 QSettings에 저장·복원된다. 유효하지 않은 값이 입력된 경우 기본값을 사용한다.

    FR-10. 멀티프로세싱 변환

    ID 요구 조건
    FR-10-1 변환 실행 시 BLF 파일을 배치 크기(FR-09-8) 프레임 단위 청크로 순차 분할하고, ProcessPoolExecutor를 사용하여 각 청크를 병렬로 디코딩·변환한다.
    FR-10-2 병렬 프로세스 수는 FR-09-7에서 설정한 값을 사용한다.
    FR-10-3 각 청크의 변환 결과를 수집하여 신호별로 시간순으로 합산(concatenate)한다. 청크 경계에서 신호 불연속이 발생하지 않도록 타임스탬프 기준으로 정렬하여 합친다.
    FR-10-4 멀티프로세싱 진행 상태는 완료된 청크 수 및 처리된 데이터 크기로 FR-06-4의 형식에 따라 표시한다.
    FR-10-5 멀티프로세싱은 워커 프로세스 간 통신 오버헤드를 최소화하기 위해 각 청크를 독립적으로 직렬화하여 서브프로세스에 전달한다. 서브프로세스에서는 can.io.BLFReadercantools를 사용하지 않고, 이미 파싱된 메시지 바이트를 받아 디코딩만 수행한다.

    3. 비기능 요구 조건

    ID 요구 조건
    NFR-01 BLF 파일 파싱 시 can.io.BLFReadercantools를 사용한다.
    NFR-02 MDF 저장 시 asammdf 라이브러리를 사용한다.
    NFR-03 앱 종료 시 창 크기·위치, 마지막으로 사용한 디렉터리, BLF 파싱 크기 제한 값 등을 QSettings에 저장하고, 다음 실행 시 복원해야 한다.
    NFR-04 대용량 BLF 파일(수백 MB)을 처리할 수 있어야 한다. BLF 스캔 및 변환은 워커 스레드에서 실행되어 UI가 응답 불가 상태가 되지 않아야 한다.
    NFR-05 BLF 파싱 중 알 수 없는 메시지는 건너뛰고 처리를 계속해야 한다 (DBC 미등록 메시지).
    NFR-06 신호 선택 저장 파일은 사람이 읽을 수 있는 JSON 형식이어야 한다.
    NFR-07 UI 문자열은 STRINGS 딕셔너리({ "ko": {...}, "en": {...}, "zh": {...} })로 관리한다. 언어 변경 시 모든 위젯에 대해 retranslate_ui() 메서드를 호출하여 문자열을 갱신한다.
    NFR-08 멀티프로세싱 사용 시 Windows에서 if __name__ == "__main__": 가드와 multiprocessing.freeze_support()를 메인 진입점에 호출하여 서브프로세스 스폰 문제를 방지한다.

    4. UI 레이아웃 (탭 구조)

    공통 헤더: 앱 제목 + 탭 바 (QTabWidget)


    탭 1: 파일 입력

    ┌─────────────────────────────────────────────────────────────────────┐
    │  BLF + DBC → MDF 변환 도구                                           │
    ├───────────┬──────────┬──────────────────┬───────────┬──────────────┤
    │ [파일 입력]│[신호 선택]│ [변환 옵션/실행] │ [미리보기] │  [설정]      │
    ├─────────────────────────────────────────────────────────────────────┤
    │                                                                     │
    │  BLF 파일                                                           │
    │  [경로 표시_____________________________________________]  [선택...] │
    │  크기: 128.4 MB                                                     │
    │                                                                     │
    │  DBC 파일                                                           │
    │  [경로 표시_____________________________________________]  [선택...] │
    │  크기: 24.1 KB                                                      │
    │                                                                     │
    │                        [▶ 파싱]                                     │
    │                                                                     │
    │  상태: BLF 스캔 중... (DBC: 20개 메시지 / BLF 스캔 40%)             │
    │  진행: [████████░░░░░░░░░░░░░░] 40%        [■ 취소]                 │
    │                                                                     │
    ├─────────────────────────────────────────────────────────────────────┤
    │  상태 표시줄                                                         │
    └─────────────────────────────────────────────────────────────────────┘

    탭 2: 신호 선택

    ┌─────────────────────────────────────────────────────────────────────┐
    │  BLF + DBC → MDF 변환 도구                                           │
    ├───────────┬──────────┬──────────────────┬───────────┬──────────────┤
    │ [파일 입력]│[신호 선택]│ [변환 옵션/실행] │ [미리보기] │  [설정]      │
    ├─────────────────────────────────────────────────────────────────────┤
    │ [전체 선택] [전체 해제] [메시지 수준] [신호 수준]  [선택 저장] [선택 로드]  BLF: 12/20 메시지 발견  선택된 신호: 3개 │
    ├──────────────────────────┬────────┬──────────┬──────────────────────┤
    │  메시지 / 신호            │  단위  │  최솟값  │  최댓값              │
    ├──────────────────────────┴────────┴──────────┴──────────────────────┤
    │  ☑ MSG_001 (0x123)   3개 신호                                       │
    │    ├ ☑ WHL_SPD_FL          km/h       0.0        300.0             │
    │    ├ ☑ WHL_SPD_FR          km/h       0.0        300.0             │
    │    └ ☐ WHL_SPD_RL          km/h       0.0        300.0             │
    │  ☑ MSG_002 (0x200)   2개 신호                                       │
    │    ├ ☑ YAW_RATE            deg/s   -300.0        300.0             │
    │    └ ☐ LAT_ACCEL           m/s²     -20.0         20.0             │
    │  ☐ MSG_003 (0x300)   ← 회색 (BLF에 없음)                           │
    │    ├ ☐ SIG_A               -          0.0          1.0             │
    │    └ ☐ SIG_B               -          0.0        255.0             │
    │  ...                                                                │
    │  (QTreeWidget, 화면 전체 높이 활용)                                  │
    ├─────────────────────────────────────────────────────────────────────┤
    │  상태 표시줄                                                         │
    └─────────────────────────────────────────────────────────────────────┘

    탭 3: 변환 옵션 및 실행

    ┌─────────────────────────────────────────────────────────────────────┐
    │  BLF + DBC → MDF 변환 도구                                           │
    ├───────────┬──────────┬──────────────────┬───────────┬──────────────┤
    │ [파일 입력]│[신호 선택]│ [변환 옵션/실행] │ [미리보기] │  [설정]      │
    ├─────────────────────────────────────────────────────────────────────┤
    │  변환 옵션                                                           │
    │  ☑ 리샘플링     주기: [20___] ms                                    │
    │  ☑ 타임스탬프 정규화 (0초 시작)                                      │
    │  MDF 버전: [MDF4 (.mf4)  ▼]                                        │
    │                                                                     │
    │  출력 파일                                                           │
    │  [경로 표시_____________________________________________]  [선택...] │
    │                                                                     │
    │  ─────────────────────────────────────────────────────────────────  │
    │  [▶ 변환 실행]   [■ 취소]                                            │
    │  상태: MDF 저장 중...                                                │
    │  진행: [████████████░░░░░░░░] 60%   BLF 파싱 → NaN 처리 → MDF 저장  │
    │        변환 중... BLF 파싱 (12.3 MB / 45.6 MB, 8 sec)               │
    │                                                                     │
    │  ─────────────────────────────────────────────────────────────────  │
    │  결과 요약                                                           │
    │  신호 수: 3          원본 프레임: 117,853       저장 행 수: 16,837   │
    │  시간 범위: 0.0 ~ 336.7 초                                           │
    │  저장 경로: C:/output/xxx_resampled_20ms.mf4                        │
    │                                                                     │
    ├─────────────────────────────────────────────────────────────────────┤
    │  상태 표시줄                                                         │
    └─────────────────────────────────────────────────────────────────────┘

    탭 4: 미리보기

    ┌─────────────────────────────────────────────────────────────────────┐
    │  BLF + DBC → MDF 변환 도구                                           │
    ├───────────┬──────────┬──────────────────┬───────────┬──────────────┤
    │ [파일 입력]│[신호 선택]│ [변환 옵션/실행] │ [미리보기] │  [설정]      │
    ├──────────────────────────────────────────────┬──────────────────────┤
    │  파일: [경로_______________________________]  │  timestamp (s)  값   │
    │  [MDF 열기]                                   │  0.000000       0.0  │
    │                                               │  0.020000       12.5 │
    │  신호  ☑개별 그래프                            │  0.040000       12.3 │
    │  ┌─────────────────────────────────────────┐  │  ...                 │
    │  │☑ WHL_SPD_FL  ☑ WHL_SPD_FR  ☐ YAW_RATE│  │  (QTableWidget,      │
    │  │☐ LAT_ACCEL  ...                        │  │   2 컬럼,            │
    │  └─────────────────────────────────────────┘  │   선택 신호 기준)    │
    │  (QListWidget, 수평 흐름, 최대 140px 높이)      │                     │
    │                                               │                     │
    │  ┌─────────────────────────────────────────┐  │                     │
    │  │                                         │  │                     │
    │  │        pyqtgraph 차트 영역              │  │                     │
    │  │        (흰 배경, 서브플롯 또는 단일)     │  │                     │
    │  │                                         │  │                     │
    │  └─────────────────────────────────────────┘  │                     │
    │      ← 좌측 패널 (4) →                         │ ← 우측 패널 (1) →  │
    ├──────────────────────────────────────────────┴──────────────────────┤
    │  상태 표시줄                                                         │
    └─────────────────────────────────────────────────────────────────────┘

    탭 5: 설정

    ┌─────────────────────────────────────────────────────────────────────┐
    │  BLF + DBC → MDF 변환 도구                                           │
    ├───────────┬──────────┬──────────────────┬───────────┬──────────────┤
    │ [파일 입력]│[신호 선택]│ [변환 옵션/실행] │ [미리보기] │  [설정]      │
    ├─────────────────────────────────────────────────────────────────────┤
    │                                                                     │
    │  언어 / Language / 语言                                              │
    │  [한국어  ▼]                                                        │
    │   ├ 한국어                                                           │
    │   ├ English                                                         │
    │   └ 中文                                                            │
    │                                                                     │
    │  BLF 파싱 크기   [5___] MB                                          │
    │  (파싱 단계에서 BLF 파일의 앞부분만 읽는 크기. 기본값: 5 MB)          │
    │                                                                     │
    │  병렬 프로세스 수   [7__]                                            │
    │  (멀티프로세싱 변환에 사용할 워커 수. 기본: cpu_count - 1)            │
    │                                                                     │
    │  배치 크기 (프레임)   [200000____]                                   │
    │  (한 번에 처리할 BLF 프레임 수. 기본: 200,000)                       │
    │                                                                     │
    └─────────────────────────────────────────────────────────────────────┘

    5. 의존 라이브러리

    라이브러리 용도 설치
    PySide6 데스크톱 GUI 프레임워크 pip install PySide6
    cantools DBC 파싱 pip install cantools
    python-can BLF 파일 읽기 pip install python-can
    asammdf MDF4 파일 저장/읽기 pip install asammdf
    pandas 데이터 처리 pip install pandas
    numpy 수치 연산 pip install numpy
    pyqtgraph 결과 미리보기 차트 pip install pyqtgraph
    multiprocessing 멀티프로세싱 변환 (Python 표준 라이브러리) 별도 설치 불필요

    6. 미결 사항 (Open Issues)

    ID 내용
    OI-01 복수의 DBC 파일 지원 여부 (멀티 버스 환경)
    OI-02 BLF에 복수의 CAN 채널이 있는 경우 채널 필터링 여부
    OI-03 변환 설정(리샘플링 여부, 주기, 정규화 여부, MDF 버전)도 신호 선택 JSON과 함께 저장/로드할지 여부
    OI-04 변환 완료 후 MDF 파일 다운로드 버튼 제공 여부 (로컬 앱이라면 불필요)

    7. 미결 사항에 대한 결정 

    • 아래는 클로드가 오픈 이슈라고 문의한 것에 대해 내가 답을 한 것이다. 
    • OI-01: MVP 개발 단계에서는 단수 DBC 파일 지원만 고려한다.
    • OI-02: BLF에 복수의 CAN 채널이 있을 경우, 동일 신호명이 여러 채널에 존재하면 신호이름_채널번호 형식으로 구분한다. 단일 채널만 존재하는 경우에는 접미사를 붙이지 않는다.
    • OI-03: JSON 저장 파일에는 선택된 신호 목록만 포함한다. 변환 설정(리샘플링 여부, 주기, 정규화 여부, MDF 버전)은 저장하지 않는다.
    • OI-04: 다운로드 버튼은 필요하지 않다. 로컬 앱으로 개발한다.