using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace IStation.WinFrmUI { /// /// 导出 分析系数 /// public partial class ExportScadaAnalysisFactorHelper { public class PumpModel { public DateTime Time { get; set; } public int Flag { get; set; } public double Rpm { get; set; } public double Hz { get; set; } public double Hz0 { get; set; } public double Flow { get; set; } public double Head { get; set; } public double CurveHead { get; set; } public double HeadDiff { get; set; } public double CorrectCurveHead { get; set; } public double CorrectHeadDiff { get; set; } } /// /// 分析系数 /// public class AnalysisFactor { /// /// 泵标志 /// public int Flag { get; set; } /// /// 频率 /// public double Hz { get; set; } /// /// 扬程标准差 /// public double? HeadSTDP { get; set; } /// /// 扬程偏差 /// public double? HeadDeviation { get; set; } /// /// 准确度 /// public double Accuracy { get; set; } } static BLL.StationSignalRecordPacket _packet = new BLL.StationSignalRecordPacket(); /// /// 绑定数据 /// public static bool Export(long monitorDataSourcesId, long stationId, string name) { var packets = _packet.Get(monitorDataSourcesId, stationId); if (packets == null || !packets.Any()) return false; var eq_list = new BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, stationId); if (eq_list == null || !eq_list.Any()) return false; var flag_list = eq_list.Select(x => x.SortCode).OrderBy(x => x).ToList(); var flag_pump_dict = eq_list.ToDictionary(x => x.SortCode, x => x.RatedParas); var flag_curve_dict = new Dictionary(); var bll_curve = new BLL.PumpCurve(); foreach (var pump in eq_list) { Model.CurveExpress qh = null; var curve_info = bll_curve.GetDefaultWorkingByPumpID(pump.ID)?.CurveInfo; if (curve_info != null) { qh = curve_info.CurveQH; } flag_curve_dict.Add(pump.SortCode, qh); } var vm_pump_list = new List(); foreach (var packet in packets) { var station_signal_records = packet.StationSignalRecords; if (station_signal_records == null || !station_signal_records.Any()) continue; foreach (var record in station_signal_records) { var pump_signal_records = record.PumpSignalRecords; if (pump_signal_records == null || !pump_signal_records.Any()) continue; pump_signal_records = pump_signal_records.OrderBy(x => x.Flag).ToList(); foreach (var pump_record in pump_signal_records) { if (pump_record.Rpm == IStation.Error.Default || pump_record.Head == IStation.Error.Default) { continue; } var flag = pump_record.Flag; var pump = flag_pump_dict[flag]; var curve_qh = flag_curve_dict[flag]; var hz = pump_record.Rpm / pump.Nr * 50; hz = Math.Round(hz, 2); var curve_head = GetCurveHead(curve_qh, pump.Nr, pump_record.Rpm, pump_record.FlowRate); curve_head = Math.Round(curve_head, 2); var pump_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(pump_record.Head, hz); var curve_head50hz = Model.CurveCalcuHelper.Calculate50HByHz(curve_head, hz); var head_diff = pump_head50hz - curve_head50hz; var vm_pump = new PumpModel(); vm_pump.Time = record.Time; vm_pump.Flag = flag; vm_pump.Rpm = pump_record.Rpm; vm_pump.Hz = hz; vm_pump.Hz0 = Math.Round(hz, 0); vm_pump.Head = pump_record.Head; vm_pump.Flow = pump_record.FlowRate; vm_pump.CurveHead = curve_head; vm_pump.HeadDiff = head_diff; vm_pump_list.Add(vm_pump); } } } if (!vm_pump_list.Any()) return false; var analysis_facotr_list = new List(); var group_by_flag_hz = vm_pump_list.GroupBy(x => new { x.Flag, x.Hz0 }); foreach (var flag_item in group_by_flag_hz) { var hz = flag_item.Key.Hz0; if (hz < 20) { continue; } var flag = flag_item.Key.Flag; var pump = flag_pump_dict[flag]; var qh = flag_curve_dict[flag]; var head_diff_list = flag_item.Select(x => x.HeadDiff).ToList(); double head_diff_avg = 0d, std_dev_pop = 0d, std_dev_pop_head_avg = 0d; var filter_std_dev_pop_tuple = FilterBySTDP(head_diff_list.ToArray(), 0.3, 0); var filter_std_dev_pop_array = filter_std_dev_pop_tuple.Item1; std_dev_pop = filter_std_dev_pop_tuple.Item2; std_dev_pop_head_avg = filter_std_dev_pop_array.Average(); head_diff_avg = std_dev_pop_head_avg; if (Math.Abs(head_diff_avg) > 5) { continue; } if (std_dev_pop>1) { continue; } if (std_dev_pop > 0.5 && flag_item.Count() < 5) { continue; } var analysis_facotr = new AnalysisFactor(); analysis_facotr.Flag = flag; analysis_facotr.Hz = hz; analysis_facotr.HeadSTDP = std_dev_pop; analysis_facotr.HeadDeviation = std_dev_pop_head_avg; analysis_facotr.Accuracy = 0; analysis_facotr_list.Add(analysis_facotr); } analysis_facotr_list = analysis_facotr_list.OrderBy(x => x.Flag).ThenBy(x => x.Hz).ToList(); var flag_range5_hz_factor_dict = new Dictionary>>(); var group_by_flag = vm_pump_list.GroupBy(x => x.Flag); foreach (var flag_item in group_by_flag) { var flag = flag_item.Key; var pump = flag_pump_dict[flag]; var qh = flag_curve_dict[flag]; if (!pump.IsBp) { continue; } flag_range5_hz_factor_dict.Add(flag, new Dictionary>()); for (double i = 5; i <= 50; i += 5) { var min_hz = i - 5; double max_hz = i; var list = flag_item.Where(x => x.Hz >= min_hz && x.Hz <= max_hz).ToList(); if (list == null || list.Count() < 5) continue; var head_diff_list = list.Select(x => x.HeadDiff).ToList(); double std_dev_pop = 0d, std_dev_pop_head_avg = 0d; var filter_tuple = FilterBySTDP(head_diff_list.ToArray(), 0.3, 0); var filter_array = filter_tuple.Item1; std_dev_pop = filter_tuple.Item2; std_dev_pop_head_avg = filter_array.Average(); flag_range5_hz_factor_dict[flag].Add(max_hz, new Tuple(std_dev_pop, std_dev_pop_head_avg, filter_array.Count())); } } var not_hz_list = new List(); foreach (var eq in eq_list) { var flag = eq.SortCode; var pump = flag_pump_dict[flag]; if (!pump.IsBp) { continue; } var qh = flag_curve_dict[flag]; var dict_item = flag_range5_hz_factor_dict[flag]; for (int hz = 1; hz <= 50; hz++) { if (analysis_facotr_list.Exists(x => x.Flag == flag && x.Hz == hz)) { continue; } var num = hz / 5; var hz_key = (num + 1) * 5; if (hz_key > 50) hz_key = 50; if (dict_item.ContainsKey(hz_key)) { var tuple = dict_item[hz_key]; var analysis_facotr = new AnalysisFactor(); analysis_facotr.Flag = flag; analysis_facotr.Hz = hz; analysis_facotr.HeadSTDP = tuple.Item1; analysis_facotr.HeadDeviation = tuple.Item2; analysis_facotr.Accuracy = 0; not_hz_list.Add(analysis_facotr); } else { var key_list = dict_item.Select(x => x.Key).ToList(); var key = key_list.Where(x => x >= hz_key)?.OrderBy(x => x).FirstOrDefault(); if (key == null) { key = key_list.OrderByDescending(x => x).FirstOrDefault(); } if (key == null) { throw new Exception("error"); } var tuple = dict_item[key.Value]; double ratio = hz / key.Value; double head_dev = tuple.Item2 * ratio; double head_stdp = tuple.Item1 * ratio; var analysis_facotr = new AnalysisFactor(); analysis_facotr.Flag = flag; analysis_facotr.Hz = hz; analysis_facotr.HeadSTDP = head_stdp; analysis_facotr.HeadDeviation = head_dev; analysis_facotr.Accuracy = -1; not_hz_list.Add(analysis_facotr); } } } var analysis_factor_list = new List(); analysis_factor_list.AddRange(analysis_facotr_list); analysis_factor_list.AddRange(not_hz_list); var root_folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "分析系数"); if (!Directory.Exists(root_folder)) { Directory.CreateDirectory(root_folder); } var fileName = root_folder + "\\" + name + ".json"; var json = JsonHelper.Object2Json(analysis_factor_list); File.WriteAllText(fileName, json); return true; } #region Function private static 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 static double GetCurveHead(Model.CurveExpress curve_qh, double nr, double rpm, double flow) { if (curve_qh == null) return default; var similar_qh = Model.CurveCalcuHelper.CalculateSimilarQH(curve_qh, nr, rpm); if (similar_qh == null) return default; var head = similar_qh.GetFitPointY(flow); return head; } #endregion } }