DLT_Splitter/Src/DLT_Utilities.cpp

409 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "DLT_Utilities.hpp"
extern "C"
{
#include "stdlib.h"
#include "string.h"
#include "sys/time.h"
}
// 构造函数
DLT_File::DLT_File()
{
// 初始化内容
this->p_file = nullptr;
this->msg_count = 0;
this->payload_max_len = 0;
this->Msg_List_Head = nullptr;
}
// 析构函数
DLT_File::~DLT_File()
{
clear();
}
// 清理请求的存储并恢复初始状态
void DLT_File::clear(void)
{
if (this->p_file != nullptr)
{
fclose(this->p_file);
this->p_file = nullptr;
}
if (this->Msg_List_Head == nullptr)
return;
// 释放分配的空间
while (this->Msg_List_Head != nullptr)
{
DLT_Type::DLT_Msg_Node *p_target = this->Msg_List_Head;
this->Msg_List_Head = this->Msg_List_Head->p_next;
free(p_target->Msg.payload_buffer);
free(p_target);
}
// 初始化内容
this->p_file = nullptr;
this->msg_count = 0;
this->payload_max_len = 0;
this->Msg_List_Head = nullptr;
}
DLT_Type::DLT_Err DLT_File::dlt_file_read_header(DLT_Type::DLT_Msg *Msg)
{
if (Msg == nullptr)
return DLT_Type::DLT_ERROR_NULL_POINTER;
// 存储头
{
// 读取存储头
if (fread(&(Msg->storage_header), sizeof(Msg->storage_header), 1, this->p_file) != 1)
{
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_END_OF_FILE;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
// 检查存储头
if (memcmp(Msg->storage_header.pattern, "DLT\x01", 4))
return DLT_Type::DLT_ERROR_INVALID_HEADER;
}
// 标准头
{
// 读取标准头
if (fread(&(Msg->standard_header), sizeof(Msg->standard_header), 1, this->p_file) != 1)
{
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
// 反向拼接len字段
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
// DLT标准头是大端序与小端序存储的uint16正好相反所以需要反向
{
uint16_t len_swap;
*((uint8_t *)&len_swap) = *(((uint8_t *)&Msg->standard_header.len) + 1);
*(((uint8_t *)&len_swap) + 1) = *((uint8_t *)&Msg->standard_header.len);
Msg->standard_header.len = len_swap;
}
}
// 消息头长度统计
size_t msg_header_len = sizeof(Msg->standard_header);
// 标准头扩展部分
{
// 含有额外的ECU ID
if (Msg->standard_header.htyp.WEID)
{
msg_header_len += sizeof(Msg->standard_header_extra.ecu);
if (fread(&(Msg->standard_header_extra.ecu), sizeof(Msg->standard_header_extra.ecu), 1, this->p_file) != 1)
{
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
}
// 含有额外的 Session ID (会话ID)
if (Msg->standard_header.htyp.WSID)
{
msg_header_len += sizeof(Msg->standard_header_extra.seid);
if (fread(&(Msg->standard_header_extra.seid), sizeof(Msg->standard_header_extra.seid), 1, this->p_file) != 1)
{
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
// 反向拼接Session ID字段
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
{
uint32_t data_swap;
*((uint8_t *)&data_swap) = *(((uint8_t *)&Msg->standard_header_extra.seid) + 3);
*(((uint8_t *)&data_swap) + 1) = *(((uint8_t *)&Msg->standard_header_extra.seid) + 2);
*(((uint8_t *)&data_swap) + 2) = *(((uint8_t *)&Msg->standard_header_extra.seid) + 1);
*(((uint8_t *)&data_swap) + 3) = *((uint8_t *)&Msg->standard_header_extra.seid);
Msg->standard_header_extra.seid = data_swap;
}
}
// 含有额外的 timestamp (0.1ms 自系统启动后的时间计数)
if (Msg->standard_header.htyp.WSID)
{
msg_header_len += sizeof(Msg->standard_header_extra.tmsp);
if (fread(&(Msg->standard_header_extra.tmsp), sizeof(Msg->standard_header_extra.tmsp), 1, this->p_file) != 1)
{
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
// 反向拼接Session ID字段
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
{
uint32_t data_swap;
*((uint8_t *)&data_swap) = *(((uint8_t *)&Msg->standard_header_extra.tmsp) + 3);
*(((uint8_t *)&data_swap) + 1) = *(((uint8_t *)&Msg->standard_header_extra.tmsp) + 2);
*(((uint8_t *)&data_swap) + 2) = *(((uint8_t *)&Msg->standard_header_extra.tmsp) + 1);
*(((uint8_t *)&data_swap) + 3) = *((uint8_t *)&Msg->standard_header_extra.tmsp);
Msg->standard_header_extra.tmsp = data_swap;
}
}
}
// 扩展头读取
if (Msg->standard_header.htyp.UEH)
{
msg_header_len += sizeof(Msg->extendedheader);
// 读取标扩展头
if (fread(&(Msg->extendedheader), sizeof(Msg->extendedheader), 1, this->p_file) != 1)
{
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
}
// 计算Payload长度
Msg->payload_length = Msg->standard_header.len - msg_header_len;
// 统计最长长度
if (Msg->payload_length > this->payload_max_len)
this->payload_max_len = Msg->payload_length;
return DLT_Type::DLT_ERROR_NONE;
}
DLT_Type::DLT_Err DLT_File::dlt_file_read_payload(DLT_Type::DLT_Msg *Msg)
{
if (Msg == nullptr)
return DLT_Type::DLT_ERROR_NULL_POINTER;
// 读取Payload
Msg->payload_buffer = (uint8_t *)malloc(Msg->payload_length);
if (Msg->payload_buffer == nullptr)
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
if (fread(Msg->payload_buffer, Msg->payload_length, 1, this->p_file) != 1)
{
free(Msg->payload_buffer);
Msg->payload_buffer = nullptr;
if (feof(this->p_file))
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
else
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
}
return ::DLT_Type::DLT_ERROR_NONE;
}
DLT_Type::DLT_Err DLT_File::dlt_file_parse(void)
{
DLT_Type::DLT_Msg_Node *p_list_end = nullptr;
DLT_Type::DLT_Err err = DLT_Type::DLT_ERROR_NONE;
while (1)
{
DLT_Type::DLT_Msg Msg;
err = dlt_file_read_header(&Msg);
if (err != DLT_Type::DLT_ERROR_NONE)
{
if (err == DLT_Type::DLT_ERROR_END_OF_FILE)
break;
return err;
}
err = dlt_file_read_payload(&Msg);
if (err != DLT_Type::DLT_ERROR_NONE)
return err;
if (this->Msg_List_Head == nullptr)
{
this->Msg_List_Head = (DLT_Type::DLT_Msg_Node *)malloc(sizeof(DLT_Type::DLT_Msg_Node));
if (this->Msg_List_Head == nullptr)
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
this->Msg_List_Head->p_next = nullptr;
this->Msg_List_Head->Msg = Msg;
p_list_end = Msg_List_Head;
}
else
{
DLT_Type::DLT_Msg_Node *p_target = (DLT_Type::DLT_Msg_Node *)malloc(sizeof(DLT_Type::DLT_Msg_Node));
if (p_target == nullptr)
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
p_target->p_next = nullptr;
p_target->Msg = Msg;
p_list_end->p_next = p_target;
p_list_end = p_target;
}
this->msg_count++;
}
return DLT_Type::DLT_ERROR_NONE;
}
DLT_Type::DLT_Err DLT_File::open(const char *file_name_str)
{
// 打开文件
this->p_file = fopen(file_name_str, "rb");
if (this->p_file == nullptr)
return DLT_Type::DLT_ERROR_FILE_OPEN_FAILED;
// 求解文件
return dlt_file_parse();
}
size_t DLT_File::get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list))
{
if (this->msg_count != 0)
p_msg_list = this->Msg_List_Head;
else
p_msg_list = nullptr;
return this->msg_count;
}
DLT_Type::DLT_Err DLT_File::export_to_csv(const char *file_name_str)
{
FILE *p_file = fopen(file_name_str, "wb");
if (p_file == nullptr)
return DLT_Type::DLT_ERROR_FILE_CREATE_FAILED;
// 打印首行
{
fprintf(p_file, "Index,Date&Time(Local),Timestamp,Count,ECU ID,Application ID,Context ID ,Session ID,Type,Sub Type,Mode,#Args,Payload,");
for (size_t count = 0; count < this->payload_max_len; count++)
fprintf(p_file, "B%d,", count);
fseek(p_file, -1, SEEK_CUR);
fprintf(p_file, "\r\n");
}
// 遍历每行数据
DLT_Type::DLT_Msg_Node *p_msg = this->Msg_List_Head;
for (size_t line_count = 0; line_count < this->msg_count; line_count++)
{
// 输出索引号
fprintf(p_file, "%d,", line_count);
// 输出日期和时间
{
time_t timestamp = (time_t)p_msg->Msg.storage_header.seconds;
struct tm *time_struct = localtime(&timestamp);
char time_str[100] = {'\0'};
// 格式化为 "YY/MM/DD HH:MM:SS"
strftime(time_str, sizeof(time_str), "%Y/%m/%d %H:%M:%S", time_struct);
fprintf(p_file, "%s.%d,", time_str, p_msg->Msg.storage_header.microseconds);
}
// 输出头附加信息
{
// 存在扩展时间戳
if (p_msg->Msg.standard_header.htyp.WTMS)
{
/**< Timestamp since system start in 0.1 milliseconds */
char time_str[20];
sprintf(time_str, "%d", p_msg->Msg.standard_header_extra.tmsp);
char *p_sec_end = time_str + strlen(time_str) - 4;
// 输出秒
for (char *p = time_str; p < p_sec_end; p++)
fputc(*p, p_file);
// 输出剩余的时间
fprintf(p_file, ".%s,", p_sec_end);
}
else
fprintf(p_file, "N/A,");
// 消息计数
fprintf(p_file, "%d,", p_msg->Msg.standard_header.mcnt);
// 存在扩展ECU ID
if (p_msg->Msg.standard_header.htyp.WEID)
fprintf(p_file, "%.4s,", p_msg->Msg.standard_header_extra.ecu);
else
fprintf(p_file, "%.4s,", p_msg->Msg.storage_header.ecu);
// 输出 Apid 和 Ctid
if (p_msg->Msg.standard_header.htyp.UEH)
{
fprintf(p_file, "%.4s,", p_msg->Msg.extendedheader.apid);
fprintf(p_file, "%.4s,", p_msg->Msg.extendedheader.ctid);
}
else
{
// skip apid && ctid
fprintf(p_file, "N/A,N/A,");
}
// 存在 Session ID
if (p_msg->Msg.standard_header.htyp.WSID)
fprintf(p_file, "%d,", p_msg->Msg.standard_header_extra.seid);
else
fprintf(p_file, "N/A,");
// 输出 Type 、Subtype 、Mode 、#Args
if (p_msg->Msg.standard_header.htyp.UEH)
{
const char *Type_str[] = {"log", "trace", "network", "control"};
const char *SubType_Str[][0xF] = {
// LOG
{"fatal", "error", "warn", "info", "debug", "verbose", nullptr},
// Trace
{"variable", "function in", "function out", "state", "vbf", nullptr},
// Network
{"IPC", "CAN", "FlexRay", "Most", "Ethernet", "SOME/IP", "0x7", "0x8", "0x9", "0xA", "0xB", "0xC", "0xD", "0xE", "0xF"},
// Control
{"Request", "response", nullptr},
};
// Type && Subtype
fprintf(p_file, "%s,", Type_str[p_msg->Msg.extendedheader.msin.MSTP]);
fprintf(p_file, "%s,", SubType_Str[p_msg->Msg.extendedheader.msin.MSTP][(p_msg->Msg.extendedheader.msin.MTIN - 1) % 0xF]);
// Mode ** #Args
fprintf(p_file, "%s,", p_msg->Msg.extendedheader.msin.VERB ? "verbose" : "non-verbose");
fprintf(p_file, "%d,", p_msg->Msg.extendedheader.noar);
}
}
// Payload概览行
fprintf(p_file, ",");
// 逐个打印 Payload
for (size_t count = 0; count < p_msg->Msg.payload_length; count++)
fprintf(p_file, "%0X,", p_msg->Msg.payload_buffer[count]);
fseek(p_file, -1, SEEK_CUR);
fprintf(p_file, "\r\n");
p_msg = p_msg->p_next;
}
return DLT_Type::DLT_ERROR_NONE;
}