1089 lines
36 KiB
Plaintext
1089 lines
36 KiB
Plaintext
using CapMachine.Model;
|
|
using CapMachine.Model.CANLIN;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace CapMachine.Wpf.Services
|
|
{
|
|
/// <summary>
|
|
/// CAN/LIN 配置导入模式。
|
|
/// </summary>
|
|
public enum CanLinImportMode
|
|
{
|
|
/// <summary>
|
|
/// 覆盖导入:同名同类型配置先删除后导入。
|
|
/// </summary>
|
|
Overwrite = 1,
|
|
|
|
/// <summary>
|
|
/// 增量导入:同名同类型配置自动重命名后导入。
|
|
/// </summary>
|
|
IncrementalRename = 2,
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导入导出执行结果。
|
|
/// </summary>
|
|
public class CanLinConfigImExportResult
|
|
{
|
|
/// <summary>
|
|
/// 执行是否成功。
|
|
/// </summary>
|
|
public bool IsSuccess { get; set; }
|
|
|
|
/// <summary>
|
|
/// 结果消息。
|
|
/// </summary>
|
|
public string Message { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 导出配置数量。
|
|
/// </summary>
|
|
public int ExportedConfigCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 导入配置数量。
|
|
/// </summary>
|
|
public int ImportedConfigCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 覆盖配置数量。
|
|
/// </summary>
|
|
public int OverwrittenConfigCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 重命名配置数量。
|
|
/// </summary>
|
|
public int RenamedConfigCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 新增规则数量。
|
|
/// </summary>
|
|
public int InsertedRuleCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 覆盖规则数量。
|
|
/// </summary>
|
|
public int UpdatedRuleCount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 重命名后的配置明细。
|
|
/// </summary>
|
|
public List<string> RenamedConfigs { get; set; } = new List<string>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// CAN/CANFD/LIN 配置导入导出服务。
|
|
/// </summary>
|
|
public class CanLinConfigImExportService
|
|
{
|
|
/// <summary>
|
|
/// 文件结构版本。
|
|
/// </summary>
|
|
private const string SchemaVersion = "1.0";
|
|
|
|
/// <summary>
|
|
/// 初始化导入导出服务。
|
|
/// </summary>
|
|
/// <param name="freeSql">数据库实例。</param>
|
|
/// <param name="logService">日志服务。</param>
|
|
public CanLinConfigImExportService(IFreeSql freeSql, ILogService logService)
|
|
{
|
|
FreeSql = freeSql;
|
|
LogService = logService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 数据库访问对象。
|
|
/// </summary>
|
|
public IFreeSql FreeSql { get; }
|
|
|
|
/// <summary>
|
|
/// 日志服务。
|
|
/// </summary>
|
|
public ILogService LogService { get; }
|
|
|
|
/// <summary>
|
|
/// 导出当前 CAN/CANFD/LIN 配置到 JSON 文件。
|
|
/// </summary>
|
|
/// <param name="filePath">目标文件路径。</param>
|
|
/// <returns>执行结果。</returns>
|
|
public CanLinConfigImExportResult ExportToFile(string filePath)
|
|
{
|
|
var result = new CanLinConfigImExportResult();
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(filePath))
|
|
{
|
|
result.Message = "导出路径不能为空";
|
|
return result;
|
|
}
|
|
|
|
var package = BuildExportPackage();
|
|
var json = JsonConvert.SerializeObject(package, Formatting.Indented);
|
|
|
|
var dir = Path.GetDirectoryName(filePath);
|
|
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
|
|
{
|
|
Directory.CreateDirectory(dir);
|
|
}
|
|
|
|
File.WriteAllText(filePath, json, Encoding.UTF8);
|
|
|
|
result.IsSuccess = true;
|
|
result.ExportedConfigCount = package.CanLinConfigPros.Count;
|
|
result.Message = $"导出成功,配置数量:{result.ExportedConfigCount}";
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogService.Error($"导出 CAN/LIN 配置失败:{ex}");
|
|
result.Message = $"导出失败:{ex.Message}";
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从 JSON 文件导入 CAN/CANFD/LIN 配置到数据库。
|
|
/// </summary>
|
|
/// <param name="filePath">源文件路径。</param>
|
|
/// <param name="importMode">导入模式。</param>
|
|
/// <returns>执行结果。</returns>
|
|
public CanLinConfigImExportResult ImportFromFile(string filePath, CanLinImportMode importMode)
|
|
{
|
|
var result = new CanLinConfigImExportResult();
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(filePath))
|
|
{
|
|
result.Message = "导入文件路径不能为空";
|
|
return result;
|
|
}
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
result.Message = "导入文件不存在";
|
|
return result;
|
|
}
|
|
|
|
var json = File.ReadAllText(filePath, Encoding.UTF8);
|
|
var package = JsonConvert.DeserializeObject<CanLinConfigPackageSnapshot>(json);
|
|
if (package == null)
|
|
{
|
|
result.Message = "导入文件解析失败";
|
|
return result;
|
|
}
|
|
|
|
if (package.CanLinConfigPros == null || package.CanLinConfigPros.Count == 0)
|
|
{
|
|
result.Message = "导入文件中没有 CAN/CANFD/LIN 配置数据";
|
|
return result;
|
|
}
|
|
|
|
FreeSql.Transaction(() =>
|
|
{
|
|
var ruleMaps = UpsertLogicRules(package.LogicRules ?? new List<LogicRuleSnapshot>(), result);
|
|
foreach (var configSnapshot in package.CanLinConfigPros)
|
|
{
|
|
ImportSingleConfig(configSnapshot, importMode, ruleMaps, result);
|
|
}
|
|
});
|
|
|
|
result.IsSuccess = true;
|
|
result.Message =
|
|
$"导入成功:新增配置 {result.ImportedConfigCount},覆盖配置 {result.OverwrittenConfigCount},重命名配置 {result.RenamedConfigCount},新增规则 {result.InsertedRuleCount},覆盖规则 {result.UpdatedRuleCount}";
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogService.Error($"导入 CAN/LIN 配置失败:{ex}");
|
|
result.Message = $"导入失败:{ex.Message}";
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 构建导出快照对象。
|
|
/// </summary>
|
|
/// <returns>导出快照。</returns>
|
|
private CanLinConfigPackageSnapshot BuildExportPackage()
|
|
{
|
|
var logicRules = FreeSql.Select<LogicRule>().OrderBy(a => a.Id).ToList();
|
|
|
|
var canConfigPros = FreeSql.Select<CanLinConfigPro>()
|
|
.Where(a => a.CANLINInfo == CANLIN.CAN)
|
|
.Include(a => a.CANConfigExd)
|
|
.IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))
|
|
.IncludeMany(a => a.CanScheduleConfigs)
|
|
.ToList();
|
|
|
|
var canFdConfigPros = FreeSql.Select<CanLinConfigPro>()
|
|
.Where(a => a.CANLINInfo == CANLIN.CANFD)
|
|
.Include(a => a.CANFdConfigExd)
|
|
.IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))
|
|
.IncludeMany(a => a.CanFdScheduleConfigs)
|
|
.ToList();
|
|
|
|
var linConfigPros = FreeSql.Select<CanLinConfigPro>()
|
|
.Where(a => a.CANLINInfo == CANLIN.LIN)
|
|
.Include(a => a.LINConfigExd)
|
|
.IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))
|
|
.IncludeMany(a => a.LinScheduleConfigs)
|
|
.ToList();
|
|
|
|
var allConfigPros = new List<CanLinConfigPro>();
|
|
allConfigPros.AddRange(canConfigPros);
|
|
allConfigPros.AddRange(canFdConfigPros);
|
|
allConfigPros.AddRange(linConfigPros);
|
|
|
|
return new CanLinConfigPackageSnapshot
|
|
{
|
|
SchemaVersion = SchemaVersion,
|
|
ExportTime = DateTime.Now,
|
|
LogicRules = logicRules.Select(MapLogicRuleSnapshot).ToList(),
|
|
CanLinConfigPros = allConfigPros.Select(MapConfigSnapshot).ToList(),
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导入单个配置程序。
|
|
/// </summary>
|
|
/// <param name="snapshot">配置快照。</param>
|
|
/// <param name="importMode">导入模式。</param>
|
|
/// <param name="ruleMaps">规则映射。</param>
|
|
/// <param name="result">结果对象。</param>
|
|
private void ImportSingleConfig(
|
|
CanLinConfigProSnapshot snapshot,
|
|
CanLinImportMode importMode,
|
|
ImportRuleMaps ruleMaps,
|
|
CanLinConfigImExportResult result)
|
|
{
|
|
if (snapshot == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var sourceName = (snapshot.ConfigName ?? string.Empty).Trim();
|
|
if (string.IsNullOrWhiteSpace(sourceName))
|
|
{
|
|
throw new InvalidOperationException("导入文件中存在空配置名称");
|
|
}
|
|
|
|
var canlinInfo = snapshot.CANLINInfo;
|
|
var finalConfigName = sourceName;
|
|
|
|
var sameConfigExists = FreeSql.Select<CanLinConfigPro>()
|
|
.Where(a => a.CANLINInfo == canlinInfo)
|
|
.Where(a => a.ConfigName == sourceName)
|
|
.Any();
|
|
|
|
if (sameConfigExists)
|
|
{
|
|
if (importMode == CanLinImportMode.Overwrite)
|
|
{
|
|
DeleteExistingConfig(sourceName, canlinInfo);
|
|
result.OverwrittenConfigCount++;
|
|
}
|
|
else
|
|
{
|
|
finalConfigName = BuildUniqueImportName(sourceName, canlinInfo);
|
|
result.RenamedConfigCount++;
|
|
result.RenamedConfigs.Add($"{sourceName} -> {finalConfigName} ({canlinInfo})");
|
|
}
|
|
}
|
|
|
|
var configExdIds = CreateConfigExd(snapshot, canlinInfo);
|
|
|
|
var insertPro = FreeSql.Insert(new CanLinConfigPro
|
|
{
|
|
ConfigName = finalConfigName,
|
|
CANLINInfo = canlinInfo,
|
|
CANConfigExdId = configExdIds.CANConfigExdId,
|
|
CANFdConfigExdId = configExdIds.CANFdConfigExdId,
|
|
LINConfigExdId = configExdIds.LINConfigExdId,
|
|
}).ExecuteInserted().FirstOrDefault();
|
|
|
|
if (insertPro == null)
|
|
{
|
|
throw new InvalidOperationException($"配置程序导入失败:{finalConfigName}");
|
|
}
|
|
|
|
var rwConfigs = snapshot.CanLinConfigContents ?? new List<CanLinRWConfigSnapshot>();
|
|
foreach (var rwConfig in rwConfigs)
|
|
{
|
|
var logicRuleId = ResolveLogicRuleId(rwConfig, ruleMaps);
|
|
var rwInsertResult = FreeSql.Insert(new CanLinRWConfig
|
|
{
|
|
RWInfo = rwConfig.RWInfo,
|
|
Name = string.IsNullOrWhiteSpace(rwConfig.Name) ? rwConfig.SignalName : rwConfig.Name,
|
|
MsgFrameName = rwConfig.MsgFrameName ?? string.Empty,
|
|
SignalName = rwConfig.SignalName ?? string.Empty,
|
|
DefautValue = rwConfig.DefautValue,
|
|
CanLinConfigProId = insertPro.Id,
|
|
LogicRuleId = logicRuleId,
|
|
}).ExecuteAffrows();
|
|
|
|
if (rwInsertResult <= 0)
|
|
{
|
|
throw new InvalidOperationException($"导入读写配置失败:{finalConfigName}/{rwConfig.SignalName}");
|
|
}
|
|
}
|
|
|
|
if (canlinInfo == CANLIN.CAN)
|
|
{
|
|
foreach (var sch in snapshot.CanScheduleConfigs ?? new List<CANScheduleConfigSnapshot>())
|
|
{
|
|
FreeSql.Insert(new CANScheduleConfig
|
|
{
|
|
MsgName = sch.MsgName,
|
|
Cycle = sch.Cycle,
|
|
OrderSend = sch.OrderSend,
|
|
SchTabIndex = sch.SchTabIndex,
|
|
CanLinConfigProId = insertPro.Id,
|
|
}).ExecuteAffrows();
|
|
}
|
|
}
|
|
else if (canlinInfo == CANLIN.CANFD)
|
|
{
|
|
foreach (var sch in snapshot.CanFdScheduleConfigs ?? new List<CANFdScheduleConfigSnapshot>())
|
|
{
|
|
FreeSql.Insert(new CANFdScheduleConfig
|
|
{
|
|
MsgName = sch.MsgName,
|
|
Cycle = sch.Cycle,
|
|
OrderSend = sch.OrderSend,
|
|
SchTabIndex = sch.SchTabIndex,
|
|
CanLinConfigProId = insertPro.Id,
|
|
}).ExecuteAffrows();
|
|
}
|
|
}
|
|
else if (canlinInfo == CANLIN.LIN)
|
|
{
|
|
foreach (var sch in snapshot.LinScheduleConfigs ?? new List<LINScheduleConfigSnapshot>())
|
|
{
|
|
FreeSql.Insert(new LINScheduleConfig
|
|
{
|
|
IsActive = sch.IsActive,
|
|
IsMsgActived = sch.IsMsgActived,
|
|
MsgName = sch.MsgName,
|
|
MsgNameIndex = sch.MsgNameIndex,
|
|
Cycle = sch.Cycle,
|
|
SchTabIndex = sch.SchTabIndex,
|
|
SchTabName = sch.SchTabName,
|
|
CanLinConfigProId = insertPro.Id,
|
|
}).ExecuteAffrows();
|
|
}
|
|
}
|
|
|
|
result.ImportedConfigCount++;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建并保存配置扩展信息。
|
|
/// </summary>
|
|
/// <param name="snapshot">配置快照。</param>
|
|
/// <param name="canlinInfo">配置类型。</param>
|
|
/// <returns>扩展配置主键集合。</returns>
|
|
private ConfigExdIds CreateConfigExd(CanLinConfigProSnapshot snapshot, CANLIN canlinInfo)
|
|
{
|
|
var ids = new ConfigExdIds();
|
|
if (canlinInfo == CANLIN.CAN)
|
|
{
|
|
var canExd = snapshot.CANConfigExd ?? new CANConfigExdSnapshot();
|
|
var insert = FreeSql.Insert(new CANConfigExd
|
|
{
|
|
BaudRate = canExd.BaudRate,
|
|
Cycle = canExd.Cycle,
|
|
DbcPath = canExd.DbcPath ?? string.Empty,
|
|
SchEnable = canExd.SchEnable,
|
|
}).ExecuteInserted().FirstOrDefault();
|
|
|
|
if (insert == null)
|
|
{
|
|
throw new InvalidOperationException("导入 CAN 扩展配置失败");
|
|
}
|
|
|
|
ids.CANConfigExdId = insert.Id;
|
|
}
|
|
else if (canlinInfo == CANLIN.CANFD)
|
|
{
|
|
var canFdExd = snapshot.CANFdConfigExd ?? new CANFdConfigExdSnapshot();
|
|
var insert = FreeSql.Insert(new CANFdConfigExd
|
|
{
|
|
DataBaudRate = canFdExd.DataBaudRate,
|
|
ArbBaudRate = canFdExd.ArbBaudRate,
|
|
ISOEnable = canFdExd.ISOEnable,
|
|
ResEnable = canFdExd.ResEnable,
|
|
Cycle = canFdExd.Cycle,
|
|
DbcPath = canFdExd.DbcPath ?? string.Empty,
|
|
SchEnable = canFdExd.SchEnable,
|
|
}).ExecuteInserted().FirstOrDefault();
|
|
|
|
if (insert == null)
|
|
{
|
|
throw new InvalidOperationException("导入 CANFD 扩展配置失败");
|
|
}
|
|
|
|
ids.CANFdConfigExdId = insert.Id;
|
|
}
|
|
else
|
|
{
|
|
var linExd = snapshot.LINConfigExd ?? new LINConfigExdSnapshot();
|
|
var insert = FreeSql.Insert(new LINConfigExd
|
|
{
|
|
BaudRate = linExd.BaudRate,
|
|
Cycle = linExd.Cycle,
|
|
LdfPath = linExd.LdfPath ?? string.Empty,
|
|
SchEnable = linExd.SchEnable,
|
|
}).ExecuteInserted().FirstOrDefault();
|
|
|
|
if (insert == null)
|
|
{
|
|
throw new InvalidOperationException("导入 LIN 扩展配置失败");
|
|
}
|
|
|
|
ids.LINConfigExdId = insert.Id;
|
|
}
|
|
|
|
return ids;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除同名同类型的旧配置。
|
|
/// </summary>
|
|
/// <param name="configName">配置名称。</param>
|
|
/// <param name="canlinInfo">配置类型。</param>
|
|
private void DeleteExistingConfig(string configName, CANLIN canlinInfo)
|
|
{
|
|
var oldConfigs = FreeSql.Select<CanLinConfigPro>()
|
|
.Where(a => a.CANLINInfo == canlinInfo)
|
|
.Where(a => a.ConfigName == configName)
|
|
.ToList();
|
|
|
|
foreach (var oldConfig in oldConfigs)
|
|
{
|
|
FreeSql.Delete<CanLinRWConfig>().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows();
|
|
FreeSql.Delete<CANScheduleConfig>().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows();
|
|
FreeSql.Delete<CANFdScheduleConfig>().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows();
|
|
FreeSql.Delete<LINScheduleConfig>().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows();
|
|
FreeSql.Delete<CanLinConfigPro>(oldConfig.Id).ExecuteAffrows();
|
|
|
|
if (canlinInfo == CANLIN.CAN && oldConfig.CANConfigExdId > 0)
|
|
{
|
|
FreeSql.Delete<CANConfigExd>(oldConfig.CANConfigExdId).ExecuteAffrows();
|
|
}
|
|
else if (canlinInfo == CANLIN.CANFD && oldConfig.CANFdConfigExdId > 0)
|
|
{
|
|
FreeSql.Delete<CANFdConfigExd>(oldConfig.CANFdConfigExdId).ExecuteAffrows();
|
|
}
|
|
else if (canlinInfo == CANLIN.LIN && oldConfig.LINConfigExdId > 0)
|
|
{
|
|
FreeSql.Delete<LINConfigExd>(oldConfig.LINConfigExdId).ExecuteAffrows();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成可用的增量重命名配置名。
|
|
/// </summary>
|
|
/// <param name="originalName">原始名称。</param>
|
|
/// <param name="canlinInfo">配置类型。</param>
|
|
/// <returns>可用名称。</returns>
|
|
private string BuildUniqueImportName(string originalName, CANLIN canlinInfo)
|
|
{
|
|
var baseName = $"{originalName}_import_{DateTime.Now:yyyyMMddHHmmss}";
|
|
var candidate = baseName;
|
|
var suffix = 1;
|
|
|
|
while (FreeSql.Select<CanLinConfigPro>()
|
|
.Where(a => a.CANLINInfo == canlinInfo)
|
|
.Where(a => a.ConfigName == candidate)
|
|
.Any())
|
|
{
|
|
candidate = $"{baseName}_{suffix}";
|
|
suffix++;
|
|
}
|
|
|
|
return candidate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导入并覆盖逻辑规则。
|
|
/// </summary>
|
|
/// <param name="logicRules">规则快照集合。</param>
|
|
/// <param name="result">执行结果。</param>
|
|
/// <returns>规则映射。</returns>
|
|
private ImportRuleMaps UpsertLogicRules(List<LogicRuleSnapshot> logicRules, CanLinConfigImExportResult result)
|
|
{
|
|
var maps = new ImportRuleMaps();
|
|
foreach (var snapshot in logicRules)
|
|
{
|
|
if (snapshot == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var ruleName = (snapshot.Name ?? string.Empty).Trim();
|
|
if (string.IsNullOrWhiteSpace(ruleName))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var oldRule = FreeSql.Select<LogicRule>().Where(a => a.Name == ruleName).First();
|
|
if (oldRule != null)
|
|
{
|
|
FreeSql.Update<LogicRule>()
|
|
.Set(a => a.Description, snapshot.Description)
|
|
.Set(a => a.Expression, snapshot.Expression)
|
|
.Set(a => a.ParameterType, snapshot.ParameterType)
|
|
.Where(a => a.Id == oldRule.Id)
|
|
.ExecuteAffrows();
|
|
|
|
maps.NameToTargetId[ruleName] = oldRule.Id;
|
|
if (snapshot.Id > 0)
|
|
{
|
|
maps.SourceIdToTargetId[snapshot.Id] = oldRule.Id;
|
|
}
|
|
result.UpdatedRuleCount++;
|
|
}
|
|
else
|
|
{
|
|
var insertRule = FreeSql.Insert(new LogicRule
|
|
{
|
|
Name = ruleName,
|
|
Description = snapshot.Description,
|
|
Expression = snapshot.Expression,
|
|
ParameterType = snapshot.ParameterType,
|
|
}).ExecuteInserted().FirstOrDefault();
|
|
|
|
if (insertRule == null)
|
|
{
|
|
throw new InvalidOperationException($"导入逻辑规则失败:{ruleName}");
|
|
}
|
|
|
|
maps.NameToTargetId[ruleName] = insertRule.Id;
|
|
if (snapshot.Id > 0)
|
|
{
|
|
maps.SourceIdToTargetId[snapshot.Id] = insertRule.Id;
|
|
}
|
|
|
|
result.InsertedRuleCount++;
|
|
}
|
|
}
|
|
|
|
return maps;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 解析读写配置对应的目标规则 Id。
|
|
/// </summary>
|
|
/// <param name="rwSnapshot">读写配置快照。</param>
|
|
/// <param name="ruleMaps">规则映射。</param>
|
|
/// <returns>规则 Id。</returns>
|
|
private long ResolveLogicRuleId(CanLinRWConfigSnapshot rwSnapshot, ImportRuleMaps ruleMaps)
|
|
{
|
|
if (rwSnapshot == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (rwSnapshot.LogicRule != null)
|
|
{
|
|
var ruleName = (rwSnapshot.LogicRule.Name ?? string.Empty).Trim();
|
|
if (!string.IsNullOrWhiteSpace(ruleName) && ruleMaps.NameToTargetId.TryGetValue(ruleName, out var byNameId))
|
|
{
|
|
return byNameId;
|
|
}
|
|
}
|
|
|
|
if (rwSnapshot.LogicRuleId > 0 && ruleMaps.SourceIdToTargetId.TryGetValue(rwSnapshot.LogicRuleId, out var bySourceId))
|
|
{
|
|
return bySourceId;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将规则实体映射为快照。
|
|
/// </summary>
|
|
/// <param name="rule">规则实体。</param>
|
|
/// <returns>规则快照。</returns>
|
|
private static LogicRuleSnapshot MapLogicRuleSnapshot(LogicRule rule)
|
|
{
|
|
return new LogicRuleSnapshot
|
|
{
|
|
Id = rule.Id,
|
|
Name = rule.Name,
|
|
Description = rule.Description,
|
|
Expression = rule.Expression,
|
|
ParameterType = rule.ParameterType,
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将配置实体映射为快照。
|
|
/// </summary>
|
|
/// <param name="configPro">配置实体。</param>
|
|
/// <returns>配置快照。</returns>
|
|
private static CanLinConfigProSnapshot MapConfigSnapshot(CanLinConfigPro configPro)
|
|
{
|
|
return new CanLinConfigProSnapshot
|
|
{
|
|
ConfigName = configPro.ConfigName,
|
|
CANLINInfo = configPro.CANLINInfo,
|
|
CreateTime = configPro.CreateTime,
|
|
CANConfigExd = configPro.CANConfigExd == null
|
|
? null
|
|
: new CANConfigExdSnapshot
|
|
{
|
|
BaudRate = configPro.CANConfigExd.BaudRate,
|
|
Cycle = configPro.CANConfigExd.Cycle,
|
|
DbcPath = configPro.CANConfigExd.DbcPath,
|
|
SchEnable = configPro.CANConfigExd.SchEnable,
|
|
},
|
|
CANFdConfigExd = configPro.CANFdConfigExd == null
|
|
? null
|
|
: new CANFdConfigExdSnapshot
|
|
{
|
|
DataBaudRate = configPro.CANFdConfigExd.DataBaudRate,
|
|
ArbBaudRate = configPro.CANFdConfigExd.ArbBaudRate,
|
|
ISOEnable = configPro.CANFdConfigExd.ISOEnable,
|
|
ResEnable = configPro.CANFdConfigExd.ResEnable,
|
|
Cycle = configPro.CANFdConfigExd.Cycle,
|
|
DbcPath = configPro.CANFdConfigExd.DbcPath,
|
|
SchEnable = configPro.CANFdConfigExd.SchEnable,
|
|
},
|
|
LINConfigExd = configPro.LINConfigExd == null
|
|
? null
|
|
: new LINConfigExdSnapshot
|
|
{
|
|
BaudRate = configPro.LINConfigExd.BaudRate,
|
|
Cycle = configPro.LINConfigExd.Cycle,
|
|
LdfPath = configPro.LINConfigExd.LdfPath,
|
|
SchEnable = configPro.LINConfigExd.SchEnable,
|
|
},
|
|
CanLinConfigContents = (configPro.CanLinConfigContents ?? new List<CanLinRWConfig>())
|
|
.Select(a => new CanLinRWConfigSnapshot
|
|
{
|
|
RWInfo = a.RWInfo,
|
|
Name = a.Name,
|
|
MsgFrameName = a.MsgFrameName,
|
|
SignalName = a.SignalName,
|
|
DefautValue = a.DefautValue,
|
|
LogicRuleId = a.LogicRuleId,
|
|
LogicRule = a.LogicRule == null ? null : MapLogicRuleSnapshot(a.LogicRule),
|
|
}).ToList(),
|
|
CanScheduleConfigs = (configPro.CanScheduleConfigs ?? new List<CANScheduleConfig>())
|
|
.Select(a => new CANScheduleConfigSnapshot
|
|
{
|
|
MsgName = a.MsgName,
|
|
Cycle = a.Cycle,
|
|
OrderSend = a.OrderSend,
|
|
SchTabIndex = a.SchTabIndex,
|
|
}).ToList(),
|
|
CanFdScheduleConfigs = (configPro.CanFdScheduleConfigs ?? new List<CANFdScheduleConfig>())
|
|
.Select(a => new CANFdScheduleConfigSnapshot
|
|
{
|
|
MsgName = a.MsgName,
|
|
Cycle = a.Cycle,
|
|
OrderSend = a.OrderSend,
|
|
SchTabIndex = a.SchTabIndex,
|
|
}).ToList(),
|
|
LinScheduleConfigs = (configPro.LinScheduleConfigs ?? new List<LINScheduleConfig>())
|
|
.Select(a => new LINScheduleConfigSnapshot
|
|
{
|
|
IsActive = a.IsActive,
|
|
IsMsgActived = a.IsMsgActived,
|
|
MsgName = a.MsgName,
|
|
MsgNameIndex = a.MsgNameIndex,
|
|
Cycle = a.Cycle,
|
|
SchTabIndex = a.SchTabIndex,
|
|
SchTabName = a.SchTabName,
|
|
}).ToList(),
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 规则映射上下文。
|
|
/// </summary>
|
|
private class ImportRuleMaps
|
|
{
|
|
/// <summary>
|
|
/// 规则名称到目标库规则 Id 的映射。
|
|
/// </summary>
|
|
public Dictionary<string, long> NameToTargetId { get; set; } = new Dictionary<string, long>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
/// <summary>
|
|
/// 源文件规则 Id 到目标库规则 Id 的映射。
|
|
/// </summary>
|
|
public Dictionary<long, long> SourceIdToTargetId { get; set; } = new Dictionary<long, long>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 扩展配置主键集合。
|
|
/// </summary>
|
|
private class ConfigExdIds
|
|
{
|
|
/// <summary>
|
|
/// CAN 扩展主键。
|
|
/// </summary>
|
|
public long CANConfigExdId { get; set; }
|
|
|
|
/// <summary>
|
|
/// CANFD 扩展主键。
|
|
/// </summary>
|
|
public long CANFdConfigExdId { get; set; }
|
|
|
|
/// <summary>
|
|
/// LIN 扩展主键。
|
|
/// </summary>
|
|
public long LINConfigExdId { get; set; }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// CAN/LIN 配置导入导出文件根对象。
|
|
/// </summary>
|
|
public class CanLinConfigPackageSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 文件结构版本。
|
|
/// </summary>
|
|
public string SchemaVersion { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 导出时间。
|
|
/// </summary>
|
|
public DateTime ExportTime { get; set; }
|
|
|
|
/// <summary>
|
|
/// 规则集合。
|
|
/// </summary>
|
|
public List<LogicRuleSnapshot> LogicRules { get; set; } = new List<LogicRuleSnapshot>();
|
|
|
|
/// <summary>
|
|
/// 配置程序集合。
|
|
/// </summary>
|
|
public List<CanLinConfigProSnapshot> CanLinConfigPros { get; set; } = new List<CanLinConfigProSnapshot>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 逻辑规则快照。
|
|
/// </summary>
|
|
public class LogicRuleSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 主键。
|
|
/// </summary>
|
|
public long Id { get; set; }
|
|
|
|
/// <summary>
|
|
/// 规则名称。
|
|
/// </summary>
|
|
public string? Name { get; set; }
|
|
|
|
/// <summary>
|
|
/// 规则描述。
|
|
/// </summary>
|
|
public string? Description { get; set; }
|
|
|
|
/// <summary>
|
|
/// 规则表达式。
|
|
/// </summary>
|
|
public string? Expression { get; set; }
|
|
|
|
/// <summary>
|
|
/// 参数类型。
|
|
/// </summary>
|
|
public string? ParameterType { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 配置程序快照。
|
|
/// </summary>
|
|
public class CanLinConfigProSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 配置名称。
|
|
/// </summary>
|
|
public string? ConfigName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 配置分类。
|
|
/// </summary>
|
|
public CANLIN CANLINInfo { get; set; }
|
|
|
|
/// <summary>
|
|
/// 创建时间。
|
|
/// </summary>
|
|
public DateTime CreateTime { get; set; }
|
|
|
|
/// <summary>
|
|
/// CAN 扩展配置。
|
|
/// </summary>
|
|
public CANConfigExdSnapshot? CANConfigExd { get; set; }
|
|
|
|
/// <summary>
|
|
/// CANFD 扩展配置。
|
|
/// </summary>
|
|
public CANFdConfigExdSnapshot? CANFdConfigExd { get; set; }
|
|
|
|
/// <summary>
|
|
/// LIN 扩展配置。
|
|
/// </summary>
|
|
public LINConfigExdSnapshot? LINConfigExd { get; set; }
|
|
|
|
/// <summary>
|
|
/// 读写配置集合。
|
|
/// </summary>
|
|
public List<CanLinRWConfigSnapshot>? CanLinConfigContents { get; set; }
|
|
|
|
/// <summary>
|
|
/// CAN 调度配置。
|
|
/// </summary>
|
|
public List<CANScheduleConfigSnapshot>? CanScheduleConfigs { get; set; }
|
|
|
|
/// <summary>
|
|
/// CANFD 调度配置。
|
|
/// </summary>
|
|
public List<CANFdScheduleConfigSnapshot>? CanFdScheduleConfigs { get; set; }
|
|
|
|
/// <summary>
|
|
/// LIN 调度配置。
|
|
/// </summary>
|
|
public List<LINScheduleConfigSnapshot>? LinScheduleConfigs { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// CAN 扩展快照。
|
|
/// </summary>
|
|
public class CANConfigExdSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 波特率。
|
|
/// </summary>
|
|
public int BaudRate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 周期。
|
|
/// </summary>
|
|
public int Cycle { get; set; }
|
|
|
|
/// <summary>
|
|
/// DBC 路径。
|
|
/// </summary>
|
|
public string? DbcPath { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度启用。
|
|
/// </summary>
|
|
public bool SchEnable { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// CANFD 扩展快照。
|
|
/// </summary>
|
|
public class CANFdConfigExdSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 数据波特率。
|
|
/// </summary>
|
|
public int DataBaudRate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 仲裁波特率。
|
|
/// </summary>
|
|
public int ArbBaudRate { get; set; }
|
|
|
|
/// <summary>
|
|
/// ISO 开关。
|
|
/// </summary>
|
|
public bool ISOEnable { get; set; }
|
|
|
|
/// <summary>
|
|
/// 终端电阻开关。
|
|
/// </summary>
|
|
public bool ResEnable { get; set; }
|
|
|
|
/// <summary>
|
|
/// 周期。
|
|
/// </summary>
|
|
public int Cycle { get; set; }
|
|
|
|
/// <summary>
|
|
/// DBC 路径。
|
|
/// </summary>
|
|
public string? DbcPath { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度启用。
|
|
/// </summary>
|
|
public bool SchEnable { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// LIN 扩展快照。
|
|
/// </summary>
|
|
public class LINConfigExdSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 波特率。
|
|
/// </summary>
|
|
public int BaudRate { get; set; }
|
|
|
|
/// <summary>
|
|
/// 周期。
|
|
/// </summary>
|
|
public int Cycle { get; set; }
|
|
|
|
/// <summary>
|
|
/// LDF 路径。
|
|
/// </summary>
|
|
public string? LdfPath { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度启用。
|
|
/// </summary>
|
|
public bool SchEnable { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 读写配置快照。
|
|
/// </summary>
|
|
public class CanLinRWConfigSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 读写类型。
|
|
/// </summary>
|
|
public RW RWInfo { get; set; }
|
|
|
|
/// <summary>
|
|
/// 配置名称。
|
|
/// </summary>
|
|
public string? Name { get; set; }
|
|
|
|
/// <summary>
|
|
/// 帧名。
|
|
/// </summary>
|
|
public string? MsgFrameName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 信号名。
|
|
/// </summary>
|
|
public string? SignalName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 默认值。
|
|
/// </summary>
|
|
public string? DefautValue { get; set; }
|
|
|
|
/// <summary>
|
|
/// 规则 Id。
|
|
/// </summary>
|
|
public long LogicRuleId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 规则对象。
|
|
/// </summary>
|
|
public LogicRuleSnapshot? LogicRule { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// CAN 调度快照。
|
|
/// </summary>
|
|
public class CANScheduleConfigSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 消息名。
|
|
/// </summary>
|
|
public string? MsgName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 周期。
|
|
/// </summary>
|
|
public int Cycle { get; set; }
|
|
|
|
/// <summary>
|
|
/// 发送方式。
|
|
/// </summary>
|
|
public int OrderSend { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度表索引。
|
|
/// </summary>
|
|
public int SchTabIndex { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// CANFD 调度快照。
|
|
/// </summary>
|
|
public class CANFdScheduleConfigSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 消息名。
|
|
/// </summary>
|
|
public string? MsgName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 周期。
|
|
/// </summary>
|
|
public int Cycle { get; set; }
|
|
|
|
/// <summary>
|
|
/// 发送方式。
|
|
/// </summary>
|
|
public int OrderSend { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度表索引。
|
|
/// </summary>
|
|
public int SchTabIndex { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// LIN 调度快照。
|
|
/// </summary>
|
|
public class LINScheduleConfigSnapshot
|
|
{
|
|
/// <summary>
|
|
/// 是否启用。
|
|
/// </summary>
|
|
public bool IsActive { get; set; }
|
|
|
|
/// <summary>
|
|
/// 是否消息激活。
|
|
/// </summary>
|
|
public bool IsMsgActived { get; set; }
|
|
|
|
/// <summary>
|
|
/// 消息名。
|
|
/// </summary>
|
|
public string? MsgName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 消息索引。
|
|
/// </summary>
|
|
public int MsgNameIndex { get; set; }
|
|
|
|
/// <summary>
|
|
/// 周期。
|
|
/// </summary>
|
|
public int Cycle { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度索引。
|
|
/// </summary>
|
|
public int SchTabIndex { get; set; }
|
|
|
|
/// <summary>
|
|
/// 调度名。
|
|
/// </summary>
|
|
public string? SchTabName { get; set; }
|
|
}
|
|
}
|