feat: ZLGCANFD新增获取报文信号值函数(最新解码报文缓存+按通道/帧ID/信号名查询,失败报错返回0)
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user