using CapMachine.Core;
using CapMachine.Model.CANLIN;
using CapMachine.Wpf.Dtos;
using CapMachine.Wpf.Services;
using FreeSql;
using Prism.Commands;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace CapMachine.Wpf.ViewModels
{
///
/// ZLG CAN/LIN 读写配置三栏管理弹窗 ViewModel。
/// 左侧:写入/读取配置;右侧:信号全集候选池;统一保存落库。
///
public class DialogZlgCanLinRwConfigViewModel : DialogViewModel
{
private readonly IFreeSql _freeSql;
private readonly ILogService _logService;
private readonly LogicRuleService _logicRuleService;
private long _canLinConfigProId;
private bool _enableHardwareCycleSchedule = true;
private bool _useCanFdSchedule;
///
/// 是否启用“加入定时调度表(ZLG auto_send)”能力。
/// 说明:该能力仅适用于 ZLG CAN/CANFD 硬件 auto_send;LIN 当前使用软件调度,不允许写入 CANScheduleConfig。
///
public bool EnableHardwareCycleSchedule
{
get { return _enableHardwareCycleSchedule; }
private set
{
_enableHardwareCycleSchedule = value;
RaisePropertyChanged();
RaisePropertyChanged(nameof(CanAddCycleTimeSch));
}
}
///
/// 是否允许执行“加入定时调度表”操作。
/// 说明:
/// - 需要 打开(调用方允许硬件调度表能力);
/// - 且弹窗处于可编辑态()。
///
public bool CanAddCycleTimeSch
{
get { return EnableHardwareCycleSchedule && IsEditable; }
}
///
/// 是否使用 CANFD 调度表(决定“加入定时调度表”写入 还是 )。
///
public bool UseCanFdSchedule
{
get { return _useCanFdSchedule; }
private set { _useCanFdSchedule = value; RaisePropertyChanged(); }
}
///
/// 构造函数。
///
/// FreeSql。
/// 日志。
/// 逻辑规则服务。
public DialogZlgCanLinRwConfigViewModel(IFreeSql freeSql, ILogService logService, LogicRuleService logicRuleService)
{
_freeSql = freeSql;
_logService = logService;
_logicRuleService = logicRuleService;
Title = "读写设置";
WriteConfigs = new ObservableCollection();
ReadConfigs = new ObservableCollection();
SignalCandidates = new ObservableCollection();
SignalTree = new ObservableCollection();
SignalCandidatesView = CollectionViewSource.GetDefaultView(SignalCandidates);
SignalCandidatesView.Filter = FilterSignalCandidate;
WriteNameCbxItems = new ObservableCollection()
{
new CbxItems(){ Key="转速",Text="转速"},
new CbxItems(){ Key="功率限制",Text="功率限制"},
new CbxItems(){ Key="使能",Text="使能"},
new CbxItems(){ Key="Anti_Sleep",Text="Anti_Sleep"},
new CbxItems(){ Key="PTC使能",Text="PTC使能"},
new CbxItems(){ Key="PTC功率",Text="PTC功率"},
new CbxItems(){ Key="PTC水流量",Text="PTC水流量"},
new CbxItems(){ Key="PTC水温",Text="PTC水温"},
};
ReadNameCbxItems = new ObservableCollection()
{
new CbxItems(){ Key="通讯Cmp转速",Text="通讯Cmp转速"},
new CbxItems(){ Key="通讯Cmp母线电压",Text="通讯Cmp母线电压"},
new CbxItems(){ Key="通讯Cmp母线电流",Text="通讯Cmp母线电流"},
new CbxItems(){ Key="通讯Cmp逆变器温度",Text="通讯Cmp逆变器温度"},
new CbxItems(){ Key="通讯Cmp相电流",Text="通讯Cmp相电流"},
new CbxItems(){ Key="通讯Cmp功率",Text="通讯Cmp功率"},
new CbxItems(){ Key="通讯Cmp芯片温度",Text="通讯Cmp芯片温度"},
new CbxItems(){ Key="通讯PTC入水温度",Text="通讯PTC入水温度"},
new CbxItems(){ Key="通讯PTC出水温度",Text="通讯PTC出水温度"},
new CbxItems(){ Key="通讯PTC峰值电流",Text="通讯PTC峰值电流"},
new CbxItems(){ Key="通讯PTC母线电流",Text="通讯PTC母线电流"},
new CbxItems(){ Key="通讯PTC膜温",Text="通讯PTC膜温"},
new CbxItems(){ Key="通讯PTC模块温度",Text="通讯PTC模块温度"},
};
IsEditable = true;
}
///
/// 是否允许编辑(由调用方根据 Active/打开状态决定)。
///
public bool IsEditable { get; private set; }
///
/// 逻辑规则集合(下拉框 ItemsSource)。
///
public IReadOnlyList LogicRuleDtos => _logicRuleService.LogicRuleDtos;
///
/// 写入配置“名称”下拉框集合(参考 CANConfigViewModel)。
///
public ObservableCollection WriteNameCbxItems { get; private set; }
///
/// 读取配置“名称”下拉框集合(参考 CANConfigViewModel)。
///
public ObservableCollection ReadNameCbxItems { get; private set; }
///
/// 写入配置集合。
///
public ObservableCollection WriteConfigs { get; private set; }
///
/// 读取配置集合。
///
public ObservableCollection ReadConfigs { get; private set; }
///
/// 信号候选集合(右侧池)。
///
public ObservableCollection SignalCandidates { get; private set; }
///
/// 信号树(按帧分组)。
///
public ObservableCollection SignalTree { get; private set; }
///
/// 候选信号视图(含过滤)。
///
public ICollectionView SignalCandidatesView { get; private set; }
private string? _signalFilterText;
///
/// 信号过滤文本(按 MsgName/SignalName/Name/Desc 匹配)。
///
public string? SignalFilterText
{
get { return _signalFilterText; }
set
{
_signalFilterText = value;
RaisePropertyChanged();
SignalCandidatesView.Refresh();
RebuildSignalTree();
}
}
///
/// 当前选中的候选信号。
///
public SignalCandidate? SelectedSignalCandidate { get; set; }
///
/// 当前选中的写入配置行。
///
public CanLinRWConfigDto? SelectedWriteConfig { get; set; }
private DelegateCommand? _addCycleTimeSch;
///
/// 将当前选中的写入配置对应的报文加入“硬件定时调度表”(ZLG auto_send)。
///
///
/// 说明:
/// - 调度表按“报文/帧(MsgFrameName)”维度配置;同一报文可包含多个写入信号,但调度表只需要一条。
/// - 该命令会直接落库到 ,随后由主界面刷新配置程序时加载显示。
///
public DelegateCommand AddCycleTimeSch => _addCycleTimeSch ??= new DelegateCommand(AddCycleTimeSchMethod);
///
/// 加入定时调度表命令处理。
///
private void AddCycleTimeSchMethod()
{
if (!EnableHardwareCycleSchedule)
{
MessageBox.Show("当前模式不支持加入硬件定时调度表(LIN 使用软件调度表)", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (!IsEditable)
{
MessageBox.Show("当前状态禁止修改", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (_canLinConfigProId <= 0)
{
MessageBox.Show("配置程序ID无效,无法加入调度表", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (SelectedWriteConfig == null)
{
MessageBox.Show("请先选中写入配置中的一行", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
if (string.IsNullOrWhiteSpace(SelectedWriteConfig.MsgFrameName))
{
MessageBox.Show("写入配置的【消息名称】为空,无法加入调度表", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
return;
}
var msgName = SelectedWriteConfig.MsgFrameName.Trim();
try
{
var exists = UseCanFdSchedule
? _freeSql.Select()
.Where(a => a.CanLinConfigProId == _canLinConfigProId)
.Where(a => a.MsgName == msgName)
.Any()
: _freeSql.Select()
.Where(a => a.CanLinConfigProId == _canLinConfigProId)
.Where(a => a.MsgName == msgName)
.Any();
if (exists)
{
MessageBox.Show($"该报文已在定时调度表中:{msgName}", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
if (UseCanFdSchedule)
{
_freeSql.Insert(new CANFdScheduleConfig
{
CanLinConfigProId = _canLinConfigProId,
MsgName = msgName,
Cycle = 100,
OrderSend = 1,
SchTabIndex = 0,
}).ExecuteAffrows();
}
else
{
_freeSql.Insert(new CANScheduleConfig
{
CanLinConfigProId = _canLinConfigProId,
MsgName = msgName,
Cycle = 100,
OrderSend = 1,
SchTabIndex = 0,
}).ExecuteAffrows();
}
MessageBox.Show($"已加入定时调度表:{msgName}(默认周期 100ms,可在调度表中修改)", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
_logService.Error($"加入定时调度表失败:{msgName},{ex}");
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
///
/// 当前选中的读取配置行。
///
public CanLinRWConfigDto? SelectedReadConfig { get; set; }
private DelegateCommand