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 "";
}
}
}