374 lines
12 KiB
C++
374 lines
12 KiB
C++
#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->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;
|
||
|
||
DLT_Type::DLT_Msg_Node *p_msg = this->Msg_List_Head;
|
||
|
||
// 打印首行
|
||
{
|
||
fprintf(p_file, "Index,Date,Time,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");
|
||
}
|
||
|
||
// 遍历每行数据
|
||
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(×tamp);
|
||
char time_str[100] = {'\0'};
|
||
// 格式化为 "YY/MM/DD 时区"
|
||
strftime(time_str, sizeof(time_str), "%Y/%m/%d UTC%z", time_struct);
|
||
fprintf(p_file, "%s,", time_str);
|
||
|
||
// 格式化为 "HH:MM:SS"
|
||
strftime(time_str, sizeof(time_str), "%H:%M:%S", time_struct);
|
||
fprintf(p_file, "T-%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);
|
||
|
||
// 存在扩展头
|
||
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);
|
||
|
||
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,");
|
||
}
|
||
}
|
||
|
||
for (size_t count = 0; count < p_msg->Msg.payload_length; count++)
|
||
fprintf(p_file, "%0X,", p_msg->Msg.payload_buffer[count]);
|
||
|
||
p_msg = p_msg->p_next;
|
||
fseek(p_file, -1, SEEK_CUR);
|
||
fprintf(p_file, "\r\n");
|
||
}
|
||
|
||
return DLT_Type::DLT_ERROR_NONE;
|
||
} |