using IStation.Curve; using IStation.Model; using SqlSugar; namespace IStation.Application { /// /// 输水调度 /// [AllowAnonymous] [Route("OpenApi/Dispatch/Solution")] [ApiDescriptionSettings("Schedule", Name = "调度", Order = 1000)] public class Schedule_Controller : IDynamicApiController, ITransient { private static readonly Service.ScheduleRequest _service_schedule_request = new(); private static readonly Service.ScheduleScada _service_schedule_scada = new(); private static readonly Service.ScheduleRule _service_schedule_rule = new(); private static readonly Service.ScheduleConclusion _service_schedule_conclusion = new(); private static readonly Service.SchedulePump _service_schedule_pump = new(); private static readonly Service.Station _service_station = new(); private static readonly Service.ScheduleConfig _service_schedule_config = new(); private static readonly Service.AnalysisDeviation _service_analysis_deviation = new(); private static readonly Service.FlowDeviation _service_flow_deviation = new(); /// /// 计算 /// [AllowAnonymous] [Route("Calculate@V1.0")] [HttpPost] [NonUnify] public StationScheduleOutput Calculate([Required] StationScheduleInput input) { var receipt_time = DateTime.Now; var request_id = Yw.YitIdHelper.NextId(); var log_title = string.Empty; log_title = "初始化基础信息文件"; var station_info = _service_station.Get(); if (station_info == null) { ScheduleLog.Info(request_id, log_title, "文件缺失!"); return new StationScheduleOutput() { flag = 0, message = "文件缺失" }; } log_title = "需水请求"; ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(input)); var target_flow1 = input.objects["TotalFlow1"]; var target_mpa_pressure1 = input.objects["TotalPressure1"]; var target_flow2 = input.objects["TotalFlow2"]; var target_mpa_pressure2 = input.objects["TotalPressure2"]; ScheduleLog.Info(request_id, log_title, $"target_flow1:{target_flow1},target_pressure1:{target_mpa_pressure1},target_flow2:{target_flow2},target_pressure2:{target_mpa_pressure2}"); var target_pressure1 = Curve.PumpCalculateHelper.Mpa2M(target_mpa_pressure1); var target_pressure2 = Curve.PumpCalculateHelper.Mpa2M(target_mpa_pressure2); var is_monitor_record_debug = false; #if DEBUG is_monitor_record_debug = true; #endif log_title = "实时ZyScada请求"; var get_msg = GlobalHelper.GetMonitorRecordList(receipt_time, out List monitor_record_list, is_monitor_record_debug); if (!string.IsNullOrEmpty(get_msg)) { ScheduleLog.Info(request_id, log_title, get_msg); } ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(monitor_record_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; var analysis_deviation_list = _service_analysis_deviation.GetList(); GlobalHelper.GetStationOpenFlagList(monitor_record_list, out List station1_open_flag_list, out List station2_open_flag_list); GlobalHelper.GetStationFlagStateList(monitor_record_list, out List station1_maintenance_flag_list, out List station2_maintenance_flag_list, out List station1_priority_flag_list, out List station2_priority_flag_list); GlobalHelper.GetFlagInletWaterLevelDict(monitor_record_list, out Dictionary station1_flag_inlet_water_level_dict, out Dictionary station2_flag_inlet_water_level_dict); station1_schedule_config.MaintenanceFlagList = new List(); station2_schedule_config.MaintenanceFlagList = new List(); station1_schedule_config.PriorityOpenFlagList = new List(); station2_schedule_config.PriorityOpenFlagList = new List(); log_title = "机泵检修"; if (station1_maintenance_flag_list != null && station1_maintenance_flag_list.Any()) { ScheduleLog.Info(request_id, log_title, $"1输水:{Yw.Untity.IntListHelper.ToString(station1_maintenance_flag_list)}"); station1_schedule_config.MaintenanceFlagList.AddRange(station1_maintenance_flag_list); } if (station2_maintenance_flag_list != null && station2_maintenance_flag_list.Any()) { ScheduleLog.Info(request_id, log_title, $"2输水:{Yw.Untity.IntListHelper.ToString(station2_maintenance_flag_list)}"); station2_schedule_config.MaintenanceFlagList.AddRange(station2_maintenance_flag_list); } log_title = "机泵优先"; if (station1_priority_flag_list != null && station1_priority_flag_list.Any()) { ScheduleLog.Info(request_id, log_title, $"1输水:{Yw.Untity.IntListHelper.ToString(station1_priority_flag_list)}"); station1_schedule_config.PriorityOpenFlagList.AddRange(station1_priority_flag_list); } if (station2_priority_flag_list != null && station2_priority_flag_list.Any()) { ScheduleLog.Info(request_id, log_title, $"2输水:{Yw.Untity.IntListHelper.ToString(station2_priority_flag_list)}"); station2_schedule_config.PriorityOpenFlagList.AddRange(station2_priority_flag_list); } log_title = "供水限制"; var limit_info= VerifyWaterSupplyLimit(station1_schedule_config.WaterSupplyLimitList,station1_open_flag_list, target_flow1); if (!string.IsNullOrEmpty(limit_info)) { ScheduleLog.Info(request_id, log_title, $"1输水:{limit_info}"); } limit_info = VerifyWaterSupplyLimit(station2_schedule_config.WaterSupplyLimitList, station2_open_flag_list, target_flow2); if (!string.IsNullOrEmpty(limit_info)) { ScheduleLog.Info(request_id, log_title, $"2输水:{limit_info}"); } log_title = "流量补差"; var helper = new Service.ScheduleHelper(); helper.Initial(station1_open_flag_list, station1_schedule_config, analysis_deviation_list); var optimal_combine1 = helper.GetOptAnaCombine(station1, station1_flag_inlet_water_level_dict, target_flow1, target_pressure1); var station2_target_flow_diff=_service_flow_deviation.GetFlowDiff(target_pressure2); ScheduleLog.Info(request_id, log_title, $"2输水:{station2_target_flow_diff:N1}"); helper.Initial(station2_open_flag_list, station2_schedule_config, analysis_deviation_list,station2_target_flow_diff); var optimal_combine2 = helper.GetOptAnaCombine(station2, station2_flag_inlet_water_level_dict, target_flow2, target_pressure2); log_title = "调度返回"; var msg = "计算结束!"; var schedule_request = new Model.ScheduleRequest { ID = request_id, TargetFlow1 = target_flow1, TargetPressure1 = target_mpa_pressure1, TargetFlow2 = target_flow2, TargetPressure2 = target_mpa_pressure2, ScheduleStatus1 = optimal_combine1 != null, ScheduleStatus2 = optimal_combine2 != null, TotalTimeSpent = (DateTime.Now - receipt_time).TotalSeconds, ReceptionTime = receipt_time }; Model.ScheduleConclusion schedule_conclusion1 = null; Model.ScheduleConclusion schedule_conclusion2 = null; List schedule_pump_list1 = null; List schedule_pump_list2 = null; var output = new StationScheduleOutput(); output.InitObjects(station1_flag_list, station2_flag_list); if (optimal_combine1 == null && optimal_combine2 == null) { output.flag = 0; output.message = "厂内调度方案无法计算!"; ScheduleLog.Info(request_id, log_title, "厂内调度方案无法计算!"); } else { if (optimal_combine1 != null) { optimal_combine1.Round(); schedule_conclusion1 = new Model.ScheduleConclusion { ID = Yw.YitIdHelper.NextId(), RequestID = request_id, Station = IStation.eDockingStation.Ch1s, TotalFlow = optimal_combine1.TotalFlow, TotalPressure = optimal_combine1.TotalPressure, TotalPower = optimal_combine1.TotalPower, TotalEfficiency = optimal_combine1.TotalEfficiency, WP = optimal_combine1.WP, UWP = optimal_combine1.UWP, Flags = IntListHelper.ToString(optimal_combine1.Flags), MeritRatio = optimal_combine1.MeritRatio }; schedule_pump_list1 = new List(); // 20250422 修改原因,水中心直接拿我的理论值套到调度上了,我返回原值给他们 output.objects["1输水总流量"] = target_flow1; output.objects["1输水总压力"] = target_mpa_pressure1; output.objects["1输水总功率"] = optimal_combine1.TotalPower; output.objects["1输水总效率"] = optimal_combine1.TotalEfficiency; output.objects["1输水总千吨能耗"] = optimal_combine1.WP; output.objects["1输水总单位能耗"] = optimal_combine1.UWP; foreach (var fre_pump in optimal_combine1.AnaFrePumps) { var flag = fre_pump.Flag; output.objects[$"1输水{flag}#流量"] = fre_pump.Flow; output.objects[$"1输水{flag}#扬程"] = fre_pump.Head; output.objects[$"1输水{flag}#功率"] = fre_pump.Power; output.objects[$"1输水{flag}#效率"] = fre_pump.Eff; output.objects[$"1输水{flag}#频率"] = fre_pump.Frequency; output.objects[$"1输水{flag}#转速"] = fre_pump.Speed; switch (flag) { case 11: { output.objects["一输水泵11号变频单泵.变频器运行"] = 1; } break; case 12: { output.objects["一输水泵12号变频单泵.变频器运行"] = 1; } break; case 13: { output.objects["一输水泵13号变频单泵.变频器运行"] = 1; } break; case 14: { output.objects["一输水泵14号变频单泵.变频器运行"] = 1; } break; case 15: { output.objects["HF长江原水厂ABPLC.6KV配电一输水.0402010201011501003一输水15号泵运行"] = 1; } break; case 16: { output.objects["HF一输水16号工频控制图.16#水泵运行"] = 1; } break; case 17: { output.objects["一输水泵17号变频单泵.变频器运行"] = 1; } break; case 18: { output.objects["一输水泵18号变频单泵.变频器运行"] = 1; } break; default: break; } var schedule_pump = new Model.SchedulePump { RequestID = request_id, Station = IStation.eDockingStation.Ch1s, Flag = flag, Flow = fre_pump.Flow, Head = fre_pump.Head, PressureDiff = fre_pump.PressureDiff, Power = fre_pump.Power, Efficiency = fre_pump.Eff, Hz = fre_pump.Frequency, Rpm = fre_pump.Speed }; schedule_pump_list1.Add(schedule_pump); } } else { output.objects["1输水总流量"] = target_flow1; output.objects["1输水总压力"] = target_mpa_pressure1; msg += $" 1输水调度计算失败,无法满足目标流量:{target_flow1},目标压力:{target_mpa_pressure1}!"; } if (optimal_combine2 != null) { optimal_combine2.Round(); schedule_conclusion2 = new Model.ScheduleConclusion { ID = Yw.YitIdHelper.NextId(), RequestID = request_id, Station = IStation.eDockingStation.Ch2s, TotalFlow = optimal_combine2.TotalFlow, TotalPressure = optimal_combine2.TotalPressure, TotalPower = optimal_combine2.TotalPower, TotalEfficiency = optimal_combine2.TotalEfficiency, WP = optimal_combine2.WP, UWP = optimal_combine2.UWP, Flags = IntListHelper.ToString(optimal_combine2.Flags), MeritRatio = optimal_combine2.MeritRatio }; schedule_pump_list2 = new List(); output.objects["2输水总流量"] = target_flow2; output.objects["2输水总压力"] = target_mpa_pressure2; output.objects["2输水总功率"] = optimal_combine2.TotalPower; output.objects["2输水总效率"] = optimal_combine2.TotalEfficiency; output.objects["2输水总千吨能耗"] = optimal_combine2.WP; output.objects["2输水总单位能耗"] = optimal_combine2.UWP; foreach (var fre_pump in optimal_combine2.AnaFrePumps) { var flag = fre_pump.Flag; output.objects[$"2输水{flag}#流量"] = fre_pump.Flow; output.objects[$"2输水{flag}#扬程"] = fre_pump.Head; output.objects[$"2输水{flag}#功率"] = fre_pump.Power; output.objects[$"2输水{flag}#效率"] = fre_pump.Eff; output.objects[$"2输水{flag}#频率"] = fre_pump.Frequency; output.objects[$"2输水{flag}#转速"] = fre_pump.Speed; switch (flag) { case 21: { output.objects["二输水21号水泵视图.泵运行"] = 1; } break; case 22: { output.objects["二输水22号水泵视图.泵运行"] = 1; } break; case 23: { output.objects["二输水23号水泵软启动.运行"] = 1; } break; case 24: { output.objects["二输水24号水泵软启动.运行"] = 1; } break; case 25: { output.objects["二输水25号水泵软启动.运行"] = 1; } break; case 26: { output.objects["二输水26号水泵软启动.运行"] = 1; } break; case 27: { output.objects["二输水27号水泵变频器.运行状态"] = 1; } break; default: break; } var schedule_pump = new Model.SchedulePump { RequestID = request_id, Station = IStation.eDockingStation.Ch2s, Flag = flag, Flow = fre_pump.Flow, Head = fre_pump.Head, PressureDiff = fre_pump.PressureDiff, Power = fre_pump.Power, Efficiency = fre_pump.Eff, Hz = fre_pump.Frequency, Rpm = fre_pump.Speed }; schedule_pump_list2.Add(schedule_pump); } } else { output.objects["2输水总流量"] = target_flow2; output.objects["2输水总压力"] = target_mpa_pressure2; msg += $" 2输水调度计算失败,无法满足目标流量:{target_flow2},目标压力:{target_mpa_pressure2}!"; } } output.flag = optimal_combine1 != null && optimal_combine2 != null ? 1 : 0; output.ReceiptTime = receipt_time; output.ReturnTime = DateTime.Now; output.message = msg; ScheduleLog.Info(request_id, log_title, msg); try { log_title = "存储方案"; var bol = false; bol = _service_schedule_request.Insert(schedule_request) > 0; if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_request 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_request)); } if (station1_schedule_config != null) { var schedule_rule1 = new Model.ScheduleRule { RequestID = request_id, Station = eDockingStation.Ch1s, Config = JsonHelper.Object2Json(station1_schedule_config) }; bol = _service_schedule_rule.Insert(schedule_rule1) > 0; if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_config1 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_rule1)); } } if (station2_schedule_config != null) { var schedule_rule2 = new Model.ScheduleRule { RequestID = request_id, Station = eDockingStation.Ch2s, Config = JsonHelper.Object2Json(station2_schedule_config) }; bol = _service_schedule_rule.Insert(schedule_rule2) > 0; if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_config2 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_rule2)); } } if (monitor_record_list != null && monitor_record_list.Any()) { var scada_list = monitor_record_list .OrderBy(x => x.DataCode) .Select(x => new Model.ScheduleScada() { RequestID = request_id, DataTime = x.DataTime, DataCode = x.DataCode, DataValue = x.DataValue, ReceiptTime = x.ReceiptTime, }).ToList(); bol = _service_schedule_scada.Inserts(scada_list); if (!bol) { ScheduleLog.Info(request_id, log_title, "scada_list 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(scada_list)); } } if (schedule_conclusion1 != null) { bol = _service_schedule_conclusion.Insert(schedule_conclusion1) > 0; if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_conclusion1 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_conclusion1)); } } if (schedule_conclusion2 != null) { bol = _service_schedule_conclusion.Insert(schedule_conclusion2) > 0; if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_conclusion2 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_conclusion2)); } } if (schedule_pump_list1 != null) { bol = _service_schedule_pump.Inserts(schedule_pump_list1); if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_pump_list1 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_pump_list1)); } } if (schedule_pump_list2 != null) { bol = _service_schedule_pump.Inserts(schedule_pump_list2); if (!bol) { ScheduleLog.Info(request_id, log_title, "schedule_pump_list2 插入异常"); ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(schedule_pump_list2)); } } var t = new System.Timers.Timer(); t.Interval = 10 * 60 * 1000; t.Elapsed += (s, e) => { var receipt_time_10 = DateTime.Now; log_title = "实时ZyScada请求(调度后10分钟验证)"; var get_msg = GlobalHelper.GetMonitorRecordList(receipt_time_10, out List monitor_record_list, is_monitor_record_debug); if (!string.IsNullOrEmpty(get_msg)) { ScheduleLog.Info(request_id, log_title, get_msg); } ScheduleLog.Debug(request_id, log_title, JsonHelper.Object2Json(monitor_record_list)); }; t.AutoReset = false; t.Start(); } catch (Exception ex) { ScheduleLog.Error(request_id, log_title, "数据库异常!", ex); } return output; } private static string VerifyWaterSupplyLimit(List waterSupplyLimits, List station_open_flag_list, double targetFlow) { if (waterSupplyLimits != null && waterSupplyLimits.Any()) { if (station_open_flag_list != null && station_open_flag_list.Any()) { var pumpCount = station_open_flag_list.Count; var exist_limit = waterSupplyLimits.Find(x => x.PumpCount == pumpCount); if (exist_limit != null) { if (targetFlow < exist_limit.Min || targetFlow > exist_limit.Max) { var flags = Yw.Untity.IntListHelper.ToString(station_open_flag_list); return $"[{flags}]:目标流量:{targetFlow},供水限制:{exist_limit.Min}-{exist_limit.Max}"; } } } } return ""; } } }