namespace IStation.Application
{
///
///
///
[Route("ChenHang/Dispatch/HydraulicModel")]
[ApiDescriptionSettings("Web", Name = "水力模型", Order = 1)]
public class HydraulicModel_Controller : IDynamicApiController
{
private readonly Service.Station _service_station = new();
private readonly Service.ScheduleConfig _service_schedule_config = new();
private static readonly string _hydraulic_model_file = Path.Combine(
Settings.ParasHelper.LocalFile.DataFolderDirectory,
Settings.ParasHelper.LocalFile.HydraulicModelFile);
///
/// 获取水力模型
///
[Route("Get@V1.0")]
[HttpGet]
public Dto.Epanet.HydraulicModelDto Get()
{
if (!File.Exists(_hydraulic_model_file))
{
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, $"水力模型文件缺失!文件路径:{_hydraulic_model_file}");
}
IStation.Epanet.NetworkHelper.Open(_hydraulic_model_file, out Epanet.Network.Network network);
if (network == null)
{
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, $"文件解析失败!文件路径:{_hydraulic_model_file}");
}
if (network == null)
return default;
var reservoirs = network.Reservoirs;
var tanks = network.Tanks;
var junctions = network.Junctions;
var pipes = network.Pipes;
var pumps = network.Pumps;
var valves = network.Valves;
var hydraulic_model_dto = new Dto.Epanet.HydraulicModelDto();
if (reservoirs != null && reservoirs.Any())
{
foreach (var item in reservoirs)
{
var dto = new Dto.Epanet.Reservoir
{
Id = item.Name,
Coordinate = new Dto.Epanet.EnPoint(item.Coordinate.X, item.Coordinate.Y)
};
hydraulic_model_dto.Reservoirs.Add(dto);
}
}
if (tanks != null && tanks.Any())
{
foreach (var item in tanks)
{
var dto = new Dto.Epanet.Tank
{
Id = item.Name,
Coordinate = new Dto.Epanet.EnPoint(item.Coordinate.X, item.Coordinate.Y),
};
hydraulic_model_dto.Tanks.Add(dto);
}
}
if (junctions != null && junctions.Any())
{
foreach (var item in junctions)
{
var dto = new Dto.Epanet.Junction
{
Id = item.Name,
Coordinate = new Dto.Epanet.EnPoint(item.Coordinate.X, item.Coordinate.Y),
};
hydraulic_model_dto.Junctions.Add(dto);
}
}
if (pipes != null && pipes.Any())
{
foreach (var item in pipes)
{
var dto = new Dto.Epanet.Pipe
{
Id = item.Name,
};
if (item.FirstNode != null)
{
var node = item.FirstNode;
dto.FirstNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
if (item.SecondNode != null)
{
var node = item.SecondNode;
dto.SecondNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
hydraulic_model_dto.Pipes.Add(dto);
}
}
if (pumps != null && pumps.Any())
{
foreach (var item in pumps)
{
var dto = new Dto.Epanet.Pump
{
Id = item.Name,
};
if (item.FirstNode != null)
{
var node = item.FirstNode;
dto.FirstNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
if (item.SecondNode != null)
{
var node = item.SecondNode;
dto.SecondNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
hydraulic_model_dto.Pumps.Add(dto);
}
}
if (valves != null && valves.Any())
{
foreach (var item in valves)
{
var dto = new Dto.Epanet.Valve
{
Id = item.Name,
};
if (item.FirstNode != null)
{
var node = item.FirstNode;
dto.FirstNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
if (item.SecondNode != null)
{
var node = item.SecondNode;
dto.SecondNode = new Dto.Epanet.Node()
{
Id = node.Name,
Coordinate = new Dto.Epanet.EnPoint(node.Coordinate.X, node.Coordinate.Y),
};
}
hydraulic_model_dto.Valves.Add(dto);
}
}
return hydraulic_model_dto;
}
///
/// 获取Scada数据
///
[Route("GetScadaList@V1.0")]
[HttpGet]
public List GetScadaList()
{
var dto_list = new List();
GlobalHelper.GetRealTimeZyScadaList(out List zy_scada_list, true);
if (zy_scada_list != null && zy_scada_list.Any())
{
foreach (var zy_scada in zy_scada_list)
{
var dto_zy_scada = new Dto.Epanet.ZyScada();
dto_zy_scada.Time = zy_scada.Time;
dto_zy_scada.Id = zy_scada.Tag;
dto_zy_scada.Value = zy_scada.Value;
dto_list.Add(dto_zy_scada);
}
}
return dto_list;
}
///
/// 调度验证
///
[AllowAnonymous]
[Route("ScheduleValidation@V1.0")]
[HttpPost]
public Dto.Epanet.HydraulicScheduleDto ScheduleValidation([Required] StationScheduleInput input)
{
if (!File.Exists(_hydraulic_model_file))
{
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, $"水力模型文件缺失!文件路径:{_hydraulic_model_file}");
}
var receipt_time = DateTime.Now;
var request_id = Yw.YitIdHelper.NextId();
var log_title = string.Empty;
var log_msg = string.Empty;
log_title = "初始化基础信息文件";
var station_info = _service_station.Get();
if (station_info == null)
{
log_msg = "文件缺失!";
Log.Info(request_id, log_title, log_msg);
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, log_msg);
}
log_title = "需水请求";
Log.Debug(request_id, log_title, JsonHelper.Object2Json(input));
var target_flow1 = input.objects["TotalFlow1"];
var target_pressure1 = input.objects["TotalPressure1"];
var target_flow2 = input.objects["TotalFlow2"];
var target_pressure2 = input.objects["TotalPressure2"];
Log.Info(request_id, log_title, $"target_flow1:{target_flow1},target_pressure1:{target_pressure1},target_flow2:{target_flow2},target_pressure2:{target_pressure2}");
var target_head1 = Curve.PumpCalculateHelper.Mpa2M(target_pressure1);
var target_head2 = Curve.PumpCalculateHelper.Mpa2M(target_pressure2);
log_title = "实时ZyScada请求";
var get_msg = GlobalHelper.GetRealTimeZyScadaList(out List zy_scada_list, true);
if (!string.IsNullOrEmpty(get_msg))
{
Log.Info(request_id, log_title, get_msg);
}
Log.Debug(request_id, log_title, JsonHelper.Object2Json(zy_scada_list));
var station1 = station_info.Station1;
var station2 = station_info.Station2;
var station1_schedule_config = _service_schedule_config.GetStation1();
var station2_schedule_config = _service_schedule_config.GetStation2();
var station1_flag_list = GlobalHelper.Station1FlagList;
var station2_flag_list = GlobalHelper.Station2FlagList;
GlobalHelper.GetStationOpenFlagList(zy_scada_list, out List station1_open_flag_list, out List station2_open_flag_list);
GlobalHelper.GetStationMaintenanceFlagList(zy_scada_list, out List station1_maintenance_flag_list, out List station2_maintenance_flag_list);
GlobalHelper.GetFlagInletWaterLevelDict(zy_scada_list, out Dictionary station1_flag_inlet_water_level_dict, out Dictionary station2_flag_inlet_water_level_dict);
//GlobalHelper.GetFlagCumulativeRuntimeDict(out Dictionary station1_flag_cumulative_run_time_dict, out Dictionary station2_flag_cumulative_run_time_dict);
log_title = "机泵检修";
if (station1_maintenance_flag_list != null && station1_maintenance_flag_list.Any())
{
Log.Info(request_id, log_title, $"1输水:{Yw.Untity.IntListHelper.ToString(station1_maintenance_flag_list)}");
station1_schedule_config.MustCloseFlagList.AddRange(station1_maintenance_flag_list);
}
if (station2_maintenance_flag_list != null && station2_maintenance_flag_list.Any())
{
Log.Info(request_id, log_title, $"2输水:{Yw.Untity.IntListHelper.ToString(station2_maintenance_flag_list)}");
station2_schedule_config.MustCloseFlagList.AddRange(station2_maintenance_flag_list);
}
var helper = new Algorithm.ScheduleHelper();
helper.Initial(station1_open_flag_list, station1_schedule_config);
var optimal_combine1 = helper.GetOptAnaCombine(station1, station1_flag_inlet_water_level_dict, target_flow1, target_head1);
helper.Initial(station2_open_flag_list, station2_schedule_config);
var optimal_combine2 = helper.GetOptAnaCombine(station2, station2_flag_inlet_water_level_dict, target_flow2, target_head2);
log_title = "调度返回";
if (optimal_combine1 == null && optimal_combine2 == null)
{
log_msg = "厂内调度方案无法计算!";
Log.Info(request_id, log_title, log_msg);
throw Yw.Dto.YOops.Oh(Yw.Dto.eResultCode.Error, Yw.Dto.InternalErrorCodes.A001, log_msg);
}
var pump_id_mapping_dict = GlobalHelper.ModelPumpIdMappingDict;
var pump_nr_dict = GlobalHelper.ModelPumpNrDict;
var flag_nr_mapping_dict = GlobalHelper.GetFlagNrMappingDict();
var pump_schedule_value_list = new List();
foreach (var item in pump_id_mapping_dict)
{
var flag = item.Key;
var model_id = item.Value;
var pump_schedule_value = new Dto.Epanet.ScheduleValue();
pump_schedule_value.ModelId = model_id;
pump_schedule_value.Unit = "hz";
pump_schedule_value.ModelValue = 0;
var scada_tag = flag_nr_mapping_dict[flag];
var zy_scada = zy_scada_list?.Find(x => x.Code == scada_tag);
if (zy_scada != null)
{
var scada_value = zy_scada.Value;
if (IStation.GlobalHelper.IsFrequency(flag))
{
scada_value /= pump_nr_dict[model_id];
}
pump_schedule_value.ScadaId = scada_tag;
pump_schedule_value.ScadaValue = scada_value;
}
pump_schedule_value_list.Add(pump_schedule_value);
}
if (optimal_combine1 != null)
{
foreach (var fre_pump in optimal_combine1.AnaFrePumps)
{
var flag = fre_pump.Flag;
var pump_schedule_value = pump_schedule_value_list.Find(x => x.ModelId == pump_id_mapping_dict[flag]);
if (pump_schedule_value != null)
{
pump_schedule_value.ModelValue = fre_pump.Frequency / 50;
}
}
}
else
{
log_msg = $"\r\n1输水调度计算失败,无法满足目标流量:{target_flow1},目标压力:{target_pressure1}!";
Log.Info(request_id, log_title, log_msg);
}
if (optimal_combine2 != null)
{
foreach (var fre_pump in optimal_combine2.AnaFrePumps)
{
var flag = fre_pump.Flag;
var pump_schedule_value = pump_schedule_value_list.Find(x => x.ModelId == pump_id_mapping_dict[flag]);
if (pump_schedule_value != null)
{
pump_schedule_value.ModelValue = fre_pump.Frequency / 50;
}
}
}
else
{
log_msg += $"\r\n2输水调度计算失败,无法满足目标流量:{target_flow2},目标压力:{target_pressure2}!";
Log.Info(request_id, log_title, log_msg);
}
var pump_pattern_custom_dict = pump_schedule_value_list.ToDictionary(x => x.ModelId, v => v.ModelValue);
var hydraulic_model_record_list = IStation.Hydraulic.ModeVerifyHelper.Verify(request_id, receipt_time, _hydraulic_model_file, zy_scada_list, pump_pattern_custom_dict);
if (hydraulic_model_record_list == null || !hydraulic_model_record_list.Any())
{
log_msg = $"模型验证数据为空!";
Log.Info(request_id, log_title, log_msg);
}
var hydraulic_schedule_dto = new Dto.Epanet.HydraulicScheduleDto();
foreach (var pump_schedule_value in pump_schedule_value_list)
{
var scada_value = pump_schedule_value.ScadaValue ?? 0;
var model_value = pump_schedule_value.ModelValue ?? 0;
var schedule_value = new Dto.Epanet.ScheduleValue(pump_schedule_value);
schedule_value.ScadaValue = Math.Round(scada_value * 50, 3);
schedule_value.ModelValue = Math.Round(model_value * 50, 3);
hydraulic_schedule_dto.ScheduleValues.Add(schedule_value);
}
foreach (var record in hydraulic_model_record_list)
{
var digits = 4;
var unit = "m";
if (record.ValueType == eValueType.Flow)
{
digits = 1;
unit = "m³/h";
}
var schedule_value = new Dto.Epanet.ScheduleValue();
schedule_value.ModelId = record.ModelId;
schedule_value.ScadaId = record.ScadaId;
schedule_value.Unit = unit;
if (record.ScadaValue.HasValue)
{
schedule_value.ScadaValue = Math.Round(record.ScadaValue.Value, digits);
}
if (record.ModelValue.HasValue)
{
schedule_value.ModelValue = Math.Round(record.ModelValue.Value, digits);
}
hydraulic_schedule_dto.ScheduleValues.Add(schedule_value);
}
return hydraulic_schedule_dto;
}
}
}