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(); this.PageTitle.Caption = "调度分析"; this.gridView1.SetNormalView(); this.gridView1.OptionsDetail.EnableMasterViewMode = true; this.gridView1.OptionsView.ShowDetailButtons = true; this.gridView1.OptionsView.ShowIndicator = false; this.gridView2.SetNormalView(); this.gridView2.OptionsView.ShowIndicator = false; this.colName.Visible = false; this.colFlag.Visible = false; this.repositoryItemDateEdit1.SetShowClock(); this.repositoryItemDateEdit2.SetShowClock(); this.barEditDateStart.EditValue = new DateTime(2024, 10, 1); this.barEditDateEnd.EditValue = new DateTime(2024, 10, 1, 0, 30, 0); this.cmbFlag.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; this.stationListCtrl1.FocusedChangedEvent += StationListCtrl1_FocusedChangedEvent; this.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() { this.chartControl1.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False;//是否在图表上显示图例 this.chartControl1.CrosshairOptions.ShowOnlyInFocusedPane = false; // Access the diagram's properties.把 Diagram 对象转换为所需的图象类型 _diagram = (SwiftPlotDiagram)this.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 (this.STDP.HasValue) { this.STDP = Math.Round(this.STDP.Value, 5); } if (this.STDPHead.HasValue) { this.STDPHead = Math.Round(this.STDPHead.Value, 5); } } } #endregion private BLL.StationSignalRecordPacket _bll = new BLL.StationSignalRecordPacket(); private Model.Station _station = null; private Model.MonitorDataSources _monitorDataSources = null; private List _pump_vm_list = null; private List> _pump_list = null; /// /// 清空数据 /// public void Clear() { _pump_vm_list = new List(); this.cmbFlag.SelectedItem = null; this.cmbFlag.Properties.Items.Clear(); ClearChart(); } /// /// /// private void ClearChart() { this.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(); this.chartControl1.EndInit(); } /// /// 初始化数据 /// public override void InitialDataSource() { this.stationListCtrl1.SetBindingData(); this.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); } /// /// 绑定数据 /// public void SetBindingData(Model.MonitorDataSources monitorDataSources, Model.Station station) { Clear(); if (monitorDataSources == null || station == null) { return; } if (this.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(); this.cmbFlag.Properties.Items.AddRange(flag_list); var pumps = new List(); 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 = GlobalHelper.GetScheduleConfig(station.SortCode); List ana_deviation_list = null; if (this.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>(json); } } SetBindingData(station.SortCode, packets, pumps, schedule_config, ana_deviation_list); } /// /// 绑定数据 /// public void SetBindingData ( int station_index, List packet_list, List pumps, Dto.ScheduleConfig schedule_config, List analysis_deviation_list ) { if (packet_list == null || !packet_list.Any()) { Clear(); return; } if (pumps == null || !pumps.Any()) { Clear(); return; } var dt_start = Convert.ToDateTime(this.barEditDateStart.EditValue); var dt_end = Convert.ToDateTime(this.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(); 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(); 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 = GlobalHelper.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(); 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; } this.stationScheduleVmBindingSource.DataSource = vm_list; this.stationScheduleVmBindingSource.ResetBindings(false); this.gridView1.BestFitColumns(); this.gridView2.BestFitColumns(); WaitFrmHelper.HideWaitForm(); } private Tuple 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(array, std_dev_pop); } if (count > 3) { return new Tuple(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(this.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; this.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)); } this.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) { this.gridView1.ExpandAllGroups(); } //全部折叠 private void barBtnCollapseAll_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { this.gridView1.CollapseAllGroups(); } //检索 private void barCekSearch_CheckedChanged(object sender, DevExpress.XtraBars.ItemClickEventArgs e) { if (this.barCekSearch.Checked) this.gridView1.ShowFindPanel(); else this.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(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], "提示", "导出完成!"); } } }