BDU/ZLGCANFD/DBCParse.cs

148 lines
5.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace ZLGCANFD
{
public class ZLG_Msg
{
public int msg_type { get; set; }
public uint msg_id { get; set; }
public double msg_cyclic { get; set; }
public byte msg_dlc { get; set; }
public string msg_name { get; set; }
public List<ZDBC.DBCSignal> signals { get; set; } = new List<ZDBC.DBCSignal>();
public string[] signal_Name { get; set; }
// 适配 ZLG 的 CANFD 帧结构 (来自 2.txt)
public CAN.ZCAN_CANFD_FRAME ACANFD;
}
public class DBCParse
{
// 存储多通道的消息数据库
public static List<List<ZLG_Msg>> MsgDatabase { get; set; } =
Enumerable.Range(0, 12).Select(_ => new List<ZLG_Msg>()).ToList();
/// <summary>
/// ZLG 专用解析逻辑:遍历 ZDBC 内部的消息链表并填充到 MsgDatabase
/// </summary>
/// <param name="hDBC">ZDBC_Init 返回的句柄</param>
/// <param name="channel">目标通道索引</param>
public static void Parse(uint hDBC, int channel)
{
if (hDBC == ZDBC.INVALID_DBC_HANDLE) return;
// 1. 初始化指针空间
int msgSize = Marshal.SizeOf(typeof(ZDBC.DBCMessage));
nint pMsg = Marshal.AllocHGlobal(msgSize);
try
{
// 清空当前通道旧数据
MsgDatabase[channel].Clear();
// 2. 迭代获取所有消息
bool hasMessage = ZDBC.ZDBC_GetFirstMessage(hDBC, pMsg);
while (hasMessage)
{
ZDBC.DBCMessage dbMsg = Marshal.PtrToStructure<ZDBC.DBCMessage>(pMsg);
ZLG_Msg temp = new ZLG_Msg();
temp.msg_id = dbMsg.nID;
temp.msg_name = Encoding.Default.GetString(dbMsg.strName).TrimEnd('\0');
temp.msg_dlc = (byte)dbMsg.nSize;
temp.msg_cyclic = dbMsg.nCycleTime;
temp.msg_type = dbMsg.nExtend; // 0-标准帧, 1-扩展帧
// 3. 处理信号
int sigCount = (int)dbMsg.nSignalCount;
temp.signal_Name = new string[sigCount];
for (int i = 0; i < sigCount; i++)
{
var sig = dbMsg.vSignals[i];
temp.signals.Add(sig);
temp.signal_Name[i] = Encoding.Default.GetString(sig.strName).TrimEnd('\0');
}
// 4. 初始化对应的 ZLG 发送帧结构 (预设好 ID 和 DLC)
temp.ACANFD = new CAN.ZCAN_CANFD_FRAME();
temp.ACANFD.can_id = dbMsg.nID;
temp.ACANFD.len = (byte)dbMsg.nSize;
temp.ACANFD.eff = dbMsg.nExtend;
temp.ACANFD.data = new byte[64];
MsgDatabase[channel].Add(temp);
// 获取下一条
hasMessage = ZDBC.ZDBC_GetNextMessage(hDBC, pMsg);
}
// 按 ID 排序
MsgDatabase[channel].Sort((a, b) => a.msg_id.CompareTo(b.msg_id));
}
finally
{
// 释放内存
Marshal.FreeHGlobal(pMsg);
}
}
/// <summary>
/// 加载 DBC 的入口函数
/// </summary>
public static int LoadDBC(string filePath, int[] channels, out uint databaseID)
{
// 初始化
databaseID = ZDBC.ZDBC_Init(0, 1);
if (databaseID == ZDBC.INVALID_DBC_HANDLE) return -1;
// 准备文件信息
ZDBC.FileInfo fileInfo = new ZDBC.FileInfo();
fileInfo.strFilePath = new byte[ZDBC._MAX_FILE_PATH_ + 1];
byte[] pathBytes = Encoding.Default.GetBytes(filePath);
Array.Copy(pathBytes, fileInfo.strFilePath, Math.Min(pathBytes.Length, ZDBC._MAX_FILE_PATH_));
fileInfo.type = ZDBC.PROTOCOL_OTHER;
fileInfo.merge = 0;
// 加载文件
nint pFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(fileInfo));
Marshal.StructureToPtr(fileInfo, pFileInfo, false);
bool success = ZDBC.ZDBC_LoadFile(databaseID, pFileInfo);
Marshal.FreeHGlobal(pFileInfo);
if (!success)
{
ZDBC.ZDBC_Release(databaseID);
return -2;
}
// 解析到各通道
foreach (var ch in channels)
{
Parse(databaseID, ch);
}
return 0;
}
/// <summary>
/// 卸载 DBC 并释放 ZDBC 句柄
/// </summary>
public static int UnLoadDBC(uint? databaseID = null)
{
if (databaseID.HasValue && databaseID.Value != ZDBC.INVALID_DBC_HANDLE)
{
ZDBC.ZDBC_Release(databaseID.Value);
}
foreach (var list in MsgDatabase)
{
list.Clear();
}
return 0;
}
}
}