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_same_type_flag_group_first = GlobalHelper.Station1SameTypeFlagGroupFirst; var station2_same_type_flag_group_first = GlobalHelper.Station2SameTypeFlagGroupFirst; 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_same_type_flag_group_first, station1_flag_inlet_water_level_dict, station1_flag_cumulative_run_time_dict, target_flow1, target_head1); helper.Initial(station2_open_flag_list, station2_schedule_config); var optimal_combine2 = helper.GetOptAnaCombine(station2, station2_same_type_flag_group_first, station2_flag_inlet_water_level_dict, station2_flag_cumulative_run_time_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; } } }