using CapMachine.Model.CANLIN;
using CapMachine.Wpf.CanDrive;
using CapMachine.Wpf.CanDrive.ZlgCan;
using ImTools;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace CapMachine.Wpf.Services
{
///
/// ZLG CAN/CANFD 驱动服务(共享设备句柄)。
///
public sealed class ZlgCanDriveService : BindableBase
{
private readonly ILogService _log;
///
/// 共享的 ZLG 驱动实例(CAN/CANFD/LIN)。
///
public ZlgCanFd200uDriver Driver { get; }
///
/// 当前选中的配置程序(沿用原有 FreeSql 模型)。
///
public CanLinConfigPro? SelectedCanLinConfigPro { get; set; }
///
/// Dbc 消息集合(用于 UI 绑定)。
///
public ObservableCollection ListCanDbcModel { get; private set; } = new ObservableCollection();
private bool _dbcParserState;
///
/// DBC 解析状态。
///
public bool DbcParserState
{
get { return _dbcParserState; }
private set { _dbcParserState = value; RaisePropertyChanged(); }
}
private bool _openState;
///
/// 设备打开状态。
///
public bool OpenState
{
get { return _openState; }
private set { _openState = value; RaisePropertyChanged(); }
}
private ZlgCanMode _mode;
///
/// CAN 模式(单选:CAN 或 CANFD)。
///
public ZlgCanMode Mode
{
get { return _mode; }
set { _mode = value; RaisePropertyChanged(); }
}
///
/// 发送使能(与 UI 的调度表使能语义对齐)。
///
public bool SchEnable
{
get { return Driver.SchEnable; }
set { Driver.SchEnable = value; RaisePropertyChanged(); }
}
///
/// 是否启用事件驱动发送。
///
public bool IsCycleSend
{
get { return Driver.IsCycleSend; }
set { Driver.IsCycleSend = value; RaisePropertyChanged(); }
}
///
/// 是否正在循环接收(对齐 Toomoss:IsCycleRevice)。
///
public bool IsCycleRevice
{
get { return Driver.IsReceiving; }
}
///
/// 最近是否发送成功(用于 UI 指示)。
///
public bool IsSendOk
{
get { return Driver.IsSendOk; }
}
///
/// 最近是否接收成功(用于 UI 指示)。
///
public bool IsReviceOk
{
get { return Driver.IsReviceOk; }
}
///
/// 要发送的 CAN 指令数据。
///
public List CmdData { get; } = new List();
private CanCmdData? SpeedCanCmdData { get; set; }
private uint _deviceIndex = 0;
private ZlgCanFdChannelOptions _channel0 = new ZlgCanFdChannelOptions();
///
/// 构造。
///
/// 日志服务。
public ZlgCanDriveService(ILogService logService)
{
_log = logService;
Driver = new ZlgCanFd200uDriver(logService);
Driver.PropertyChanged += (_, __) =>
{
OpenState = Driver.OpenState;
RaisePropertyChanged(nameof(IsCycleRevice));
RaisePropertyChanged(nameof(IsSendOk));
RaisePropertyChanged(nameof(IsReviceOk));
};
OpenState = Driver.OpenState;
Mode = ZlgCanMode.Can;
}
///
/// 初始化 CAN 配置信息,并将配置中的名称映射到 DBC 信号集合(用于 UI 显示)。
///
/// 选中的配置。
public void InitCanConfig(CanLinConfigPro selectedCanLinConfigPro)
{
SelectedCanLinConfigPro = selectedCanLinConfigPro;
if (SelectedCanLinConfigPro?.CanLinConfigContents == null) return;
foreach (var item in SelectedCanLinConfigPro.CanLinConfigContents)
{
var find = ListCanDbcModel.FindFirst(a => a.SignalName == item.SignalName);
if (find != null)
{
find.Name = item.Name;
}
}
}
///
/// 更新配置(从 DTO/DB 同步到驱动)。
///
/// 设备索引。
/// 仲裁波特率(bps)。
/// 数据波特率(bps)。
/// 终端电阻使能。
/// 是否合并接收。
/// 合并接收缓冲帧数。
public void UpdateConfig(uint deviceIndex, uint arbBaudRate, uint dataBaudRate, bool resEnable, bool mergeReceive = false, int mergeReceiveBufferFrames = 100)
{
_deviceIndex = deviceIndex;
_channel0.ArbitrationBaudRate = arbBaudRate;
_channel0.DataBaudRate = dataBaudRate;
_channel0.EnableInternalResistance = resEnable;
_channel0.EnableMergeReceive = mergeReceive;
_channel0.MergeReceiveBufferFrames = mergeReceiveBufferFrames;
}
///
/// 打开 CAN/CANFD(按 Mode)。
///
public void StartCanDrive()
{
if (OpenState)
{
return;
}
Driver.OpenAndInitCan(_deviceIndex, _channel0);
Driver.StartReceiveLoop(_channel0.EnableMergeReceive, _channel0.MergeReceiveBufferFrames);
OpenState = Driver.OpenState;
}
///
/// 使能/停止循环接收。
///
/// true=启动接收线程,false=停止接收线程。
public void SetReceiveEnabled(bool enable)
{
if (!OpenState)
{
throw new InvalidOperationException("设备未连接,无法切换循环接收。");
}
if (enable)
{
if (!Driver.IsReceiving)
{
Driver.StartReceiveLoop(_channel0.EnableMergeReceive, _channel0.MergeReceiveBufferFrames);
}
}
else
{
if (Driver.IsReceiving)
{
Driver.StopReceiveLoop();
}
}
RaisePropertyChanged(nameof(IsCycleRevice));
}
///
/// 关闭设备(会同时关闭共享的 LIN 通道)。
///
public void CloseDevice()
{
try
{
Driver.Close();
}
finally
{
OpenState = Driver.OpenState;
DbcParserState = false;
}
}
///
/// 加载 DBC。
///
/// DBC 路径。
public ObservableCollection StartDbc(string path)
{
if (!OpenState)
{
throw new InvalidOperationException("请先打开设备后再加载 DBC。");
}
ListCanDbcModel = Driver.StartDbc(path);
DbcParserState = ListCanDbcModel != null && ListCanDbcModel.Count > 0;
return ListCanDbcModel;
}
///
/// 加载要发送的数据(订阅数据变化事件)。
///
/// 指令数据集合。
public void LoadCmdDataToDrive(List cmdData)
{
var list = cmdData ?? new List();
CmdData.Clear();
CmdData.AddRange(list);
foreach (var item in CmdData)
{
if (string.Equals(item.ConfigName, "转速", StringComparison.Ordinal))
{
SpeedCanCmdData = item;
}
}
Driver.LoadCmdDataToDrive(CmdData, channelIndex: 0, frameType: Mode == ZlgCanMode.Can ? (byte)ZDBC.FT_CAN : (byte)ZDBC.FT_CANFD);
}
///
/// 手动发送(目前对齐原服务:仅发送转速)。
///
/// 转速。
public void SendMsgToCanDrive(double speedData)
{
if (!OpenState)
{
return;
}
if (SpeedCanCmdData != null)
{
SpeedCanCmdData.SignalCmdValue = speedData;
}
else
{
_log.Warn("未配置转速指令项(ConfigName=转速),忽略手动发送。");
}
// 若未启用事件驱动发送,则这里主动发送一次(与旧行为兼容)
if (!IsCycleSend || !SchEnable)
{
var firstMsg = CmdData.FirstOrDefault()?.MsgName;
if (!string.IsNullOrWhiteSpace(firstMsg))
{
Driver.SendOneMsgByCmdData(firstMsg, 0, Mode == ZlgCanMode.Can ? (byte)ZDBC.FT_CAN : (byte)ZDBC.FT_CANFD);
}
}
}
}
///
/// ZLG CAN 工作模式。
///
public enum ZlgCanMode
{
///
/// CAN 经典帧。
///
Can = 0,
///
/// CAN FD。
///
CanFd = 1
}
}