报文设置扩展
This commit is contained in:
120
ZLGUSBCANFD/ZLGDBCParser.cs
Normal file
120
ZLGUSBCANFD/ZLGDBCParser.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user