215 lines
9.4 KiB
C#
215 lines
9.4 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Threading;
|
||
|
|
using System.Windows;
|
||
|
|
using System.Windows.Controls;
|
||
|
|
using System.Windows.Media;
|
||
|
|
using Newtonsoft.Json.Linq;
|
||
|
|
using OxyPlot;
|
||
|
|
using OxyPlot.Axes;
|
||
|
|
using OxyPlot.Series;
|
||
|
|
|
||
|
|
namespace YKC
|
||
|
|
{
|
||
|
|
public partial class RealtimePage : Page
|
||
|
|
{
|
||
|
|
private Timer _pollTimer;
|
||
|
|
private int _currentPile = 1;
|
||
|
|
private int _currentGun = 1;
|
||
|
|
|
||
|
|
public RealtimePage()
|
||
|
|
{
|
||
|
|
InitializeComponent();
|
||
|
|
InitLinePlot(plotCurrent, OxyColor.Parse("#3B82F6"));
|
||
|
|
InitLinePlot(plotVoltage, OxyColor.Parse("#8B5CF6"));
|
||
|
|
InitLinePlot(plotPower, OxyColor.Parse("#F59E0B"));
|
||
|
|
InitBarPlot(plotAmount);
|
||
|
|
|
||
|
|
Loaded += (s, e) =>
|
||
|
|
{
|
||
|
|
Dispatcher.BeginInvoke(new Action(RefreshData),
|
||
|
|
System.Windows.Threading.DispatcherPriority.Background);
|
||
|
|
_pollTimer = new Timer((_) =>
|
||
|
|
Dispatcher.BeginInvoke(new Action(RefreshData)), null, 2000, 2000);
|
||
|
|
};
|
||
|
|
Unloaded += (s, e) => _pollTimer?.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void InitLinePlot(OxyPlot.Wpf.PlotView pv, OxyColor color)
|
||
|
|
{
|
||
|
|
var model = new PlotModel { PlotAreaBorderColor = OxyColors.Transparent };
|
||
|
|
model.Axes.Add(new DateTimeAxis
|
||
|
|
{
|
||
|
|
Position = AxisPosition.Bottom,
|
||
|
|
TextColor = OxyColor.Parse("#94A3B8"),
|
||
|
|
AxislineColor = OxyColor.Parse("#E2E8F0"),
|
||
|
|
TicklineColor = OxyColor.Parse("#E2E8F0"),
|
||
|
|
MajorGridlineColor = OxyColor.Parse("#F1F5F9"),
|
||
|
|
StringFormat = "HH:mm:ss",
|
||
|
|
FontSize = 10
|
||
|
|
});
|
||
|
|
model.Axes.Add(new LinearAxis
|
||
|
|
{
|
||
|
|
Position = AxisPosition.Left,
|
||
|
|
TextColor = OxyColor.Parse("#94A3B8"),
|
||
|
|
AxislineColor = OxyColors.Transparent,
|
||
|
|
TicklineColor = OxyColors.Transparent,
|
||
|
|
MajorGridlineStyle = LineStyle.Dash,
|
||
|
|
MajorGridlineColor = OxyColor.Parse("#F1F5F9"),
|
||
|
|
FontSize = 10,
|
||
|
|
MinimumPadding = 0.1,
|
||
|
|
MaximumPadding = 0.1
|
||
|
|
});
|
||
|
|
model.Series.Add(new LineSeries
|
||
|
|
{
|
||
|
|
Color = color,
|
||
|
|
StrokeThickness = 2,
|
||
|
|
MarkerType = MarkerType.None,
|
||
|
|
CanTrackerInterpolatePoints = false
|
||
|
|
});
|
||
|
|
pv.Model = model;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void InitBarPlot(OxyPlot.Wpf.PlotView pv)
|
||
|
|
{
|
||
|
|
var model = new PlotModel { PlotAreaBorderColor = OxyColors.Transparent };
|
||
|
|
var catAxis = new CategoryAxis
|
||
|
|
{
|
||
|
|
Position = AxisPosition.Bottom,
|
||
|
|
TextColor = OxyColor.Parse("#64748B"),
|
||
|
|
FontSize = 12,
|
||
|
|
AxislineColor = OxyColor.Parse("#E2E8F0"),
|
||
|
|
TicklineColor = OxyColor.Parse("#E2E8F0")
|
||
|
|
};
|
||
|
|
catAxis.Labels.Add("服务费");
|
||
|
|
catAxis.Labels.Add("电费");
|
||
|
|
catAxis.Labels.Add("总金额");
|
||
|
|
model.Axes.Add(catAxis);
|
||
|
|
model.Axes.Add(new LinearAxis
|
||
|
|
{
|
||
|
|
Position = AxisPosition.Left,
|
||
|
|
Title = "元",
|
||
|
|
TextColor = OxyColor.Parse("#94A3B8"),
|
||
|
|
FontSize = 10,
|
||
|
|
AxislineColor = OxyColors.Transparent,
|
||
|
|
TicklineColor = OxyColors.Transparent,
|
||
|
|
MajorGridlineStyle = LineStyle.Dash,
|
||
|
|
MajorGridlineColor = OxyColor.Parse("#F1F5F9"),
|
||
|
|
MinimumPadding = 0,
|
||
|
|
MaximumPadding = 0.15
|
||
|
|
});
|
||
|
|
model.Series.Add(new RectangleBarSeries { FillColor = OxyColor.Parse("#1E9FFF") });
|
||
|
|
model.Series.Add(new RectangleBarSeries { FillColor = OxyColor.Parse("#10B981") });
|
||
|
|
model.Series.Add(new RectangleBarSeries { FillColor = OxyColor.Parse("#6366F1") });
|
||
|
|
pv.Model = model;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PileGun_Changed(object sender, SelectionChangedEventArgs e)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (cmbPile == null || cmbGun == null) return;
|
||
|
|
_currentPile = cmbPile.SelectedIndex + 1;
|
||
|
|
_currentGun = cmbGun.SelectedIndex + 1;
|
||
|
|
RefreshData();
|
||
|
|
}
|
||
|
|
catch { }
|
||
|
|
}
|
||
|
|
|
||
|
|
private void RefreshData()
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (txtCurrent == null || plotCurrent == null || plotCurrent.Model == null) return;
|
||
|
|
var latest = PilesStoreHolder.Instance.GetLatest(_currentPile, _currentGun);
|
||
|
|
if (latest == null) return;
|
||
|
|
|
||
|
|
txtCurrent.Text = FormatValue(latest.Value<double?>("current")) + " A";
|
||
|
|
txtVoltage.Text = FormatValue(latest.Value<double?>("voltage")) + " V";
|
||
|
|
txtPower.Text = FormatValue(latest.Value<double?>("power")) + " kW";
|
||
|
|
txtEnergy.Text = FormatValue(latest.Value<double?>("energy")) + " kWh";
|
||
|
|
txtTotalAmount.Text = "¥ " + FormatValue(latest.Value<double?>("total_amount"));
|
||
|
|
|
||
|
|
int? st = latest.Value<int?>("status");
|
||
|
|
if (st == 0) { txtStatus.Text = "离线"; txtStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#909399")); }
|
||
|
|
else if (st == 1) { txtStatus.Text = "故障"; txtStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#EF4444")); }
|
||
|
|
else if (st == 2) { txtStatus.Text = "空闲"; txtStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#10B981")); }
|
||
|
|
else if (st == 3) { txtStatus.Text = "充电中"; txtStatus.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#3B82F6")); }
|
||
|
|
else { txtStatus.Text = "--"; }
|
||
|
|
|
||
|
|
txtOrderNo.Text = latest.Value<string>("order_no") ?? "--";
|
||
|
|
txtSoc.Text = latest.Value<double?>("soc") != null ? latest.Value<double>("soc").ToString("F1") + "%" : "--";
|
||
|
|
txtCumTime.Text = FormatMin(latest.Value<double?>("cumulative_time"));
|
||
|
|
txtRemTime.Text = FormatMin(latest.Value<double?>("remaining_time"));
|
||
|
|
|
||
|
|
UpdateCharts();
|
||
|
|
}
|
||
|
|
catch { }
|
||
|
|
}
|
||
|
|
|
||
|
|
private void UpdateCharts()
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (plotCurrent == null || plotCurrent.Model == null || plotCurrent.Model.Series.Count == 0) return;
|
||
|
|
if (plotAmount == null || plotAmount.Model == null || plotAmount.Model.Series.Count == 0) return;
|
||
|
|
|
||
|
|
var chartData = PilesStoreHolder.Instance.GetChartData(_currentPile, _currentGun);
|
||
|
|
if (chartData == null || chartData.Count == 0) return;
|
||
|
|
|
||
|
|
var curPoints = new List<DataPoint>();
|
||
|
|
var volPoints = new List<DataPoint>();
|
||
|
|
var powPoints = new List<DataPoint>();
|
||
|
|
|
||
|
|
foreach (var item in chartData)
|
||
|
|
{
|
||
|
|
long unixTs = item.Value<long>("t");
|
||
|
|
var dt = DateTimeOffset.FromUnixTimeSeconds(unixTs).DateTime;
|
||
|
|
double oxyTime = DateTimeAxis.ToDouble(dt);
|
||
|
|
curPoints.Add(new DataPoint(oxyTime, item.Value<double?>("current") ?? 0));
|
||
|
|
volPoints.Add(new DataPoint(oxyTime, item.Value<double?>("voltage") ?? 0));
|
||
|
|
powPoints.Add(new DataPoint(oxyTime, item.Value<double?>("power") ?? 0));
|
||
|
|
}
|
||
|
|
|
||
|
|
((LineSeries)plotCurrent.Model.Series[0]).Points.Clear();
|
||
|
|
((LineSeries)plotCurrent.Model.Series[0]).Points.AddRange(curPoints);
|
||
|
|
((LineSeries)plotVoltage.Model.Series[0]).Points.Clear();
|
||
|
|
((LineSeries)plotVoltage.Model.Series[0]).Points.AddRange(volPoints);
|
||
|
|
((LineSeries)plotPower.Model.Series[0]).Points.Clear();
|
||
|
|
((LineSeries)plotPower.Model.Series[0]).Points.AddRange(powPoints);
|
||
|
|
plotCurrent.InvalidatePlot(true);
|
||
|
|
plotVoltage.InvalidatePlot(true);
|
||
|
|
plotPower.InvalidatePlot(true);
|
||
|
|
|
||
|
|
var latest = PilesStoreHolder.Instance.GetLatest(_currentPile, _currentGun);
|
||
|
|
if (latest != null)
|
||
|
|
{
|
||
|
|
double sf = latest.Value<double?>("service_fee") ?? 0;
|
||
|
|
double ef = latest.Value<double?>("electricity_fee") ?? 0;
|
||
|
|
double ta = latest.Value<double?>("total_amount") ?? 0;
|
||
|
|
|
||
|
|
((RectangleBarSeries)plotAmount.Model.Series[0]).Items.Clear();
|
||
|
|
((RectangleBarSeries)plotAmount.Model.Series[0]).Items.Add(new RectangleBarItem(-0.25, 0, 0.25, sf));
|
||
|
|
((RectangleBarSeries)plotAmount.Model.Series[1]).Items.Clear();
|
||
|
|
((RectangleBarSeries)plotAmount.Model.Series[1]).Items.Add(new RectangleBarItem(0.75, 0, 1.25, ef));
|
||
|
|
((RectangleBarSeries)plotAmount.Model.Series[2]).Items.Clear();
|
||
|
|
((RectangleBarSeries)plotAmount.Model.Series[2]).Items.Add(new RectangleBarItem(1.75, 0, 2.25, ta));
|
||
|
|
plotAmount.InvalidatePlot(true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch { }
|
||
|
|
}
|
||
|
|
|
||
|
|
private string FormatValue(double? v)
|
||
|
|
{
|
||
|
|
return v.HasValue ? v.Value.ToString("F2") : "--";
|
||
|
|
}
|
||
|
|
|
||
|
|
private string FormatMin(double? v)
|
||
|
|
{
|
||
|
|
return v.HasValue ? Math.Round(v.Value).ToString() + " min" : "--";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|