周立功开发过程1
This commit is contained in:
320
CapMachine.Wpf/Services/ZlgCanDriveService.cs
Normal file
320
CapMachine.Wpf/Services/ZlgCanDriveService.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// ZLG CAN/CANFD 驱动服务(共享设备句柄)。
|
||||
/// </summary>
|
||||
public sealed class ZlgCanDriveService : BindableBase
|
||||
{
|
||||
private readonly ILogService _log;
|
||||
|
||||
/// <summary>
|
||||
/// 共享的 ZLG 驱动实例(CAN/CANFD/LIN)。
|
||||
/// </summary>
|
||||
public ZlgCanFd200uDriver Driver { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前选中的配置程序(沿用原有 FreeSql 模型)。
|
||||
/// </summary>
|
||||
public CanLinConfigPro? SelectedCanLinConfigPro { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dbc 消息集合(用于 UI 绑定)。
|
||||
/// </summary>
|
||||
public ObservableCollection<CanDbcModel> ListCanDbcModel { get; private set; } = new ObservableCollection<CanDbcModel>();
|
||||
|
||||
private bool _dbcParserState;
|
||||
/// <summary>
|
||||
/// DBC 解析状态。
|
||||
/// </summary>
|
||||
public bool DbcParserState
|
||||
{
|
||||
get { return _dbcParserState; }
|
||||
private set { _dbcParserState = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private bool _openState;
|
||||
/// <summary>
|
||||
/// 设备打开状态。
|
||||
/// </summary>
|
||||
public bool OpenState
|
||||
{
|
||||
get { return _openState; }
|
||||
private set { _openState = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private ZlgCanMode _mode;
|
||||
/// <summary>
|
||||
/// CAN 模式(单选:CAN 或 CANFD)。
|
||||
/// </summary>
|
||||
public ZlgCanMode Mode
|
||||
{
|
||||
get { return _mode; }
|
||||
set { _mode = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送使能(与 UI 的调度表使能语义对齐)。
|
||||
/// </summary>
|
||||
public bool SchEnable
|
||||
{
|
||||
get { return Driver.SchEnable; }
|
||||
set { Driver.SchEnable = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用事件驱动发送。
|
||||
/// </summary>
|
||||
public bool IsCycleSend
|
||||
{
|
||||
get { return Driver.IsCycleSend; }
|
||||
set { Driver.IsCycleSend = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在循环接收(对齐 Toomoss:IsCycleRevice)。
|
||||
/// </summary>
|
||||
public bool IsCycleRevice
|
||||
{
|
||||
get { return Driver.IsReceiving; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最近是否发送成功(用于 UI 指示)。
|
||||
/// </summary>
|
||||
public bool IsSendOk
|
||||
{
|
||||
get { return Driver.IsSendOk; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最近是否接收成功(用于 UI 指示)。
|
||||
/// </summary>
|
||||
public bool IsReviceOk
|
||||
{
|
||||
get { return Driver.IsReviceOk; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 要发送的 CAN 指令数据。
|
||||
/// </summary>
|
||||
public List<CanCmdData> CmdData { get; } = new List<CanCmdData>();
|
||||
|
||||
private CanCmdData? SpeedCanCmdData { get; set; }
|
||||
|
||||
private uint _deviceIndex = 0;
|
||||
private ZlgCanFdChannelOptions _channel0 = new ZlgCanFdChannelOptions();
|
||||
|
||||
/// <summary>
|
||||
/// 构造。
|
||||
/// </summary>
|
||||
/// <param name="logService">日志服务。</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 CAN 配置信息,并将配置中的名称映射到 DBC 信号集合(用于 UI 显示)。
|
||||
/// </summary>
|
||||
/// <param name="selectedCanLinConfigPro">选中的配置。</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新配置(从 DTO/DB 同步到驱动)。
|
||||
/// </summary>
|
||||
/// <param name="deviceIndex">设备索引。</param>
|
||||
/// <param name="arbBaudRate">仲裁波特率(bps)。</param>
|
||||
/// <param name="dataBaudRate">数据波特率(bps)。</param>
|
||||
/// <param name="resEnable">终端电阻使能。</param>
|
||||
/// <param name="mergeReceive">是否合并接收。</param>
|
||||
/// <param name="mergeReceiveBufferFrames">合并接收缓冲帧数。</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开 CAN/CANFD(按 Mode)。
|
||||
/// </summary>
|
||||
public void StartCanDrive()
|
||||
{
|
||||
if (OpenState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Driver.OpenAndInitCan(_deviceIndex, _channel0);
|
||||
Driver.StartReceiveLoop(_channel0.EnableMergeReceive, _channel0.MergeReceiveBufferFrames);
|
||||
OpenState = Driver.OpenState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使能/停止循环接收。
|
||||
/// </summary>
|
||||
/// <param name="enable">true=启动接收线程,false=停止接收线程。</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭设备(会同时关闭共享的 LIN 通道)。
|
||||
/// </summary>
|
||||
public void CloseDevice()
|
||||
{
|
||||
try
|
||||
{
|
||||
Driver.Close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
OpenState = Driver.OpenState;
|
||||
DbcParserState = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载 DBC。
|
||||
/// </summary>
|
||||
/// <param name="path">DBC 路径。</param>
|
||||
public ObservableCollection<CanDbcModel> StartDbc(string path)
|
||||
{
|
||||
if (!OpenState)
|
||||
{
|
||||
throw new InvalidOperationException("请先打开设备后再加载 DBC。");
|
||||
}
|
||||
|
||||
ListCanDbcModel = Driver.StartDbc(path);
|
||||
DbcParserState = ListCanDbcModel != null && ListCanDbcModel.Count > 0;
|
||||
return ListCanDbcModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载要发送的数据(订阅数据变化事件)。
|
||||
/// </summary>
|
||||
/// <param name="cmdData">指令数据集合。</param>
|
||||
public void LoadCmdDataToDrive(List<CanCmdData> cmdData)
|
||||
{
|
||||
var list = cmdData ?? new List<CanCmdData>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动发送(目前对齐原服务:仅发送转速)。
|
||||
/// </summary>
|
||||
/// <param name="speedData">转速。</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ZLG CAN 工作模式。
|
||||
/// </summary>
|
||||
public enum ZlgCanMode
|
||||
{
|
||||
/// <summary>
|
||||
/// CAN 经典帧。
|
||||
/// </summary>
|
||||
Can = 0,
|
||||
/// <summary>
|
||||
/// CAN FD。
|
||||
/// </summary>
|
||||
CanFd = 1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user