周立功的CAN /FD实现
This commit is contained in:
@@ -4,7 +4,10 @@ using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace CapMachine.Wpf.Services
|
||||
{
|
||||
@@ -150,8 +153,165 @@ namespace CapMachine.Wpf.Services
|
||||
/// <param name="path">LDF 路径。</param>
|
||||
public ObservableCollection<LinLdfModel> StartLdf(string path)
|
||||
{
|
||||
_log.Warn("ZLG LIN 当前版本未接入 LDF 解析(项目内仅存在 USB2XXX.dll 的 LDFParser)。");
|
||||
throw new NotSupportedException("ZLG LIN 暂未支持 LDF 解析,请后续提供/确认 ZLG 的 LDF DLL 接口(如 zldf.dll)后再接入。");
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
throw new ArgumentException("LDF 路径为空", nameof(path));
|
||||
}
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new FileNotFoundException($"LDF 文件不存在:{path}", path);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var text = File.ReadAllText(path, Encoding.UTF8);
|
||||
|
||||
// 去除单行注释,简化解析
|
||||
text = Regex.Replace(text, @"//.*?$", string.Empty, RegexOptions.Multiline);
|
||||
|
||||
var models = ParseLdfFramesAndSignals(text);
|
||||
|
||||
ListLinLdfModel.Clear();
|
||||
foreach (var item in models)
|
||||
{
|
||||
ListLinLdfModel.Add(item);
|
||||
}
|
||||
|
||||
LdfParserState = true;
|
||||
return ListLinLdfModel;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"ZLG LIN 解析 LDF 失败:{ex.Message}");
|
||||
LdfParserState = false;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<LinLdfModel> ParseLdfFramesAndSignals(string ldfText)
|
||||
{
|
||||
// 说明:此解析器只用于生成“帧-信号全集池”,不做位宽/缩放等语义解析。
|
||||
// 目标:尽可能容错地从 Frames 区域提取 FrameName 与其包含的 SignalName 列表。
|
||||
|
||||
var framesBlock = TryExtractNamedBlock(ldfText, "Frames");
|
||||
if (string.IsNullOrWhiteSpace(framesBlock))
|
||||
{
|
||||
return new List<LinLdfModel>();
|
||||
}
|
||||
|
||||
var result = new List<LinLdfModel>();
|
||||
var exists = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
// Frame 定义一般形式:FrameName : ... { ... }
|
||||
// 这里以非贪婪匹配提取每个 Frame 的 body
|
||||
var frameRegex = new Regex(@"(?s)(?<name>[A-Za-z_][A-Za-z0-9_]*)\s*:\s*.*?\{(?<body>.*?)\}\s*;?", RegexOptions.Compiled);
|
||||
var sigRegex = new Regex(@"(?m)^\s*(?<sig>[A-Za-z_][A-Za-z0-9_]*)\s*[,;]", RegexOptions.Compiled);
|
||||
|
||||
foreach (Match fm in frameRegex.Matches(framesBlock))
|
||||
{
|
||||
var frameName = fm.Groups["name"].Value;
|
||||
var body = fm.Groups["body"].Value;
|
||||
if (string.IsNullOrWhiteSpace(frameName) || string.IsNullOrWhiteSpace(body))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (Match sm in sigRegex.Matches(body))
|
||||
{
|
||||
var sigName = sm.Groups["sig"].Value;
|
||||
if (string.IsNullOrWhiteSpace(sigName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 排除明显的关键字(避免误采集)
|
||||
if (IsReservedKeyword(sigName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var key = $"{frameName}:{sigName}";
|
||||
if (!exists.Add(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(new LinLdfModel
|
||||
{
|
||||
MsgName = frameName,
|
||||
SignalName = sigName,
|
||||
Name = null,
|
||||
SignalDesc = null,
|
||||
SignalUnit = null,
|
||||
IsSeletedInfo = 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string? TryExtractNamedBlock(string text, string blockName)
|
||||
{
|
||||
// 提取形如:blockName { ... } 的块内容(不包含外层大括号)。
|
||||
// 基于括号深度扫描,避免正则在嵌套结构上失效。
|
||||
var idx = CultureInvariantIndexOf(text, blockName);
|
||||
if (idx < 0) return null;
|
||||
|
||||
var braceIdx = text.IndexOf('{', idx);
|
||||
if (braceIdx < 0) return null;
|
||||
|
||||
int depth = 0;
|
||||
for (int i = braceIdx; i < text.Length; i++)
|
||||
{
|
||||
var ch = text[i];
|
||||
if (ch == '{') depth++;
|
||||
else if (ch == '}')
|
||||
{
|
||||
depth--;
|
||||
if (depth == 0)
|
||||
{
|
||||
return text.Substring(braceIdx + 1, i - braceIdx - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int CultureInvariantIndexOf(string text, string value)
|
||||
{
|
||||
return text.IndexOf(value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool IsReservedKeyword(string token)
|
||||
{
|
||||
// LDF 常见关键字/区块名(用于降低误匹配概率)
|
||||
switch (token)
|
||||
{
|
||||
case "Frames":
|
||||
case "Signals":
|
||||
case "Signal":
|
||||
case "Nodes":
|
||||
case "Master":
|
||||
case "Slaves":
|
||||
case "Diagnostic":
|
||||
case "Diagnostics":
|
||||
case "Checksum":
|
||||
case "Event_triggered_frames":
|
||||
case "Sporadic_frames":
|
||||
case "Schedule_tables":
|
||||
case "Node_attributes":
|
||||
case "Node_composition":
|
||||
case "LIN_protocol":
|
||||
case "LIN_protocol_version":
|
||||
case "LIN_speed":
|
||||
case "Protocol_version":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user