Files
ADP/ZLGUSBCANFD/ZLGDBCParser.cs
2026-07-06 10:21:10 +08:00

120 lines
4.7 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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ZLGUSBCANFD
{
public class _Msg_
{
public int msg_type { get; set; }
public int msg_id { get; set; }
public int msg_cyclic { get; set; }
public byte msg_dlc { get; set; }
public string msg_name { get; set; }
public string[] signal_Name { get; set; }
public int msg_brs { get; set; }
}
public enum Msg_Type
{
CAN = 0,
CANFD = 1,
}
public class ZLGDBCParser
{
// 补齐这个属性4个通道的静态报文数据库缓存供 ViewModel 直接读取
public static List<List<_Msg_>> MsgDatabase { get; set; } =
[.. Enumerable.Range(0, 4).Select(_ => new List<_Msg_>())];
/// <summary>
/// 外部调用:解析特定通道的 DBC 并自动存入对应的 MsgDatabase 缓存中
/// </summary>
/// <param name="chDbcHandle">ZDBC句柄</param>
/// <param name="channel">通道号索引 (0-11)</param>
public static void ParseAndLoadToDatabase(uint chDbcHandle, int channel)
{
if (channel < 0 || channel >= MsgDatabase.Count) return;
// 清空当前通道旧缓存
MsgDatabase[channel].Clear();
// 解析并填充
var parsedList = ParseZlgDbc(chDbcHandle);
MsgDatabase[channel].AddRange(parsedList);
}
/// <summary>
/// 全手工解析周立功 DBC 句柄下的所有消息和信号
/// </summary>
/// <param name="chDbcHandle">对应通道的 ZDBC 句柄</param>
/// <returns>返回对齐同星业务层的自定义报文列表</returns>
public static List<_Msg_> ParseZlgDbc(uint chDbcHandle)
{
List<_Msg_> msgList = new List<_Msg_>();
// 显式指定周立功命名空间下的 INVALID_DBC_HANDLE 校验
if (chDbcHandle == 0 || chDbcHandle == ZLGUSBCANFD.ZDBC.INVALID_DBC_HANDLE)
return msgList;
// 显式指定周立功命名空间下的结构体大小
int msgSize = Marshal.SizeOf(typeof(ZLGUSBCANFD.ZDBC.DBCMessage));
IntPtr pMsg = Marshal.AllocHGlobal(msgSize);
try
{
// 1. 获取周立功 DBC 的第一条报文
bool hasMessage = ZLGUSBCANFD.ZDBC.ZDBC_GetFirstMessage(chDbcHandle, pMsg);
while (hasMessage)
{
// 强制指定周立功底层 DBCMessage 结构映射
var zlgMsg = (ZLGUSBCANFD.ZDBC.DBCMessage)Marshal.PtrToStructure(pMsg, typeof(ZLGUSBCANFD.ZDBC.DBCMessage));
// 1. 优先在字节数组中找到第一个 \0 的位置
int nullIndex = Array.IndexOf(zlgMsg.strName, (byte)0);
_Msg_ myMsg = new _Msg_
{
msg_id = (int)zlgMsg.nID,
// 2. 只翻译 \0 之前的有效字节,彻底解决乱码与规避不必要的内存开销
msg_name = nullIndex >= 0
? Encoding.Default.GetString(zlgMsg.strName, 0, nullIndex)
: Encoding.Default.GetString(zlgMsg.strName).TrimEnd('\0'),
msg_dlc = (byte)zlgMsg.nSize,
msg_cyclic = (int)zlgMsg.nCycleTime,
// 如果底层识别出是扩展帧(nExtend==1),这里对齐映射为你的业务类型
msg_type = zlgMsg.nExtend == 1 ? (int)Msg_Type.CANFD : (int)Msg_Type.CAN,
signal_Name = new string[zlgMsg.nSignalCount]
};
// 2. 提取该报文下的所有信号名称
for (int i = 0; i < zlgMsg.nSignalCount; i++)
{
var signal = zlgMsg.vSignals[i];
string sigName = Encoding.Default.GetString(signal.strName).TrimEnd('\0');
myMsg.signal_Name[i] = sigName;
}
msgList.Add(myMsg);
// 3. 移向下一条报文
hasMessage = ZLGUSBCANFD.ZDBC.ZDBC_GetNextMessage(chDbcHandle, pMsg);
}
}
finally
{
// 彻底释放非托管内存,避免上位机高频切换加载 DBC 时导致内存泄漏
Marshal.FreeHGlobal(pMsg);
}
// 按 ID 排序,对齐你的树状展现或者二分查找业务逻辑
msgList.Sort((a, b) => a.msg_id.CompareTo(b.msg_id));
return msgList;
}
}
}