using System;
|
using System.Collections.Generic;
|
using System.IO;
|
using System.Linq;
|
|
namespace IStation.WinFrmUI
|
{
|
/// <summary>
|
/// 导出 分析系数
|
/// </summary>
|
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; }
|
|
}
|
|
/// <summary>
|
/// 分析系数
|
/// </summary>
|
public class AnalysisFactor
|
{
|
|
/// <summary>
|
/// 泵标志
|
/// </summary>
|
public int Flag { get; set; }
|
|
/// <summary>
|
/// 频率
|
/// </summary>
|
public double Hz { get; set; }
|
|
/// <summary>
|
/// 扬程标准差
|
/// </summary>
|
public double? HeadSTDP { get; set; }
|
|
/// <summary>
|
/// 扬程偏差
|
/// </summary>
|
public double? HeadDeviation { get; set; }
|
|
/// <summary>
|
/// 准确度
|
/// </summary>
|
public double Accuracy { get; set; }
|
|
|
}
|
|
static BLL.StationSignalRecordPacket _packet = new BLL.StationSignalRecordPacket();
|
|
/// <summary>
|
/// 绑定数据
|
/// </summary>
|
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<int, Model.CurveExpress>();
|
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<PumpModel>();
|
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<AnalysisFactor>();
|
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<int, Dictionary<double, Tuple<double, double, int>>>();
|
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<double, Tuple<double, double, int>>());
|
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<double, double, int>(std_dev_pop, std_dev_pop_head_avg, filter_array.Count()));
|
|
}
|
}
|
|
|
var not_hz_list = new List<AnalysisFactor>();
|
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<AnalysisFactor>();
|
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<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 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
|
|
|
}
|
}
|