周立功开发过程1

This commit is contained in:
2026-02-02 21:22:01 +08:00
parent 4d16b474c6
commit 2e8ad1cffa
42 changed files with 11571 additions and 122 deletions

View File

@@ -0,0 +1,722 @@
using AutoMapper;
using CapMachine.Core;
using CapMachine.Model.CANLIN;
using CapMachine.Wpf.CanDrive;
using CapMachine.Wpf.Dtos;
using CapMachine.Wpf.Services;
using ImTools;
using Microsoft.Win32;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using static CapMachine.Wpf.Models.ComEnum;
namespace CapMachine.Wpf.ViewModels
{
/// <summary>
/// ZLG CAN/CANFD 合并配置 ViewModel模式切换单选
/// </summary>
public class ZlgCanDriveConfigViewModel : NavigationViewModel
{
/// <summary>
/// 构造函数。
/// </summary>
public ZlgCanDriveConfigViewModel(IDialogService dialogService, IFreeSql freeSql,
IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService,
ComActionService comActionService, ILogService logService, LogicRuleService logicRuleService,
ConfigService configService, ZlgCanDriveService zlgCanDriveService, ZlgLinDriveService zlgLinDriveService,
IMapper mapper)
{
DialogService = dialogService;
FreeSql = freeSql;
EventAggregator = eventAggregator;
RegionManager = regionManager;
SysRunService = sysRunService;
ComActionService = comActionService;
LogService = logService;
LogicRuleService = logicRuleService;
ConfigService = configService;
ZlgCanDriveService = zlgCanDriveService;
ZlgLinDriveService = zlgLinDriveService;
Mapper = mapper;
SelectedMode = ZlgCanMode.Can;
InitLoadCanConfigPro();
}
/// <summary>
/// Dialog 服务。
/// </summary>
public IDialogService DialogService { get; }
/// <summary>
/// FreeSql。
/// </summary>
public IFreeSql FreeSql { get; }
/// <summary>
/// 事件聚合。
/// </summary>
public IEventAggregator EventAggregator { get; }
/// <summary>
/// 区域导航。
/// </summary>
public IRegionManager RegionManager { get; }
/// <summary>
/// 系统运行服务。
/// </summary>
public SysRunService SysRunService { get; }
/// <summary>
/// 通信互斥控制。
/// </summary>
public ComActionService ComActionService { get; }
/// <summary>
/// 日志。
/// </summary>
public ILogService LogService { get; }
/// <summary>
/// 逻辑规则服务。
/// </summary>
public LogicRuleService LogicRuleService { get; }
/// <summary>
/// 配置服务。
/// </summary>
public ConfigService ConfigService { get; }
/// <summary>
/// ZLG CAN 服务。
/// </summary>
public ZlgCanDriveService ZlgCanDriveService { get; }
/// <summary>
/// ZLG LIN 服务(用于互斥判断)。
/// </summary>
public ZlgLinDriveService ZlgLinDriveService { get; }
/// <summary>
/// Mapper。
/// </summary>
public IMapper Mapper { get; }
private List<CanLinConfigPro> _canLinConfigPros = new List<CanLinConfigPro>();
private string? _opTip;
/// <summary>
/// 操作提示(用于 UI 状态展示)。
/// </summary>
public string? OpTip
{
get { return _opTip; }
set { _opTip = value; RaisePropertyChanged(); }
}
private string? _lastError;
/// <summary>
/// 最近一次错误信息(用于 UI 状态展示)。
/// </summary>
public string? LastError
{
get { return _lastError; }
set { _lastError = value; RaisePropertyChanged(); }
}
private ZlgCanMode _selectedMode;
/// <summary>
/// 模式选择CAN/CANFD单选
/// </summary>
public ZlgCanMode SelectedMode
{
get { return _selectedMode; }
set
{
_selectedMode = value;
RaisePropertyChanged();
RaisePropertyChanged(nameof(DbcPathTitle));
RaisePropertyChanged(nameof(SelectedModeKey));
RaisePropertyChanged(nameof(CurrentDbcPath));
RaisePropertyChanged(nameof(CurrentCycle));
RaisePropertyChanged(nameof(CurrentSchEnable));
RaisePropertyChanged(nameof(CanBaudRate));
RaisePropertyChanged(nameof(CanFdArbBaudRate));
RaisePropertyChanged(nameof(CanFdDataBaudRate));
RaisePropertyChanged(nameof(ConnectButtonText));
ZlgCanDriveService.Mode = value;
InitLoadCanConfigPro();
}
}
/// <summary>
/// 连接按钮文字(对齐 Toomoss 风格)。
/// </summary>
public string ConnectButtonText
{
get { return SelectedMode == ZlgCanMode.Can ? "连接CAN" : "连接CANFD"; }
}
/// <summary>
/// 绑定用:模式 KeyCan/CanFd
/// </summary>
public string SelectedModeKey
{
get { return SelectedMode == ZlgCanMode.Can ? "Can" : "CanFd"; }
set
{
if (string.Equals(value, "Can", StringComparison.OrdinalIgnoreCase))
{
SelectedMode = ZlgCanMode.Can;
return;
}
if (string.Equals(value, "CanFd", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "CanFD", StringComparison.OrdinalIgnoreCase))
{
SelectedMode = ZlgCanMode.CanFd;
return;
}
}
}
/// <summary>
/// DBC 路径标题。
/// </summary>
public string DbcPathTitle
{
get { return SelectedMode == ZlgCanMode.Can ? "CAN DBC 文件路径:" : "CANFD DBC 文件路径:"; }
}
private ObservableCollection<CanLinConfigPro>? _listCanLinConfigPro;
/// <summary>
/// 配置程序集合。
/// </summary>
public ObservableCollection<CanLinConfigPro>? ListCanLinConfigPro
{
get { return _listCanLinConfigPro; }
set { _listCanLinConfigPro = value; RaisePropertyChanged(); }
}
/// <summary>
/// 选中的配置程序。
/// </summary>
public CanLinConfigPro? SelectCanLinConfigPro { get; set; }
private ObservableCollection<CanDbcModel>? _listCanDbcModel;
/// <summary>
/// DBC 信号集合。
/// </summary>
public ObservableCollection<CanDbcModel>? ListCanDbcModel
{
get { return _listCanDbcModel; }
set { _listCanDbcModel = value; RaisePropertyChanged(); }
}
/// <summary>
/// 当前选中的 DBC 信号。
/// </summary>
public CanDbcModel? SelectedCanDbcModel { get; set; }
private CANConfigExdDto? _selectedCANConfigExdDto;
/// <summary>
/// CAN 配置 DTO。
/// </summary>
public CANConfigExdDto? SelectedCANConfigExdDto
{
get { return _selectedCANConfigExdDto; }
set { _selectedCANConfigExdDto = value; RaisePropertyChanged(); }
}
private CANFdConfigExdDto? _selectedCANFdConfigExdDto;
/// <summary>
/// CANFD 配置 DTO。
/// </summary>
public CANFdConfigExdDto? SelectedCANFdConfigExdDto
{
get { return _selectedCANFdConfigExdDto; }
set { _selectedCANFdConfigExdDto = value; RaisePropertyChanged(); }
}
private void InitLoadCanConfigPro()
{
var info = SelectedMode == ZlgCanMode.Can ? CANLIN.CAN : CANLIN.CANFD;
_canLinConfigPros = FreeSql.Select<CanLinConfigPro>()
.Where(a => a.CANLINInfo == info)
.Include(a => a.CANConfigExd)
.Include(a => a.CANFdConfigExd)
.IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))
.ToList();
ListCanLinConfigPro = new ObservableCollection<CanLinConfigPro>(_canLinConfigPros);
}
private void SyncSelectedConfig()
{
if (SelectCanLinConfigPro == null)
{
return;
}
if (SelectedMode == ZlgCanMode.Can)
{
SelectedCANConfigExdDto = Mapper.Map<CANConfigExdDto>(SelectCanLinConfigPro.CANConfigExd);
SelectedCANFdConfigExdDto = null;
}
else
{
SelectedCANFdConfigExdDto = Mapper.Map<CANFdConfigExdDto>(SelectCanLinConfigPro.CANFdConfigExd);
SelectedCANConfigExdDto = null;
}
RaisePropertyChanged(nameof(CurrentDbcPath));
RaisePropertyChanged(nameof(CurrentCycle));
RaisePropertyChanged(nameof(CurrentSchEnable));
RaisePropertyChanged(nameof(CanBaudRate));
RaisePropertyChanged(nameof(CanFdArbBaudRate));
RaisePropertyChanged(nameof(CanFdDataBaudRate));
}
/// <summary>
/// 当前 DBC 路径(随模式切换映射到对应 DTO
/// </summary>
public string? CurrentDbcPath
{
get
{
return SelectedMode == ZlgCanMode.Can
? SelectedCANConfigExdDto?.DbcPath
: SelectedCANFdConfigExdDto?.DbcPath;
}
set
{
if (SelectedMode == ZlgCanMode.Can)
{
if (SelectedCANConfigExdDto == null) return;
SelectedCANConfigExdDto.DbcPath = value;
}
else
{
if (SelectedCANFdConfigExdDto == null) return;
SelectedCANFdConfigExdDto.DbcPath = value;
}
RaisePropertyChanged();
}
}
/// <summary>
/// 当前周期(随模式切换映射到对应 DTO
/// </summary>
public int CurrentCycle
{
get
{
return SelectedMode == ZlgCanMode.Can
? (SelectedCANConfigExdDto?.Cycle ?? 0)
: (SelectedCANFdConfigExdDto?.Cycle ?? 0);
}
set
{
if (SelectedMode == ZlgCanMode.Can)
{
if (SelectedCANConfigExdDto == null) return;
SelectedCANConfigExdDto.Cycle = value;
}
else
{
if (SelectedCANFdConfigExdDto == null) return;
SelectedCANFdConfigExdDto.Cycle = value;
}
RaisePropertyChanged();
}
}
/// <summary>
/// 当前调度使能(随模式切换映射到对应 DTO
/// </summary>
public bool CurrentSchEnable
{
get
{
return SelectedMode == ZlgCanMode.Can
? (SelectedCANConfigExdDto?.SchEnable ?? false)
: (SelectedCANFdConfigExdDto?.SchEnable ?? false);
}
set
{
if (SelectedMode == ZlgCanMode.Can)
{
if (SelectedCANConfigExdDto == null) return;
SelectedCANConfigExdDto.SchEnable = value;
}
else
{
if (SelectedCANFdConfigExdDto == null) return;
SelectedCANFdConfigExdDto.SchEnable = value;
}
RaisePropertyChanged();
}
}
/// <summary>
/// CAN 波特率。
/// </summary>
public int CanBaudRate
{
get { return SelectedCANConfigExdDto?.BaudRate ?? 0; }
set
{
if (SelectedCANConfigExdDto == null) return;
SelectedCANConfigExdDto.BaudRate = value;
RaisePropertyChanged();
}
}
/// <summary>
/// CANFD 仲裁波特率。
/// </summary>
public int CanFdArbBaudRate
{
get { return SelectedCANFdConfigExdDto?.ArbBaudRate ?? 0; }
set
{
if (SelectedCANFdConfigExdDto == null) return;
SelectedCANFdConfigExdDto.ArbBaudRate = value;
RaisePropertyChanged();
}
}
/// <summary>
/// CANFD 数据波特率。
/// </summary>
public int CanFdDataBaudRate
{
get { return SelectedCANFdConfigExdDto?.DataBaudRate ?? 0; }
set
{
if (SelectedCANFdConfigExdDto == null) return;
SelectedCANFdConfigExdDto.DataBaudRate = value;
RaisePropertyChanged();
}
}
private void MatchSeletedAndCanDbcModel()
{
if (ListCanDbcModel == null || ListCanDbcModel.Count == 0) return;
if (SelectCanLinConfigPro?.CanLinConfigContents == null || SelectCanLinConfigPro.CanLinConfigContents.Count == 0) return;
foreach (var itemCanDbcModel in ListCanDbcModel)
{
var findData = SelectCanLinConfigPro.CanLinConfigContents.FindFirst(a => a.SignalName == itemCanDbcModel.SignalName);
if (findData != null)
{
switch (findData.RWInfo)
{
case RW.Write:
itemCanDbcModel.IsSeletedInfo = 1;
break;
case RW.Read:
itemCanDbcModel.IsSeletedInfo = 2;
break;
default:
itemCanDbcModel.IsSeletedInfo = 0;
break;
}
}
else
{
itemCanDbcModel.IsSeletedInfo = 0;
}
}
}
private DelegateCommand<object>? _canConfigProGridSelectionChangedCmd;
/// <summary>
/// 配置程序选中变化。
/// </summary>
public DelegateCommand<object> CanConfigProGridSelectionChangedCmd
{
get
{
if (_canConfigProGridSelectionChangedCmd == null)
{
_canConfigProGridSelectionChangedCmd = new DelegateCommand<object>(CanConfigProGridSelectionChangedCmdMethod);
}
return _canConfigProGridSelectionChangedCmd;
}
}
private void CanConfigProGridSelectionChangedCmdMethod(object par)
{
if (par == null) return;
if (par is SelectionChangedEventArgs) return;
if (par is CanLinConfigPro)
{
SelectCanLinConfigPro = par as CanLinConfigPro;
SyncSelectedConfig();
return;
}
var args = par as SelectionChangedEventArgs;
if (args == null || args.AddedItems == null || args.AddedItems.Count == 0) return;
var selected = args.AddedItems[0] as CanLinConfigPro;
if (selected == null) return;
SelectCanLinConfigPro = selected;
SyncSelectedConfig();
}
private DelegateCommand? _loadDbcCmd;
/// <summary>
/// 选择 DBC 文件。
/// </summary>
public DelegateCommand LoadDbcCmd
{
get
{
if (_loadDbcCmd == null)
{
_loadDbcCmd = new DelegateCommand(LoadDbcCmdMethod);
}
return _loadDbcCmd;
}
}
private void LoadDbcCmdMethod()
{
try
{
if (SelectCanLinConfigPro == null)
{
MessageBox.Show("选中CAN配置名称后再操作", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
OpenFileDialog openFileDialogInfo = new OpenFileDialog();
openFileDialogInfo.Filter = "(*.dbc;*.dbc)|*.dbc;*.dbc|all|*.*";
openFileDialogInfo.CheckFileExists = true;
openFileDialogInfo.CheckPathExists = true;
openFileDialogInfo.ShowDialog();
string fileName = openFileDialogInfo.FileName;
CurrentDbcPath = fileName;
}
catch
{
MessageBox.Show("可能未选择信息", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Hand);
}
}
private DelegateCommand<object>? _schEnableCmd;
/// <summary>
/// 调度使能写入驱动。
/// </summary>
public DelegateCommand<object> SchEnableCmd
{
get
{
if (_schEnableCmd == null)
{
_schEnableCmd = new DelegateCommand<object>(SchEnableCmdCall);
}
return _schEnableCmd;
}
}
private void SchEnableCmdCall(object par)
{
// 与旧 Toomoss 行为对齐UI 勾选后立即下发到驱动
ZlgCanDriveService.SchEnable = CurrentSchEnable;
}
private DelegateCommand<string>? _canOpCmd;
/// <summary>
/// CAN 操作命令。
/// </summary>
public DelegateCommand<string> CanOpCmd
{
get
{
if (_canOpCmd == null)
{
_canOpCmd = new DelegateCommand<string>(CanOpCmdMethod);
}
return _canOpCmd;
}
}
private void CanOpCmdMethod(string par)
{
if (string.IsNullOrWhiteSpace(par))
{
return;
}
try
{
switch (par)
{
case "Open":
if (ComActionService.IsCanToDoWork() == false)
{
MessageBox.Show("请关闭LIN连接后才能开启CAN同一个时刻只能有一个通信驱动压缩机", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (ZlgLinDriveService.OpenState)
{
MessageBox.Show("请先关闭 ZLG LIN 连接后再开启 ZLG CAN", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (SelectCanLinConfigPro == null)
{
MessageBox.Show("选中CAN配置名称后再操作", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (SelectedMode == ZlgCanMode.Can)
{
if (SelectedCANConfigExdDto == null)
{
MessageBox.Show("CAN配置为空", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
// ZLG 底层实际为 CANFD 通道CAN 经典帧使用 arbitration 波特率data 亦沿用,保持一致即可)
ZlgCanDriveService.UpdateConfig(0, (uint)SelectedCANConfigExdDto.BaudRate, (uint)SelectedCANConfigExdDto.BaudRate, resEnable: true);
}
else
{
if (SelectedCANFdConfigExdDto == null)
{
MessageBox.Show("CANFD配置为空", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
ZlgCanDriveService.UpdateConfig(0, (uint)SelectedCANFdConfigExdDto.ArbBaudRate, (uint)SelectedCANFdConfigExdDto.DataBaudRate, SelectedCANFdConfigExdDto.ResEnable);
}
ZlgCanDriveService.StartCanDrive();
if (ZlgCanDriveService.OpenState)
{
LastError = null;
OpTip = "CAN 已连接";
ConfigService.CanLinRunStateModel.CurSysSelectedCanLin = SelectedMode == ZlgCanMode.Can ? CanLinEnum.Can : CanLinEnum.CANFD;
}
else
{
OpTip = "CAN 连接失败";
MessageBox.Show("CAN 连接失败OpenState=false请检查设备/驱动/参数。", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
// 自动解析 DBC
if (!string.IsNullOrWhiteSpace(CurrentDbcPath))
{
ListCanDbcModel = ZlgCanDriveService.StartDbc(CurrentDbcPath);
MatchSeletedAndCanDbcModel();
}
break;
case "Close":
ZlgCanDriveService.CloseDevice();
ConfigService.CanLinRunStateModel.CurSysSelectedCanLin = CanLinEnum.No;
LastError = null;
OpTip = "CAN 已关闭";
break;
case "Parse":
if (!ZlgCanDriveService.OpenState)
{
MessageBox.Show("请先打开CAN后再解析", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (string.IsNullOrWhiteSpace(CurrentDbcPath))
{
MessageBox.Show("请选择DBC文件后再操作", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Hand);
return;
}
ListCanDbcModel = ZlgCanDriveService.StartDbc(CurrentDbcPath);
MatchSeletedAndCanDbcModel();
LastError = null;
OpTip = "DBC 已解析";
break;
case "CycleSend":
ZlgCanDriveService.IsCycleSend = !ZlgCanDriveService.IsCycleSend;
OpTip = ZlgCanDriveService.IsCycleSend ? "循环发送:已开启" : "循环发送:已关闭";
break;
case "CycleRecive":
ZlgCanDriveService.SetReceiveEnabled(!ZlgCanDriveService.IsCycleRevice);
OpTip = ZlgCanDriveService.IsCycleRevice ? "循环接收:已开启" : "循环接收:已关闭";
break;
case "Save":
if (SelectCanLinConfigPro == null)
{
MessageBox.Show("选中CAN配置名称后再操作", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (SelectedMode == ZlgCanMode.Can)
{
if (SelectedCANConfigExdDto == null) return;
FreeSql.Update<CANConfigExd>()
.Set(a => a.DbcPath, SelectedCANConfigExdDto.DbcPath)
.Set(a => a.Cycle, SelectedCANConfigExdDto.Cycle)
.Set(a => a.BaudRate, SelectedCANConfigExdDto.BaudRate)
.Set(a => a.SchEnable, SelectedCANConfigExdDto.SchEnable)
.Where(a => a.Id == SelectedCANConfigExdDto.Id)
.ExecuteUpdated();
}
else
{
if (SelectedCANFdConfigExdDto == null) return;
FreeSql.Update<CANFdConfigExd>()
.Set(a => a.DbcPath, SelectedCANFdConfigExdDto.DbcPath)
.Set(a => a.Cycle, SelectedCANFdConfigExdDto.Cycle)
.Set(a => a.DataBaudRate, SelectedCANFdConfigExdDto.DataBaudRate)
.Set(a => a.ArbBaudRate, SelectedCANFdConfigExdDto.ArbBaudRate)
.Set(a => a.ISOEnable, SelectedCANFdConfigExdDto.ISOEnable)
.Set(a => a.ResEnable, SelectedCANFdConfigExdDto.ResEnable)
.Set(a => a.SchEnable, SelectedCANFdConfigExdDto.SchEnable)
.Where(a => a.Id == SelectedCANFdConfigExdDto.Id)
.ExecuteUpdated();
}
InitLoadCanConfigPro();
LastError = null;
OpTip = "配置已保存";
break;
}
}
catch (Exception ex)
{
LastError = ex.Message;
OpTip = "操作失败";
LogService.Error($"ZLG CAN 操作失败:{par}{ex}");
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}