using IStation.Epanet;
|
using IStation.Epanet.Enums;
|
|
namespace IStation.Service
|
{
|
/// <summary>
|
/// 模型验证辅助类
|
/// </summary>
|
public partial class ModeVerifyHelper
|
{
|
/// <summary>
|
/// 实时验证
|
/// </summary>
|
/// <param name="verify_id">验证标识</param>
|
/// <param name="verify_time">验证时间</param>
|
/// <param name="verify_file_path">验证模型文件</param>
|
/// <param name="monitor_record_list">ZyScada数据列表</param>
|
/// <param name="pump_pattern_custom_dict">自定义泵模式</param>
|
/// <returns></returns>
|
public static List<Model.HydraulicRecord> Verify(
|
long verify_id,
|
DateTime verify_time,
|
string verify_file_path,
|
List<Model.MonitorRecord> monitor_record_list,
|
Dictionary<string, double?> pump_pattern_custom_dict = null)
|
{
|
var log_title = "初始化验证数据";
|
var log_msg = string.Empty;
|
if (monitor_record_list == null || !monitor_record_list.Any())
|
{
|
log_msg = "monitor_record_list 数据为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
var pump_nr_dict = GlobalHelper.ModelPumpNrDict;
|
var pattern_id_mapping_dict = GlobalHelper.ModelPatternIdMappingDict;
|
var flow_id_mapping_dict = GlobalHelper.ModelFlowIdMappingDict;
|
var pressure_id_mapping_dict = GlobalHelper.ModelPressureIdMappingDict;
|
var pressure_id_kPa_list = GlobalHelper.ModelPressureIdkPaList;
|
|
var pattern_dict = new Dictionary<string, float[]>();
|
var scada_dict = new Dictionary<string, double>();
|
|
var exist_pump_pattern_custom_dict = pump_pattern_custom_dict != null && pump_pattern_custom_dict.Any();
|
|
#region 初始化 pattern_dict scada_dict
|
|
foreach (var monitor_record in monitor_record_list)
|
{
|
var tag = monitor_record.DataCode;
|
var value = monitor_record.DataValue;
|
|
#region Pattern
|
|
foreach (var item in pattern_id_mapping_dict)
|
{
|
if (item.Value != tag)
|
continue;
|
var pattern_id = item.Key;
|
var factor = value ?? 0;
|
if (exist_pump_pattern_custom_dict)
|
{
|
if (pump_pattern_custom_dict.ContainsKey(pattern_id))
|
{
|
factor = pump_pattern_custom_dict[pattern_id] ?? 0;
|
}
|
}
|
else
|
{
|
if (value.HasValue && pump_nr_dict.ContainsKey(pattern_id))
|
{
|
factor /= pump_nr_dict[pattern_id];
|
factor = factor < 0 ? 0 : factor;
|
}
|
}
|
|
pattern_dict.Add(pattern_id, new float[] { (float)factor });
|
}
|
|
#endregion
|
|
#region Scada
|
|
foreach (var item in flow_id_mapping_dict)
|
{
|
if (item.Value != tag)
|
continue;
|
scada_dict.Add(tag, value ?? 0);
|
}
|
|
foreach (var item in pressure_id_mapping_dict)
|
{
|
if (item.Value != tag)
|
continue;
|
var pressure_value = value ?? 0;
|
if (pressure_id_kPa_list.Contains(tag))
|
{
|
pressure_value /= 1000;
|
}
|
pressure_value = IStation.Curve.PumpCalculateHelper.Mpa2M(pressure_value);
|
scada_dict.Add(tag, pressure_value);
|
}
|
#endregion
|
}
|
|
#endregion
|
|
|
var hydraulic_record_list = Verify(verify_id, verify_time, verify_file_path, flow_id_mapping_dict, pressure_id_mapping_dict, pattern_dict, scada_dict);
|
return hydraulic_record_list;
|
|
}
|
|
|
/// <summary>
|
/// 实时验证
|
/// </summary>
|
/// <param name="verify_id">验证标识</param>
|
/// <param name="verify_time">验证时间</param>
|
/// <param name="verify_file_path">验证模型文件</param>
|
/// <param name="flow_id_mapping_dict">流量Scada标识字典</param>
|
/// <param name="pressure_id_mapping_dict">压力Scada标识字典</param>
|
/// <param name="pattern_dict">模式数据</param>
|
/// <param name="scada_dict">Scada数据</param>
|
/// <returns></returns>
|
public static List<Model.HydraulicRecord> Verify(
|
long verify_id,
|
DateTime verify_time,
|
string verify_file_path,
|
Dictionary<string, string> flow_id_mapping_dict,
|
Dictionary<string, string> pressure_id_mapping_dict,
|
Dictionary<string, float[]> pattern_dict,
|
Dictionary<string, double> scada_dict)
|
{
|
var log_title = "开始验证";
|
var log_msg = string.Empty;
|
var hydraulic_record_list = new List<Model.HydraulicRecord>();
|
if (flow_id_mapping_dict == null || !flow_id_mapping_dict.Any())
|
{
|
log_msg = "流量标签字典为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
if (pressure_id_mapping_dict == null || !pressure_id_mapping_dict.Any())
|
{
|
log_msg = "压力标签字典为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
if (pattern_dict == null || !pattern_dict.Any())
|
{
|
log_msg = "模式数据为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
if (scada_dict == null || !scada_dict.Any())
|
{
|
log_msg = "Scada数据为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
var err = EpanetMethods.ENopen(verify_file_path, "", "");
|
if (err != 0)
|
{
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
err = EpanetMethods.ENopenH();
|
if (err != 0)
|
{
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
|
log_title = "验证";
|
var model_id_build = new StringBuilder(31);
|
var pattern_init = true;
|
foreach (var pattern in pattern_dict)
|
{
|
var pattern_id = pattern.Key;
|
var pattern_factor_array = pattern.Value;
|
var pattern_factor_array_count = pattern_factor_array.Length == 0 ? 1 : pattern_factor_array.Length;
|
err = EpanetMethods.ENgetpatternindex(pattern_id, out int pattern_index);
|
|
if (err != ErrorCode.Ok)
|
{
|
pattern_init = false;
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
continue;
|
}
|
err = EpanetMethods.ENsetpattern(pattern_index, pattern_factor_array, pattern_factor_array_count);
|
if (err != ErrorCode.Ok)
|
{
|
pattern_init = false;
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
continue;
|
}
|
}
|
|
if (!pattern_init)
|
{
|
log_msg = $"{verify_time:G}:模式初始化失败!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
EpanetMethods.ENinitH(0);
|
EpanetMethods.ENrunH(out _);
|
EpanetMethods.ENgetcount(CountType.Link, out int link_count);
|
EpanetMethods.ENgetcount(CountType.Node, out int node_count);
|
|
for (int link_index = 1; link_index <= link_count; link_index++)
|
{
|
if (EpanetMethods.ENgetlinkid(link_index, model_id_build) != ErrorCode.Ok)
|
continue;
|
var model_id = model_id_build.ToString();
|
|
if (flow_id_mapping_dict.ContainsKey(model_id))
|
{
|
var scada_id = flow_id_mapping_dict[model_id];
|
var scada_value = scada_dict[scada_id];
|
EpanetMethods.ENgetlinkvalue(link_index, LinkValue.Flow, out float model_value);
|
model_value = Math.Abs(model_value);
|
|
var record = new IStation.Model.HydraulicRecord
|
{
|
VerificationID = verify_id,
|
Time = verify_time,
|
ModelId = model_id,
|
ScadaId = scada_id,
|
ValueType = IStation.eValueType.Flow,
|
ModelValue = (double)model_value,
|
ScadaValue = scada_value
|
};
|
record.DifferenceValue = record.ScadaValue - record.ModelValue;
|
hydraulic_record_list.Add(record);
|
}
|
|
EpanetMethods.ENgetlinktype(link_index, out LinkType linkType);
|
if (linkType == LinkType.Pump)
|
{
|
EpanetMethods.ENgetlinkvalue(link_index, LinkValue.InitStatus, out float on_off);
|
}
|
}
|
|
for (int node_index = 1; node_index <= node_count; node_index++)
|
{
|
if (EpanetMethods.ENgetnodeid(node_index, model_id_build) != ErrorCode.Ok)
|
continue;
|
var model_id = model_id_build.ToString();
|
|
if (pressure_id_mapping_dict.ContainsKey(model_id))
|
{
|
var scada_id = pressure_id_mapping_dict[model_id];
|
var scada_value = scada_dict[scada_id];
|
|
EpanetMethods.ENgetnodevalue(node_index, NodeValue.Head, out float model_value);
|
|
var record = new IStation.Model.HydraulicRecord
|
{
|
VerificationID = verify_id,
|
Time = verify_time,
|
ModelId = model_id,
|
ScadaId = scada_id,
|
ValueType = IStation.eValueType.Head,
|
ModelValue = (double)model_value,
|
ScadaValue = scada_value
|
};
|
record.DifferenceValue = record.ScadaValue - record.ModelValue;
|
hydraulic_record_list.Add(record);
|
}
|
}
|
|
EpanetMethods.ENcloseH();
|
EpanetMethods.ENclose();
|
return hydraulic_record_list;
|
}
|
|
|
|
/// <summary>
|
/// 历史数据验证
|
/// </summary>
|
/// <param name="verify_id">验证标识</param>
|
/// <param name="verify_file_path">验证模型文件</param>
|
/// <param name="monitor_record_day_dict">ZyScada数据列表</param>
|
/// <returns></returns>
|
public static Dictionary<DateTime, List<Model.HydraulicRecord>> Verify(
|
long verify_id,
|
string verify_file_path,
|
Dictionary<DateTime, Dictionary<DateTime, List<Model.MonitorRecord>>> monitor_record_day_dict)
|
{
|
var log_title = "初始化验证数据";
|
var log_msg = string.Empty;
|
if (monitor_record_day_dict == null || !monitor_record_day_dict.Any())
|
{
|
log_msg = "monitor_record_day_dict 数据为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
var pump_nr_dict = GlobalHelper.ModelPumpNrDict;
|
var pattern_id_mapping_dict = GlobalHelper.ModelPatternIdMappingDict;
|
var flow_id_mapping_dict = GlobalHelper.ModelFlowIdMappingDict;
|
var pressure_id_mapping_dict = GlobalHelper.ModelPressureIdMappingDict;
|
var pressure_id_kPa_list = GlobalHelper.ModelPressureIdkPaList;
|
|
var day_value_dict = new Dictionary<DateTime, Tuple<Dictionary<string, float[]>, Dictionary<DateTime, Dictionary<string, double>>>>();
|
foreach (var day_item in monitor_record_day_dict)
|
{
|
var day = day_item.Key;
|
var monitor_record_list_dict = day_item.Value;
|
|
var pattern_list_dict = new Dictionary<string, List<float>>();
|
foreach (var item in pattern_id_mapping_dict)
|
{
|
pattern_list_dict.Add(item.Key, new List<float>());
|
}
|
|
|
var scada_dict_dict = new Dictionary<DateTime, Dictionary<string, double>>();
|
|
#region 初始化 pattern_dict scada_dict
|
for (int i = 0; i < monitor_record_list_dict.Count; i++)
|
{
|
var item = monitor_record_list_dict.ElementAt(i);
|
var time = item.Key;
|
var monitor_record_list = item.Value;
|
|
var scada_dict = new Dictionary<string, double>();
|
foreach (var monitor_record in monitor_record_list)
|
{
|
var tag = monitor_record.DataCode;
|
var value = monitor_record.DataValue;
|
|
#region Pattern
|
foreach (var mapping in pattern_id_mapping_dict)
|
{
|
if (mapping.Value != tag)
|
continue;
|
var pattern_id = mapping.Key;
|
var factor = value ?? 0;
|
|
if (value.HasValue && pump_nr_dict.ContainsKey(pattern_id))
|
{
|
factor /= pump_nr_dict[pattern_id];
|
factor = factor < 0 ? 0 : factor;
|
}
|
pattern_list_dict[pattern_id].Add((float)factor);
|
}
|
|
#endregion
|
|
#region Scada
|
|
foreach (var mapping in flow_id_mapping_dict)
|
{
|
if (mapping.Value != tag)
|
continue;
|
scada_dict.Add(tag, value ?? 0);
|
}
|
|
foreach (var mapping in pressure_id_mapping_dict)
|
{
|
if (mapping.Value != tag)
|
continue;
|
var pressure_value = value ?? 0;
|
if (pressure_id_kPa_list.Contains(tag))
|
{
|
pressure_value /= 1000;
|
}
|
pressure_value = IStation.Curve.PumpCalculateHelper.Mpa2M(pressure_value);
|
scada_dict.Add(tag, pressure_value);
|
}
|
#endregion
|
}
|
scada_dict_dict.Add(time, scada_dict);
|
}
|
#endregion
|
|
var pattern_array_dict = pattern_list_dict.ToDictionary(x => x.Key, y => y.Value.ToArray());
|
day_value_dict.Add(day, new(pattern_array_dict, scada_dict_dict));
|
}
|
|
var hydraulic_record_list_dict = Verify(verify_id, verify_file_path, flow_id_mapping_dict, pressure_id_mapping_dict, day_value_dict);
|
return hydraulic_record_list_dict;
|
}
|
|
/// <summary>
|
/// 历史数据验证
|
/// </summary>
|
/// <param name="verify_id">验证标识</param>
|
/// <param name="verify_file_path">验证模型文件</param>
|
/// <param name="flow_id_mapping_dict">流量Scada标识字典</param>
|
/// <param name="pressure_id_mapping_dict">压力Scada标识字典</param>
|
/// <param name="day_value_dict">日数据列表</param>
|
/// <returns></returns>
|
public static Dictionary<DateTime, List<Model.HydraulicRecord>> Verify(
|
long verify_id,
|
string verify_file_path,
|
Dictionary<string, string> flow_id_mapping_dict,
|
Dictionary<string, string> pressure_id_mapping_dict,
|
Dictionary<DateTime, Tuple<Dictionary<string, float[]>, Dictionary<DateTime, Dictionary<string, double>>>> day_value_dict)
|
{
|
#region 入参验证
|
|
var log_title = "开始验证";
|
var log_msg = string.Empty;
|
var hydraulic_record_list_dict = new Dictionary<DateTime, List<Model.HydraulicRecord>>();
|
if (flow_id_mapping_dict == null || !flow_id_mapping_dict.Any())
|
{
|
log_msg = "流量标签字典为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
if (pressure_id_mapping_dict == null || !pressure_id_mapping_dict.Any())
|
{
|
log_msg = "压力标签字典为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
if (day_value_dict == null || !day_value_dict.Any())
|
{
|
log_msg = "日数据列表为空!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
#endregion
|
|
#region 加载模型
|
|
|
var err = EpanetMethods.ENopen(verify_file_path, "", "");
|
if (err != 0)
|
{
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
//EpanetMethods.ENsettimeparam(TimeParameter.PatternStep, 1);
|
//EpanetMethods.ENsettimeparam(TimeParameter.HydStep, 1);
|
//EpanetMethods.ENsettimeparam(TimeParameter.ReportStep, 1);
|
err = EpanetMethods.ENopenH();
|
if (err != 0)
|
{
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
|
#endregion
|
|
log_title = "验证";
|
var model_id_build = new StringBuilder(31);
|
var pattern_init = true;
|
var pattern_time_step = 0;
|
foreach (var day_value in day_value_dict)
|
{
|
var day = day_value.Key;
|
var pattern_dict = day_value.Value.Item1;
|
var time_value_dict = day_value.Value.Item2;
|
if (time_value_dict == null || !time_value_dict.Any())
|
{
|
continue;
|
}
|
|
#region 模式初始化
|
pattern_init = true;
|
pattern_time_step = 0;
|
foreach (var pattern in pattern_dict)
|
{
|
var pattern_id = pattern.Key;
|
var pattern_factor_array = pattern.Value;
|
var pattern_factor_array_count = pattern_factor_array.Length == 0 ? 1 : pattern_factor_array.Length;
|
err = EpanetMethods.ENgetpatternindex(pattern_id, out int pattern_index);
|
if (err != ErrorCode.Ok)
|
{
|
pattern_init = false;
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
continue;
|
}
|
|
err = EpanetMethods.ENsetpattern(pattern_index, pattern_factor_array, pattern_factor_array_count);
|
if (err != ErrorCode.Ok)
|
{
|
pattern_init = false;
|
log_msg = err.GetMsg();
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
continue;
|
}
|
|
}
|
|
if (!pattern_init)
|
{
|
log_msg = $"{day:G}:模式初始化失败!";
|
HydraulicLog.Info(verify_id, log_title, log_msg);
|
return default;
|
}
|
#endregion
|
|
#region 模型验证
|
|
var time_value_dict_dict = time_value_dict.ToDictionary(x => x.Key.TimeOfDay.TotalSeconds, y => y);
|
|
EpanetMethods.ENinitH(0);
|
do
|
{
|
EpanetMethods.ENrunH(out int current_ts);
|
EpanetMethods.ENgetcount(CountType.Link, out int link_count);
|
EpanetMethods.ENgetcount(CountType.Node, out int node_count);
|
|
var current_time = TimeSpan.FromSeconds(current_ts);
|
if (time_value_dict_dict.ContainsKey(current_time.TotalSeconds))
|
{
|
var hydraulic_record_list = new List<Model.HydraulicRecord>();
|
|
var time_value = time_value_dict_dict[current_ts];
|
var verify_time = time_value.Key;
|
var scada_dict = time_value.Value;
|
for (int link_index = 1; link_index <= link_count; link_index++)
|
{
|
if (EpanetMethods.ENgetlinkid(link_index, model_id_build) != ErrorCode.Ok)
|
continue;
|
var model_id = model_id_build.ToString();
|
|
if (flow_id_mapping_dict.ContainsKey(model_id))
|
{
|
var scada_id = flow_id_mapping_dict[model_id];
|
var scada_value = scada_dict[scada_id];
|
|
EpanetMethods.ENgetlinkvalue(link_index, LinkValue.Flow, out float model_value);
|
var record = new IStation.Model.HydraulicRecord
|
{
|
VerificationID = verify_id,
|
Time = verify_time,
|
ModelId = model_id,
|
ScadaId = scada_id,
|
ValueType = IStation.eValueType.Flow,
|
ModelValue = (double)Math.Abs(model_value),
|
ScadaValue = scada_value
|
};
|
record.DifferenceValue = record.ScadaValue - record.ModelValue;
|
hydraulic_record_list.Add(record);
|
}
|
|
EpanetMethods.ENgetlinktype(link_index, out LinkType linkType);
|
if (linkType == LinkType.Pump)
|
{
|
EpanetMethods.ENgetlinkvalue(link_index, LinkValue.InitStatus, out float on_off);
|
}
|
}
|
|
for (int node_index = 1; node_index <= node_count; node_index++)
|
{
|
if (EpanetMethods.ENgetnodeid(node_index, model_id_build) != ErrorCode.Ok)
|
continue;
|
var model_id = model_id_build.ToString();
|
|
|
if (pressure_id_mapping_dict.ContainsKey(model_id))
|
{
|
var scada_id = pressure_id_mapping_dict[model_id];
|
var scada_value = scada_dict[scada_id];
|
|
EpanetMethods.ENgetnodevalue(node_index, NodeValue.Head, out float model_value);
|
var record = new IStation.Model.HydraulicRecord
|
{
|
VerificationID = verify_id,
|
Time = verify_time,
|
ModelId = model_id,
|
ScadaId = scada_id,
|
ValueType = IStation.eValueType.Head,
|
ModelValue = (double)model_value,
|
ScadaValue = scada_value
|
};
|
record.DifferenceValue = record.ScadaValue - record.ModelValue;
|
hydraulic_record_list.Add(record);
|
}
|
}
|
|
hydraulic_record_list_dict.Add(verify_time, hydraulic_record_list);
|
}
|
|
EpanetMethods.ENnextH(out pattern_time_step);
|
|
} while (pattern_time_step > 0);
|
|
#endregion
|
|
}
|
EpanetMethods.ENcloseH();
|
EpanetMethods.ENclose();
|
return hydraulic_record_list_dict;
|
}
|
|
|
|
}
|
}
|