using DevExpress.XtraCharts;
|
using DevExpress.XtraEditors;
|
using IStation.Vm;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel.DataAnnotations;
|
using System.Drawing;
|
using System.IO;
|
using System.Linq;
|
|
namespace IStation.WinFrmUI.Monitor
|
{
|
public partial class ScheduleCalcPage : DocumentPage
|
{
|
public ScheduleCalcPage()
|
{
|
InitializeComponent();
|
PageTitle.Caption = "调度分析";
|
|
gridView1.SetNormalView();
|
gridView1.OptionsDetail.EnableMasterViewMode = true;
|
gridView1.OptionsView.ShowDetailButtons = true;
|
gridView1.OptionsView.ShowIndicator = false;
|
gridView2.SetNormalView();
|
gridView2.OptionsView.ShowIndicator = false;
|
|
colName.Visible = false;
|
colFlag.Visible = false;
|
|
repositoryItemDateEdit1.SetShowClock();
|
repositoryItemDateEdit2.SetShowClock();
|
barEditDateStart.EditValue = new DateTime(2024, 10, 1);
|
barEditDateEnd.EditValue = new DateTime(2024, 10, 1, 0, 30, 0);
|
|
|
cmbFlag.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor;
|
|
stationListCtrl1.FocusedChangedEvent += StationListCtrl1_FocusedChangedEvent;
|
monitorDataSourcesTreeList1.FocusedChangedEvent += MonitorDataSourcesListCtrl1_FocusedChangedEvent;
|
|
InitialDiagarm();
|
}
|
|
|
private SwiftPlotDiagram _diagram;//图表
|
private Series _series_default_head; //
|
private Series _series_curve_head; //
|
private Series _series_correct_curve_head; //
|
private Series _series_head_diff; //
|
private Series _series_hz; //
|
|
private void InitialDiagarm()
|
{
|
chartControl1.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False;//是否在图表上显示图例
|
chartControl1.CrosshairOptions.ShowOnlyInFocusedPane = false;
|
// Access the diagram's properties.把 Diagram 对象转换为所需的图象类型
|
_diagram = (SwiftPlotDiagram)chartControl1.Diagram;
|
_diagram.EnableAxisXScrolling = true;//X轴是否允许滚动
|
_diagram.EnableAxisXZooming = true;//X轴是否允许缩放
|
_diagram.PaneLayout.Direction = PaneLayoutDirection.Vertical;//窗格的对齐方式
|
|
_diagram.AxisX.DateTimeScaleOptions.MeasureUnit = DateTimeMeasureUnit.Minute;
|
|
|
_series_default_head = chartControl1.GetSeriesByName("SeriesDefaultHead");
|
_series_curve_head = chartControl1.GetSeriesByName("SeriesCurveHead");
|
_series_correct_curve_head = chartControl1.GetSeriesByName("SeriesCorrectCurveHead");
|
_series_head_diff = chartControl1.GetSeriesByName("SeriesHeadDiff");
|
_series_hz = chartControl1.GetSeriesByName("SeriesHz");
|
|
_series_default_head.CrosshairLabelPattern = "原始值:{V}";
|
_series_curve_head.CrosshairLabelPattern = "曲线值:{V}";
|
_series_correct_curve_head.CrosshairLabelPattern = "修正值:{V}";
|
_series_head_diff.CrosshairLabelPattern = "偏差值:{V}";
|
_series_hz.CrosshairLabelPattern = "频率:{V}";
|
|
|
//定制窗格的滚动条的外观
|
ScrollBarOptions scrollBarOptions = _diagram.DefaultPane.ScrollBarOptions;
|
scrollBarOptions.BackColor = Color.White;
|
scrollBarOptions.BarColor = Color.LightSlateGray;
|
scrollBarOptions.BorderColor = Color.DarkGray;
|
scrollBarOptions.BarThickness = 15;
|
scrollBarOptions.XAxisScrollBarAlignment = ScrollBarAlignment.Far;
|
scrollBarOptions.XAxisScrollBarVisible = true;
|
|
}
|
|
|
#region ViewModel
|
|
public class PumpViewModel
|
{
|
[Display(Name = "年")]
|
public int Year { get; set; }
|
|
[Display(Name = "月")]
|
public int Month { get; set; }
|
|
[Display(Name = "时间")]
|
public string Time { get; set; }
|
|
[Display(Name = "泵")]
|
public int Flag { get; set; }
|
|
[Display(Name = "转速")]
|
public double Rpm { get; set; }
|
|
[Display(Name = "频率")]
|
public double Hz { get; set; }
|
|
[Display(Name = "频率")]
|
public double Hz0 { get; set; }
|
|
[Display(Name = "水位")]
|
public double WaterLevel { get; set; }
|
|
[Display(Name = "进口压力")]
|
public double InletPressure { get; set; }
|
|
[Display(Name = "出口压力")]
|
public double OutletPressure { get; set; }
|
|
[Display(Name = "压差")]
|
public double PressureDiff { get; set; }
|
|
[Display(Name = "瞬时流量")]
|
public double Flow { get; set; }
|
|
[Display(Name = "扬程")]
|
public double Head { get; set; }
|
|
[Display(Name = "瞬时功率")]
|
public double Power { get; set; }
|
|
|
[Display(Name = "曲线扬程")]
|
public double CurveHead { get; set; }
|
|
[Display(Name = "扬程差值")]
|
public double HeadDiff { get; set; }
|
|
[Display(Name = "修正曲线扬程")]
|
public double CorrectCurveHead { get; set; }
|
|
[Display(Name = "修正扬程差值")]
|
public double CorrectHeadDiff { get; set; }
|
|
|
[Display(Name = "修正压差")]
|
public double CorrectPressureDiff { get; set; }
|
|
[Display(Name = "修正压差差值")]
|
public double CorrectPressureDiffDiff { get; set; }
|
|
}
|
|
public class PumpFactorViewModel
|
{
|
[Display(Name = "泵")]
|
public int Flag { get; set; }
|
|
[Display(Name = "频率")]
|
public double Hz { get; set; }
|
|
[Display(Name = "总体标准差")]
|
public double? STDP { get; set; }
|
|
[Display(Name = "扬程(STDP)")]
|
public double? STDPHead { get; set; }
|
|
|
[Display(Name = "备注")]
|
public string Note { get; set; }
|
|
public void Round()
|
{
|
if (STDP.HasValue)
|
{
|
STDP = Math.Round(STDP.Value, 5);
|
}
|
if (STDPHead.HasValue)
|
{
|
STDPHead = Math.Round(STDPHead.Value, 5);
|
}
|
|
}
|
}
|
#endregion
|
|
private BLL.StationSignalRecordPacket _bll = new BLL.StationSignalRecordPacket();
|
private Model.Station _station = null;
|
private Model.MonitorDataSources _monitorDataSources = null;
|
|
private List<PumpViewModel> _pump_vm_list = null;
|
private List<Model.Equipment<Model.Pump>> _pump_list = null;
|
|
/// <summary>
|
/// 清空数据
|
/// </summary>
|
public void Clear()
|
{
|
_pump_vm_list = new List<PumpViewModel>();
|
cmbFlag.SelectedItem = null;
|
cmbFlag.Properties.Items.Clear();
|
|
ClearChart();
|
}
|
|
|
/// <summary>
|
///
|
/// </summary>
|
private void ClearChart()
|
{
|
|
chartControl1.BeginInit();
|
_series_default_head.Points.Clear();
|
_series_curve_head.Points.Clear();
|
_series_correct_curve_head.Points.Clear();
|
|
_series_head_diff.Points.Clear();
|
_series_hz.Points.Clear();
|
chartControl1.EndInit();
|
}
|
|
/// <summary>
|
/// 初始化数据
|
/// </summary>
|
public override void InitialDataSource()
|
{
|
stationListCtrl1.SetBindingData();
|
monitorDataSourcesTreeList1.SetBindingData();
|
}
|
|
//泵站变换
|
private void StationListCtrl1_FocusedChangedEvent(Model.Station obj)
|
{
|
_station = obj;
|
SetBindingData(_monitorDataSources, _station);
|
}
|
|
//来源变换
|
private void MonitorDataSourcesListCtrl1_FocusedChangedEvent(Model.MonitorDataSources obj)
|
{
|
_monitorDataSources = obj;
|
SetBindingData(_monitorDataSources, _station);
|
}
|
|
/// <summary>
|
/// 绑定数据
|
/// </summary>
|
public void SetBindingData(Model.MonitorDataSources monitorDataSources, Model.Station station)
|
{
|
Clear();
|
if (monitorDataSources == null || station == null)
|
{
|
return;
|
}
|
if (barCekLoad.Checked)
|
{
|
return;
|
}
|
var packets = _bll.Get(monitorDataSources.ID, station.ID);
|
_pump_list = new BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, station.ID);
|
var flag_list = _pump_list.Select(x => x.SortCode).OrderBy(x => x).ToList();
|
cmbFlag.Properties.Items.AddRange(flag_list);
|
|
var pumps = new List<Dto.Pump>();
|
foreach (var pump in _pump_list)
|
{
|
var curve = new BLL.PumpCurve().GetDefaultWorkingByPumpID(pump.ID);
|
if (curve == null)
|
continue;
|
var rhs = new Dto.Pump();
|
rhs.Flag = pump.SortCode;
|
rhs.Code = pump.NO;
|
rhs.Name = pump.Name;
|
rhs.Qr = pump.RatedParas.Qr;
|
rhs.Hr = pump.RatedParas.Hr;
|
rhs.Nr = pump.RatedParas.Nr;
|
rhs.Pr = pump.RatedParas.Pr;
|
rhs.Er = pump.RatedParas.Er;
|
rhs.Ic = pump.RatedParas.Ic;
|
rhs.Oc = pump.RatedParas.Oc;
|
rhs.IOd = pump.RatedParas.IOd;
|
rhs.IsBp = pump.RatedParas.IsBp;
|
rhs.CurveQH = curve.CurveInfo.CurveQH;
|
rhs.CurveQE = curve.CurveInfo.CurveQE;
|
rhs.CurveQP = curve.CurveInfo.CurveQP;
|
pumps.Add(rhs);
|
}
|
|
var schedule_config = GlobalHelperW.GetScheduleConfig(station.SortCode);
|
|
|
List<Dto.AnalysisDeviation> ana_deviation_list = null;
|
|
if (barCekUseAnaDev.Checked)
|
{
|
var root_folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "分析");
|
var fileName_2 = root_folder + "\\" + "AnalysisDeviation.json";
|
if (File.Exists(fileName_2))
|
{
|
var json = File.ReadAllText(fileName_2);
|
ana_deviation_list = JsonHelper.Json2Object<List<Dto.AnalysisDeviation>>(json);
|
}
|
}
|
|
|
SetBindingData(station.SortCode, packets, pumps, schedule_config, ana_deviation_list);
|
|
|
}
|
|
/// <summary>
|
/// 绑定数据
|
/// </summary>
|
public void SetBindingData
|
(
|
int station_index,
|
List<Model.StationSignalRecordPacket> packet_list,
|
List<Dto.Pump> pumps,
|
Dto.ScheduleConfig schedule_config,
|
List<Dto.AnalysisDeviation> analysis_deviation_list
|
)
|
{
|
if (packet_list == null || !packet_list.Any())
|
{
|
Clear();
|
return;
|
}
|
|
if (pumps == null || !pumps.Any())
|
{
|
Clear();
|
return;
|
}
|
|
|
var dt_start = Convert.ToDateTime(barEditDateStart.EditValue);
|
var dt_end = Convert.ToDateTime(barEditDateEnd.EditValue);
|
//packet_list = packet_list.Where(x => (x.Year >= dt_start.Year && x.Year <= dt_end.Year) && (x.Month >= dt_start.Month && x.Month <= dt_end.Month)).ToList();
|
packet_list = packet_list.Where(x => (x.Year >= dt_start.Year && x.Year <= dt_end.Year) && (x.Month >= dt_start.Month && x.Month <= dt_end.Month)).ToList();
|
if (packet_list == null || !packet_list.Any())
|
{
|
Clear();
|
return;
|
}
|
|
|
WaitFrmHelper.ShowWaitForm();
|
|
var vm_list = new List<Vm.StationScheduleVm>();
|
foreach (var packet in packet_list)
|
{
|
var station_signal_records = packet.StationSignalRecords?.Where(x => x.Time >= dt_start && x.Time <= dt_end);
|
if (station_signal_records == null || !station_signal_records.Any())
|
continue;
|
|
foreach (var station_r in station_signal_records)
|
{
|
var time = station_r.Time;
|
var total_flow = station_r.TotalFlow;
|
var total_pressure = station_r.TotalPressure;
|
var pump_total_flow = station_r.PumpSignalRecords.Sum(x => x.FlowRate);
|
var diff_flow = station_r.DiffFlow;
|
if (total_pressure < 0)
|
{
|
continue;
|
}
|
if (total_flow <= 0 && pump_total_flow <= 0)
|
{
|
continue;
|
}
|
if (pump_total_flow > 0 && Math.Abs(diff_flow) > 2000)
|
{
|
continue;
|
}
|
total_flow = Math.Round(total_flow, 1);
|
pump_total_flow = Math.Round(pump_total_flow, 1);
|
diff_flow = Math.Round(diff_flow, 1);
|
total_pressure = Math.Round(total_pressure, 2);
|
|
|
|
var target_flow = pump_total_flow > 0 ? pump_total_flow : total_flow;
|
var target_pressure = total_pressure;
|
var open_flag_list = new List<int>();
|
|
var pump_err = false;
|
var pump_signal_records = station_r.PumpSignalRecords;
|
pump_signal_records = pump_signal_records.OrderBy(x => x.Flag).ToList();
|
foreach (var pump_r in pump_signal_records)
|
{
|
if (pump_r.Rpm < 0)
|
{
|
pump_err = true;
|
}
|
if (pump_r.Head == IStation.Error.Default)
|
{
|
pump_err = true;
|
}
|
|
open_flag_list.Add(pump_r.Flag);
|
}
|
if (pump_err)
|
{
|
continue;
|
}
|
|
|
var flag_inlet_water_level_dict = GlobalHelperW.GetFlagInletWaterLevelDict(station_index, station_r.ModelRecordDict);
|
var helper = new Service.ScheduleHelper();
|
helper.Initial(open_flag_list, schedule_config, analysis_deviation_list);
|
var opt_combine = helper.GetOptAnaCombine(pumps, flag_inlet_water_level_dict, target_flow, target_pressure);
|
if (opt_combine == null)
|
{
|
throw new Exception("opt_combine==null");
|
}
|
|
var vm = new Vm.StationScheduleVm();
|
vm.Name = $"{station_index}输水";
|
vm.Flag = station_index;
|
vm.Time = time;
|
vm.TargetFlow = target_flow;
|
vm.TargetPressure = target_pressure;
|
vm.CalcFlow = opt_combine.TotalFlow;
|
vm.CalcPressure = opt_combine.TotalPressure;
|
|
|
var total_flow_dev = vm.TargetFlow - vm.CalcFlow;
|
var total_pressure_dev = vm.TargetPressure - vm.CalcPressure;
|
|
total_flow_dev = Math.Round(total_flow_dev, 1);
|
total_pressure_dev = Math.Round(total_pressure_dev, 1);
|
|
vm.FlowDeviation = total_flow_dev;
|
vm.PressureDeviation = total_pressure_dev;
|
vm.PumpSchedules = new List<PumpScheduleVm>();
|
|
foreach (var pump in pumps)
|
{
|
var flag = pump.Flag;
|
var wl = flag_inlet_water_level_dict[flag];
|
|
var target_pump = pump_signal_records.Find(x => x.Flag == pump.Flag);
|
var schedule_pump = opt_combine.AnaFrePumps.Find(x => x.Flag == pump.Flag);
|
|
if (target_pump == null && schedule_pump == null)
|
continue;
|
var vm_pump = new Vm.PumpScheduleVm();
|
vm_pump.Flag = flag;
|
vm_pump.WL = wl;
|
if (target_pump != null)
|
{
|
if (flag == 15 || flag == 16)
|
{
|
target_pump.Rpm = pump.Nr;
|
}
|
vm_pump.TargetRpm = target_pump.Rpm;
|
vm_pump.TargetFlow = target_pump.FlowRate;
|
vm_pump.TargetHead = target_pump.Head;
|
vm_pump.TargetPressureDiff = Model.CurveCalcuHelper.Mpa2M(target_pump.OutletPressure - target_pump.InletPressure);
|
}
|
|
if (schedule_pump != null)
|
{
|
vm_pump.CalcRpm = schedule_pump.Speed;
|
vm_pump.CalcFlow = schedule_pump.Flow;
|
vm_pump.CalcHead = schedule_pump.Head;
|
vm_pump.CalcPressureDiff = schedule_pump.PressureDiff;
|
}
|
|
var rpm_dev = vm_pump.TargetRpm - vm_pump.CalcRpm;
|
var flow_dev = vm_pump.TargetFlow - vm_pump.CalcFlow;
|
var pressure_diff_dev = vm_pump.TargetPressureDiff - vm_pump.CalcPressureDiff;
|
|
|
vm_pump.RpmDeviation = rpm_dev;
|
vm_pump.FlowDeviation = flow_dev;
|
vm_pump.PressureDeviation = pressure_diff_dev;
|
vm_pump.Round();
|
vm.PumpSchedules.Add(vm_pump);
|
}
|
|
vm.Round();
|
vm_list.Add(vm);
|
}
|
}
|
|
if (!vm_list.Any())
|
{
|
Clear();
|
return;
|
}
|
|
stationScheduleVmBindingSource.DataSource = vm_list;
|
stationScheduleVmBindingSource.ResetBindings(false);
|
gridView1.BestFitColumns();
|
gridView2.BestFitColumns();
|
|
|
WaitFrmHelper.HideWaitForm();
|
}
|
|
private Tuple<double[], double> FilterBySTDP(double[] array, double min_dev, int count)
|
{
|
if (array == null || !array.Any())
|
{
|
return default;
|
}
|
var array_avg = array.Average();
|
var array_count = array.Count();
|
|
|
FilterOutliersHelper.STDEV(array, out double std_dev, out double std_dev_pop);
|
if (Math.Abs(std_dev_pop) < min_dev)
|
{
|
return new Tuple<double[], double>(array, std_dev_pop);
|
}
|
if (count > 3)
|
{
|
return new Tuple<double[], double>(array, std_dev_pop);
|
}
|
var filter_array = array.Where(x => !(Math.Abs(x - array_avg) > Math.Abs(std_dev_pop * 2))).ToArray();
|
if (filter_array == null || !filter_array.Any())
|
{
|
return default;
|
}
|
count++;
|
return FilterBySTDP(filter_array, min_dev, count);
|
}
|
|
|
|
private void cmbFlag_SelectedIndexChanged(object sender, EventArgs e)
|
{
|
ClearChart();
|
if (_pump_vm_list == null || !_pump_vm_list.Any())
|
return;
|
if (!int.TryParse(cmbFlag.Text, out int flag))
|
return;
|
var vm_list = _pump_vm_list.Where(x => x.Flag == flag).ToList();
|
if (vm_list == null || !vm_list.Any())
|
return;
|
chartControl1.BeginInit();
|
foreach (var vm in vm_list)
|
{
|
//if (Math.Abs(vm.HeadDiff) > 2)
|
// continue;
|
//if (vm.Head<2)
|
// continue;
|
var time = Convert.ToDateTime(vm.Time);
|
_series_default_head.Points.Add(new SeriesPoint(time, vm.Head));
|
_series_curve_head.Points.Add(new SeriesPoint(time, vm.CurveHead));
|
_series_correct_curve_head.Points.Add(new SeriesPoint(time, vm.CorrectCurveHead));
|
|
_series_head_diff.Points.Add(new SeriesPoint(time, vm.CorrectHeadDiff));
|
_series_hz.Points.Add(new SeriesPoint(time, vm.Hz));
|
}
|
|
chartControl1.EndInit();
|
}
|
|
//加载
|
private void barCekLoad_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
|
{
|
SetBindingData(_monitorDataSources, _station);
|
}
|
|
|
#region 菜单
|
|
//全部展开
|
private void barBtnExpandAll_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
|
{
|
gridView1.ExpandAllGroups();
|
}
|
|
//全部折叠
|
private void barBtnCollapseAll_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
|
{
|
gridView1.CollapseAllGroups();
|
}
|
|
//检索
|
private void barCekSearch_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
|
{
|
if (barCekSearch.Checked)
|
gridView1.ShowFindPanel();
|
else
|
gridView1.HideFindPanel();
|
}
|
|
// 刷新数据
|
private void barBtnRefresh_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
|
{
|
InitialDataSource();
|
}
|
|
#endregion
|
|
private void barBtnExportAnalysisFactor_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
|
{
|
if (_monitorDataSources == null || _station == null)
|
{
|
return;
|
}
|
|
WaitFrmHelper.ShowWaitForm("正在导出");
|
|
var bol = false;
|
var flag_hz_head_diff_list = _pump_vm_list.Select(x => new Tuple<int, double, double>(x.Flag, x.Hz0, x.HeadDiff)).ToList();
|
bol = AnalysisHelper.SaveAnalysisFactorDtoList(_station.SortCode, _pump_list, flag_hz_head_diff_list);
|
|
if (!bol)
|
{
|
XtraMessageBox.Show("导出失败!");
|
return;
|
}
|
WaitFrmHelper.HideWaitForm();
|
AlertTool.ShowInfo(System.Windows.Forms.Application.OpenForms[0], "提示", "导出完成!");
|
}
|
|
|
}
|
}
|