| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- using System;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Threading.Tasks;
- using System.Windows;
- using Prism.Commands;
- using TeamAAS.Feeder.Interfaces;
- using TeamAAS.Feeder.Models;
- using TeamAAS.Views;
- namespace TeamAAS.ViewModels
- {
- /// <summary>
- /// 供料器扩展功能(partial SettingViewModel):
- /// 系统参数(超时)、料斗输入输出、输入触发、收发通讯日志、Feeder IP 自动搜索。
- /// 命令均采用懒加载,避免改动主构造函数。
- /// </summary>
- public partial class SettingViewModel
- {
- private const string FeederLogSource = "Feeder";
- #region 收发通讯日志(SendLog/ReceiveLog)
- /// <summary>收发报文日志(仅界面显示,不落文件)。</summary>
- public ObservableCollection<FeederCommLogEntry> CommLogs { get; }
- = new ObservableCollection<FeederCommLogEntry>();
- private const int MaxCommLogEntries = 500;
- /// <summary>订阅自 IFeeder.MessageExchanged,可能在非 UI 线程触发。</summary>
- private void OnFeederMessageExchanged(IFeeder dev, string content, bool isSend)
- {
- var entry = new FeederCommLogEntry
- {
- Time = DateTime.Now,
- IsSend = isSend,
- Content = content
- };
- var dispatcher = Application.Current?.Dispatcher;
- if (dispatcher != null && !dispatcher.CheckAccess())
- dispatcher.BeginInvoke(new Action(() => AppendCommLog(entry)));
- else
- AppendCommLog(entry);
- }
- private void AppendCommLog(FeederCommLogEntry entry)
- {
- CommLogs.Add(entry);
- while (CommLogs.Count > MaxCommLogEntries)
- CommLogs.RemoveAt(0);
- }
- private DelegateCommand _clearCommLogCommand;
- public DelegateCommand ClearCommLogCommand =>
- _clearCommLogCommand ?? (_clearCommLogCommand = new DelegateCommand(() => CommLogs.Clear()));
- #endregion
- #region 系统参数(超时/背光)
- private FeederSystemParam _systemParam = new FeederSystemParam();
- public FeederSystemParam SystemParam
- {
- get { return _systemParam; }
- set { SetProperty(ref _systemParam, value); }
- }
- private DelegateCommand _readSystemParamCommand;
- public DelegateCommand ReadSystemParamCommand =>
- _readSystemParamCommand ?? (_readSystemParamCommand = new DelegateCommand(async () => await ReadSystemParamAsync()));
- private DelegateCommand _writeSystemParamCommand;
- public DelegateCommand WriteSystemParamCommand =>
- _writeSystemParamCommand ?? (_writeSystemParamCommand = new DelegateCommand(async () => await WriteSystemParamAsync()));
- private async Task ReadSystemParamAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- FeederStatusText = "读取系统参数...";
- var p = await _activeDevice.GetSystemParamAsync();
- SystemParam = p;
- FeederStatusText = "系统参数已读取";
- AppLogger.Info($"读取系统参数: 背光超时={p.LightTimeout} 亮度={p.LightBrightness} 闪烁={p.LightFlashTime} 平台振动超时={p.PlatShakeTimeout} 料斗振动超时={p.HopperShakeTimeout}", FeederLogSource);
- }
- catch (Exception ex)
- {
- FeederStatusText = "读取系统参数失败";
- AppLogger.Error("读取供料器系统参数失败", ex, FeederLogSource);
- DialogHelper.ShowError("读取系统参数失败", ex);
- }
- }
- private async Task WriteSystemParamAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- FeederStatusText = "写入系统参数...";
- var p = SystemParam;
- await _activeDevice.SetSystemParamAsync(p);
- FeederStatusText = "系统参数已写入并保存";
- AppLogger.Info($"写入系统参数: 背光超时={p.LightTimeout} 亮度={p.LightBrightness} 闪烁={p.LightFlashTime} 平台振动超时={p.PlatShakeTimeout} 料斗振动超时={p.HopperShakeTimeout}", FeederLogSource);
- DialogHelper.Success("系统参数已写入设备");
- }
- catch (Exception ex)
- {
- FeederStatusText = "写入系统参数失败";
- AppLogger.Error("写入供料器系统参数失败", ex, FeederLogSource);
- DialogHelper.ShowError("写入系统参数失败", ex);
- }
- }
- #endregion
- #region 料斗输入输出
- /// <summary>料斗输出参数组序号(0~25)。</summary>
- public int[] HopperGroupList { get; } = Enumerable.Range(0, 26).ToArray();
- private int _selectedHopperGroup;
- public int SelectedHopperGroup
- {
- get { return _selectedHopperGroup; }
- set { SetProperty(ref _selectedHopperGroup, value); }
- }
- private HopperOutputParam _hopperParam = new HopperOutputParam();
- public HopperOutputParam HopperParam
- {
- get { return _hopperParam; }
- set { SetProperty(ref _hopperParam, value); }
- }
- private DelegateCommand _readHopperParamCommand;
- public DelegateCommand ReadHopperParamCommand =>
- _readHopperParamCommand ?? (_readHopperParamCommand = new DelegateCommand(async () => await ReadHopperParamAsync()));
- private DelegateCommand _writeHopperParamCommand;
- public DelegateCommand WriteHopperParamCommand =>
- _writeHopperParamCommand ?? (_writeHopperParamCommand = new DelegateCommand(async () => await WriteHopperParamAsync()));
- private DelegateCommand _runHopperOutputCommand;
- public DelegateCommand RunHopperOutputCommand =>
- _runHopperOutputCommand ?? (_runHopperOutputCommand = new DelegateCommand(async () => await RunHopperOutputAsync()));
- private DelegateCommand _stopHopperOutputCommand;
- public DelegateCommand StopHopperOutputCommand =>
- _stopHopperOutputCommand ?? (_stopHopperOutputCommand = new DelegateCommand(async () => await StopHopperOutputAsync()));
- private async Task ReadHopperParamAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- FeederStatusText = $"读取料斗输出参数(组 {SelectedHopperGroup})...";
- HopperParam = await _activeDevice.GetHopperParamAsync(SelectedHopperGroup);
- FeederStatusText = "料斗输出参数已读取";
- AppLogger.Info($"读取料斗输出参数 组={SelectedHopperGroup}", FeederLogSource);
- }
- catch (Exception ex)
- {
- FeederStatusText = "读取料斗参数失败";
- AppLogger.Error("读取料斗输出参数失败", ex, FeederLogSource);
- DialogHelper.ShowError("读取料斗参数失败", ex);
- }
- }
- private async Task WriteHopperParamAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- FeederStatusText = $"下载料斗输出参数(组 {SelectedHopperGroup})...";
- await _activeDevice.SetHopperParamAsync(SelectedHopperGroup, HopperParam);
- FeederStatusText = "料斗输出参数已下载";
- AppLogger.Info($"下载料斗输出参数 组={SelectedHopperGroup} 数字1={HopperParam.HopperDigitalOutput1} 模拟1={HopperParam.HopperAnalogOutput1} 数字2={HopperParam.HopperDigitalOutput2} 模拟2={HopperParam.HopperAnalogOutput2} 持续={HopperParam.HopperDuration}ms", FeederLogSource);
- DialogHelper.Success("料斗输出参数已下载到设备");
- }
- catch (Exception ex)
- {
- FeederStatusText = "下载料斗参数失败";
- AppLogger.Error("下载料斗输出参数失败", ex, FeederLogSource);
- DialogHelper.ShowError("下载料斗参数失败", ex);
- }
- }
- private async Task RunHopperOutputAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- int id = SelectedHopperGroup + 1;
- FeederStatusText = $"执行料斗动作 {id}...";
- await _activeDevice.RunHopperOutputAsync(id, HopperParam.HopperDuration > 0 ? HopperParam.HopperDuration : (int?)null);
- FeederStatusText = $"料斗动作 {id} 执行完成";
- AppLogger.Info($"执行料斗动作 id={id} 持续={HopperParam.HopperDuration}ms", FeederLogSource);
- }
- catch (Exception ex)
- {
- FeederStatusText = "料斗动作执行失败";
- AppLogger.Error("执行料斗动作失败", ex, FeederLogSource);
- DialogHelper.ShowError("料斗动作执行失败", ex);
- }
- }
- private async Task StopHopperOutputAsync()
- {
- if (_activeDevice == null) return;
- try
- {
- await _activeDevice.StopHopperOutputAsync();
- FeederStatusText = "料斗振动已停止";
- AppLogger.Info("停止料斗振动", FeederLogSource);
- }
- catch (Exception ex)
- {
- AppLogger.Error("停止料斗振动失败", ex, FeederLogSource);
- DialogHelper.ShowError("停止料斗振动失败", ex);
- }
- }
- #endregion
- #region 输入触发序列ID
- private int _inputTrigger1;
- public int InputTrigger1
- {
- get { return _inputTrigger1; }
- set { SetProperty(ref _inputTrigger1, value); }
- }
- private int _inputTrigger2;
- public int InputTrigger2
- {
- get { return _inputTrigger2; }
- set { SetProperty(ref _inputTrigger2, value); }
- }
- private DelegateCommand _readInputTriggerCommand;
- public DelegateCommand ReadInputTriggerCommand =>
- _readInputTriggerCommand ?? (_readInputTriggerCommand = new DelegateCommand(async () => await ReadInputTriggerAsync()));
- private DelegateCommand _writeInputTriggerCommand;
- public DelegateCommand WriteInputTriggerCommand =>
- _writeInputTriggerCommand ?? (_writeInputTriggerCommand = new DelegateCommand(async () => await WriteInputTriggerAsync()));
- private async Task ReadInputTriggerAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- InputTrigger1 = await _activeDevice.GetInputTriggerAsync(0);
- InputTrigger2 = await _activeDevice.GetInputTriggerAsync(1);
- FeederStatusText = $"输入触发已读取: 输入1={InputTrigger1} 输入2={InputTrigger2}";
- AppLogger.Info($"读取输入触发序列ID: 输入1={InputTrigger1} 输入2={InputTrigger2}", FeederLogSource);
- }
- catch (Exception ex)
- {
- FeederStatusText = "读取输入触发失败";
- AppLogger.Error("读取输入触发序列ID失败", ex, FeederLogSource);
- DialogHelper.ShowError("读取输入触发失败", ex);
- }
- }
- private async Task WriteInputTriggerAsync()
- {
- if (!EnsureFeederConnected()) return;
- try
- {
- await _activeDevice.SetInputTriggerAsync(0, InputTrigger1);
- await _activeDevice.SetInputTriggerAsync(1, InputTrigger2);
- FeederStatusText = "输入触发已写入";
- AppLogger.Info($"写入输入触发序列ID: 输入1={InputTrigger1} 输入2={InputTrigger2}", FeederLogSource);
- DialogHelper.Success("输入触发参数已写入设备");
- }
- catch (Exception ex)
- {
- FeederStatusText = "写入输入触发失败";
- AppLogger.Error("写入输入触发序列ID失败", ex, FeederLogSource);
- DialogHelper.ShowError("写入输入触发失败", ex);
- }
- }
- #endregion
- #region Feeder IP 自动搜索
- private DelegateCommand _searchFeederIpCommand;
- public DelegateCommand SearchFeederIpCommand =>
- _searchFeederIpCommand ?? (_searchFeederIpCommand = new DelegateCommand(OpenFeederSearchDialog));
- private void OpenFeederSearchDialog()
- {
- if (SelectedFeeder == null)
- {
- DialogHelper.Warning("请先选择或添加一个供料器");
- return;
- }
- var dialog = new SearchFeederWindow { Owner = Application.Current.MainWindow };
- if (dialog.ShowDialog() == true && dialog.SelectedResult != null)
- {
- var r = dialog.SelectedResult;
- SelectedFeeder.IP = r.IP;
- SelectedFeeder.Port = r.Port;
- FeederStatusText = $"已回填 {r.IP}:{r.Port}";
- AppLogger.Info($"搜索回填 Feeder IP: {r.FeederType} {r.IP}:{r.Port} MAC={r.MAC}", FeederLogSource);
- }
- }
- #endregion
- /// <summary>确保已连接供料器;未连接则提示并返回 false。</summary>
- private bool EnsureFeederConnected()
- {
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return false;
- }
- return true;
- }
- }
- /// <summary>供料器收发报文日志条目(界面 SendLog/ReceiveLog 显示用)。</summary>
- public class FeederCommLogEntry
- {
- public DateTime Time { get; set; }
- public bool IsSend { get; set; }
- public string Content { get; set; }
- public string Direction => IsSend ? "TX →" : "RX ←";
- public string TimeText => Time.ToString("HH:mm:ss.fff");
- public string Display => $"{TimeText} {Direction} {Content}";
- }
- }
|