feat: ZLGCANFD新增获取报文信号值函数(最新解码报文缓存+按通道/帧ID/信号名查询,失败报错返回0)

This commit is contained in:
2026-09-14 14:36:05 +08:00
parent 3d30d33f7b
commit b1a160d159
+80
View File
@@ -40,6 +40,10 @@ namespace ZLGUSBCANFD
// 每次 设置报文 会累积写入此表,发送时以 DBC 初始值为底再叠加此表覆盖值 // 每次 设置报文 会累积写入此表,发送时以 DBC 初始值为底再叠加此表覆盖值
private readonly ConcurrentDictionary<(uint , uint ID), Dictionary<string, double>> _signalOverrides = new ConcurrentDictionary<(uint, uint), Dictionary<string, double>>(); private readonly ConcurrentDictionary<(uint , uint ID), Dictionary<string, double>> _signalOverrides = new ConcurrentDictionary<(uint, uint), Dictionary<string, double>>();
// 最新解码报文缓存:Key = (通道号, 帧ID)Value = 最近一次 DBC 解码成功的报文快照(含各信号原始值)
// 接收线程解码成功时写入,供 获取报文信号值 主动查询最新信号物理值
private readonly ConcurrentDictionary<(uint , uint ID), ZDBC.DBCMessage> _latestDecodedMessages = new ConcurrentDictionary<(uint, uint), ZDBC.DBCMessage>();
// 动态硬件参数 // 动态硬件参数
private readonly uint _deviceType; // 76: USBCANFD-400U private readonly uint _deviceType; // 76: USBCANFD-400U
private readonly uint _deviceIndex; // 设备索引 private readonly uint _deviceIndex; // 设备索引
@@ -300,6 +304,13 @@ namespace ZLGUSBCANFD
_dbcHandles[] = 0; _dbcHandles[] = 0;
_isDbcLoadedArray[] = false; _isDbcLoadedArray[] = false;
DBCParser.MsgDatabase[(int)].Clear(); DBCParser.MsgDatabase[(int)].Clear();
// 同步清理该通道的最新解码报文缓存,避免残留旧信号值
foreach (var key in _latestDecodedMessages.Keys)
{
if (key. == )
_latestDecodedMessages.TryRemove(key, out _);
}
} }
} }
} }
@@ -344,6 +355,8 @@ namespace ZLGUSBCANFD
if (_isDbcLoadedArray[channelIndex] && ZDBC.ZDBC_Decode(_dbcHandles[channelIndex], ptrDbcMsg, framePtr, 1, 0)) if (_isDbcLoadedArray[channelIndex] && ZDBC.ZDBC_Decode(_dbcHandles[channelIndex], ptrDbcMsg, framePtr, 1, 0))
{ {
var msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrDbcMsg, typeof(ZDBC.DBCMessage)); var msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrDbcMsg, typeof(ZDBC.DBCMessage));
// 缓存最新解码报文快照,供 获取报文信号值 查询
_latestDecodedMessages[(channelIndex, msg.nID)] = msg;
OnDbcMessageDecoded?.Invoke(channelIndex, msg); OnDbcMessageDecoded?.Invoke(channelIndex, msg);
} }
} }
@@ -369,6 +382,8 @@ namespace ZLGUSBCANFD
if (_isDbcLoadedArray[channelIndex] && ZDBC.ZDBC_Decode(_dbcHandles[channelIndex], ptrDbcMsg, framePtr, 1, 1)) if (_isDbcLoadedArray[channelIndex] && ZDBC.ZDBC_Decode(_dbcHandles[channelIndex], ptrDbcMsg, framePtr, 1, 1))
{ {
var msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrDbcMsg, typeof(ZDBC.DBCMessage)); var msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrDbcMsg, typeof(ZDBC.DBCMessage));
// 缓存最新解码报文快照,供 获取报文信号值 查询
_latestDecodedMessages[(channelIndex, msg.nID)] = msg;
OnDbcMessageDecoded?.Invoke(channelIndex, msg); OnDbcMessageDecoded?.Invoke(channelIndex, msg);
} }
} }
@@ -1023,6 +1038,71 @@ namespace ZLGUSBCANFD
#endregion #endregion
#region 4.2
/// <summary>
/// 获取指定通道最新一帧 DBC 报文中某个信号的物理值(帧 ID 支持 string 兼容模式)。
/// <para>
/// 返回值为最近一次接收并解码成功的报文快照:物理值 = 原始值 × 因子 + 偏移,
/// 与监控界面广播的数值口径一致。若报文尚未收到、DBC 未加载、报文或信号名称不存在,
/// 将记录错误日志并返回 0。
/// </para>
/// </summary>
/// <param name="通道号">CAN/CANFD 通道索引</param>
/// <param name="帧IDStr">对应报文的帧 ID(可以是 "26"、"0x1A"、"1A"</param>
/// <param name="信号名称">DBC 中定义的英文信号名称(不区分大小写)</param>
/// <returns>信号物理值;失败时返回 0</returns>
public virtual double (uint , string IDStr, string )
{
if (!TryParseFrameId(IDStr, out uint ID))
{
LoggerHelper.Error($"[ZLGCANFD] 获取报文信号值失败: 无法解析的帧 ID '{帧IDStr}'");
return 0;
}
if ( >= _maxChannels)
{
LoggerHelper.Error($"[ZLGCANFD] 获取报文信号值失败: 通道号 {通道号} 越界(有效范围 0~{_maxChannels - 1}");
return 0;
}
if (!_isDbcLoadedArray[])
{
LoggerHelper.Error($"[ZLGCANFD] 获取报文信号值失败: 通道 {通道号} 尚未加载 DBC 文件");
return 0;
}
if (string.IsNullOrWhiteSpace())
{
LoggerHelper.Error("[ZLGCANFD] 获取报文信号值失败: 信号名称为空");
return 0;
}
// 查找该通道该帧 ID 最近一次解码成功的报文快照
if (!_latestDecodedMessages.TryGetValue((, ID), out var msg))
{
LoggerHelper.Error($"[ZLGCANFD] 获取报文信号值失败: 通道 {通道号} 未收到帧 ID 0x{帧ID:X} 的报文(尚未接收或 DBC 中无此报文)");
return 0;
}
// 在报文信号集合中查找目标信号(不区分大小写,与 设置报文 的信号匹配口径一致)
for (int i = 0; i < msg.nSignalCount; i++)
{
var signal = msg.vSignals[i];
string name = Encoding.Default.GetString(signal.strName).TrimEnd('\0');
if (string.Equals(name, , StringComparison.OrdinalIgnoreCase))
{
// 物理值 = 原始值 × 因子 + 偏移(与 CANSignalBroadcaster 广播公式一致)
return signal.nRawvalue * signal.nFactor + signal.nOffset;
}
}
LoggerHelper.Error($"[ZLGCANFD] 获取报文信号值失败: 帧 ID 0x{帧ID:X} 的报文中不存在信号 '{信号名称}'");
return 0;
}
#endregion
#region 5. #region 5.
/// <summary> /// <summary>