|
|
@@ -5,6 +5,7 @@ using OxyPlot;
|
|
|
using OxyPlot.Axes;
|
|
|
using OxyPlot.Legends;
|
|
|
using OxyPlot.Series;
|
|
|
+using OxyPlot.Wpf;
|
|
|
using Prism.Commands;
|
|
|
using Prism.Events;
|
|
|
using Prism.Ioc;
|
|
|
@@ -13,6 +14,7 @@ using Prism.Regions;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
+using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Windows;
|
|
|
@@ -29,6 +31,7 @@ using TeamAAS_VP.Resources.Languages;
|
|
|
using TeamAAS_VP.Services;
|
|
|
using TeamAAS_VP.ViewModels.DebugMod;
|
|
|
using TeamAAS_VP.Views.DebugMod;
|
|
|
+using static TeamAAS_VP.Models.SystemConfiguration;
|
|
|
|
|
|
namespace TeamAAS_VP.ViewModels
|
|
|
{
|
|
|
@@ -43,7 +46,7 @@ namespace TeamAAS_VP.ViewModels
|
|
|
|
|
|
#region 属性
|
|
|
|
|
|
- private ObservableCollection<TaskMessage> messageQueue=new ObservableCollection<TaskMessage>();
|
|
|
+ private ObservableCollection<TaskMessage> messageQueue = new ObservableCollection<TaskMessage>();
|
|
|
|
|
|
/// <summary>
|
|
|
/// 运行信息队列
|
|
|
@@ -51,7 +54,7 @@ namespace TeamAAS_VP.ViewModels
|
|
|
public ObservableCollection<TaskMessage> MessageQueue
|
|
|
{
|
|
|
get { return messageQueue; }
|
|
|
- set { SetProperty(ref messageQueue,value); }
|
|
|
+ set { SetProperty(ref messageQueue, value); }
|
|
|
}
|
|
|
|
|
|
private ObservableCollection<ProductModel> _ProductList;
|
|
|
@@ -82,14 +85,14 @@ namespace TeamAAS_VP.ViewModels
|
|
|
public ProductModel SelectProduct
|
|
|
{
|
|
|
get { return _SelectProduct; }
|
|
|
- set { SetProperty(ref _SelectProduct,value); }
|
|
|
+ set { SetProperty(ref _SelectProduct, value); }
|
|
|
}
|
|
|
|
|
|
private bool CanLoad
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
- if (SelectProduct!=null && IsLoadProduct)
|
|
|
+ if (SelectProduct != null && IsLoadProduct)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
@@ -124,6 +127,16 @@ namespace TeamAAS_VP.ViewModels
|
|
|
set { SetProperty(ref _CurrentProduct, value); }
|
|
|
}
|
|
|
|
|
|
+ private ObservableCollection<PlotModel> _PressurePlotModels = new ObservableCollection<PlotModel>();
|
|
|
+ /// <summary>
|
|
|
+ /// 每个元素是一个 PlotModel,对应一个压力传感器
|
|
|
+ /// </summary>
|
|
|
+ public ObservableCollection<PlotModel> PressurePlotModels
|
|
|
+ {
|
|
|
+ get { return _PressurePlotModels; }
|
|
|
+ set { SetProperty(ref _PressurePlotModels, value); }
|
|
|
+ }
|
|
|
+
|
|
|
private PlotModel _LockCurvePlotModel;
|
|
|
/// <summary>
|
|
|
/// 锁付曲线
|
|
|
@@ -145,17 +158,19 @@ namespace TeamAAS_VP.ViewModels
|
|
|
set { SetProperty(ref _LockResults, value); }
|
|
|
}
|
|
|
|
|
|
+ // 可选:记录传感器 Id -> 索引 的映射,便于外部(如 Management)按 Id 更新
|
|
|
+ private readonly Dictionary<string, int> _sensorIdToIndex = new Dictionary<string, int>();
|
|
|
#endregion
|
|
|
|
|
|
#region 命令
|
|
|
public DelegateCommand LoadedCommand { get; set; }
|
|
|
private DelegateCommand<ProductModel> _LoadProductCommand;
|
|
|
public DelegateCommand<ProductModel> LoadProductCommand =>
|
|
|
- _LoadProductCommand ?? (_LoadProductCommand = new DelegateCommand<ProductModel>(ExecuteLoadProductCommand).ObservesCanExecute(()=> CanLoad).ObservesProperty(()=> SelectProduct).ObservesProperty(()=> IsLoadProduct));
|
|
|
+ _LoadProductCommand ?? (_LoadProductCommand = new DelegateCommand<ProductModel>(ExecuteLoadProductCommand).ObservesCanExecute(() => CanLoad).ObservesProperty(() => SelectProduct).ObservesProperty(() => IsLoadProduct));
|
|
|
|
|
|
private DelegateCommand _ResetCounterCommand;
|
|
|
public DelegateCommand ResetCounterCommand =>
|
|
|
- _ResetCounterCommand ?? (_ResetCounterCommand = new DelegateCommand(ExecuteResetCounterCommand).ObservesCanExecute(() => DoCondition).ObservesProperty(()=>isCanExecute));
|
|
|
+ _ResetCounterCommand ?? (_ResetCounterCommand = new DelegateCommand(ExecuteResetCounterCommand).ObservesCanExecute(() => DoCondition).ObservesProperty(() => isCanExecute));
|
|
|
|
|
|
private bool DoCondition
|
|
|
{
|
|
|
@@ -188,13 +203,23 @@ namespace TeamAAS_VP.ViewModels
|
|
|
_remoteCommandService.CycleTimingTicked += _remoteCommandService_CycleTimingTicked;
|
|
|
_systemDatabaseService = systemDatabaseService;
|
|
|
_eventAggregator.GetEvent<LockFinishNotification>().Subscribe(OnLockFinish);
|
|
|
+ _eventAggregator.GetEvent<PressureFinishNotification>().Subscribe(OnPressureFinish);
|
|
|
+
|
|
|
+ //获取所有的压力传感器配置,初始化曲线图
|
|
|
+ var systemConfig = _configService.GetSystemConfiguration();
|
|
|
+ if (systemConfig.PressureSensorConfig != null)
|
|
|
+ {
|
|
|
+ InitPressurePlots(systemConfig.PressureSensorConfig.ToArray());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private void _remoteCommandService_CycleTimingTicked(object sender, TimeSpan e)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- if (App.Current!=null)
|
|
|
+ if (App.Current != null)
|
|
|
{
|
|
|
App.Current.Invoke(() =>
|
|
|
{
|
|
|
@@ -209,7 +234,7 @@ namespace TeamAAS_VP.ViewModels
|
|
|
}
|
|
|
|
|
|
#region 方法
|
|
|
- bool isFirst=true;
|
|
|
+ bool isFirst = true;
|
|
|
private void OnLoad()
|
|
|
{
|
|
|
if (!isFirst)
|
|
|
@@ -342,7 +367,7 @@ namespace TeamAAS_VP.ViewModels
|
|
|
|
|
|
private void LoginChange(Models.User user)
|
|
|
{
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -368,7 +393,7 @@ namespace TeamAAS_VP.ViewModels
|
|
|
//初始化曲线图
|
|
|
private void InitLockCurvePlotModel()
|
|
|
{
|
|
|
- var model = new PlotModel { Title = "锁付曲线", TitleFontSize = 16};
|
|
|
+ var model = new PlotModel { Title = "锁付曲线", TitleFontSize = 16 };
|
|
|
// 设置图例
|
|
|
var legend = new Legend
|
|
|
{
|
|
|
@@ -381,7 +406,7 @@ namespace TeamAAS_VP.ViewModels
|
|
|
// 设置X轴
|
|
|
var xAxis = new LinearAxis
|
|
|
{
|
|
|
- Key="X",
|
|
|
+ Key = "X",
|
|
|
Position = AxisPosition.Bottom,
|
|
|
Title = "角度 (°)",
|
|
|
Minimum = 0,
|
|
|
@@ -437,9 +462,106 @@ namespace TeamAAS_VP.ViewModels
|
|
|
series.Points.Add(new OxyPlot.DataPoint(waveData.LockAngle, waveData.Torque));
|
|
|
}
|
|
|
LockCurvePlotModel.InvalidatePlot(true);
|
|
|
+
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 保压完成时调用
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="tuple"></param>
|
|
|
+ private void OnPressureFinish((bool IsSuccess, int Index, (DateTime Timestamp, float Value)[] values, string SavePath) tuple)
|
|
|
+ {
|
|
|
+ //更新对应传感器的曲线图
|
|
|
+ if (_sensorIdToIndex.TryGetValue(tuple.Index.ToString(), out int index))
|
|
|
+ {
|
|
|
+ App.Current.Dispatcher.BeginInvoke(new Action(() => {
|
|
|
+ var model = PressurePlotModels[index];
|
|
|
+ var series = model.Series[0] as LineSeries;
|
|
|
+ series.Points.Clear();
|
|
|
+ //第一个点的时间作为X轴起点
|
|
|
+ DateTime xAxisStart = tuple.values[0].Timestamp;
|
|
|
+ foreach (var dataPoint in tuple.values)
|
|
|
+ {
|
|
|
+ // 计算相对于起点的秒数作为X轴坐标
|
|
|
+ double xValue = (dataPoint.Timestamp - xAxisStart).TotalSeconds;
|
|
|
+ series.Points.Add(new OxyPlot.DataPoint(xValue, dataPoint.Value));
|
|
|
+ }
|
|
|
+ model.InvalidatePlot(true);
|
|
|
+ if (!string.IsNullOrEmpty(tuple.SavePath))
|
|
|
+ {
|
|
|
+ if (!Directory.Exists(Path.GetDirectoryName(tuple.SavePath)))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(Path.GetDirectoryName(tuple.SavePath));
|
|
|
+ }
|
|
|
+ PngExporter.Export(model, tuple.SavePath, (int)model.Width, (int)model.Height);
|
|
|
+ }
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化由配置决定的曲线数量(在读取 SystemConfiguration 后调用)
|
|
|
+ public void InitPressurePlots(IEnumerable<PressureSensorSettings> sensors)
|
|
|
+ {
|
|
|
+ PressurePlotModels.Clear();
|
|
|
+ _sensorIdToIndex.Clear();
|
|
|
+
|
|
|
+ int idx = 0;
|
|
|
+ foreach (var s in sensors)
|
|
|
+ {
|
|
|
+ var model = CreatePlotModelForSensor(s);
|
|
|
+ PressurePlotModels.Add(model);
|
|
|
+ // 假设 PressureSensorConfig 有唯一 Id(string 或 int)
|
|
|
+ _sensorIdToIndex[s.SensorId.ToString()] = idx++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private PlotModel CreatePlotModelForSensor(PressureSensorSettings sensor)
|
|
|
+ {
|
|
|
+ var model = new PlotModel { Title = sensor.SensorName ?? $"Sensor {sensor.SensorId}", TitleFontSize = 16 };
|
|
|
+ // 设置图例
|
|
|
+ var legend = new Legend
|
|
|
+ {
|
|
|
+ LegendPosition = LegendPosition.TopRight,
|
|
|
+ LegendPlacement = LegendPlacement.Outside,
|
|
|
+ LegendOrientation = LegendOrientation.Vertical,
|
|
|
+ LegendBorderThickness = 0
|
|
|
+ };
|
|
|
+ model.Legends.Add(legend);
|
|
|
+ // 设置X轴
|
|
|
+ var xAxis = new LinearAxis
|
|
|
+ {
|
|
|
+ Key = "X",
|
|
|
+ Position = AxisPosition.Bottom,
|
|
|
+ Title = "Time (s)",
|
|
|
+ Minimum = 0,
|
|
|
+ MajorGridlineStyle = LineStyle.Solid,
|
|
|
+ MinorGridlineStyle = LineStyle.Dot
|
|
|
+ };
|
|
|
+ model.Axes.Add(xAxis);
|
|
|
+ // 设置Y轴
|
|
|
+ var yAxis = new LinearAxis
|
|
|
+ {
|
|
|
+ Key = "Y",
|
|
|
+ Position = AxisPosition.Left,
|
|
|
+ Title = "Pressure",
|
|
|
+ MajorGridlineStyle = LineStyle.Solid,
|
|
|
+ MinorGridlineStyle = LineStyle.Dot
|
|
|
+ };
|
|
|
+ model.Axes.Add(yAxis);
|
|
|
+ // 添加示例数据系列
|
|
|
+ var series = new LineSeries
|
|
|
+ {
|
|
|
+ Title = sensor.SensorName ?? $"Sensor {sensor.SensorId}",
|
|
|
+ StrokeThickness = 2,
|
|
|
+ MarkerSize = 3,
|
|
|
+ MarkerType = MarkerType.Circle,
|
|
|
+ CanTrackerInterpolatePoints = false,
|
|
|
+ };
|
|
|
+ model.Series.Add(series);
|
|
|
+ return model;
|
|
|
+ }
|
|
|
#endregion
|
|
|
|
|
|
#region 继承
|