WpfApp/Services/ChartManager.cs

200 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using guoke;
using LiveCharts;
using LiveCharts.Wpf;
using System;
using System.Collections.Generic;
using System.Windows.Threading;
using WpfApp.src.config;
namespace WpfApp.Services
{
public class ChartManager
{
private readonly Dispatcher dispatcher;
private readonly LogService log;
private readonly DatabaseService db;
private readonly EventService<GeneralEventArgs> even;
private const string SENSOR_DATA_EVENT = "SensorDataUpdate";
// 最大保留点数
private const int MAX_POINTS = 20;
// 每个图表的数据封装
private class ChartData
{
public ColumnSeries ColumnSeries;
public ChartValues<double> StandardMin = new ChartValues<double>();
public ChartValues<double> StandardAvg = new ChartValues<double>();
public ChartValues<double> StandardMax = new ChartValues<double>();
public List<string> Labels = new List<string>();
}
// 管理多个图表
private Dictionary<CartesianChart, ChartData> charts = new Dictionary<CartesianChart, ChartData>();
public ChartManager(Dispatcher uiDispatcher,
LogService logService,
DatabaseService databaseService,
EventService<GeneralEventArgs> eventService)
{
dispatcher = uiDispatcher;
log = logService;
db = databaseService;
even = eventService;
SubscribeToSensorDataEvents();
}
/// <summary>
/// 初始化图表(一次性设置标准线和柱状图)
/// </summary>
public void InitChart(CartesianChart chart)
{
dispatcher.Invoke(() =>
{
if (chart == null) return;
// 如果已经初始化过,先清除
if (charts.ContainsKey(chart))
{
charts.Remove(chart);
}
var data = new ChartData();
data.ColumnSeries = new ColumnSeries
{
Title = "实时值",
Values = new ChartValues<double>()
};
var line1 = new LineSeries { Title = "标准下限", Values = data.StandardMin };
var line2 = new LineSeries { Title = "标准均值", Values = data.StandardAvg };
var line3 = new LineSeries { Title = "标准上限", Values = data.StandardMax };
chart.Series = new SeriesCollection { data.ColumnSeries, line1, line2, line3 };
chart.AxisX.Clear();
chart.AxisY.Clear();
chart.AxisX.Add(new Axis
{
Title = "时间",
Labels = data.Labels
});
chart.AxisY.Add(new Axis
{
Title = "数值"
});
charts[chart] = data;
});
}
/// <summary>
/// 接收到传感器实时数据(单点更新)
/// </summary>
private void OnSensorDataReceived(object sender, GeneralEventArgs e)
{
if (e is SensorDataEventArgs sensorArgs)
{
string chartTitle = sensorArgs.ChartTitle; // 例如 "myChart1"
double value = sensorArgs.SensorValue;
string timeLabel = DateTime.Now.ToString("HH:mm:ss");
// 找到对应图表并更新
foreach (var chart in charts.Keys)
{
if (chart.Name == chartTitle)
{
UpdateChartPoint(chart, timeLabel, value);
break;
}
}
}
}
/// <summary>
/// 更新单个图表的数据点(柱状图 + 标准线 + X轴标签
/// </summary>
public void UpdateChartPoint(CartesianChart chart, string label, double value)
{
if (chart == null || !charts.TryGetValue(chart, out var data))
return;
dispatcher.Invoke(() =>
{
// 保留四位小数
double roundedValue = Math.Round(value, 4);
data.ColumnSeries.Values.Add(roundedValue);
// 对标准线固定值,强制 double
data.StandardMin.Add(Math.Round((double)5, 4));
data.StandardAvg.Add(Math.Round((double)10, 4));
data.StandardMax.Add(Math.Round((double)30, 4));
data.Labels.Add(label);
// 超过最大点数时,移除最旧的数据
if (data.ColumnSeries.Values.Count > MAX_POINTS)
{
data.ColumnSeries.Values.RemoveAt(0);
data.StandardMin.RemoveAt(0);
data.StandardAvg.RemoveAt(0);
data.StandardMax.RemoveAt(0);
data.Labels.RemoveAt(0);
}
// 刷新 X 轴标签
chart.AxisX[0].Labels = new List<string>(data.Labels);
});
}
/// <summary>
/// 手动添加数据到指定图表
/// </summary>
public void AddData(CartesianChart chart, double value, string label)
{
UpdateChartPoint(chart, label, value);
}
/// <summary>
/// 手动清除指定图表的数据
/// </summary>
public void ClearChart(CartesianChart chart)
{
if (chart == null || !charts.TryGetValue(chart, out var data))
return;
dispatcher.Invoke(() =>
{
data.ColumnSeries.Values.Clear();
data.StandardMin.Clear();
data.StandardAvg.Clear();
data.StandardMax.Clear();
data.Labels.Clear();
chart.AxisX[0].Labels.Clear();
});
}
/// <summary>
/// 清除所有图表
/// </summary>
public void ClearAllCharts()
{
foreach (var chart in charts.Keys)
{
ClearChart(chart);
}
}
/// <summary>
/// 订阅传感器数据事件
/// </summary>
private void SubscribeToSensorDataEvents()
{
even?.AddEventHandler(SENSOR_DATA_EVENT, OnSensorDataReceived);
}
}
}