using IStation.Curve;
|
using IStation.Model;
|
using SqlSugar;
|
|
namespace IStation.Application
|
{
|
/// <summary>
|
/// 输水调度
|
/// </summary>
|
[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();
|
|
/// <summary>
|
/// 计算
|
/// </summary>
|
[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<Model.MonitorRecord> 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<int> station1_open_flag_list, out List<int> station2_open_flag_list);
|
GlobalHelper.GetStationFlagStateList(monitor_record_list, out List<int> station1_maintenance_flag_list, out List<int> station2_maintenance_flag_list, out List<int> station1_priority_flag_list, out List<int> station2_priority_flag_list);
|
GlobalHelper.GetFlagInletWaterLevelDict(monitor_record_list, out Dictionary<int, double> station1_flag_inlet_water_level_dict, out Dictionary<int, double> station2_flag_inlet_water_level_dict);
|
|
station1_schedule_config.MaintenanceFlagList = new List<int>();
|
station2_schedule_config.MaintenanceFlagList = new List<int>();
|
station1_schedule_config.PriorityOpenFlagList = new List<int>();
|
station2_schedule_config.PriorityOpenFlagList = new List<int>();
|
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<Model.SchedulePump> schedule_pump_list1 = null;
|
List<Model.SchedulePump> 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<Model.SchedulePump>();
|
|
// 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<Model.SchedulePump>();
|
|
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<Model.MonitorRecord> 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<WaterSupplyLimit> waterSupplyLimits, List<int> 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 "";
|
}
|
|
|
|
}
|
}
|