You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
seuuung a62cebd17f Convert DCT_test from submodule to regular folder 2 months ago
..
DCT_test Convert DCT_test from submodule to regular folder 2 months ago
DCT_test.slnx Convert DCT_test from submodule to regular folder 2 months ago
README.md Convert DCT_test from submodule to regular folder 2 months ago
Run_DCT_test.bat Convert DCT_test from submodule to regular folder 2 months ago
build_csharp.bat Convert DCT_test from submodule to regular folder 2 months ago

README.md

DCT 테스트 서버 프로그램 구조 및 실차 로그 파일(log.txt) 연동 가이드

본 문서는 안드로이드 태블릿용 DCT 캘리브레이션 및 진단 계측 앱의 통신 테스트를 위해 제작된 C# WPF 기반 DCT 테스트 서버(DCT_test.exe)의 전체 소프트웨어 아키텍처와, 실제 차량 및 제어기에서 수집된 대규모 실차 계측 데이터(log.txt)를 프로그램과 연결하기 위한 코드 작성 가이드를 기술합니다.


목차

  1. 프로그램 개요 및 실행 방법
  2. 테스트 프로그램 전체 아키텍처 및 모듈 구조
  3. 핵심 소스코드 파일 및 역할 명세
  4. 전송 패킷 바이너리 프로토콜 명세
  5. log.txt 실차 대용량 데이터 연동 메커니즘
  6. 실차 로그 파서 코드 작성 가이드 및 C# 템플릿
  7. 수동 검증 절차 및 시나리오

1. 프로그램 개요 및 실행 방법

1.1 프로그램 목적

  • 실제 차량이나 전용 하드웨어 인터페이스 장비 없이도 안드로이드 태블릿 앱이 Wi-Fi TCP(포트 6000)를 통해 실시간 계측 신호를 수신하고, UDP 비콘(포트 6005)을 통해 PC 서버를 자동 탐색(Discovery)할 수 있도록 지원하는 테스트 도구입니다.
  • 기본 탑재된 실제 차량 주행 거동 물리 시뮬레이션(가속, 감속, 회생제동, 공조 AUTO 연동)뿐만 아니라, 실제 차량 시험에서 획득한 대용량 실차 데이터(log.txt)를 읽어 실시간으로 단말에 재전송(Replay)하는 기능을 제공합니다.

1.2 실행 방법

  • dct_test 폴더 또는 최상위 경로의 Run_DCT_test.bat 배치 파일을 실행합니다.
  • 기본 동작 사양:
    • 전송 주기: 30 Hz (33ms, 최적) - 안드로이드 앱의 30Hz 배치 렌더러와 1:1 동기화
    • 기본 프로필: 1. [MDB + CAN] MDB 실차공조 및 CAN DBC 동시 스트리밍
    • 재생 모드: 실차 거동 모의 (Simulation) 기본 선택

2. 테스트 프로그램 전체 아키텍처 및 모듈 구조

테스트 프로그램은 계층형 아키텍처(Layered Architecture)로 설계되어 있으며, 고속 통신 패킷 브로드캐스트 스레드와 WPF UI 렌더링 스레드가 완전히 분리되어 송신 지터(Jitter)를 0ms 수준으로 제어합니다.

graph TD
    subgraph PresentationLayer ["WPF UI 계층"]
        UI["MainWindow.xaml / MainWindow.xaml.cs"]
        Grid["송신 신호 모니터링 테이블 (GridTxSignals)"]
        Log["실시간 패킷 모니터링 콘솔 (TextLogConsole)"]
        Ctrl["재생 제어부 (재생 / 일시정지 / 정지 / 주기 / 배속)"]
    end

    subgraph DataSourceLayer ["데이터 소스 계층"]
        SimEngine["실제 차량 주행 물리 시뮬레이터 (관성 가감속/회생제동/수온/DATC)"]
        LogReader["로그 파일 파서 (LogFileReader.cs)"]
        LogFile["실제 차량 주행/수신 로그 파일 (log.txt)"]
        LogFile --> LogReader
    end

    subgraph ProtocolLayer ["바이너리 프로토콜 계층"]
        Packet["DctPacket.cs / DctPacketType.cs"]
        Framing["헤더(0xA1) + 커맨드 + 시퀀스 + 길이 + 페이로드 + 체크섬 + 푸터(0x7E)"]
        Packet --> Framing
    end

    subgraph NetworkLayer ["소켓 통신 계층"]
        Server["DctServer.cs"]
        TcpServer["TCP Server (포트 6000) - 다중 클라이언트 관리 및 브로드캐스트"]
        UdpBeacon["UDP Beacon (포트 6005) - LAN 단말 자동 검색용 DCT_BEACON 송출"]
        Server --> TcpServer
        Server --> UdpBeacon
    end

    subgraph TargetClient ["외부 수신 단말"]
        Android["안드로이드 태블릿 앱 (DCT App)"]
    end

    SimEngine -->|시뮬레이션 모드| Packet
    LogReader -->|파일 리플레이 모드| Packet
    Packet --> Server
    TcpServer -->|TCP 패킷 스트리밍| Android
    UdpBeacon -.->|LAN 비콘 디스커버리| Android
    Server -->|100ms 비동기 분리| UI

3. 핵심 소스코드 파일 및 역할 명세

파일 경로 주요 역할 및 상세 기능
dct_test/DCT_test/MainWindow.xaml WPF UI 레이아웃 정의 (서버 제어 패널, 데이터 소스 라디오 버튼, 파일 드롭존, 재생 제어부, 송신 신호 그리드, 실시간 로그 콘솔)
dct_test/DCT_test/MainWindow.xaml.cs UI 이벤트 처리 및 전송 타이머 제어
• TelemetryStreamWorker: 고해상도 Stopwatch 기반 정밀 틱 타이머(30Hz) 및 100ms 주기 비동기 UI 분리 루프
• LoadLogFile: 드래그 앤 드롭 파일 수신 및 LogFileReader 결과 적재
dct_test/DCT_test/LogFileReader.cs 실제 차량 계측 로그 파일(log.txt)을 읽어 DctPacket 바이너리 패킷으로 변환하는 전담 파서
사용자가 보유한 실차 데이터 포맷에 맞추어 직접 파싱 코드를 작성할 수 있는 핵심 확장 지점
dct_test/DCT_test/DctServer.cs 비동기 TCP 6000 포트 소켓 서버 (태블릿 연결 세션 유지 및 패킷 브로드캐스트), Keep-Alive ACK(0x80) 자동 응답, UDP 6005 비콘 브로드캐스터
dct_test/DCT_test/DctPacket.cs PC 레거시 및 안드로이드 태블릿 앱 규격과 100% 호환되는 바이너리 프레임 인코딩/디코딩, 8비트 Inverted Sum 체크섬 계산, 원시 바이트 스트림 파서(ParseStream) 내장

4. 전송 패킷 바이너리 프로토콜 명세

LogFileReader에서 log.txt를 읽어 생성해야 하는 표준 DctPacket의 세부 바이트 구조입니다.

4.1 패킷 프레임 공통 구조 (7 바이트 오버헤드)

[0xA1] [Command: 1B] [Seq: 2B (Little-Endian)] [Length: 2B (Little-Endian)] [Payload: N Bytes] [Checksum: 1B] [0x7E]
  • 시작 바이트: 0xA1
  • 종료 바이트: 0x7E
  • Checksum 계산 공식: (byte)((~sum) & 0xFF) (헤더 0xA1부터 페이로드 마지막 바이트까지의 단순 누적합에 대한 1의 보수)

4.2 MDB 스트림 패킷 (Command = 0xA3, Type = 0x01)

  • 페이로드 공통 접두사: [Type = 0x01] [ReclID = 160 또는 161]
  • Record 161 (DATC 공조 계측 신호: 총 41개 신호 = 페이로드 70 바이트):
    • Offset + 0: AutoFlag (1 바이트, 1=AUTO, 0=MANUAL)
    • Offset + 1: SpecSel (1 바이트)
    • Offset + 2: AutoBlrStep (1 바이트, 1~8단)
    • Offset + 3: DrTempSet (1 바이트, 값 / 0.5f, 예: 22.0도 -> 44)
    • Offset + 4: PsTempSet (1 바이트, 값 / 0.5f)
    • Offset + 5: BlrwLevel (1 바이트, 1~8단)
    • Offset + 6: BlrwVolt (1 바이트, 값 / 0.1f)
    • Offset + 7..8: Incar_Snr (2 바이트 signed short Little-Endian, 값 * 10, 예: 23.5도 -> 235)
    • Offset + 9..10: Incar_Flt (2 바이트 signed short)
    • Offset + 11..12: TIN (2 바이트 signed short)
    • Offset + 13..14: Amb_Snr (2 바이트 signed short, 값 * 10)
    • Offset + 15..16: Amb_Flt (2 바이트 signed short)
    • Offset + 17..18: Evap_Snr (2 바이트 signed short, 값 * 10)
    • Offset + 19..20: Evap_Flt (2 바이트 signed short)
  • Record 160 (차속, 수온, 습도 등 차체/엔진 신호: 총 29개 신호 = 페이로드 32 바이트):
    • Offset + 21: Humidity (1 바이트, 0~100%)
    • Offset + 25: Speed (1 바이트 unsigned char, 0~255 KPH)
    • Offset + 26: Water (1 바이트, (수온도 + 48.0f) / 0.75f)

4.3 CAN DBC 스트림 패킷 (Command = 0xA3, Type = 0x02)

  • CAN ID 548 (ALDC_01_100ms, DLC 32 바이트):
    • 페이로드 헤더 (7 바이트): [Type: 0x02] [CurPage: 0x01] [TotPage: 0x01] [FrameCount: 0x01] [ID_Low: 0x24] [ID_High: 0x02] [DLC: 32]
    • CAN Data Byte 15: ALDC_LSCmdVoltVal (1 바이트, 값 / 0.1f)
    • CAN Data Byte 17..18: ALDC_HSActVoltVal (2 바이트 signed short, 값 / 0.1f)
    • CAN Data Byte 28~29 (Bit 226, 8 bits): ALDC_VBVoltVal (배터리 전압, 값 / 0.1f)

4.4 A2L XCP DAQ 스트림 패킷 (Command = 0xD0)

  • 페이로드: XCP DAQ ODT 버퍼 (실제 설정된 DAQ 리스트에 따른 바이너리 바이트열)

5. log.txt 실차 대용량 데이터 연동 메커니즘

5.1 실차 데이터 특성 이해

실차 시험 계측 로그(log.txt)는 단순 몇 개의 신호만 추출된 파일이 아닙니다. 실제 환경에서는 다음 두 가지 형태 중 하나로 수집됩니다:

  1. 원시 통신 패킷 스트림 로그 (Raw Captured Packet Log):
    • 실제 ECU나 통신 모듈(CAN, MDB, XCP)로부터 수신된 원시 바이너리 프레임(0xA1 ... 0x7E)이 헥사 텍스트(Hex Dump) 또는 바이너리로 연속 기록된 형태.
    • 단일 파일 내에 Record 160(29개 신호), Record 161(41개 신호), CAN DBC(수십 개 신호), XCP DAQ 등 수백 개의 실차 파라미터가 프레임 단위로 온전히 포함되어 있습니다.
  2. 다채널 시계열 계측 로그 (Multi-Channel Time-Series CSV/TXT Log):
    • 시험 장비에서 수십 개에서 수백 개의 센서 신호(열, Columns)가 타임스탬프와 함께 나열된 텍스트 형태.
    • 예: Time, Incar_Snr, Amb_Snr, Evap_Snr, Speed, Water, RPM, Throttle, BlrwLevel, VBatt, DrTempSet, ... (수십~수백 개 신호)

5.2 프로그램과 연결되는 전체 데이터 파이프라인

프로그램 내부에서 로그 파일이 안드로이드 태블릿 앱까지 전달되는 흐름은 다음과 같습니다:

sequenceDiagram
    autonumber
    participant User as "사용자"
    participant UI as "MainWindow (WPF)"
    participant Reader as "LogFileReader.cs"
    participant Worker as "TelemetryStreamWorker"
    participant Server as "DctServer (TCP 6000)"
    participant App as "안드로이드 태블릿 앱"

    User->>UI: 1. log.txt 파일을 UI 드롭존에 드래그 앤 드롭 (또는 파일 찾아보기)
    UI->>Reader: 2. LoadLogFile(filePath) 호출 -> _fileReader.Load(filePath)
    Note over Reader: 3. log.txt 파싱 및 데이터 변환 (DctPacket 생성 및 신호 메타데이터 등록)
    Reader-->>UI: 4. LogFileReadResult 반환 (Packets 리스트, InitialSignalItems 목록)
    UI->>UI: 5. _loadedLogRecords 리스트에 패킷 적재 및 좌측 신호 테이블 갱신
    User->>UI: 6. 데이터 소스를 [실차 로그 파일 리플레이]로 선택 후 [재생] 클릭
    UI->>Worker: 7. TelemetryStreamWorker 가동 (설정된 전송 주기, 기본 30Hz)
    loop 파일 패킷 브로드캐스트
        Worker->>Server: 8. _server.BroadcastPacket(_loadedLogRecords[idx++])
        Server->>App: 9. TCP 6000 소켓을 통해 태블릿으로 바이너리 패킷 송출
        App->>App: 10. 태블릿 차트 및 수치 그리드에 실차 전체 신호 렌더링
    end

6. 실차 로그 파서 코드 작성 가이드 및 C# 템플릿

사용자가 보유한 log.txt의 형식에 맞추어 dct_test/DCT_test/LogFileReader.cs 파일에 구현할 수 있는 두 가지 대표적인 완성형 코드 템플릿입니다.

6.1 케이스 A: 수신된 원시 패킷 Hex 로그 파싱 템플릿

실제 수신된 프레임이 헥사 텍스트(예: A1 00 46 A3 01 A1 ... 7E) 형태로 기록된 로그 파일을 처리하는 경우입니다. DctPacket.ParseStream을 활용하면 수백 개의 신호가 포함된 원시 프레임이 바이트 손실 없이 그대로 복원됩니다.

using System;
using System.Collections.Generic;
using System.IO;

namespace DCT_test
{
    public class LogFileReader
    {
        public LogFileReadResult Load(string filePath)
        {
            var result = new LogFileReadResult
            {
                FileName = Path.GetFileName(filePath)
            };

            if (!File.Exists(filePath))
            {
                result.ErrorMessage = $"파일이 존재하지 않습니다: {filePath}";
                return result;
            }

            try
            {
                result.FileSizeMb = new FileInfo(filePath).Length / (1024.0 * 1024.0);

                var byteBuffer = new List<byte>();

                // 1. log.txt로부터 Hex 텍스트 라인을 읽어 바이트 버퍼 구성
                using (var reader = new StreamReader(filePath))
                {
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        line = line.Trim();
                        if (string.IsNullOrEmpty(line) || line.StartsWith("#")) continue;

                        // 공백, 쉼표, 콜론 등으로 분리된 Hex 바이트 문자열 파싱
                        string[] hexTokens = line.Split(new[] { ' ', ',', '\t', '-' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var token in hexTokens)
                        {
                            if (byte.TryParse(token, System.Globalization.NumberStyles.HexNumber, null, out byte b))
                            {
                                byteBuffer.Add(b);
                            }
                        }
                    }
                }

                // 2. DctPacket.ParseStream을 호출하여 전체 원시 패킷(MDB 160/161, CAN, XCP 등) 자동 추출
                result.Packets = DctPacket.ParseStream(byteBuffer);

                // 3. UI 신호 목록에 표시할 정보 구성
                result.InitialSignalItems.Add(new TxSignalItem { Source = "[FILE]", Name = "Total Frames", Value = $"{result.Packets.Count}", Unit = "pkts" });
                result.InitialSignalItems.Add(new TxSignalItem { Source = "[FILE]", Name = "Raw Bytes", Value = $"{byteBuffer.Count}", Unit = "bytes" });

                result.Success = result.Packets.Count > 0;
                if (!result.Success)
                {
                    result.ErrorMessage = "유효한 DCT 패킷(0xA1...0x7E)을 찾을 수 없습니다.";
                }
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.ErrorMessage = $"파일 파싱 오류: {ex.Message}";
            }

            return result;
        }
    }
}

6.2 케이스 B: 수십~수백 개 신호가 포함된 다채널 텍스트/CSV 로그 파싱 템플릿

타임스탬프와 함께 수십 개의 센서 및 제어 파라미터가 기록된 실차 주행 로그를 MDB 161(공조 41종) 및 MDB 160(주행 29종), CAN DBC 프레임으로 동적 매핑하여 전송하는 구조입니다.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

namespace DCT_test
{
    public class LogFileReader
    {
        public LogFileReadResult Load(string filePath)
        {
            var result = new LogFileReadResult
            {
                FileName = Path.GetFileName(filePath)
            };

            if (!File.Exists(filePath))
            {
                result.ErrorMessage = $"파일이 존재하지 않습니다: {filePath}";
                return result;
            }

            try
            {
                result.FileSizeMb = new FileInfo(filePath).Length / (1024.0 * 1024.0);

                using (var reader = new StreamReader(filePath))
                {
                    // 1. 헤더 행을 읽어 수십~수백 개의 전체 신호 열(Column) 인덱스 매핑 구성
                    string headerLine = reader.ReadLine();
                    if (string.IsNullOrEmpty(headerLine))
                    {
                        result.ErrorMessage = "파일 헤더가 비어 있습니다.";
                        return result;
                    }

                    string[] headers = headerLine.Split(new[] { ',', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    var colMap = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
                    for (int i = 0; i < headers.Length; i++)
                    {
                        colMap[headers[i].Trim()] = i;
                    }

                    // 2. UI '송신 중인 신호 목록'에 파일에 포함된 주요 신호들을 동적으로 등록
                    foreach (var h in headers)
                    {
                        result.InitialSignalItems.Add(new TxSignalItem
                        {
                            Source = "[FILE]",
                            Name = h.Trim(),
                            Value = "0.0",
                            Unit = ""
                        });
                    }

                    // 헬퍼 함수: 특정 신호 열이 존재하면 파싱, 없으면 기본값 반환
                    float GetVal(string[] tokens, string sigName, float defVal = 0.0f)
                    {
                        if (colMap.TryGetValue(sigName, out int idx) && idx < tokens.Length)
                        {
                            if (float.TryParse(tokens[idx], NumberStyles.Float, CultureInfo.InvariantCulture, out float v))
                                return v;
                        }
                        return defVal;
                    }

                    // 3. 데이터 행을 순차적으로 읽어 MDB / CAN 바이너리 패킷 조립
                    string line;
                    ushort seq = 0;

                    while ((line = reader.ReadLine()) != null)
                    {
                        line = line.Trim();
                        if (string.IsNullOrEmpty(line) || line.StartsWith("#")) continue;

                        string[] tokens = line.Split(new[] { ',', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (tokens.Length < 2) continue;

                        // A. 실차 MDB Record 161 (DATC 공조 41종 신호 패킹: 70 바이트)
                        byte[] mdb161 = new byte[2 + 68];
                        mdb161[0] = 0x01; // Type: MDB
                        mdb161[1] = 161;  // ReclID: 161
                        int off161 = 2;

                        byte autoFlag = (byte)GetVal(tokens, "AutoFlag", 1.0f);
                        byte blowerLevel = (byte)GetVal(tokens, "BlrwLevel", 4.0f);
                        float drTempSet = GetVal(tokens, "DrTempSet", 22.0f);
                        float psTempSet = GetVal(tokens, "PsTempSet", 22.0f);
                        float blowerVolt = GetVal(tokens, "BlrwVolt", 12.8f);

                        mdb161[off161 + 0] = autoFlag;
                        mdb161[off161 + 2] = blowerLevel;
                        mdb161[off161 + 3] = (byte)Math.Round(drTempSet / 0.5f);
                        mdb161[off161 + 4] = (byte)Math.Round(psTempSet / 0.5f);
                        mdb161[off161 + 5] = blowerLevel;
                        mdb161[off161 + 6] = (byte)Math.Round(blowerVolt / 0.1f);

                        // 온도 신호들 (0.1도 스케일링 short)
                        short incarRaw = (short)Math.Round(GetVal(tokens, "Incar_Snr", 23.0f) * 10.0f);
                        short ambRaw = (short)Math.Round(GetVal(tokens, "Amb_Snr", 30.0f) * 10.0f);
                        short evapRaw = (short)Math.Round(GetVal(tokens, "Evap_Snr", 4.5f) * 10.0f);

                        mdb161[off161 + 7] = (byte)(incarRaw & 0xFF); mdb161[off161 + 8] = (byte)((incarRaw >> 8) & 0xFF);
                        mdb161[off161 + 9] = (byte)(incarRaw & 0xFF); mdb161[off161 + 10] = (byte)((incarRaw >> 8) & 0xFF);
                        mdb161[off161 + 11] = (byte)(incarRaw & 0xFF); mdb161[off161 + 12] = (byte)((incarRaw >> 8) & 0xFF);
                        mdb161[off161 + 13] = (byte)(ambRaw & 0xFF); mdb161[off161 + 14] = (byte)((ambRaw >> 8) & 0xFF);
                        mdb161[off161 + 15] = (byte)(ambRaw & 0xFF); mdb161[off161 + 16] = (byte)((ambRaw >> 8) & 0xFF);
                        mdb161[off161 + 17] = (byte)(evapRaw & 0xFF); mdb161[off161 + 18] = (byte)((evapRaw >> 8) & 0xFF);
                        mdb161[off161 + 19] = (byte)(evapRaw & 0xFF); mdb161[off161 + 20] = (byte)((evapRaw >> 8) & 0xFF);

                        result.Packets.Add(DctPacket.Create(0xA3, mdb161, seq));

                        // B. 실차 MDB Record 160 (차속, 수온, 습도 패킹: 32 바이트)
                        byte[] mdb160 = new byte[2 + 30];
                        mdb160[0] = 0x01;
                        mdb160[1] = 160;
                        int off160 = 2;

                        float speed = GetVal(tokens, "Speed", 0.0f);
                        float water = GetVal(tokens, "Water", 85.0f);
                        float humidity = GetVal(tokens, "Humidity", 50.0f);

                        mdb160[off160 + 21] = (byte)Math.Max(0, Math.Min(100, (int)Math.Round(humidity)));
                        mdb160[off160 + 25] = (byte)Math.Max(0, Math.Min(255, (int)Math.Round(speed)));
                        mdb160[off160 + 26] = (byte)Math.Max(0, Math.Min(255, (int)Math.Round((water + 48.0f) / 0.75f)));

                        result.Packets.Add(DctPacket.Create(0xA3, mdb160, seq));

                        // C. 실차 CAN DBC ALDC_01_100ms 패킷 (배터리 전압 및 지령 전압 패킹: 39 바이트)
                        byte[] canData = new byte[32];
                        float lsVolt = GetVal(tokens, "ALDC_LSCmdVoltVal", 13.5f);
                        float vBatt = GetVal(tokens, "ALDC_VBVoltVal", 13.8f);

                        canData[15] = (byte)Math.Round(lsVolt / 0.1f);
                        uint vbRaw = (uint)Math.Round(vBatt / 0.1f);
                        canData[28] = (byte)(((uint)canData[28] & 0x03u) | (((uint)vbRaw & 0x3Fu) << 2));
                        canData[29] = (byte)(((uint)canData[29] & 0xFCu) | (((uint)vbRaw >> 6) & 0x03u));

                        byte[] canPayload = new byte[4 + 3 + 32];
                        canPayload[0] = 0x02; canPayload[1] = 0x01; canPayload[2] = 0x01; canPayload[3] = 0x01;
                        canPayload[4] = 0x24; canPayload[5] = 0x02; canPayload[6] = 32;
                        Array.Copy(canData, 0, canPayload, 7, 32);

                        result.Packets.Add(DctPacket.Create(0xA3, canPayload, seq));

                        seq++;
                    }
                }

                result.Success = result.Packets.Count > 0;
                if (!result.Success)
                {
                    result.ErrorMessage = "파싱된 패킷 레코드가 0개입니다. 파일 데이터 구조를 확인하세요.";
                }
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.ErrorMessage = $"파일 파싱 오류: {ex.Message}";
            }

            return result;
        }
    }
}

7. 수동 검증 절차 및 시나리오

  1. 파일 로드 및 메타데이터 인식 확인:
    • Run_DCT_test.bat를 실행합니다.
    • 상단 2. 데이터 소스 모드 선택에서 실차 로그 파일 리플레이 (File Replay) 라디오 버튼을 선택합니다.
    • 준비한 실차 대용량 log.txt 파일을 드롭존 영역에 드래그 앤 드롭하거나 [파일 찾아보기] 버튼으로 지정합니다.
    • 현재 로드된 파일: [log.txt] (N 레코드, M MB) 텍스트가 표시되고 좌측 테이블에 파일 신호 목록이 갱신되는지 확인합니다.
  2. 서버 시작 및 패킷 스트리밍:
    • [서버 시작] 버튼을 클릭하여 TCP 6000 포트 수신 대기 상태로 전환합니다.
    • [재생] 버튼을 클릭합니다.
    • 우측 로그 콘솔에 [TX (FILE)] 로그가 순차적으로 출력되며 좌측 수치 테이블의 값들이 실제 주행 데이터 흐름에 맞게 갱신되는지 확인합니다.
  3. 태블릿 앱 연동 및 다채널 데이터 렌더링 검증:
    • 안드로이드 태블릿 앱을 실행하여 PC의 IP로 접속합니다.
    • 차트 화면에서 Incar_Snr, Speed, ALDC_VBVoltVal, BlrwLevel 등 여러 신호를 등록합니다.
    • log.txt에 기록된 실제 주행 거동(도심 주행 가감속, 회생제동 전압, 공조 냉각 등)이 왜곡 없이 태블릿 화면에 실시간으로 재생되는지 확인합니다.