126 lines
4.3 KiB
C#
126 lines
4.3 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Runtime.InteropServices;
|
||
using System.Text;
|
||
|
||
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,
|
||
}
|
||
|
||
/// <summary>
|
||
/// DBC 报文解析器(实例类,每个 ZLGCANFD 拥有独立的解析器实例)。
|
||
/// 不同 CAN 卡的作用域各自维护自己的 MsgDatabase,互不干扰。
|
||
/// </summary>
|
||
public class ZLGDBCParser
|
||
{
|
||
/// <summary>
|
||
/// 每个通道的报文数据库缓存,供 ViewModel 直接读取。
|
||
/// 索引 = 通道号 (0 ~ maxChannels-1)。
|
||
/// </summary>
|
||
public List<List<_Msg_>> MsgDatabase { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 最大通道数(与所属 ZLGCANFD 一致)。
|
||
/// </summary>
|
||
public int MaxChannels { get; }
|
||
|
||
public ZLGDBCParser(int maxChannels = 4)
|
||
{
|
||
MaxChannels = maxChannels;
|
||
MsgDatabase = new List<List<_Msg_>>(
|
||
Enumerable.Range(0, maxChannels).Select(_ => new List<_Msg_>())
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析特定通道的 DBC 并自动存入对应的 MsgDatabase 缓存中。
|
||
/// </summary>
|
||
/// <param name="chDbcHandle">ZDBC 句柄</param>
|
||
/// <param name="channel">通道号索引 (0 ~ maxChannels-1)</param>
|
||
public 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_>();
|
||
|
||
if (chDbcHandle == 0 || chDbcHandle == ZDBC.INVALID_DBC_HANDLE)
|
||
return msgList;
|
||
|
||
int msgSize = Marshal.SizeOf(typeof(ZDBC.DBCMessage));
|
||
IntPtr pMsg = Marshal.AllocHGlobal(msgSize);
|
||
|
||
try
|
||
{
|
||
bool hasMessage = ZDBC.ZDBC_GetFirstMessage(chDbcHandle, pMsg);
|
||
|
||
while (hasMessage)
|
||
{
|
||
var zlgMsg = (ZDBC.DBCMessage)Marshal.PtrToStructure(pMsg, typeof(ZDBC.DBCMessage));
|
||
|
||
int nullIndex = Array.IndexOf(zlgMsg.strName, (byte)0);
|
||
|
||
_Msg_ myMsg = new _Msg_
|
||
{
|
||
msg_id = (int)zlgMsg.nID,
|
||
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,
|
||
msg_type = zlgMsg.nExtend == 1 ? (int)Msg_Type.CANFD : (int)Msg_Type.CAN,
|
||
signal_Name = new string[zlgMsg.nSignalCount]
|
||
};
|
||
|
||
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);
|
||
hasMessage = ZDBC.ZDBC_GetNextMessage(chDbcHandle, pMsg);
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
Marshal.FreeHGlobal(pMsg);
|
||
}
|
||
|
||
msgList.Sort((a, b) => a.msg_id.CompareTo(b.msg_id));
|
||
return msgList;
|
||
}
|
||
}
|
||
}
|