在汽车行业里面,关于通信的话题绝对离不开的公司Vector,他们家的CANoe几乎是每个汽车厂家必备的设备。工程师在调试的时候,用于记录数据的BLF格式,是加密过的,需要用到CANoe才能打开,但是又不通每个人的电脑装个CANoe,毕竟这玩意要软件硬件一起搭配使用。但是Vector公司也提供了解析BLF文件格式的库,那就好办了,自己用他的库写一个转换软件就好了
以下是我自己用QT写的一个小工具。文末有下载地址
开发环境:
VS2022+QT5.14,看你的吧,什么开发环境不是重点,有个界面就行
BLF解析库:下载地址。实在没有积分的,就直接去github下载工程文件吧
在VS配置好环境就行
主要部分:
void KUSBLFTOASC::runConveter()
{
QByteArray dd = m_sBlfName.toLocal8Bit();
LPCSTR pFileName = dd.data();
DWORD dwWritten;
LONG64 sta = 0;
QFile file(m_sAscName);
DWORD *pRead=new DWORD();
*pRead = 1;
{
HANDLE hFile;
VBLObjectHeaderBase base;
VBLCANMessage message;
VBLCANMessage2_t message2;
VBLEnvironmentVariable variable;
VBLEthernetFrame ethframe;
VBLAppText appText;
VBLFileStatisticsEx statistics = { sizeof(statistics) };
BOOL bSuccess;
if (NULL == pRead)
{
emit sigInit(-88);
return;
}
*pRead = 0;
/* open file */
hFile = BLCreateFile(pFileName, GENERIC_READ);
if (INVALID_HANDLE_VALUE == hFile)
{
emit sigInit(-88);
return ;
}
BLGetFileStatisticsEx(hFile, &statistics);
int n = statistics.mObjectCount / 100;
int mn = 0;
emit sigInit(n);
emit sigStatus(0);
bSuccess = TRUE;
bool isok = file.open(QIODevice::WriteOnly);
if (!isok)
{
emit sigInit(-88);
return;
}
QTextStream filestream(&file);
QString data = "date " + Mon.at(statistics.mMeasurementStartTime.wMonth) + " "
+ Week.at(statistics.mMeasurementStartTime.wDayOfWeek)
+ " " + QString::number(statistics.mMeasurementStartTime.wDay)
+ " " + QString::number(statistics.mMeasurementStartTime.wHour)
+ ":" + QString::number(statistics.mMeasurementStartTime.wMinute)
+ ":" + QString::number(statistics.mMeasurementStartTime.wSecond)
+ "." + QString::number(statistics.mMeasurementStartTime.wMilliseconds) + "\nbase hex timestamps absolute\ninternal events logged\n// version N/A\n";
filestream << data;
/* read base object header from file */
while (RunState&&bSuccess && BLPeekObject(hFile, &base))
{
switch (base.mObjectType)
{
case BL_OBJ_TYPE_CAN_MESSAGE:
/* read CAN message */
message2.mHeader.mBase = base;
bSuccess = BLReadObjectSecure(hFile, &message2.mHeader.mBase, sizeof(message2));
/* free memory for the CAN message */
if (bSuccess) {
QString id = QString::number(message2.mID - 0x7FFFFFFF, 16);
QString dir = CAN_MSG_DIR(message2.mFlags) == 0 ? "\tRx" : "\tTx";
QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15")
.arg(QString::number(message2.mHeader.mObjectTimeStamp/1000000000.0,'f',6))
.arg(QString::number(message2.mChannel))
.arg("0x" + QString::number((message2.mID - 0x7FFFFFFF)-1, 16).toUpper())
.arg(dir)
.arg("d")
.arg(QString::number(message2.mDLC))
.arg(QString::number(message2.mData[0],16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[1], 16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[2], 16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[3], 16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[4], 16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[5], 16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[6], 16).toUpper(), 2, QLatin1Char('0'))
.arg(QString::number(message2.mData[7], 16).toUpper(), 2, QLatin1Char('0'))
/*.arg("Length = "+QString::number(message2.mFrameLength))
.arg("BitCount = "+QString::number(message2.mBitCount))*/
.arg("ID = "+QString::number(message2.mID - 0x7FFFFFFF-1)+"x") + "\n";
if (isFilter)
{
if (fifter.size() > 0)
{
for (int i = 0; i < fifter.size(); i++)
{
if (id.toUpper() == fifter.at(i).toUpper())
{
filestream << str;
}
}
}
}
else
{
filestream << str;
}
BLFreeObject(hFile, &message2.mHeader.mBase);
}
break;
case BL_OBJ_TYPE_ENV_INTEGER:
case BL_OBJ_TYPE_ENV_DOUBLE:
case BL_OBJ_TYPE_ENV_STRING:
case BL_OBJ_TYPE_ENV_DATA:
/* read environment variable */
variable.mHeader.mBase = base;
bSuccess = BLReadObjectSecure(hFile, &variable.mHeader.mBase, sizeof(variable));
/* free memory for the environment variable */
if (bSuccess) {
BLFreeObject(hFile, &variable.mHeader.mBase);
}
break;
case BL_OBJ_TYPE_ETHERNET_FRAME:
/* read ethernet frame */
ethframe.mHeader.mBase = base;
bSuccess = BLReadObjectSecure(hFile, ðframe.mHeader.mBase, sizeof(ethframe));
/* free memory for the frame */
if (bSuccess) {
BLFreeObject(hFile, ðframe.mHeader.mBase);
}
break;
case BL_OBJ_TYPE_APP_TEXT:
/* read text */
appText.mHeader.mBase = base;
bSuccess = BLReadObjectSecure(hFile, &appText.mHeader.mBase, sizeof(appText));
if (NULL != appText.mText)
{
printf("%s\n", appText.mText);
}
/* free memory for the text */
if (bSuccess) {
BLFreeObject(hFile, &appText.mHeader.mBase);
}
break;
default:
/* skip all other objects */
bSuccess = BLSkipObject(hFile, &base);
break;
}
if (bSuccess)
{
*pRead += 1;
}
++sta;
if(sta%100==0 || (sta/100)>= n)
emit sigStatus(++mn);
if (!RunState)
{
filestream.flush();
file.close();
return;
}
}
filestream.flush();
file.close();
emit sigStatus(n);
emit sigInit(-99);
/* close file */
if (!BLCloseHandle(hFile))
{
return ;
}
}
}
代码没几行,自己看应该能看懂
附上Github工程地址:https://github.com/BiggerBinBin/KUS-BLFTOASC
或者直接程序下载使用:https://github.com/BiggerBinBin/KUS-BLFTOASC/releases/download/V1.0/KUS-BLFTOASC_V1.0.exe