ningshuxia
2024-05-07 ec22b14b0395df0ab97d1adf5b589a187bb62e59
调度接口(60)
已重命名4个文件
已修改11个文件
已添加9个文件
1733 ■■■■ 文件已修改
IStation.WebApi.sln 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/0-core/3-helper/Log - 复制.cs 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/0-core/3-helper/Log.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/DispatchSolution_Controller - 复制.cs 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/DispatchSolution_Controller.cs 379 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/input/FactoryDispatchInput.cs 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/input/ScadaDispatchInput.cs 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/input/StationDispatchInput.cs 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/output/DispatchSolutionOutput.cs 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/output/PumpDispatchOutput.cs 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/output/ScadaDispatchOutput.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/dto/output/StationDispatchOutput.cs 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/helper/ExternalPipeScada.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch - 复制/1-solution/helper/TempOutHelper.cs 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch/1-solution/DispatchSolution_Controller.cs 452 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch/1-solution/dto/input/ScadaDispatchInput.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch/1-solution/dto/input/StationDispatchInput.cs 90 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/1-dispatch/1-solution/dto/output/StationDispatchOutput.cs 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Application.Core/IStation.Application.Core.csproj 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Entry.Core/IStation.Entry.Core.csproj.user 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Entry.Core/Properties/PublishProfiles/FolderProfile.pubxml.user 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Service.Core/GlobalUsings.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WebApi/IStation.Service.Core/IStation.Service.Core.csproj 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.WebApi.sln
@@ -15,6 +15,8 @@
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.WebApi.Core", "WebApi\IStation.WebApi.Core\IStation.WebApi.Core.csproj", "{8077F0D3-3FCC-44BF-8AB3-DF1A105CC798}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.Algorithm", "Schedule\IStation.Algorithm\IStation.Algorithm.csproj", "{FAE82C28-80D5-4D50-93DC-CDBCF697793F}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@
        {8077F0D3-3FCC-44BF-8AB3-DF1A105CC798}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {8077F0D3-3FCC-44BF-8AB3-DF1A105CC798}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {8077F0D3-3FCC-44BF-8AB3-DF1A105CC798}.Release|Any CPU.Build.0 = Release|Any CPU
        {FAE82C28-80D5-4D50-93DC-CDBCF697793F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {FAE82C28-80D5-4D50-93DC-CDBCF697793F}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {FAE82C28-80D5-4D50-93DC-CDBCF697793F}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {FAE82C28-80D5-4D50-93DC-CDBCF697793F}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs
@@ -103,8 +103,299 @@
        DAL.ScheduleAnaLog _dalAnaLog = new DAL.ScheduleAnaLog();
        /* private List<int> _combineFlags1 = new List<int>() { 11, 12, 13, 14, 16, 17, 18 };
         private List<int> _combineFlags2 = new List<int>() { 15 };*/
        public OptimalCombine AnaOptimalCombine(List<Pump> pumps, List<int> flags_part1, List<int> flags_part2, double target_flow, double target_head, List<int> current_open_pump_flags, List<int> must_open_pump_flags, List<int> must_not_open_pump_flags)
        {
            if (pumps == null || !pumps.Any())
            {
                return default;
            }
            target_flow = Math.Round(target_flow, 1);
            target_head = Math.Round(target_head, 1);
            #region å­˜åœ¨-当前开泵列表
            var exist_current_open_pump_flags = current_open_pump_flags != null && current_open_pump_flags.Count > 0;
            #endregion
            #region å­˜åœ¨-必开泵列表
            var must_open_pump_flags_remark = string.Empty;
            var exist_must_open_pump_flags = must_open_pump_flags != null && must_open_pump_flags.Count > 0;
            if (exist_must_open_pump_flags)
            {
                must_open_pump_flags = must_open_pump_flags.OrderBy(x => x).ToList();
                must_open_pump_flags_remark = IntListHelper.ToString(must_open_pump_flags);
            }
            #endregion
            #region å­˜åœ¨-必不能开泵列表
            var exist_must_not_open_pump_flags = must_not_open_pump_flags != null && must_not_open_pump_flags.Count > 0;
            #endregion
            var pump_flag_list = pumps.Select(x => x.ID).ToList();
            var optimal_combine_list = new List<OptimalCombine>();
            for (int pumpCount = 1; pumpCount <= pumps.Count; pumpCount++)
            {
                if (pumpCount == 1)
                {
                    var max_total_flow = pumps.Max(x => x.Qr);
                    if (max_total_flow < target_flow)
                        continue;
                }
                var combine_list = PermutationAndCombination<int>.GetCombination(pump_flag_list.ToArray(), pumpCount);//排列组合
                foreach (var combine in combine_list)
                {
                    double combine_merit_ratio = 1;//组合择优率
                    if (exist_must_open_pump_flags)
                    {
                        var combine_remark = IntListHelper.ToString(combine.OrderBy(x => x));
                        if (!combine_remark.Contains(must_open_pump_flags_remark))
                            continue;
                    }
                    if (exist_must_not_open_pump_flags)
                    {
                        var exist_intersected = combine.Intersect(must_not_open_pump_flags).Count() > 0;
                        if (exist_intersected)
                            continue;
                    }
                    int start_stop_count = 0;//启停数量
                    if (exist_current_open_pump_flags)
                    {
                        var start_pump_count = combine.Except(current_open_pump_flags).Count();
                        var close_pump_count = current_open_pump_flags.Except(combine).Count();
                        start_stop_count = start_pump_count + close_pump_count;//启停数量
                    }
                    else
                    {
                        start_stop_count = combine.Count();
                        if (exist_must_open_pump_flags)
                        {
                            start_stop_count = combine.Except(must_open_pump_flags).Count();
                        }
                    }
                    var total_loss_ratio = Math.Pow(_start_stop_loss_coefficient, start_stop_count);//启停一次损失些能耗
                    combine_merit_ratio *= total_loss_ratio;
                    List<int> combine_flag_list_part1 = new List<int>();
                    List<int> combine_flag_list_part2 = new List<int>();
                    foreach (var pump in combine)
                    {
                        if (flags_part1.Contains(pump))
                        {
                            combine_flag_list_part1.Add(pump);
                        }
                        else
                        {
                            combine_flag_list_part2.Add(pump);
                        }
                    }
                    //区分同型号泵
                    List<FreCombine> fre_combine_list_part1 = new List<FreCombine>();
                    List<FreCombine> fre_combine_list_part2 = new List<FreCombine>();
                    if (combine_flag_list_part1.Count > 0)
                    {
                        var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>();
                        foreach (var flag in combine_flag_list_part1)
                        {
                            var runFlag = GetGFlag(flag);
                            if (conclusion_list_dic.ContainsKey(flag))
                                continue;
                            var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head);
                            conclusion_list_dic[flag] = conclusionList;
                        }
                        if (conclusion_list_dic.Count < 1)
                        {
                            continue;
                        }
                        for (decimal fre = _frequency_max; fre >= _frequency_min; fre -= _frequency_space)
                        {
                            var freCombine = new FreCombine();
                            freCombine.Frequency = (double)fre;
                            freCombine.Flags = new List<int>();
                            foreach (var item in conclusion_list_dic)
                            {
                                var conclusion = item.Value.Find(x => x.Pump1 == (double)fre);
                                if (conclusion != null)
                                {
                                    freCombine.Flags.Add(item.Key);
                                    freCombine.Flow += conclusion.Flow;
                                    freCombine.Power += conclusion.Power;
                                    freCombine.RunCount++;
                                }
                            }
                            if (freCombine.Flags.Count < 1)
                                continue;
                            fre_combine_list_part1.Add(freCombine);
                        }
                    }
                    if (combine_flag_list_part2.Count > 0)
                    {
                        var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>();
                        foreach (var flag in combine_flag_list_part2)
                        {
                            var runFlag = GetGFlag(flag);
                            if (conclusion_list_dic.ContainsKey(flag))
                                continue;
                            var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head);
                            conclusion_list_dic[flag] = conclusionList;
                        }
                        if (conclusion_list_dic.Count < 1)
                        {
                            continue;
                        }
                        for (decimal fre = _frequency_max; fre >= _frequency_min; fre -= _frequency_space)
                        {
                            var freCombine = new FreCombine();
                            freCombine.Frequency = (double)fre;
                            freCombine.Flags = new List<int>();
                            foreach (var item in conclusion_list_dic)
                            {
                                var conclusion = item.Value.Find(x => x.Pump1 == (double)fre);
                                if (conclusion != null)
                                {
                                    freCombine.Flags.Add(item.Key);
                                    freCombine.Flow += conclusion.Flow;
                                    freCombine.Power += conclusion.Power;
                                    freCombine.RunCount++;
                                }
                            }
                            if (freCombine.Flags.Count < 1)
                                continue;
                            fre_combine_list_part2.Add(freCombine);
                        }
                    }
                    if (fre_combine_list_part1.Count == 0 && fre_combine_list_part2.Count == 0)
                        continue;
                    double total_flow_deviation = target_flow;//总流量偏差
                    double total_power = double.MaxValue;//总功率
                    double total_flow = double.MaxValue;//总流量
                    FreCombine optimal_combine_part1 = null;
                    FreCombine optimal_combine_part2 = null;
                    if (fre_combine_list_part1.Count < 1 || fre_combine_list_part2.Count < 1)
                    {
                        if (fre_combine_list_part1.Count < 1)
                        {
                            fre_combine_list_part1 = fre_combine_list_part2;
                        }
                        for (int Index_part1 = 0; Index_part1 < fre_combine_list_part1.Count; Index_part1++)
                        {
                            var fre_combine1 = fre_combine_list_part1[Index_part1];
                            var current_flow = fre_combine1.Flow;
                            var current_power = fre_combine1.Power;
                            var diff_flow = Math.Abs(current_flow - target_flow);
                            if (diff_flow < total_flow_deviation)
                            {
                                optimal_combine_part1 = fre_combine1;
                                total_power = fre_combine1.Power;
                                total_flow = current_flow;
                                total_flow_deviation = diff_flow;
                            }
                            if (diff_flow < target_flow * 0.01 && current_power < total_power)
                            {
                                optimal_combine_part1 = fre_combine1;
                                total_power = fre_combine1.Power;
                                total_flow = current_flow;
                            }
                        }
                    }
                    else
                    {
                        for (int Index_part1 = 0; Index_part1 < fre_combine_list_part1.Count; Index_part1++)
                        {
                            for (int Index_part2 = 0; Index_part2 < fre_combine_list_part2.Count; Index_part2++)
                            {
                                var fre_combine1 = fre_combine_list_part1[Index_part1];
                                var fre_combine2 = fre_combine_list_part2[Index_part2];
                                var current_flow = fre_combine1.Flow + fre_combine2.Flow;
                                var current_power = fre_combine1.Power + fre_combine2.Power;
                                var diff_flow = Math.Abs(current_flow - target_flow);
                                if (diff_flow < total_flow_deviation)
                                {
                                    optimal_combine_part1 = fre_combine1;
                                    optimal_combine_part2 = fre_combine2;
                                    total_power = fre_combine1.Power + fre_combine2.Power;
                                    total_flow = current_flow;
                                    total_flow_deviation = diff_flow;
                                }
                                if (diff_flow < target_flow * 0.01 && current_power < total_power)
                                {
                                    optimal_combine_part1 = fre_combine1;
                                    optimal_combine_part2 = fre_combine2;
                                    total_power = fre_combine1.Power + fre_combine2.Power;
                                    total_flow = current_flow;
                                }
                            }
                        }
                    }
                    if (optimal_combine_part1 == null && optimal_combine_part2 == null)
                        continue;
                    var total_flow_deviation_ratio = Math.Abs((1 - Math.Abs((total_flow / target_flow))));
                    if (total_flow_deviation_ratio > _sel_opt_flow_deviation_ratio)
                        continue;
                    if (total_flow_deviation_ratio > _sel_opt_reasonable_flow_deviation_ratio)
                    {
                        combine_merit_ratio -= total_flow_deviation_ratio;
                    }
                    #region åˆ†æžæœ€ä¼˜ç»„合方案
                    var optimal_combine = new OptimalCombine();
                    optimal_combine.Combines = new List<FreCombine>();
                    optimal_combine.Flags = new List<int>();
                    if (optimal_combine_part1 != null)
                    {
                        optimal_combine.Combines.Add(optimal_combine_part1);
                        optimal_combine.Flags.AddRange(optimal_combine_part1.Flags);
                    }
                    if (optimal_combine_part2 != null)
                    {
                        optimal_combine.Combines.Add(optimal_combine_part2);
                        optimal_combine.Flags.AddRange(optimal_combine_part2.Flags);
                    }
                    optimal_combine.Flow = Math.Round(total_flow, 1);
                    optimal_combine.Power = Math.Round(total_power, 1);
                    optimal_combine.Flags = optimal_combine.Flags.OrderBy(x => x).ToList();
                    optimal_combine.FlagCount = optimal_combine.Flags.Count;
                    optimal_combine.Remark = IntListHelper.ToString(optimal_combine.Flags);
                    optimal_combine.MeritRatio = combine_merit_ratio;
                    optimal_combine.Head = Math.Round(target_head, 1);
                    optimal_combine_list.Add(optimal_combine);
                    #endregion
                }
            }
            if (optimal_combine_list.Count < 1)
                return default;
            optimal_combine_list = optimal_combine_list.OrderByDescending(x => x.MeritRatio).ToList();
            return optimal_combine_list.First();
        }
        public string Ana(List<Pump> pumps, List<int> flags_part1, List<int> flags_part2, double target_flow, double target_head, List<int> current_open_pump_flags, List<int> must_open_pump_flags, List<int> must_not_open_pump_flags)
        {
@@ -406,6 +697,7 @@
        }
        /// <summary>
        /// æ’入分析日志
        /// </summary> 
WebApi/IStation.Application.Core/0-core/3-helper/Log - ¸´ÖÆ.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
namespace IStation.Application
{
    /// <summary>
    ///
    /// </summary>
    public class Log
    {
        /// <summary>
        /// å†™å…¥ä¿¡æ¯æ—¥å¿—
        /// </summary>
        /// <param name="flowId"></param>
        /// <param name="info"></param>
        public static void Info(string flowId, string info)
        {
            Yw.LogHelper.Info(GetLogInfo(flowId, info));
        }
        /// <summary>
        /// å†™å…¥è°ƒè¯•日志
        /// </summary>
        /// <param name="flowId"></param>
        /// <param name="info"></param>
        public static void Debug(s string info)
        {
            Yw.LogHelper.Debug(GetLogInfo(flowId, info));
        }
        /// <summary>
        /// å†™å…¥é”™è¯¯æ—¥å¿—
        /// </summary>
        /// <param name="flowId"></param>
        /// <param name="info"></param>
        /// <param name="ex"></param>
        public static void Error(string flowId, string info, Exception ex = null)
        {
            Yw.LogHelper.Error(GetLogInfo(flowId, info), ex);
        }
        private static string GetLogInfo(string info)
        {
            return $"{flowId}:{info}";
        }
    }
}
WebApi/IStation.Application.Core/0-core/3-helper/Log.cs
@@ -7,42 +7,38 @@
    {
        /// <summary>
        /// å†™å…¥ä¿¡æ¯æ—¥å¿—
        /// </summary>
        /// <param name="flowId"></param>
        /// </summary>
        /// <param name="info"></param>
        public static void Info(string flowId, string info)
        public static void Info(string info)
        {
            Yw.LogHelper.Info(GetLogInfo(flowId, info));
            Yw.LogHelper.Info(GetLogInfo(info));
        }
        /// <summary>
        /// å†™å…¥è°ƒè¯•日志
        /// </summary>
        /// <param name="flowId"></param>
        /// </summary>
        /// <param name="info"></param>
        public static void Debug(string flowId, string info)
        public static void Debug(string info)
        {
            Yw.LogHelper.Debug(GetLogInfo(flowId, info));
            Yw.LogHelper.Debug(GetLogInfo(info));
        }
        /// <summary>
        /// å†™å…¥é”™è¯¯æ—¥å¿—
        /// </summary>
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ex"></param>
        public static void Error(string flowId, string info, Exception ex = null)
        public static void Error(string info, Exception ex = null)
        {
            Yw.LogHelper.Error(GetLogInfo(flowId, info), ex);
            Yw.LogHelper.Error(GetLogInfo(info), ex);
        }
        private static string GetLogInfo(string flowId, string info)
        private static string GetLogInfo(string info)
        {
            return $"{flowId}:{info}";
            return $"{info}";
        }
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/DispatchSolution_Controller - ¸´ÖÆ.cs
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/DispatchSolution_Controller.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,379 @@
namespace IStation.Application
{
    /// <summary>
    /// è°ƒåº¦æ–¹æ¡ˆ
    /// </summary>
    [Route("OpenApi/Dispatch/Solution")]
    [ApiDescriptionSettings("Solution", Name = "陈行调度方案", Order = 1)]
    public class DispatchSolution_Controller : IDynamicApiController
    {
        /// <summary>
        /// è®¡ç®—
        /// </summary>
        [AllowAnonymous]
        [Route("Calculate@V1.0")]
        [HttpPost]
        public async Task<DispatchSolutionOutput> Calculate([Required] StationDispatchInput input)
        {
            if (input == null)
                return null;
            string flowId = input.FlowId;
            Log.Debug(flowId, JsonHelper.Object2Json(input));
            var scadaInput = GetScadaDispatchInput(DateTime.Now.AddSeconds(300), DateTime.Now);
            var scadaOutput = await GetRealScada(flowId, scadaInput);
            if (scadaOutput == null || scadaOutput.Scadas == null)
            {
                Log.Info(flowId, "Scada:数据获取失败,调度终止!");
                throw YOops.Oh(eResultCode.Error, InternalErrorCodes.L001, "Scada:数据获取失败,调度终止!");
            }
            return TempOutHelper.GetDispatchSolutionOutput(input.FlowId);
        }
        private async Task<ScadaDispatchOutput> GetRealScada(string flowId, ScadaDispatchInput input)
        {
            if (input == null)
            {
                Log.Info(flowId, "ScadaDispatchInput is null");
                return default;
            }
            var ws = new ClientWebSocket();
            ws.Options.RemoteCertificateValidationCallback = delegate { return true; };
            await ws.ConnectAsync(new Uri("ws://localhost:5102/api/WebSocket/GetNotReadCount"), CancellationToken.None);
            if (ws.State != WebSocketState.Open)
            {
                Log.Info(flowId, "webSocket:连接失败!");
                return default;
            }
            Log.Info(flowId, "webSocket:连接成功!");
            ScadaDispatchOutput output = null;
            var inputJson = JsonHelper.Object2Json(input);
            Log.Debug(flowId, inputJson);
            var inputBytes = Encoding.UTF8.GetBytes(inputJson);
            await ws.SendAsync(inputBytes, WebSocketMessageType.Text, true, CancellationToken.None);
            try
            {
                List<byte> outputBytes = new List<byte>();//全部消息容器
                var buffer = new byte[1024 * 4];//缓冲区
                var result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); //监听Socket信息
                while (!result.CloseStatus.HasValue)  //是否关闭
                {
                    if (result.MessageType == WebSocketMessageType.Text)//文本消息
                    {
                        outputBytes.AddRange(buffer.Take(result.Count));
                        if (result.EndOfMessage)//消息是否已接收完全
                        {
                            //发送过来的消息
                            string outputJson = Encoding.UTF8.GetString(outputBytes.ToArray(), 0, outputBytes.Count);
                            output = new ScadaDispatchOutput();
                            output.Scadas = JsonHelper.Json2Object<Dictionary<string, Dictionary<DateTime, string>>>(outputJson);
                            break;
                        }
                    }
                    result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);//继续监听Socket信息
                }
            }
            catch (Exception ex)
            {
                Log.Error(flowId, ex.Message);
            }
            finally
            {
                try
                {
                    //关闭WebSocket
                    await ws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "AcknowledgeCloseframe", CancellationToken.None);
                }
                catch (Exception ex)
                {
                    Log.Error(flowId, "关闭WebSocket异常", ex);
                }
                ws.Abort();
                ws.Dispose();
            }
            return output;
        }
        private ScadaDispatchInput GetScadaDispatchInput(DateTime startTime, DateTime endTime, double resolution = 300)
        {
            var tagDict = new Dictionary<string, string>
            {
                  //{ "_0402010204089903001", "长江水位" },
                  //{ "_0402010204089904009", "二取水前池液位" },
                  //{ "_0402010201030103006", "陈行水库水位" },
                  //{ "_0402010204012101001", "二取水1号泵状态" },
                  //{ "_0402010204012201001", "二取水2号泵状态" },
                  //{ "_0402010204012301001", "二取水3号泵状态" },
                  //{ "_0402010204012401001", "二取水4号泵状态" },
                  //{ "_0402010204012501001", "二取水5号泵状态" },
                  //{ "_0402010204012103002", "二取水1号泵累计流量" },
                  //{ "_0402010204012203002", "二取水2号泵累计流量" },
                  //{ "_0402010204012303002", "二取水3号泵累计流量" },
                  //{ "_0402010204012403002", "二取水4号泵累计流量" },
                  //{ "_0402010204012503002", "二取水5号泵累计流量" },
                  //{ "_0402010204040193046", "二取水1号泵有功电能" },
                  //{ "_0402010204040193047", "二取水2号泵有功电能" },
                  //{ "_0402010204012308007", "二取水3号泵有功电能" },
                  //{ "_0402010204012408007", "二取水4号泵有功电能" },
                  //{ "_0402010204012508007", "二取水5号泵有功电能" },
                  { "_0402010201090105774", "一输水11号出口压力" },
                  { "_0402010201040502031", "一输水11号有功功率" },
                  { "_0402010201040502044", "一输水11号有功电度" },
                  { "_0402010201011195062", "一输水11号泵转速" },
                  { "_0402010201011101001", "一输水11号泵运行状态" },
                  { "_0402010201011194012", "一输水11号泵频率" },
                  { "_0402010201090105005", "一输水12号出口压力" },
                  { "_0402010201041402031", "一输水12号有功功率" },
                  { "_0402010201041402044", "一输水12号有功电度" },
                  { "_0402010201011295062", "一输水12号泵转速" },
                  { "_0402010201011201001", "一输水12号泵运行状态" },
                  { "_0402010201011294012", "一输水12号泵频率" },
                  { "_0402010201090105776", "一输水13号出口压力" },
                  { "_0402010201040602031", "一输水13号有功功率" },
                  { "_0402010201040602044", "一输水13号有功电度" },
                  { "_0402010201011395062", "一输水13号泵转速" },
                  { "_0402010201011301001", "一输水13号泵运行状态" },
                  { "_0402010201011394012", "一输水13号泵频率" },
                  { "_0402010201090105007", "一输水14号出口压力" },
                  { "_0402010201041302031", "一输水14号有功功率" },
                  { "_0402010201041302044", "一输水14号有功电度" },
                  { "_0402010201011495062", "一输水14号泵转速" },
                  { "_0402010201011401001", "一输水14号泵运行状态" },
                  { "_0402010201011494012", "一输水14号泵频率" },
                  { "_0402010201090105008", "一输水15号出口压力" },
                  { "_0402010201040702031", "一输水15号有功功率" },
                  { "_0402010201040702044", "一输水15号有功电度" },
                  { "_0402010201011595062", "一输水15号泵转速" },
                  { "_0402010201011501003", "一输水15号泵运行状态" },
                  { "_0402010201090105016", "一输水16号出口压力" },
                  { "_0402010201041202031", "一输水16号有功功率" },
                  { "_0402010201041202044", "一输水16号有功电度" },
                  { "_0402010201011695062", "一输水16号泵转速" },
                  { "_0402010201011601003", "一输水16号泵运行状态" },
                  { "_0402010201090105017", "一输水17号出口压力" },
                  { "_0402010201040802031", "一输水17号有功功率" },
                  { "_0402010201040802044", "一输水17号有功电度" },
                  { "_0402010201011795062", "一输水17号泵转速" },
                  { "_0402010201011795056", "一输水17号泵运行状态" },
                  { "_0402010201090105018", "一输水18号出口压力" },
                  { "_0402010201041102031", "一输水18号有功功率" },
                  { "_0402010201041102044", "一输水18号有功电度" },
                  { "_0402010201011895062", "一输水18号泵转速" },
                  { "_0402010201011895056", "一输水18号泵运行状态" },
                  { "_0402010201090104011", "一输水前池液位1" },
                  { "_0402010201091104123", "一输水前池液位2" },
                  { "_0402010201091104122", "一输水前池液位3" },
                  { "_0402010201090105002", "一输水嘉定1线压力" },
                  { "_0402010201030191001", "一输水嘉定1线瞬时流量" },
                  { "_0402010201030191002", "一输水嘉定1线累计流量" },
                  { "_0402010201090105011", "一输水嘉定2线压力" },
                  { "_0402010201090199011", "一输水嘉定2线瞬时流量" },
                  { "_0402010201090199012", "一输水嘉定2线累计流量" },
                  { "_0402010201090105784", "一输水嘉定3线压力" },
                  { "_0402010201090199311", "一输水嘉定3线瞬时流量" },
                  { "_0402010201090199312", "一输水嘉定3线累计流量" },
                  { "_0402010204012105001", "二取水一号机泵出口压力" },
                  { "_0402010204012101001", "二取水一号机泵开停状态" },
                  { "_0402010204040193004", "二取水一号机泵有功功率" },
                  { "_0402010204040193046", "二取水一号机泵有功电度" },
                  { "_0402010204012103001", "二取水一号机泵瞬时流量" },
                  { "_0402010204012103002", "二取水一号机泵累计流量" },
                  { "_0402010204012305001", "二取水三号机泵出口压力" },
                  { "_0402010204012301001", "二取水三号机泵开停状态" },
                  { "_0402010204012308008", "二取水三号机泵有功功率" },
                  { "_0402010204012308007", "二取水三号机泵有功电度" },
                  { "_0402010204012303001", "二取水三号机泵瞬时流量" },
                  { "_0402010204012303002", "二取水三号机泵累计流量" },
                  { "_0402010204012205001", "二取水二号机泵出口压力" },
                  { "_0402010204012201001", "二取水二号机泵开停状态" },
                  { "_0402010204040193005", "二取水二号机泵有功功率" },
                  { "_0402010204040193047", "二取水二号机泵有功电度" },
                  { "_0402010204012203001", "二取水二号机泵瞬时流量" },
                  { "_0402010204012203002", "二取水二号机泵累计流量" },
                  { "_0402010204012505001", "二取水五号机泵出口压力" },
                  { "_0402010204012501001", "二取水五号机泵开停状态" },
                  { "_0402010204012508008", "二取水五号机泵有功功率" },
                  { "_0402010204012508007", "二取水五号机泵有功电度" },
                  { "_0402010204012503001", "二取水五号机泵瞬时流量" },
                  { "_0402010204012503002", "二取水五号机泵累计流量" },
                  { "_0402010204089904009", "二取水前池液位" },
                  { "_0402010204012405001", "二取水四号机泵出口压力" },
                  { "_0402010204012401001", "二取水四号机泵开停状态" },
                  { "_0402010204012408008", "二取水四号机泵有功功率" },
                  { "_0402010204012408007", "二取水四号机泵有功电度" },
                  { "_0402010204012403001", "二取水四号机泵瞬时流量" },
                  { "_0402010204012403002", "二取水四号机泵累计流量" },
                  { "_0402010201012105001", "二输水21号泵出口压力" },
                  { "_0402010201040102049", "二输水21号泵有功功率" },
                  { "_0402010201040102187", "二输水21号泵有功电度" },
                  { "_0402010201090103901", "二输水21号泵瞬时流量" },
                  { "_0402010201010294045", "二输水21号泵累计流量" },
                  { "_0402010201012199001", "二输水21号泵转速" },
                  { "_0402010201012193021", "二输水21号泵运行状态" },
                  { "_0402010201040102178", "二输水21号泵频率" },
                  { "_0402010201012205001", "二输水22号泵出口压力" },
                  { "_0402010201040102053", "二输水22号泵有功功率" },
                  { "_0402010201040102213", "二输水22号泵有功电度" },
                  { "_0402010201090103001", "二输水22号泵瞬时流量" },
                  { "_0402010201090103002", "二输水22号泵累计流量" },
                  { "_0402010201012299001", "二输水22号泵转速" },
                  { "_0402010201012201001", "二输水22号泵运行状态" },
                  { "_0402010201040102204", "二输水22号泵频率" },
                  { "_0402010201012305001", "二输水23号泵出口压力" },
                  { "_0402010201040102055", "二输水23号泵有功功率" },
                  { "_0402010201040102136", "二输水23号泵有功电度" },
                  { "_0402010201040102054", "二输水23号泵电流" },
                  { "_0402010201090103003", "二输水23号泵瞬时流量" },
                  { "_0402010201090103004", "二输水23号泵累计流量" },
                  { "_0402010201012399001", "二输水23号泵转速" },
                  { "_0402010201010194135", "二输水23号泵运行状态" },
                  { "_0402010201040102217", "二输水23号泵频率" },
                  { "_0402010201090105003", "二输水2400管压力" },
                  { "_0402010201090103017", "二输水2400管瞬时流量" },
                  { "_0402010201090103018", "二输水2400管累计流量" },
                  { "_0402010201012405001", "二输水24号泵出口压力" },
                  { "_0402010201040102057", "二输水24号泵有功功率" },
                  { "_0402010201040102149", "二输水24号泵有功电度" },
                  { "_0402010201090103005", "二输水24号泵瞬时流量" },
                  { "_0402010201090103006", "二输水24号泵累计流量" },
                  { "_0402010201012499001", "二输水24号泵转速" },
                  { "_0402010201012401001", "二输水24号泵运行状态" },
                  { "_0402010201040102140", "二输水24号泵频率" },
                  { "_0402010201012505001", "二输水25号泵出口压力" },
                  { "_0402010201040202004", "二输水25号泵有功功率" },
                  { "_0402010201040202141", "二输水25号泵有功电度" },
                  { "_0402010201090103007", "二输水25号泵瞬时流量" },
                  { "_0402010201090103008", "二输水25号泵累计流量" },
                  { "_0402010201012599001", "二输水25号泵转速" },
                  { "_0402010201012501001", "二输水25号泵运行状态" },
                  { "_0402010201040202132", "二输水25号泵频率" },
                  { "_0402010201012605001", "二输水26号泵出口压力" },
                  { "_0402010201040202006", "二输水26号泵有功功率" },
                  { "_0402010201040202028", "二输水26号泵有功电度" },
                  { "_0402010201090103009", "二输水26号泵瞬时流量" },
                  { "_0402010201090103010", "二输水26号泵累计流量" },
                  { "_0402010201012699001", "二输水26号泵转速" },
                  { "_0402010201010194152", "二输水26号泵运行状态" },
                  { "_0402010201040202145", "二输水26号泵频率" },
                  { "_0402010201090105004", "二输水2700管压力" },
                  { "_0402010201090194002", "二输水2700管瞬时流量" },
                  { "_0402010201090194444", "二输水2700管累计流量" },
                  { "_0402010201012705001", "二输水27号泵出口压力" },
                  { "_0402010201040202012", "二输水27号泵有功功率" },
                  { "_0402010201040202193", "二输水27号泵有功电度" },
                  { "_0402010201090103903", "二输水27号泵瞬时流量" },
                  { "_0402010201090194001", "二输水27号泵累计流量" },
                  { "_0402010201012799001", "二输水27号泵转速" },
                  { "_0402010201012793021", "二输水27号泵运行状态" },
                  { "_0402010201040202184", "二输水27号泵频率" },
                  { "_0402010204089903001", "陈行取水口长江液位" },
                  { "_0402010201030103006", "陈行水库液位" },
            };
            var input = new ScadaDispatchInput();
            input.search = "history";
            input.starttime = startTime.ToString("G");
            input.endtime = endTime.ToString("G");
            input.Resolution = resolution.ToString();
            input.taglist = tagDict.Select(x => x.Key).ToArray();
            return input;
        }
        //private async Task<ScadaDispatchOutput> GetRealScada(string flowId, ScadaDispatchInput input)
        //{
        //    if (input == null)
        //    {
        //        Log.Info(flowId, "ScadaDispatchInput is null");
        //        return default;
        //    }
        //    var ws = await CreateAsync("ws://localhost:5102/api/WebSocket/GetNotReadCount");
        //    if (ws == null || ws.State != WebSocketState.Open)
        //    {
        //        Log.Info(flowId, "webSocket:连接失败!");
        //        return default;
        //    }
        //    Log.Info(flowId, "webSocket:连接成功!");
        //    ScadaDispatchOutput output = null;
        //    var inputJson = JsonHelper.Object2FormatJson(input);
        //    Log.Debug(flowId, inputJson);
        //    var inputBytes = Encoding.UTF8.GetBytes(inputJson);
        //    await ws.SendAsync(inputBytes, WebSocketMessageType.Text, true, CancellationToken.None);
        //    try
        //    {
        //        var buffer = new ArraySegment<byte>(new byte[1024 * 4]);
        //        WebSocketReceiveResult result = null;
        //        using (var ms = new MemoryStream())
        //        {
        //            do
        //            {
        //                result = await ws.ReceiveAsync(buffer, CancellationToken.None);
        //                ms.Write(buffer.Array, buffer.Offset, result.Count);
        //            }
        //            while (!result.EndOfMessage);
        //            ms.Seek(0, SeekOrigin.Begin);
        //            if (result.MessageType == WebSocketMessageType.Text && !result.CloseStatus.HasValue)
        //            {
        //                using (var reader = new StreamReader(ms, Encoding.UTF8))
        //                {
        //                    string outputJson = reader.ReadToEnd();
        //                    output = new ScadaDispatchOutput();
        //                    output.Scadas = JsonHelper.Json2Object<Dictionary<string, Dictionary<DateTime, string>>>(outputJson);
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        Log.Error(flowId, ex.Message);
        //    }
        //    finally
        //    {
        //        try
        //        {
        //            //关闭WebSocket
        //            await ws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "AcknowledgeCloseframe", CancellationToken.None);
        //        }
        //        catch (Exception ex)
        //        {
        //            Log.Error(flowId, "关闭WebSocket异常", ex);
        //        }
        //        ws.Abort();
        //        ws.Dispose();
        //    }
        //    return output;
        //}
        ///// <summary>
        ///// åˆ›å»ºå®¢æˆ·ç«¯å®žä¾‹
        ///// </summary>
        ///// <returns></returns>
        //public static async Task<ClientWebSocket> CreateAsync(string ServerUri)
        //{
        //    var webSocket = new ClientWebSocket();
        //    webSocket.Options.RemoteCertificateValidationCallback = delegate { return true; };
        //    await webSocket.ConnectAsync(new Uri(ServerUri), CancellationToken.None);
        //    if (webSocket.State == WebSocketState.Open)
        //    {
        //        return webSocket;
        //    }
        //    return null;
        //}
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/input/FactoryDispatchInput.cs
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/input/ScadaDispatchInput.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
namespace IStation.Application
{
    /// <summary>
    /// å®žæ—¶æ•°æ®è°ƒåº¦
    /// </summary>
    public class ScadaDispatchInput
    {
        /// <summary>
        ///
        /// </summary>
        public string search { get; set; } = "history";
        /// <summary>
        ///
        /// </summary>
        public string starttime { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string endtime { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string Resolution { get; set; } = "300";
        /// <summary>
        ///
        /// </summary>
        public string[] taglist { get; set; }
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/input/StationDispatchInput.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
namespace IStation.Application
{
    /// <summary>
    /// æ³µç«™è°ƒåº¦
    /// </summary>
    public class StationDispatchInput : IValidatableObject
    {
        /// <summary>
        /// è°ƒåº¦æµç¨‹æ ‡è¯†ï¼ˆæ–¹æ¡ˆè®¡ç®—后返回,区分调度方案的唯一性)
        /// </summary>
        public string FlowId { get; set; }
        /// <summary>
        /// æ°´åŽ‚åˆ—è¡¨
        /// </summary>
        public List<FactoryDispatchInput> Factory { get; set; }
        /// <summary>
        ///
        /// </summary>
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Factory == null || Factory.Count < 1)
            {
                yield return
                    new ValidationResult("Factory ä¸èƒ½ä¸ºç©º", new[] { nameof(Factory) });
            }
            else
            {
                for (int i = 0; i < Factory.Count; i++)
                {
                    var f = Factory[i];
                    if (f.Value < 1)
                    {
                        yield return
                            new ValidationResult($"水厂增水量过低! ID:{f.Id} Value:{f.Value}", new[] { nameof(Factory) });
                    }
                }
            }
        }
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/output/DispatchSolutionOutput.cs
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/output/PumpDispatchOutput.cs
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/output/ScadaDispatchOutput.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
namespace IStation.Application
{
    /// <summary>
    /// å®žæ—¶æ•°æ®
    /// </summary>
    public class ScadaDispatchOutput
    {
        /// <summary>
        ///
        /// </summary>
        public Dictionary<string, Dictionary<DateTime, string>> Scadas { get; set; }
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/dto/output/StationDispatchOutput.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
namespace IStation.Application
{
    /// <summary>
    /// æ³µç«™è°ƒåº¦ç»“æžœ
    /// </summary>
    public class StationDispatchOutput
    {
        /// <summary>
        ///
        /// </summary>
        public StationDispatchOutput() { }
        /// <summary>
        ///
        /// </summary>
        public StationDispatchOutput(StationDispatchOutput rhs)
        {
            this.Id = rhs.Id;
            this.Index = rhs.Index;
            this.Q = rhs.Q;
            this.H = rhs.H;
            this.E = rhs.E;
            this.P = rhs.P;
            this.WP = rhs.WP;
            this.UWP = rhs.UWP;
            this.Pumps = rhs.Pumps?.ToList();
        }
        /// <summary>
        /// æ³µç«™æ ‡è¯†
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// æ³µç«™ç´¢å¼•  0:陈行1输水 1:陈行2输水
        /// </summary>
        public int Index { get; set; }
        /// <summary>
        /// æµé‡ m³/h
        /// </summary>
        public double Q { get; set; }
        /// <summary>
        /// æ‰¬ç¨‹ m
        /// </summary>
        public double H { get; set; }
        /// <summary>
        /// æ•ˆçއ %
        /// </summary>
        public double E { get; set; }
        /// <summary>
        /// åŠŸçŽ‡ kw
        /// </summary>
        public double P { get; set; }
        /// <summary>
        /// åƒå¨æ°´èƒ½è€—  kw/m.m3/h
        /// </summary>
        public double WP { get; set; }
        /// <summary>
        /// å•位能耗 kw/m3/h
        /// </summary>
        public double UWP { get; set; }
        /// <summary>
        /// æ³µåˆ—表
        /// </summary>
        public List<PumpDispatchOutput> Pumps { get; set; }
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/helper/ExternalPipeScada.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
namespace IStation.Application
{
    internal class ExternalPipeScada
    {
        public double JD1Flow { get; set; }
        public double JD1Pressure { get; set; }
        public double JD2Flow { get; set; }
        public double JD2Pressure { get; set; }
        public double JD3Flow { get; set; }
        public double JD3Pressure { get; set; }
        public double DN2400Flow { get; set; }
        public double DN2400Pressure { get; set; }
        public double DN2700Flow { get; set; }
        public double DN2700Pressure { get; set; }
    }
}
WebApi/IStation.Application.Core/1-dispatch - ¸´ÖÆ/1-solution/helper/TempOutHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
using IStation.Common;
namespace IStation.Application
{
    internal class TempOutHelper
    {
        public static DispatchSolutionOutput GetDispatchSolutionOutput(string flowId)
        {
            var output = new DispatchSolutionOutput();
            output.SolutionId = "temp999";
            output.FlowId = flowId;
            output.Station = new List<StationDispatchOutput>();
            var chss1Pumps = new List<PumpDispatchOutput>
            {
                GetPumpDispatchOutput("Pump11", 0, true, 4307.7588, 15.8093, 81.6112, 227.219, 37.6271, 444),
                GetPumpDispatchOutput("Pump12", 1, true, 4024.6057, 15.742, 81.3045, 212.1781, 36.523, 431),
                GetPumpDispatchOutput("Pump13", 2, true, 3941.9631, 16.1554, 82.7758, 209.4876, 36.533, 431.1),
                GetPumpDispatchOutput("Pump17", 6, true, 4130.7578, 15.9835, 82.6751, 217.4493, 36.6102, 432)
            };
            // var chss1totalH = 20.7518;
            var chss1totalH = chss1Pumps.Average(x => x.H);
            var chss1totalQ = chss1Pumps.Sum(x => x.Q);
            var chss1totalP = chss1Pumps.Sum(x => x.P);
            var chss1totalE = PumpParaHelper.CalculateE(chss1totalQ, chss1totalH, chss1totalP);
            var chss1 = GetStationDispatchOutput(1, chss1totalQ, chss1totalH, chss1totalE, chss1totalP, chss1Pumps);
            var chss2Pumps = new List<PumpDispatchOutput>
            {
                GetPumpDispatchOutput("Pump22", 1, true, 9589.2422, 15.3166, 75.3, 533.233,33.4343, 331),
                GetPumpDispatchOutput("Pump23", 2, true, 9423.4463, 15.1016, 72.4, 567.1, 34.4242, 340.8),
                GetPumpDispatchOutput("Pump25", 4, true, 10226.1523, 15.0448, 72.4, 563.2, 34.3434, 340),
                GetPumpDispatchOutput("Pump26", 5, true, 10011.1924, 15.1511, 74, 558.6, 33.9394, 336)
            };
            var chss2totalH = chss2Pumps.Average(x => x.H);
            var chss2totalQ = chss2Pumps.Sum(x => x.Q);
            var chss2totalP = chss2Pumps.Sum(x => x.P);
            var chss2totalE = PumpParaHelper.CalculateE(chss2totalQ, chss2totalH, chss2totalP);
            var chss2 = GetStationDispatchOutput(2, chss2totalQ, chss2totalH, chss2totalE, chss2totalP, chss2Pumps);
            output.Station.Add(chss1);
            output.Station.Add(chss2);
            return output;
        }
        private static StationDispatchOutput GetStationDispatchOutput(int index, double q, double h, double e, double p, List<PumpDispatchOutput> pumps)
        {
            var model = new StationDispatchOutput();
            model.Id = index.ToString();
            model.Index = index;
            model.Q = Math.Round(q, 1);
            model.H = Math.Round(h, 1);
            model.E = Math.Round(e, 1);
            model.P = Math.Round(p, 1);
            model.WP = Math.Round(Calcu_WP(p, q), 1);
            model.UWP = Math.Round(Calcu_UWP(p, q, h), 1);
            model.Pumps = pumps;
            return model;
        }
        private static PumpDispatchOutput GetPumpDispatchOutput(string id, int index, bool isBp, double q, double h, double e, double p, double fre, double speed)
        {
            var model = new PumpDispatchOutput();
            model.Id = id;
            model.Index = index;
            model.Name = id;
            model.IsBp = isBp;
            model.Q = Math.Round(q, 1);
            model.H = Math.Round(h, 1);
            model.E = Math.Round(e, 1);
            model.P = Math.Round(p, 1);
            model.Frequency = Math.Round(fre, 1);
            model.Speed = Math.Round(speed, 1);
            return model;
        }
        /// <summary>
        /// å•位水耗 åƒå¨æ°´
        /// </summary>
        private static double Calcu_UWP(double P, double Q, double H)
        {
            if (Q <= 0.001)
                return 0;
            if (H <= 0.00001)
                return 0;
            if (P <= 0.001)
                return 0;
            return P * 1000f / Q / H;
        }
        /// <summary>
        /// å•位水耗 åƒå¨æ°´
        /// </summary>
        private static double Calcu_UWP(double P, double Q, double inletPress, double outletPress)
        {
            double H = (outletPress - inletPress) * 102;
            if (Q <= 0.001)
                return 0;
            if (H <= 0.00001)
                return 0;
            if (P <= 0.001)
                return 0;
            return P * 1000f / Q / H;
        }
        /// <summary>
        /// å•位水耗
        /// </summary>
        private static double Calcu_WP(double P, double Q)
        {
            if (Q <= 0.001)
                return 0;
            if (P <= 0.001)
                return 0;
            return P * 1000f / Q;
        }
    }
}
WebApi/IStation.Application.Core/1-dispatch/1-solution/DispatchSolution_Controller.cs
@@ -1,4 +1,6 @@
namespace IStation.Application
using Yw.Calculation;
namespace IStation.Application
{
    /// <summary>
    /// è°ƒåº¦æ–¹æ¡ˆ
@@ -7,373 +9,161 @@
    [ApiDescriptionSettings("Solution", Name = "陈行调度方案", Order = 1)]
    public class DispatchSolution_Controller : IDynamicApiController
    {
        /// <summary>
        /// è®¡ç®—
        /// </summary>
        [AllowAnonymous]
        [Route("Calculate@V1.0")]
        [HttpPost]
        public async Task<DispatchSolutionOutput> Calculate([Required] StationDispatchInput input)
        [NonUnify]
        public async Task<StationDispatchOutput> Calculate([Required] StationDispatchInput input)
        {
            if (input == null)
                return null;
            string flowId = input.FlowId;
            Log.Debug(flowId, JsonHelper.Object2Json(input));
            var receipt_time = DateTime.Now;
            Log.Debug(JsonHelper.Object2Json(input));
            //获取Scada实时数据
            //......
            var scadaInput = GetScadaDispatchInput(DateTime.Now.AddSeconds(300), DateTime.Now);
            var scadaOutput = await GetRealScada(flowId, scadaInput);
            if (scadaOutput == null || scadaOutput.Scadas == null)
            var total_flow1 = input.objects["TotalFlow1"];
            var total_pressure1 = input.objects["TotalPressure1"];
            total_pressure1 = Mpa2M(total_pressure1);
            var total_flow2 = input.objects["TotalFlow2"];
            var total_pressure2 = input.objects["TotalPressure2"];
            total_pressure2 = Mpa2M(total_pressure2);
            var optimal_combine1 = GetOptimalCombine1(total_flow1, total_pressure1, null, null, null);
            var optimal_combine2 = GetOptimalCombine2(total_flow2, total_pressure2, null, null, null);
            var output = new StationDispatchOutput();
            output.objects = new Dictionary<string, double>();
            if (optimal_combine1 == null && optimal_combine2 == null)
            {
                Log.Info(flowId, "Scada:数据获取失败,调度终止!");
                throw YOops.Oh(eResultCode.Error, InternalErrorCodes.L001, "Scada:数据获取失败,调度终止!");
                output.flag = 0;
                output.message = "场内调度方案无法计算!";
                Log.Info("计算失败:场内调度方案无法计算!");
            }
            return TempOutHelper.GetDispatchSolutionOutput(input.FlowId);
        }
        private async Task<ScadaDispatchOutput> GetRealScada(string flowId, ScadaDispatchInput input)
        {
            if (input == null)
            else
            {
                Log.Info(flowId, "ScadaDispatchInput is null");
                return default;
            }
            var ws = new ClientWebSocket();
            ws.Options.RemoteCertificateValidationCallback = delegate { return true; };
            await ws.ConnectAsync(new Uri("ws://localhost:5102/api/WebSocket/GetNotReadCount"), CancellationToken.None);
            if (ws.State != WebSocketState.Open)
            {
                Log.Info(flowId, "webSocket:连接失败!");
                return default;
            }
            Log.Info(flowId, "webSocket:连接成功!");
            ScadaDispatchOutput output = null;
            var inputJson = JsonHelper.Object2Json(input);
            Log.Debug(flowId, inputJson);
            var inputBytes = Encoding.UTF8.GetBytes(inputJson);
            await ws.SendAsync(inputBytes, WebSocketMessageType.Text, true, CancellationToken.None);
            try
            {
                List<byte> outputBytes = new List<byte>();//全部消息容器
                var buffer = new byte[1024 * 4];//缓冲区
                var result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); //监听Socket信息
                while (!result.CloseStatus.HasValue)  //是否关闭
                if (optimal_combine1 != null)
                {
                    if (result.MessageType == WebSocketMessageType.Text)//文本消息
                    output.objects["1输水总流量"] = optimal_combine1.Flow;
                    output.objects["1输水总压力"] = M2Mpa(optimal_combine1.Head);
                    foreach (var combine in optimal_combine1.Combines)
                    {
                        outputBytes.AddRange(buffer.Take(result.Count));
                        if (result.EndOfMessage)//消息是否已接收完全
                        foreach (var pump_flag in combine.Flags)
                        {
                            //发送过来的消息
                            string outputJson = Encoding.UTF8.GetString(outputBytes.ToArray(), 0, outputBytes.Count);
                            output = new ScadaDispatchOutput();
                            output.Scadas = JsonHelper.Json2Object<Dictionary<string, Dictionary<DateTime, string>>>(outputJson);
                            break;
                            output.objects[$"1输水{pump_flag}#频率"] = combine.Frequency;
                        }
                    }
                    result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);//继续监听Socket信息
                }
            }
            catch (Exception ex)
            {
                Log.Error(flowId, ex.Message);
            }
            finally
            {
                try
                if (optimal_combine2 != null)
                {
                    //关闭WebSocket
                    await ws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "AcknowledgeCloseframe", CancellationToken.None);
                    output.objects["2输水总流量"] = optimal_combine2.Flow;
                    output.objects["2输水总压力"] = M2Mpa(optimal_combine2.Head);
                    foreach (var combine in optimal_combine2.Combines)
                    {
                        foreach (var pump_flag in combine.Flags)
                        {
                            output.objects[$"2输水{pump_flag}#频率"] = combine.Frequency;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(flowId, "关闭WebSocket异常", ex);
                }
                ws.Abort();
                ws.Dispose();
                output.flag = 1;
                Log.Info("计算成功!");
            }
            output.ReceiptTime = receipt_time;
            output.ReturnTime = DateTime.Now;
            return output;
        }
        private ScadaDispatchInput GetScadaDispatchInput(DateTime startTime, DateTime endTime, double resolution = 300)
        private string _data_floder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
        private List<IStation.Model.Pump> _station_pumps1 = null;
        private List<IStation.Model.Pump> _station_pumps2 = null;
        /// <summary>
        /// èŽ·å–1输水最优调度方案
        /// </summary>
        /// <returns></returns>
        IStation.Algorithm.OptimalCombine GetOptimalCombine1(double target_flow, double target_head, List<int> current_open_pump_flags, List<int> must_open_pump_flags, List<int> must_not_open_pump_flags)
        {
            var tagDict = new Dictionary<string, string>
            if (_station_pumps1 == null)
            {
                  //{ "_0402010204089903001", "长江水位" },
                  //{ "_0402010204089904009", "二取水前池液位" },
                  //{ "_0402010201030103006", "陈行水库水位" },
                  //{ "_0402010204012101001", "二取水1号泵状态" },
                  //{ "_0402010204012201001", "二取水2号泵状态" },
                  //{ "_0402010204012301001", "二取水3号泵状态" },
                  //{ "_0402010204012401001", "二取水4号泵状态" },
                  //{ "_0402010204012501001", "二取水5号泵状态" },
                  //{ "_0402010204012103002", "二取水1号泵累计流量" },
                  //{ "_0402010204012203002", "二取水2号泵累计流量" },
                  //{ "_0402010204012303002", "二取水3号泵累计流量" },
                  //{ "_0402010204012403002", "二取水4号泵累计流量" },
                  //{ "_0402010204012503002", "二取水5号泵累计流量" },
                  //{ "_0402010204040193046", "二取水1号泵有功电能" },
                  //{ "_0402010204040193047", "二取水2号泵有功电能" },
                  //{ "_0402010204012308007", "二取水3号泵有功电能" },
                  //{ "_0402010204012408007", "二取水4号泵有功电能" },
                  //{ "_0402010204012508007", "二取水5号泵有功电能" },
                  { "_0402010201090105774", "一输水11号出口压力" },
                  { "_0402010201040502031", "一输水11号有功功率" },
                  { "_0402010201040502044", "一输水11号有功电度" },
                  { "_0402010201011195062", "一输水11号泵转速" },
                  { "_0402010201011101001", "一输水11号泵运行状态" },
                  { "_0402010201011194012", "一输水11号泵频率" },
                  { "_0402010201090105005", "一输水12号出口压力" },
                  { "_0402010201041402031", "一输水12号有功功率" },
                  { "_0402010201041402044", "一输水12号有功电度" },
                  { "_0402010201011295062", "一输水12号泵转速" },
                  { "_0402010201011201001", "一输水12号泵运行状态" },
                  { "_0402010201011294012", "一输水12号泵频率" },
                  { "_0402010201090105776", "一输水13号出口压力" },
                  { "_0402010201040602031", "一输水13号有功功率" },
                  { "_0402010201040602044", "一输水13号有功电度" },
                  { "_0402010201011395062", "一输水13号泵转速" },
                  { "_0402010201011301001", "一输水13号泵运行状态" },
                  { "_0402010201011394012", "一输水13号泵频率" },
                  { "_0402010201090105007", "一输水14号出口压力" },
                  { "_0402010201041302031", "一输水14号有功功率" },
                  { "_0402010201041302044", "一输水14号有功电度" },
                  { "_0402010201011495062", "一输水14号泵转速" },
                  { "_0402010201011401001", "一输水14号泵运行状态" },
                  { "_0402010201011494012", "一输水14号泵频率" },
                  { "_0402010201090105008", "一输水15号出口压力" },
                  { "_0402010201040702031", "一输水15号有功功率" },
                  { "_0402010201040702044", "一输水15号有功电度" },
                  { "_0402010201011595062", "一输水15号泵转速" },
                  { "_0402010201011501003", "一输水15号泵运行状态" },
                  { "_0402010201090105016", "一输水16号出口压力" },
                  { "_0402010201041202031", "一输水16号有功功率" },
                  { "_0402010201041202044", "一输水16号有功电度" },
                  { "_0402010201011695062", "一输水16号泵转速" },
                  { "_0402010201011601003", "一输水16号泵运行状态" },
                  { "_0402010201090105017", "一输水17号出口压力" },
                  { "_0402010201040802031", "一输水17号有功功率" },
                  { "_0402010201040802044", "一输水17号有功电度" },
                  { "_0402010201011795062", "一输水17号泵转速" },
                  { "_0402010201011795056", "一输水17号泵运行状态" },
                  { "_0402010201090105018", "一输水18号出口压力" },
                  { "_0402010201041102031", "一输水18号有功功率" },
                  { "_0402010201041102044", "一输水18号有功电度" },
                  { "_0402010201011895062", "一输水18号泵转速" },
                  { "_0402010201011895056", "一输水18号泵运行状态" },
                  { "_0402010201090104011", "一输水前池液位1" },
                  { "_0402010201091104123", "一输水前池液位2" },
                  { "_0402010201091104122", "一输水前池液位3" },
                  { "_0402010201090105002", "一输水嘉定1线压力" },
                  { "_0402010201030191001", "一输水嘉定1线瞬时流量" },
                  { "_0402010201030191002", "一输水嘉定1线累计流量" },
                  { "_0402010201090105011", "一输水嘉定2线压力" },
                  { "_0402010201090199011", "一输水嘉定2线瞬时流量" },
                  { "_0402010201090199012", "一输水嘉定2线累计流量" },
                  { "_0402010201090105784", "一输水嘉定3线压力" },
                  { "_0402010201090199311", "一输水嘉定3线瞬时流量" },
                  { "_0402010201090199312", "一输水嘉定3线累计流量" },
                  { "_0402010204012105001", "二取水一号机泵出口压力" },
                  { "_0402010204012101001", "二取水一号机泵开停状态" },
                  { "_0402010204040193004", "二取水一号机泵有功功率" },
                  { "_0402010204040193046", "二取水一号机泵有功电度" },
                  { "_0402010204012103001", "二取水一号机泵瞬时流量" },
                  { "_0402010204012103002", "二取水一号机泵累计流量" },
                  { "_0402010204012305001", "二取水三号机泵出口压力" },
                  { "_0402010204012301001", "二取水三号机泵开停状态" },
                  { "_0402010204012308008", "二取水三号机泵有功功率" },
                  { "_0402010204012308007", "二取水三号机泵有功电度" },
                  { "_0402010204012303001", "二取水三号机泵瞬时流量" },
                  { "_0402010204012303002", "二取水三号机泵累计流量" },
                  { "_0402010204012205001", "二取水二号机泵出口压力" },
                  { "_0402010204012201001", "二取水二号机泵开停状态" },
                  { "_0402010204040193005", "二取水二号机泵有功功率" },
                  { "_0402010204040193047", "二取水二号机泵有功电度" },
                  { "_0402010204012203001", "二取水二号机泵瞬时流量" },
                  { "_0402010204012203002", "二取水二号机泵累计流量" },
                  { "_0402010204012505001", "二取水五号机泵出口压力" },
                  { "_0402010204012501001", "二取水五号机泵开停状态" },
                  { "_0402010204012508008", "二取水五号机泵有功功率" },
                  { "_0402010204012508007", "二取水五号机泵有功电度" },
                  { "_0402010204012503001", "二取水五号机泵瞬时流量" },
                  { "_0402010204012503002", "二取水五号机泵累计流量" },
                  { "_0402010204089904009", "二取水前池液位" },
                  { "_0402010204012405001", "二取水四号机泵出口压力" },
                  { "_0402010204012401001", "二取水四号机泵开停状态" },
                  { "_0402010204012408008", "二取水四号机泵有功功率" },
                  { "_0402010204012408007", "二取水四号机泵有功电度" },
                  { "_0402010204012403001", "二取水四号机泵瞬时流量" },
                  { "_0402010204012403002", "二取水四号机泵累计流量" },
                  { "_0402010201012105001", "二输水21号泵出口压力" },
                  { "_0402010201040102049", "二输水21号泵有功功率" },
                  { "_0402010201040102187", "二输水21号泵有功电度" },
                  { "_0402010201090103901", "二输水21号泵瞬时流量" },
                  { "_0402010201010294045", "二输水21号泵累计流量" },
                  { "_0402010201012199001", "二输水21号泵转速" },
                  { "_0402010201012193021", "二输水21号泵运行状态" },
                  { "_0402010201040102178", "二输水21号泵频率" },
                  { "_0402010201012205001", "二输水22号泵出口压力" },
                  { "_0402010201040102053", "二输水22号泵有功功率" },
                  { "_0402010201040102213", "二输水22号泵有功电度" },
                  { "_0402010201090103001", "二输水22号泵瞬时流量" },
                  { "_0402010201090103002", "二输水22号泵累计流量" },
                  { "_0402010201012299001", "二输水22号泵转速" },
                  { "_0402010201012201001", "二输水22号泵运行状态" },
                  { "_0402010201040102204", "二输水22号泵频率" },
                  { "_0402010201012305001", "二输水23号泵出口压力" },
                  { "_0402010201040102055", "二输水23号泵有功功率" },
                  { "_0402010201040102136", "二输水23号泵有功电度" },
                  { "_0402010201040102054", "二输水23号泵电流" },
                  { "_0402010201090103003", "二输水23号泵瞬时流量" },
                  { "_0402010201090103004", "二输水23号泵累计流量" },
                  { "_0402010201012399001", "二输水23号泵转速" },
                  { "_0402010201010194135", "二输水23号泵运行状态" },
                  { "_0402010201040102217", "二输水23号泵频率" },
                  { "_0402010201090105003", "二输水2400管压力" },
                  { "_0402010201090103017", "二输水2400管瞬时流量" },
                  { "_0402010201090103018", "二输水2400管累计流量" },
                  { "_0402010201012405001", "二输水24号泵出口压力" },
                  { "_0402010201040102057", "二输水24号泵有功功率" },
                  { "_0402010201040102149", "二输水24号泵有功电度" },
                  { "_0402010201090103005", "二输水24号泵瞬时流量" },
                  { "_0402010201090103006", "二输水24号泵累计流量" },
                  { "_0402010201012499001", "二输水24号泵转速" },
                  { "_0402010201012401001", "二输水24号泵运行状态" },
                  { "_0402010201040102140", "二输水24号泵频率" },
                  { "_0402010201012505001", "二输水25号泵出口压力" },
                  { "_0402010201040202004", "二输水25号泵有功功率" },
                  { "_0402010201040202141", "二输水25号泵有功电度" },
                  { "_0402010201090103007", "二输水25号泵瞬时流量" },
                  { "_0402010201090103008", "二输水25号泵累计流量" },
                  { "_0402010201012599001", "二输水25号泵转速" },
                  { "_0402010201012501001", "二输水25号泵运行状态" },
                  { "_0402010201040202132", "二输水25号泵频率" },
                  { "_0402010201012605001", "二输水26号泵出口压力" },
                  { "_0402010201040202006", "二输水26号泵有功功率" },
                  { "_0402010201040202028", "二输水26号泵有功电度" },
                  { "_0402010201090103009", "二输水26号泵瞬时流量" },
                  { "_0402010201090103010", "二输水26号泵累计流量" },
                  { "_0402010201012699001", "二输水26号泵转速" },
                  { "_0402010201010194152", "二输水26号泵运行状态" },
                  { "_0402010201040202145", "二输水26号泵频率" },
                  { "_0402010201090105004", "二输水2700管压力" },
                  { "_0402010201090194002", "二输水2700管瞬时流量" },
                  { "_0402010201090194444", "二输水2700管累计流量" },
                  { "_0402010201012705001", "二输水27号泵出口压力" },
                  { "_0402010201040202012", "二输水27号泵有功功率" },
                  { "_0402010201040202193", "二输水27号泵有功电度" },
                  { "_0402010201090103903", "二输水27号泵瞬时流量" },
                  { "_0402010201090194001", "二输水27号泵累计流量" },
                  { "_0402010201012799001", "二输水27号泵转速" },
                  { "_0402010201012793021", "二输水27号泵运行状态" },
                  { "_0402010201040202184", "二输水27号泵频率" },
                  { "_0402010204089903001", "陈行取水口长江液位" },
                  { "_0402010201030103006", "陈行水库液位" },
            };
                var filePath = _data_floder + "\\" + "陈行一输.json";
                var jsonInfo = File.ReadAllText(filePath);
                _station_pumps1 = JsonHelper.Json2Object<List<Model.Pump>>(jsonInfo);
                if (_station_pumps1 == null)
                {
                    Log.Error($"文件缺失:{filePath}");
                    return default;
                }
            }
            var input = new ScadaDispatchInput();
            input.search = "history";
            input.starttime = startTime.ToString("G");
            input.endtime = endTime.ToString("G");
            input.Resolution = resolution.ToString();
            input.taglist = tagDict.Select(x => x.Key).ToArray();
            return input;
            var flags_part1 = new List<int>() { 11, 12, 13, 14, 16, 17, 18 };
            var flags_part2 = new List<int>() { 15 };
            var helper = new Algorithm.SchedulingHelper();
            var optimal_combine = helper.AnaOptimalCombine(_station_pumps1, flags_part1, flags_part2, target_flow, target_head, current_open_pump_flags, must_open_pump_flags, must_not_open_pump_flags);
            if (optimal_combine == null)
            {
                Log.Error($"一输水方案计算失败: optimal_combine1 is null");
            }
            return optimal_combine;
        }
        /// <summary>
        /// èŽ·å–2输水最优调度方案
        /// </summary>
        /// <returns></returns>
        IStation.Algorithm.OptimalCombine GetOptimalCombine2(double target_flow, double target_head, List<int> current_open_pump_flags, List<int> must_open_pump_flags, List<int> must_not_open_pump_flags)
        {
            if (_station_pumps2 == null)
            {
                var filePath = _data_floder + "\\" + "陈行二输.json";
                var jsonInfo = File.ReadAllText(filePath);
                _station_pumps2 = JsonHelper.Json2Object<List<Model.Pump>>(jsonInfo);
                if (_station_pumps2 == null)
                {
                    Log.Error($"文件缺失:{filePath}");
                    return default;
                }
            }
            var flags_part1 = new List<int>() { 22, 23, 24, 25, 26 };
            var flags_part2 = new List<int>() { 21, 27 };
            var helper = new Algorithm.SchedulingHelper();
            var optimal_combine = helper.AnaOptimalCombine(_station_pumps2, flags_part1, flags_part2, target_flow, target_head, current_open_pump_flags, must_open_pump_flags, must_not_open_pump_flags);
            if (optimal_combine == null)
            {
                Log.Error($"二输水方案计算失败: optimal_combine1 is null");
            }
            return optimal_combine;
        }
        #region Mpa<=>m
        //private async Task<ScadaDispatchOutput> GetRealScada(string flowId, ScadaDispatchInput input)
        //{
        //    if (input == null)
        //    {
        //        Log.Info(flowId, "ScadaDispatchInput is null");
        //        return default;
        //    }
        /// <summary>
        /// Mpa=>m
        /// </summary>
        public static double Mpa2M(double mpa)
        {
            return mpa * ConstantParas.WaterDensity / ConstantParas.g;
        }
        //    var ws = await CreateAsync("ws://localhost:5102/api/WebSocket/GetNotReadCount");
        //    if (ws == null || ws.State != WebSocketState.Open)
        //    {
        //        Log.Info(flowId, "webSocket:连接失败!");
        //        return default;
        //    }
        //    Log.Info(flowId, "webSocket:连接成功!");
        /// <summary>
        /// m=>Mpa
        /// </summary>
        public static double M2Mpa(double m)
        {
            return m * ConstantParas.g / ConstantParas.WaterDensity;
        }
        //    ScadaDispatchOutput output = null;
        //    var inputJson = JsonHelper.Object2FormatJson(input);
        //    Log.Debug(flowId, inputJson);
        //    var inputBytes = Encoding.UTF8.GetBytes(inputJson);
        //    await ws.SendAsync(inputBytes, WebSocketMessageType.Text, true, CancellationToken.None);
        //    try
        //    {
        //        var buffer = new ArraySegment<byte>(new byte[1024 * 4]);
        //        WebSocketReceiveResult result = null;
        //        using (var ms = new MemoryStream())
        //        {
        //            do
        //            {
        //                result = await ws.ReceiveAsync(buffer, CancellationToken.None);
        //                ms.Write(buffer.Array, buffer.Offset, result.Count);
        //            }
        //            while (!result.EndOfMessage);
        //            ms.Seek(0, SeekOrigin.Begin);
        //            if (result.MessageType == WebSocketMessageType.Text && !result.CloseStatus.HasValue)
        //            {
        //                using (var reader = new StreamReader(ms, Encoding.UTF8))
        //                {
        //                    string outputJson = reader.ReadToEnd();
        //                    output = new ScadaDispatchOutput();
        //                    output.Scadas = JsonHelper.Json2Object<Dictionary<string, Dictionary<DateTime, string>>>(outputJson);
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        Log.Error(flowId, ex.Message);
        //    }
        //    finally
        //    {
        //        try
        //        {
        //            //关闭WebSocket
        //            await ws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "AcknowledgeCloseframe", CancellationToken.None);
        //        }
        //        catch (Exception ex)
        //        {
        //            Log.Error(flowId, "关闭WebSocket异常", ex);
        //        }
        //        ws.Abort();
        //        ws.Dispose();
        //    }
        //    return output;
        //}
        ///// <summary>
        ///// åˆ›å»ºå®¢æˆ·ç«¯å®žä¾‹
        ///// </summary>
        ///// <returns></returns>
        //public static async Task<ClientWebSocket> CreateAsync(string ServerUri)
        //{
        //    var webSocket = new ClientWebSocket();
        //    webSocket.Options.RemoteCertificateValidationCallback = delegate { return true; };
        //    await webSocket.ConnectAsync(new Uri(ServerUri), CancellationToken.None);
        //    if (webSocket.State == WebSocketState.Open)
        //    {
        //        return webSocket;
        //    }
        //    return null;
        //}
        #endregion
    }
}
WebApi/IStation.Application.Core/1-dispatch/1-solution/dto/input/ScadaDispatchInput.cs
@@ -31,13 +31,7 @@
        public string[] taglist { get; set; }
        /// <summary>
        /// è‡ªåŠ¨ç”Ÿæˆ
        /// </summary>
        public void AutoCreate()
        {
            var list = new List<string>();
        }
    }
}
WebApi/IStation.Application.Core/1-dispatch/1-solution/dto/input/StationDispatchInput.cs
@@ -6,39 +6,105 @@
    public class StationDispatchInput : IValidatableObject
    {
        /// <summary>
        /// è°ƒåº¦æµç¨‹æ ‡è¯†ï¼ˆæ–¹æ¡ˆè®¡ç®—后返回,区分调度方案的唯一性)
        /// å¯¹è±¡åˆ—表
        /// </summary>
        public string FlowId { get; set; }
        public Dictionary<string, double> objects { get; set; }
        /// <summary>
        /// æ°´åŽ‚åˆ—è¡¨
        /// è®¡ç®—状态  0:失败 1:成功
        /// </summary>
        public List<FactoryDispatchInput> Factory { get; set; }
        public int flag { get; set; }
        /// <summary>
        ///
        /// æŽ¥æ”¶æ—¶é—´
        /// </summary>
        public DateTime ReceiptTime { get; set; }
        /// <summary>
        /// è¿”回时间
        /// </summary>
        public DateTime ReturnTime { get; set; }
        /// <summary>
        /// å¤‡æ³¨ä¿¡æ¯
        /// </summary>
        public string message { get; set; }
        /// <summary>
        /// éªŒè¯
        /// </summary>
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Factory == null || Factory.Count < 1)
            if (objects == null || objects.Count < 1)
            {
                yield return
                    new ValidationResult("Factory ä¸èƒ½ä¸ºç©º", new[] { nameof(Factory) });
                    new ValidationResult("objects ä¸èƒ½ä¸ºç©º", new[] { nameof(objects) });
            }
            else if (objects.Count < 4)
            {
                yield return
                  new ValidationResult("objects æ•°æ®ç¼ºå¤±", new[] { nameof(objects) });
            }
            else
            {
                for (int i = 0; i < Factory.Count; i++)
                if (!objects.ContainsKey("TotalFlow1"))
                {
                    var f = Factory[i];
                    if (f.Value < 1)
                    yield return
                  new ValidationResult(" objects [TotalFlow1]数据缺失", new[] { nameof(objects) });
                }
                else
                {
                    if (objects["TotalFlow1"] < 1)
                    {
                        yield return
                            new ValidationResult($"水厂增水量过低! ID:{f.Id} Value:{f.Value}", new[] { nameof(Factory) });
                            new ValidationResult($"一输水增水量过低! tag:TotalFlow1 Value:{objects["TotalFlow1"]}", new[] { nameof(objects) });
                    }
                }
                if (!objects.ContainsKey("TotalPressure1"))
                {
                    yield return
                  new ValidationResult(" objects [TotalPressure1]数据缺失", new[] { nameof(objects) });
                }
                else
                {
                    if (objects["TotalPressure1"] < 0.01)
                    {
                        yield return
                            new ValidationResult($"一输水增压过低! tag:TotalPressure1 Value:{objects["TotalPressure1"]}", new[] { nameof(objects) });
                    }
                }
                if (!objects.ContainsKey("TotalFlow2"))
                {
                    yield return
                  new ValidationResult(" objects [TotalFlow2]数据缺失", new[] { nameof(objects) });
                }
                else
                {
                    if (objects["TotalFlow2"] < 1)
                    {
                        yield return
                            new ValidationResult($"二输水增水量过低! tag:TotalFlow2 Value:{objects["TotalFlow2"]}", new[] { nameof(objects) });
                    }
                }
                if (!objects.ContainsKey("TotalPressure2"))
                {
                    yield return
                  new ValidationResult(" objects [TotalPressure2]数据缺失", new[] { nameof(objects) });
                }
                else
                {
                    if (objects["TotalPressure2"] < 0.01)
                    {
                        yield return
                            new ValidationResult($"二输水增压过低! tag:TotalPressure2 Value:{objects["TotalPressure2"]}", new[] { nameof(objects) });
                    }
                }
            }
        }
WebApi/IStation.Application.Core/1-dispatch/1-solution/dto/output/StationDispatchOutput.cs
@@ -11,65 +11,29 @@
        public StationDispatchOutput() { }
        /// <summary>
        ///
        /// å¯¹è±¡åˆ—表
        /// </summary>
        public StationDispatchOutput(StationDispatchOutput rhs)
        {
            this.Id = rhs.Id;
            this.Index = rhs.Index;
            this.Q = rhs.Q;
            this.H = rhs.H;
            this.E = rhs.E;
            this.P = rhs.P;
            this.WP = rhs.WP;
            this.UWP = rhs.UWP;
            this.Pumps = rhs.Pumps?.ToList();
        }
        public Dictionary<string, double> objects { get; set; }
        /// <summary>
        /// æ³µç«™æ ‡è¯†
        /// è®¡ç®—状态  0:失败 1:成功
        /// </summary>
        public string Id { get; set; }
        public int flag { get; set; }
        /// <summary>
        /// æ³µç«™ç´¢å¼•  0:陈行1输水 1:陈行2输水
        /// æŽ¥æ”¶æ—¶é—´
        /// </summary>
        public int Index { get; set; }
        public DateTime ReceiptTime { get; set; }
        /// <summary>
        /// æµé‡ m³/h
        /// è¿”回时间
        /// </summary>
        public double Q { get; set; }
        public DateTime ReturnTime { get; set; }
        /// <summary>
        /// æ‰¬ç¨‹ m
        /// å¤‡æ³¨ä¿¡æ¯
        /// </summary>
        public double H { get; set; }
        /// <summary>
        /// æ•ˆçއ %
        /// </summary>
        public double E { get; set; }
        /// <summary>
        /// åŠŸçŽ‡ kw
        /// </summary>
        public double P { get; set; }
        /// <summary>
        /// åƒå¨æ°´èƒ½è€—  kw/m.m3/h
        /// </summary>
        public double WP { get; set; }
        /// <summary>
        /// å•位能耗 kw/m3/h
        /// </summary>
        public double UWP { get; set; }
        /// <summary>
        /// æ³µåˆ—表
        /// </summary>
        public List<PumpDispatchOutput> Pumps { get; set; }
        public string message { get; set; }
    }
}
WebApi/IStation.Application.Core/IStation.Application.Core.csproj
@@ -11,7 +11,18 @@
    </PropertyGroup>
    <ItemGroup>
      <Compile Remove="1-dispatch - å¤åˆ¶\**" />
      <EmbeddedResource Remove="1-dispatch - å¤åˆ¶\**" />
      <None Remove="1-dispatch - å¤åˆ¶\**" />
    </ItemGroup>
    <ItemGroup>
      <Compile Remove="0-core\3-helper\Log - å¤åˆ¶.cs" />
      <Compile Remove="1-dispatch\1-solution\DispatchSolution_Controller - å¤åˆ¶.cs" />
      <Compile Remove="1-dispatch\1-solution\dto\input\FactoryDispatchInput.cs" />
      <Compile Remove="1-dispatch\1-solution\dto\output\DispatchSolutionOutput.cs" />
      <Compile Remove="1-dispatch\1-solution\dto\output\PumpDispatchOutput.cs" />
      <Compile Remove="1-dispatch\1-solution\helper\TempOutHelper.cs" />
    </ItemGroup>
    <ItemGroup>
@@ -48,10 +59,11 @@
    <ItemGroup>
        <PackageReference Include="Yw.Application.Core" Version="3.0.5" />
        <PackageReference Include="Yw.Quartz.Core" Version="1.0.0" />
        <PackageReference Include="Yw.Quartz.Core" Version="3.0.0" />
    </ItemGroup>
    <ItemGroup>
      <ProjectReference Include="..\..\Schedule\IStation.Algorithm\IStation.Algorithm.csproj" />
      <ProjectReference Include="..\IStation.Server\IStation.Server.csproj" />
      <ProjectReference Include="..\IStation.Service.Core\IStation.Service.Core.csproj" />
    </ItemGroup>
WebApi/IStation.Entry.Core/IStation.Entry.Core.csproj.user
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <NameOfLastUsedPublishProfile>D:\WorkCode\IStation\Code\Service.Ch.V1.0\WebApi\IStation.Entry.Core\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
  </PropertyGroup>
</Project>
WebApi/IStation.Entry.Core/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -4,7 +4,8 @@
-->
<Project>
  <PropertyGroup>
    <_PublishTargetUrl>D:\WorkData\模块\权限\Yw.Entry.Core\bin\Release\net6.0\publish\</_PublishTargetUrl>
    <History>True|2023-06-26T03:38:29.6648988Z;True|2023-06-21T16:17:40.6226554+08:00;True|2023-06-21T13:30:18.8163322+08:00;True|2023-06-21T13:19:43.9290154+08:00;True|2023-06-21T11:35:28.3376504+08:00;</History>
    <_PublishTargetUrl>D:\WorkCode\IStation\Code\Service.Ch.V1.0\WebApi\IStation.Entry.Core\bin\Release\net6.0\publish\</_PublishTargetUrl>
    <History>True|2024-05-07T02:48:01.6650551Z;True|2024-05-07T10:33:33.1990927+08:00;True|2024-05-07T10:20:40.5715968+08:00;False|2024-05-07T10:20:22.6825823+08:00;False|2024-05-07T10:19:44.6799744+08:00;True|2023-06-26T11:38:29.6648988+08:00;True|2023-06-21T16:17:40.6226554+08:00;True|2023-06-21T13:30:18.8163322+08:00;True|2023-06-21T13:19:43.9290154+08:00;True|2023-06-21T11:35:28.3376504+08:00;</History>
    <LastFailureDetails />
  </PropertyGroup>
</Project>
WebApi/IStation.Service.Core/GlobalUsings.cs
@@ -1,5 +1,2 @@
global using SqlSugar;
global using Yw.Untity;
global using System.Text;
global using IStation.Epanet.Enums;
global using System.Text;
global using Yw;
WebApi/IStation.Service.Core/IStation.Service.Core.csproj
@@ -12,12 +12,21 @@
    </PropertyGroup>
    <ItemGroup>
      <Compile Remove="4-dal\1-dispatch_solution\**" />
      <Compile Remove="6-service\1-dispatch_solution\**" />
      <EmbeddedResource Remove="4-dal\1-dispatch_solution\**" />
      <EmbeddedResource Remove="6-service\1-dispatch_solution\**" />
      <None Remove="4-dal\1-dispatch_solution\**" />
      <None Remove="6-service\1-dispatch_solution\**" />
      <Compile Remove="2-model\**" />
      <Compile Remove="4-dal\**" />
      <Compile Remove="5-cache\**" />
      <Compile Remove="6-service\**" />
      <Compile Remove="7-utils\**" />
      <EmbeddedResource Remove="2-model\**" />
      <EmbeddedResource Remove="4-dal\**" />
      <EmbeddedResource Remove="5-cache\**" />
      <EmbeddedResource Remove="6-service\**" />
      <EmbeddedResource Remove="7-utils\**" />
      <None Remove="2-model\**" />
      <None Remove="4-dal\**" />
      <None Remove="5-cache\**" />
      <None Remove="6-service\**" />
      <None Remove="7-utils\**" />
    </ItemGroup>
    <ItemGroup>