chengsc
2025-04-28 25f52fdb9a195ab651bff2ebb318119ce7f1f633
修改问题
5个文件已修改
901 ■■■■ 已修改文件
Admin.NET/WCS.Application/Entity/WcsStorageLocat.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/OpenApi/OpenApi.cs 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCService.cs 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs 266 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Util/FourWayCarUtil.cs 549 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Entity/WcsStorageLocat.cs
@@ -126,7 +126,7 @@
    public string? AisleTwo { get; set; }
    /// <summary>
    /// 储位类型 1储位 0通道
    /// 储位类型 1子通道 0主通道 2 输送线口
    /// </summary>
    [SugarColumn(ColumnName = "Make", ColumnDescription = "储位类型", Length = 32)]
    public string? Make { get; set; }
Admin.NET/WCS.Application/OpenApi/OpenApi.cs
@@ -58,38 +58,38 @@
        {
            throw Oops.Bah("任务:" + models.TaskNo + ";不存在!");
        }
        var data1 = FourWayCarUtil.GetCarPath("090601", "080401");
        var data1 = FourWayCarUtil.GetCarPath("090501", "080501","0");
        if (data1 == null) //|| data1.Count == 0
        {
            throw Oops.Bah("分配路径不存在!");
        }
        // 根据任务状态 补充起始结束节点状态
        var data2 = FourWayCarUtil.GetCarPathUp(data1, 1);
        var data2 = FourWayCarUtil.GetCarPathUp(data1, 0);
        var path = "";
        var executionPath1 = "";
        foreach (var item in data1)
        {
            //路径节点
            var pathXYZ = item.X.ToString().PadLeft(2, '0') + item.Y.ToString().PadLeft(2, '0') + item.Z.ToString().PadLeft(2, '0') + item.NodeCom.ToString();
            path += pathXYZ + ";";
            if (item.IsSendPlc)
            {
                executionPath1 += pathXYZ + ";";
            }
        }
        // 插入四向车任务表
        var carTask1 = new WcsCarTasks()
        {
            TaskNo = taskInfo.TaskNo,
            PreId = "",
            ExecutionPath = executionPath1,
            Path = path,
            CarNo = "",
            Status = TaskStatusEnum.Wait
        };
        var i = _db.Insertable(carTask1).ExecuteCommand();
        Console.WriteLine(""+i);
        //foreach (var item in data1)
        //{
        //    //路径节点
        //    var pathXYZ = item.X.ToString().PadLeft(2, '0') + item.Y.ToString().PadLeft(2, '0') + item.Z.ToString().PadLeft(2, '0') + item.NodeCom.ToString();
        //    path += pathXYZ + ";";
        //    if (item.IsSendPlc)
        //    {
        //        executionPath1 += pathXYZ + ";";
        //    }
        //}
        //// 插入四向车任务表
        //var carTask1 = new WcsCarTasks()
        //{
        //    TaskNo = taskInfo.TaskNo,
        //    PreId = "",
        //    ExecutionPath = executionPath1,
        //    Path = path,
        //    CarNo = "",
        //    Status = TaskStatusEnum.Wait
        //};
        //var i = _db.Insertable(carTask1).ExecuteCommand();
        //Console.WriteLine(""+i);
    }
    /// WCS接受WMS下发的任务(多
Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -159,7 +159,7 @@
                    var (resultTaskStatus, valueTaskStatus) = plcConn.GetDBValue(modPosTaskStatus.PosType, modPosTaskStatus.PlcPos);
                    //判断读取任务状态是否成功 并且任务状态是1 0:无任务,1:任务完成,2:任务取消,3:任务暂停,4:任务异常 5:任务执行中
                    WcsCarTasks carTask2 = null;//null 新任务  not null 路径2任务
                    WcsCarTasks carTaskNext = null;//null 新任务  not null 当前小车&&当前任务 下一节任务
                    
                    if (resultTaskStatus.IsSucceed && valueTaskStatus == 1)
                    {
@@ -182,7 +182,7 @@
                            break;//没有查询到总任务
                        }
                        //获取路径2的任务 下发
                        carTask2 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == carTask.TaskNo && m.CarNo == modDevice.PlcIdIP && m.PreId.Contains(carTask.Id.ToString())).OrderBy(m=>m.CreateTime).First();
                        carTaskNext = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == carTask.TaskNo && m.CarNo == modDevice.PlcIdIP && m.Status <= TaskStatusEnum.Doing).OrderBy(m=>m.CreateTime).First();
                        
                        if (carTask != null && carTask.Status != TaskStatusEnum.Complete)
                        {
@@ -201,8 +201,8 @@
                            
                            HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
                        }
                        //没有路径2的任务 变更总任务信息
                        if (carTask2 == null && modFinshTask != null && modFinshTask.Status != TaskStatusEnum.Complete)
                        //总任务下没有其他未执行小车的任务 变更总任务信息
                        if (carTaskNext == null && modFinshTask != null && modFinshTask.Status != TaskStatusEnum.Complete)
                        {
                            modFinshTask.Status = TaskStatusEnum.Complete;
                            modFinshTask.FinishDate = DateTime.Now;
@@ -236,37 +236,37 @@
                    WcsTask modTask;
                    //要下发路径2任务
                    if (carTask2 != null)
                    if (carTaskNext != null)
                    {
                        modTask = _db.Queryable<WcsTask>().First(s => s.IsDelete == false && s.TaskNo == carTask2.TaskNo && s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar);
                        modTask = _db.Queryable<WcsTask>().First(s => s.IsDelete == false && s.TaskNo == carTaskNext.TaskNo && s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar);
                        carTask2= _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == modTask.TaskNo && m.CarNo == modDevice.PlcIdIP).OrderBy(m => m.CreateTime).First();
                        carTaskNext = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == modTask.TaskNo && m.CarNo == modDevice.PlcIdIP && m.Status == TaskStatusEnum.Wait).OrderBy(m => m.CreateTime).First();
                    }
                    else
                    {
                        // 获取任务信息
                        modTask = _db.Queryable<WcsTask>().Where(s => s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar).OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime).First();
                        modTask = _db.Queryable<WcsTask>().Where(s => s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar).OrderBy(m => m.Levels).OrderBy(m => m.CreateTime).First();
                        if (modTask == null)
                        {
                            return;
                        }
                        carTask2 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == modTask.TaskNo && m.CarNo == modDevice.PlcIdIP).OrderBy(m => m.CreateTime).First();
                        carTaskNext = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == modTask.TaskNo && m.CarNo == modDevice.PlcIdIP && m.Status == TaskStatusEnum.Wait).OrderBy(m => m.CreateTime).First();
                    }
                    //return;
                    if (modTask == null || carTask2 == null)
                    if (modTask == null || carTaskNext == null)
                    {
                        //判断小车是否有空闲时间记录 没有:添加  有:判断当前时间与记录时间是否满足5分钟 满足:添加让小车去充电任务
                        return;
                    }
                    
                    if (carTask2.Status == TaskStatusEnum.Doing)
                    if (carTaskNext.Status == TaskStatusEnum.Doing)
                    {
                        Thread.Sleep(3000);
                        return;
                    }
                    //判断当前任务是否还有前置任务未完成
                    var preStrs = carTask2.PreId.Split(';');
                    var preStrs = carTaskNext.PreId.Split(';');
                    foreach (var preStr in preStrs)
                    {
                        if (string.IsNullOrWhiteSpace(preStr))
@@ -301,7 +301,7 @@
                    int posStatus = Convert.ToInt32(modNodeStatus.PlcPos);
                    //交互路径
                    var execuPath = carTask2.ExecutionPath.Split(';');
                    var execuPath = carTaskNext.ExecutionPath.Split(';');
                    if (Convert.ToInt32(valuex) != Convert.ToInt32(execuPath[0].Substring(0, 2)) || Convert.ToInt32(valuey) != Convert.ToInt32(execuPath[0].Substring(2, 2)) || Convert.ToInt32(valuez) != Convert.ToInt32(execuPath[0].Substring(4, 2)))
                    {
                        return; //小车位置与路径起始位置不同
@@ -343,15 +343,15 @@
                        var result = plcConn.SetDBValue(modStart.PosType, modStart.PlcPos, "1");
                        if (result.IsSucceed)
                        {
                            carTask2.Status = TaskStatusEnum.Doing;
                            carTask2.CarTaskNo = carTaskNo;
                            _db.Updateable(carTask2).ExecuteCommand();
                            carTaskNext.Status = TaskStatusEnum.Doing;
                            carTaskNext.CarTaskNo = carTaskNo;
                            _db.Updateable(carTaskNext).ExecuteCommand();
                            //清除小车空闲时间
                            var taskMonitor = new WcsTaskMonitor()
                            {
                                TaskNo = carTask2.TaskNo,
                                TaskNo = carTaskNext.TaskNo,
                                PlcName = modDevice.Text,
                                InteractiveMsg = $"向穿梭车下发任务{carTask2.TaskNo}"
                                InteractiveMsg = $"向穿梭车下发任务{carTaskNext.TaskNo}"
                            };
                            _db.Insertable(taskMonitor).ExecuteCommand();
                            //下发任务日志
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -338,7 +338,7 @@
                        Thread.Sleep(1000);
                        Thread.Sleep(3000);
                    }
                    catch (OperationCanceledException)
                    {
@@ -460,266 +460,58 @@
                    #endregion
                    #region 获取适合执行当前任务的小车 生成路径(需考虑小车阻阻挡)
                    // 获取适合执行当前任务的小车 生成路径(需考虑小车阻阻挡)
                    var assignCar = kXCarList.OrderBy(m => m.Level).FirstOrDefault();
                    if (assignCar == null)
                    {
                        continue;//没有空闲小车
                    }
                    var data = new List<CarModel>();
                    if (assignCar.Level != 0)
                    {
                        //判断小车位置是否与任务的起始储位相同,不相同:获取小车到取货储位路径
                        var carLocate = assignCar.X.ToString().PadLeft(2, '0')+assignCar.Y.ToString().PadLeft(2, '0')+ assignCar.Z.ToString().PadLeft(2, '0');
                        //获取小车去取货储位任务路径
                        var data1 = FourWayCarUtil.GetCarPath(carLocate, waitTask.StartLocate);
                        var datas = FourWayCarUtil.GetCarPathUp(data1, 0);
                        data.AddRange(datas);
                        var datas1 = FourWayCarUtil.GetCarPathUp(data1, 0);
                        if (datas1 == null)
                        {
                            continue;
                        }
                        else
                        {
                            var bl = FourWayCarUtil.AddCarTask(datas1, kXCarList, assignCar, waitTask,0);
                            //分配错误,删除分配信息
                            if (!bl)
                            {
                                var carTask = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == waitTask.TaskNo).ToList();
                                _db.Deleteable(carTask).ExecuteCommand();
                            }
                        }
                    }
                    //获取小车去放货储位任务路径
                    var data2 = FourWayCarUtil.GetCarPath(waitTask.StartLocate, waitTask.EndLocate, "1");
                    var datas2 = FourWayCarUtil.GetCarPathUp(data2, 1);
                    data.AddRange(datas2);
                    if (data == null) { continue; }
                    var preId1 = "";//前置任务Id
                    var executionPath1 = "";//交互路径
                    var executionPath2 = "";//交互路径
                    var path = "";//所有路径
                    var isOk = "1"; //是否完整路径  1完整 2 两条路径
                    for (int i = 0; i < data.Count; i++)
                    if (datas2 == null)
                    {
                        //路径节点
                        var pathXYZ = data[i].X.ToString().PadLeft(2, '0') + data[i].Y.ToString().PadLeft(2, '0') + data[i].Z.ToString().PadLeft(2, '0')+ data[i].NodeCom.ToString();
                        path += pathXYZ + ";";
                        //获取等待或正在执行的任务中包含当前节点的小车任务
                        var taskList = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing) && m.Path.Contains(pathXYZ)).Select(m => m.Id).Distinct().ToList();
                        foreach (var item in taskList)
                        {
                            //判断如果是完整路径 记录交互路径
                            if (isOk == "1")
                            {
                                //if (i == 0)
                                //{
                                //    return;//第一个节点有和其他任务路径冲突,无法避免
                                //}
                                var pathXYZQian = data[i - 1].X.ToString().PadLeft(2, '0') + data[i - 1].Y.ToString().PadLeft(2, '0') + data[i - 1].Z.ToString().PadLeft(2, '0') + data[i].NodeCom.ToString();
                                if (!executionPath1.Contains(pathXYZQian))
                                {
                                    executionPath1 += pathXYZQian + ";";
                                }
                                executionPath2 += pathXYZQian + ";";
                            }
                            //判断添加前置任务Id
                            if (!preId1.Contains(item + ""))
                            {
                                preId1 += item + ";";
                            }
                            isOk = "2";
                        }
                        if (data[i].IsSendPlc)
                        {
                            if (isOk == "1")
                            {
                                executionPath1 += pathXYZ + ";";
                        continue;
                            }
                            else
                            {
                                executionPath2 += pathXYZ + ";";
                            }
                        }
                    }
                    #endregion
                    #region 判断是否有空闲小车阻挡路径 3
                    var preId3 = "";//前置任务Id
                    foreach (var item in kXCarList)
                        var bl = FourWayCarUtil.AddCarTask(datas2,kXCarList,assignCar,waitTask,1);
                        //分配错误,删除分配信息
                        if (!bl)
                    {
                        if (item == assignCar)
                        {
                            continue;//排除当前分配任务的小车
                        }
                        //小车位置
                        var carXYZ = item.X.ToString().PadLeft(2, '0') + item.Y.ToString().PadLeft(2, '0') + item.Z.ToString().PadLeft(2, '0') ;
                        //分配的任务路径中 当前小车是否阻挡
                        if (path.Contains(carXYZ))
                        {
                            //获取等待或正在执行的任务中包含当前节点的小车任务,不会有太多任务,同层有几个小车最多有几个任务
                            var taskList3 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing)).ToList();
                            var str3 = "";//所有已分配或执行的任务全路径之和
                            foreach (var item2 in taskList3)
                            {
                                str3 += item2.Path;
                            }
                            var endLocate3 = "";
                            var executionPath3 = "";
                            var path3 = "";
                            var datas3 = new List<CarModel>();
                            //查找目标位置
                            while (endLocate3 == "" || datas3.Count == 0 || datas3 == null)
                            {
                                endLocate3 = FourWayCarUtil.GetCarEndLocation(carXYZ, str3);
                                var data3 = FourWayCarUtil.GetCarPath(carXYZ, endLocate3, "0");
                                datas3 = FourWayCarUtil.GetCarPathUp(data3, 0);
                            }
                            foreach (var itemPath in datas3)
                            {
                                var pathXYZ = itemPath.X.ToString().PadLeft(2, '0') + itemPath.Y.ToString().PadLeft(2, '0') + itemPath.Z.ToString().PadLeft(2, '0') + itemPath.NodeCom.ToString();
                                path3 += pathXYZ + ";";
                                if (itemPath.IsSendPlc)
                                {
                                    executionPath3 += pathXYZ + ";";
                                }
                            }
                            WcsTask modTask = new WcsTask()
                            {
                                TaskNo = _taskService.GetTaskCode(),
                                TaskType = TaskTypeEnum.Move,
                                Type = PLCTypeEnum.ShuttleCar,
                                StartLocate = carXYZ,
                                EndLocate = endLocate3,
                                PalletNo = "",
                                Status = TaskStatusEnum.Wait,
                                Levels = 2,
                                Origin = "WCS"
                            };
                            _db.Insertable(modTask).ExecuteCommand();
                            HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                            //移动小车
                            var carTaskYC = new WcsCarTasks()
                            {
                                TaskNo = modTask.TaskNo,
                                PreId = "",
                                ExecutionPath = executionPath3,
                                Path = path3,
                                CarNo = item.CarPlcIp,
                                Status = TaskStatusEnum.Wait
                            };
                            var idLong = _db.Insertable(carTaskYC).ExecuteReturnBigIdentity();
                            preId3 += idLong + ";";
                        }
                    }
                    #endregion
                    #region 判断现有任务中最终节点是否在当前分配路径中,如有 添加移走小车任务并加入前置任务 4
                    //获取等待或正在执行的任务中包含当前节点的小车任务,不会有太多任务,同层有几个小车最多有几个任务
                    var taskList4 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing)).ToList();
                    var preId4 = "";//前置任务Id
                    var str4 = "";//所有已分配或执行的任务全路径之和
                    foreach (var item in taskList4)
                    {
                        str4 += item.Path;
                    }
                    //判断现有任务中最终节点是否在当前分配路径中,如有 添加移走小车任务并加入前置任务
                    foreach (var item in taskList4)
                    {
                        var lastPathList = item.ExecutionPath.Split(';');
                        //  a;b;c; 最后一个位是“”,所以lastPathList.Length - 2
                        var lastPath = lastPathList[lastPathList.Length - 2];
                        //如果此此分配路径包含醉舞中最终节点路径,添加移走小车
                        if (path.Contains(lastPath))
                        {
                            var endLocate = "";
                            var executionPath4 = "";
                            var path4 = "";
                            var datas4 = new List<CarModel>();
                            //查找目标位置
                            while (endLocate == "" || datas4.Count == 0 || datas4 == null)
                            {
                                endLocate = FourWayCarUtil.GetCarEndLocation(lastPath, str4);
                                var data4 = FourWayCarUtil.GetCarPath(lastPath, endLocate);
                                datas4 = FourWayCarUtil.GetCarPathUp(data4, 0);
                            }
                            foreach (var itemPath in datas4)
                            {
                                var pathXYZ = itemPath.X.ToString().PadLeft(2, '0') + itemPath.Y.ToString().PadLeft(2, '0') + itemPath.Z.ToString().PadLeft(2, '0') + itemPath.NodeCom.ToString();
                                path4 += pathXYZ + ";";
                                if (itemPath.IsSendPlc)
                                {
                                    executionPath4 += pathXYZ + ";";
                                }
                            }
                            WcsTask modTask = new WcsTask()
                            {
                                TaskNo = _taskService.GetTaskCode(),
                                TaskType = TaskTypeEnum.Move,
                                Type = PLCTypeEnum.ShuttleCar,
                                StartLocate = lastPath,
                                EndLocate = endLocate,
                                PalletNo = "",
                                Status = TaskStatusEnum.Wait,
                                Levels = 2,
                                Origin = "WCS"
                            };
                            _db.Insertable(modTask).ExecuteCommand();
                            HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                            //移动小车
                            var carTaskYC = new WcsCarTasks()
                            {
                                TaskNo = modTask.TaskNo,
                                PreId = "",
                                ExecutionPath = executionPath4,
                                Path = path4,
                                CarNo = item.CarNo,
                                Status = TaskStatusEnum.Wait
                            };
                            var idLong = _db.Insertable(carTaskYC).ExecuteReturnBigIdentity();
                            preId4 += idLong + ";";
                        }
                    }
                    #endregion
                    #region 插入任务数据  改变任务状态
                    // 插入四向车任务表
                    var carTask1 = new WcsCarTasks()
                    {
                        TaskNo = waitTask.TaskNo,
                        PreId = preId1+ preId3+preId4,
                        ExecutionPath = executionPath1,
                        Path = path,
                        CarNo = assignCar.CarPlcIp,
                        Status = TaskStatusEnum.Wait
                    };
                    _db.Insertable(carTask1).ExecuteCommand();
                    if (!string.IsNullOrWhiteSpace(executionPath1) && isOk == "2")
                    {
                        // 插入四向车任务表
                        var carTask2 = new WcsCarTasks()
                        {
                            TaskNo = waitTask.TaskNo,
                            PreId = preId1,
                            ExecutionPath = executionPath2,
                            Path = path,
                            CarNo = assignCar.CarPlcIp,
                            Status = TaskStatusEnum.Wait
                        };
                        _db.Insertable(carTask2).ExecuteCommand();
                    }
                    // 改变总任务表状态
                    waitTask.Status = TaskStatusEnum.Doing;
                    waitTask.UpdateTime = DateTime.Now;
                            waitTask.Status = TaskStatusEnum.Wait;
                    _db.Updateable(waitTask).ExecuteCommand();
                    HubUtil.PublicTask(waitTask.Adapt<WcsTaskOutput>());
                            var carTask = _db.Queryable<WcsCarTasks>().Where(m=>m.IsDelete == false && m.TaskNo == waitTask.TaskNo).ToList();
                            _db.Deleteable(carTask).ExecuteCommand();
                        }
                    }
                    #endregion
                    Thread.Sleep(3000);
                }
Admin.NET/WCS.Application/Util/FourWayCarUtil.cs
@@ -7,6 +7,7 @@
using System.Text;
using System.Threading.Tasks;
using WCS.Application.Entity;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.CustomServiceKfSessionGetWaitCaseResponse.Types;
namespace WCS.Application.Util;
@@ -14,8 +15,10 @@
{
    private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
    private static readonly WcsTaskService _taskService = App.GetService<WcsTaskService>();
    /// <summary>
    ///
    /// 完善小车下发节点、节点命令
    /// </summary>
    /// <param name="list">集合</param>
    /// <param name="moveType">移动类型 0:移动 1:移货 </param>
@@ -24,7 +27,7 @@
    {
        for (int i = 0; i < list.Count; i++)
        {
            if (i > 0 && i < list.Count - 1)
            if (i >= 0 && i < list.Count - 1)
            {
                if (list[i].X == list[i + 1].X)
                {
@@ -34,6 +37,21 @@
                {
                    list[i].NodeCom = 3;
                }
            }
            if (i > 0 && i < list.Count - 1)
            {
                if (list[i].Make != list[i - 1].Make || list[i].Make != list[i + 1].Make)
                {
                    if (list[i].X != list[i - 1].X || list[i].X != list[i + 1].X)
                    {
                        list[i].IsSendPlc = true;
                    }
                    //list[i - 1].IsSendPlc = true;
                }
            }
            if (i== 0)
            {
@@ -56,7 +74,14 @@
                list[i].IsSendPlc = true;
                if (moveType == 0)
                {
                    list[i].NodeCom = list[i + 1].NodeCom;
                    if (list[i].X == list[i - 1].X)
                    {
                        list[i].NodeCom = 2;
                    }
                    else if (list[i].Y == list[i - 1].Y)
                    {
                        list[i].NodeCom = 3;
                    }
                }
                else
                {
@@ -66,6 +91,328 @@
        }
        return list;
    }
    /// <summary>
    /// 获取小车移动的目标位置
    /// </summary>
    /// <param name="startLocation">起始位置</param>
    /// <param name="noPathStr">不能存放的储位字符串</param>
    /// <returns></returns>
    public static string GetCarEndLocation(string startLocation, string noPathStr)
    {
        if (string.IsNullOrEmpty(startLocation))
        {
            return null;
        }
        // 起始位置
        CarModel start = new CarModel()
        {
            X = int.Parse(startLocation.Substring(0, 2)),
            Y = int.Parse(startLocation.Substring(2, 2)),
            Z = int.Parse(startLocation.Substring(4, 2)),
            NodeCom = 0
        };
        // 获取储位表信息存储到集合里
        var layer = int.Parse(startLocation.Substring(4, 2));
        //  获取当前层储位信息
        var locationModels = _db.Queryable<WcsStorageLocat>()
            .Where(m => m.WareHouseNo == "W01" && m.Layer == layer && m.IsDelete == false)
        .ToList();
        #region MyRegion
        var list = locationModels.Where(m => !noPathStr.Contains(m.LocatNo)).OrderBy(m => Math.Abs(start.X - m.Row) + Math.Abs(start.Y - m.Column)).ToList();
        var locateStr = "";
        foreach (var item in list)
        {
            // 储位状态为损坏不可通行 储位状态为屏蔽为可通行不可存储托盘
            if (item.Flag == "2")
            {
                continue;
            }
            locateStr = item.LocatNo;
            break;
        }
        return locateStr;
        #endregion
    }
    /// <summary>
    /// 获取任务号
    /// </summary>
    /// <returns></returns>
    public static int GetTaskNo()
    {
        var list = _db.Queryable<WcsCarTasks>().ToList();
        var maxNo = list.Max(m => m.CarTaskNo);
        if (maxNo != null && maxNo > 0)
        {
            if (maxNo++ > 65535)
            {
                return 1;
            }
            return (int)maxNo++;
        }
        return 1;
    }
    public static bool AddCarTask(List<CarModel> data, List<CarInfo> kXCarList, CarInfo assignCar, WcsTask waitTask,int moveType)
    {
        #region 获取适合执行当前任务的小车 生成路径(需考虑小车阻阻挡)
        var preId1 = "";//前置任务Id
        var executionPath1 = "";//交互路径
        var executionPath2 = "";//交互路径
        var path = "";//所有路径
        var isOk = "1"; //是否完整路径  1完整 2 两条路径
        for (int i = 0; i < data.Count; i++)
        {
            //路径节点
            var pathXYZ = data[i].X.ToString().PadLeft(2, '0') + data[i].Y.ToString().PadLeft(2, '0') + data[i].Z.ToString().PadLeft(2, '0') + data[i].NodeCom.ToString();
            var pathXYZ2 = data[i].X.ToString().PadLeft(2, '0') + data[i].Y.ToString().PadLeft(2, '0') + data[i].Z.ToString().PadLeft(2, '0');
            path += pathXYZ + ";";
            //获取等待或正在执行的任务中包含当前节点的小车任务
            var taskList = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing) && m.Path.Contains(pathXYZ2) && m.CarNo != assignCar.CarPlcIp).Select(m => m.Id).Distinct().ToList();
            foreach (var item in taskList)
            {
                //判断如果是完整路径 记录交互路径
                if (isOk == "1")
                {
                    if (i == 0)
                    {
                        continue;
                    }
                    var pathXYZQian = data[i - 1].X.ToString().PadLeft(2, '0') + data[i - 1].Y.ToString().PadLeft(2, '0') + data[i - 1].Z.ToString().PadLeft(2, '0')+ data[i - 1].NodeCom.ToString();
                    var pathXYZQian2 = data[i - 1].X.ToString().PadLeft(2, '0') + data[i - 1].Y.ToString().PadLeft(2, '0') + data[i - 1].Z.ToString().PadLeft(2, '0');
                    if (!executionPath1.Contains(pathXYZQian2))
                    {
                        executionPath1 += pathXYZQian + ";";
                    }
                    executionPath2 += pathXYZQian + ";";
                    //判断添加前置任务Id
                    if (!preId1.Contains(item + ""))
                    {
                        preId1 += item + ";";
                    }
                }
                isOk = "2";
            }
            if (data[i].IsSendPlc)
            {
                if (isOk == "1")
                {
                    executionPath1 += pathXYZ + ";";
                }
                else
                {
                    executionPath2 += pathXYZ + ";";
                }
            }
        }
        #endregion
        #region 判断是否有空闲小车阻挡路径 3
        var preId3 = "";//前置任务Id
        foreach (var item in kXCarList)
        {
            if (item == assignCar)
            {
                continue;//排除当前分配任务的小车
            }
            //小车位置
            var carXYZ = item.X.ToString().PadLeft(2, '0') + item.Y.ToString().PadLeft(2, '0') + item.Z.ToString().PadLeft(2, '0');
            //分配的任务路径中 当前小车是否阻挡
            if (path.Contains(carXYZ))
            {
                //获取等待或正在执行的任务中包含当前节点的小车任务,不会有太多任务,同层有几个小车最多有几个任务
                var taskList3 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing)).ToList();
                var str3 = "";//所有已分配或执行的任务全路径之和
                foreach (var item2 in taskList3)
                {
                    str3 += item2.Path;
                }
                var endLocate3 = "";
                var executionPath3 = "";
                var path3 = "";
                var datas3 = new List<CarModel>();
                //查找目标位置
                while (endLocate3 == "" || datas3.Count == 0 || datas3 == null)
                {
                    endLocate3 = FourWayCarUtil.GetCarEndLocation(carXYZ, str3);
                    var data3 = FourWayCarUtil.GetCarPath(carXYZ, endLocate3, "0");
                    datas3 = FourWayCarUtil.GetCarPathUp(data3, 0);
                }
                foreach (var itemPath in datas3)
                {
                    var pathXYZ = itemPath.X.ToString().PadLeft(2, '0') + itemPath.Y.ToString().PadLeft(2, '0') + itemPath.Z.ToString().PadLeft(2, '0') + itemPath.NodeCom.ToString();
                    path3 += pathXYZ + ";";
                    if (itemPath.IsSendPlc)
                    {
                        executionPath3 += pathXYZ + ";";
                    }
                }
                WcsTask modTask = new WcsTask()
                {
                    TaskNo = _taskService.GetTaskCode(),
                    TaskType = TaskTypeEnum.Move,
                    Type = PLCTypeEnum.ShuttleCar,
                    StartLocate = carXYZ,
                    EndLocate = endLocate3,
                    PalletNo = "",
                    Status = TaskStatusEnum.Wait,
                    Levels = 999,
                    Origin = "WCS"
                };
                _db.Insertable(modTask).ExecuteCommand();
                HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                //移动小车
                var carTaskYC = new WcsCarTasks()
                {
                    TaskNo = modTask.TaskNo,
                    PreId = "",
                    ExecutionPath = executionPath3,
                    Path = path3,
                    CarNo = item.CarPlcIp,
                    Status = TaskStatusEnum.Wait
                };
                var idLong = _db.Insertable(carTaskYC).ExecuteReturnSnowflakeId();
                preId3 += idLong + ";";
            }
        }
        #endregion
        #region 判断现有任务中最终节点是否在当前分配路径中,如有 添加移走小车任务并加入前置任务 4
        //获取等待或正在执行的任务中包含当前节点的小车任务,不会有太多任务,同层有几个小车最多有几个任务
        var taskList4 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing) && m.CarNo!=assignCar.CarPlcIp).ToList();
        var preId4 = "";//前置任务Id
        var str4 = "";//所有已分配或执行的任务全路径之和
        foreach (var item in taskList4)
        {
            str4 += item.Path;
        }
        //判断现有任务中最终节点是否在当前分配路径中,如有 添加移走小车任务并加入前置任务
        foreach (var item in taskList4)
        {
            var lastPathList = item.ExecutionPath.Split(';');
            //  a;b;c; 最后一个位是“”,所以lastPathList.Length - 2
            var lastPath = lastPathList[lastPathList.Length - 2];
            var lastPath2 = lastPath.Substring(0,6);
            //如果此此分配路径包含醉舞中最终节点路径,添加移走小车
            if (path.Contains(lastPath2))
            {
                var endLocate = "";
                var executionPath4 = "";
                var path4 = "";
                var datas4 = new List<CarModel>();
                //查找目标位置
                while (endLocate == "" || datas4.Count == 0 || datas4 == null)
                {
                    endLocate = FourWayCarUtil.GetCarEndLocation(lastPath, str4);
                    var data4 = FourWayCarUtil.GetCarPath(lastPath, endLocate);
                    datas4 = FourWayCarUtil.GetCarPathUp(data4, 0);
                }
                foreach (var itemPath in datas4)
                {
                    var pathXYZ = itemPath.X.ToString().PadLeft(2, '0') + itemPath.Y.ToString().PadLeft(2, '0') + itemPath.Z.ToString().PadLeft(2, '0') + itemPath.NodeCom.ToString();
                    path4 += pathXYZ + ";";
                    if (itemPath.IsSendPlc)
                    {
                        executionPath4 += pathXYZ + ";";
                    }
                }
                WcsTask modTask = new WcsTask()
                {
                    TaskNo = _taskService.GetTaskCode(),
                    TaskType = TaskTypeEnum.Move,
                    Type = PLCTypeEnum.ShuttleCar,
                    StartLocate = lastPath,
                    EndLocate = endLocate,
                    PalletNo = "",
                    Status = TaskStatusEnum.Wait,
                    Levels = 999,
                    Origin = "WCS"
                };
                _db.Insertable(modTask).ExecuteCommand();
                HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                //移动小车
                var carTaskYC = new WcsCarTasks()
                {
                    TaskNo = modTask.TaskNo,
                    PreId = "",
                    ExecutionPath = executionPath4,
                    Path = path4,
                    CarNo = item.CarNo,
                    Status = TaskStatusEnum.Wait
                };
                var idLong = _db.Insertable(carTaskYC).ExecuteReturnSnowflakeId();
                preId4 += idLong + ";";
            }
        }
        #endregion
        #region 插入任务数据  改变任务状态
        // 插入四向车任务表
        var carTask1 = new WcsCarTasks()
        {
            TaskNo = waitTask.TaskNo,
            PreId = preId1 + preId3 + preId4,
            ExecutionPath = executionPath1,
            Path = path,
            CarNo = assignCar.CarPlcIp,
            Status = TaskStatusEnum.Wait
        };
        _db.Insertable(carTask1).ExecuteCommand();
        if (!string.IsNullOrWhiteSpace(executionPath1) && isOk == "2")
        {
            // 插入四向车任务表
            var carTask2 = new WcsCarTasks()
            {
                TaskNo = waitTask.TaskNo,
                PreId = preId1,
                ExecutionPath = executionPath2,
                Path = path,
                CarNo = assignCar.CarPlcIp,
                Status = TaskStatusEnum.Wait
            };
            _db.Insertable(carTask2).ExecuteCommand();
        }
        if (moveType == 1)
        {
            // 改变总任务表状态
            waitTask.Status = TaskStatusEnum.Doing;
            waitTask.UpdateTime = DateTime.Now;
            _db.Updateable(waitTask).ExecuteCommand();
            HubUtil.PublicTask(waitTask.Adapt<WcsTaskOutput>());
        }
        return true;
        #endregion
    }
    /// <summary>
    /// 获取小车路径
@@ -141,7 +488,7 @@
                // 存储小车可运行的方向
                var validDirections = new List<CarModel>();
                var currentLocation = locationModels.FirstOrDefault(m => m.Row == current.X && m.Column == current.Y);
                if (currentLocation.Make == "0")
                if (currentLocation.Make == "0"|| currentLocation.Make == "2")
                {
                    // 主通道
                    validDirections.Add(new CarModel() { X = 1, Y = 0 }); // 右
@@ -226,40 +573,8 @@
                    {
                        neighbor.IsSendPlc = false;
                        //if (current.X == neighbor.X)
                        //{
                        //    current.NodeCom = 2;
                        //}
                        //else if (current.Y == neighbor.Y)
                        //{
                        //    current.NodeCom = 3;
                        //}
                        //// 补充参数
                        //if (current.Equals(start))
                        //{
                        //    current.NodeCom = moveType;
                        //    current.IsSendPlc = true;
                        //}
                        //if (neighbor.Equals(end))
                        //{
                        //    //neighbor.NodeCom = moveType != 0 ? 2:0 ;
                        //    if (moveType == 1)
                        //    {
                        //        neighbor.NodeCom = 4;
                        //    }
                        //    else
                        //    {
                        //        neighbor.NodeCom = current.NodeCom;
                        //    }
                        //    neighbor.IsSendPlc = true;
                        //}
                        if (currentModel.Make != locationModel.Make)
                        {
                            neighbor.IsSendPlc = true;
                        }
                        neighbor.Make = locationModel.Make;
                        current.Make = currentModel.Make;
                        // 更新实际距离与预估距离
                        cameFrom[neighbor] = current;
@@ -283,159 +598,6 @@
        }
        return null;
    }
    /// <summary>
    /// 获取小车移动的目标位置
    /// </summary>
    /// <param name="startLocation">起始位置</param>
    /// <param name="noPathStr">不能存放的储位字符串</param>
    /// <returns></returns>
    public static string GetCarEndLocation(string startLocation,string noPathStr)
    {
        if (string.IsNullOrEmpty(startLocation))
        {
            return null;
        }
        // 起始位置
        CarModel start = new CarModel()
        {
            X = int.Parse(startLocation.Substring(0, 2)),
            Y = int.Parse(startLocation.Substring(2, 2)),
            Z = int.Parse(startLocation.Substring(4, 2)),
            NodeCom = 0
        };
        // 获取储位表信息存储到集合里
        var layer = int.Parse(startLocation.Substring(4, 2));
        //  获取当前层储位信息
        var locationModels = _db.Queryable<WcsStorageLocat>()
            .Where(m => m.WareHouseNo == "W01" && m.Layer == layer && m.IsDelete == false)
        .ToList();
        #region MyRegion
        var list = locationModels.Where(m => !noPathStr.Contains(m.LocatNo)).OrderBy(m=> Math.Abs(start.X - m.Row) + Math.Abs(start.Y - m.Column)).ToList();
        var locateStr = "";
        foreach (var item in list)
        {
            // 储位状态为损坏不可通行 储位状态为屏蔽为可通行不可存储托盘
            if (item.Flag == "2")
            {
                continue;
            }
            locateStr = item.LocatNo;
            break;
        }
        return locateStr;
        #endregion
        #region 使用算法计算小车可移动的目标路径
        //try
        //{
        //    // 定义关闭节点字典
        //    var closeSet = new Dictionary<CarModel, CarModel>();
        //    // 存储小车可运行的方向
        //    var validDirections = new List<CarModel>();
        //    var currentLocation = locationModels.FirstOrDefault(m => m.Row == start.X && m.Column == start.Y);
        //    if (currentLocation.Make == "0")
        //    {
        //        // 主通道
        //        validDirections.Add(new CarModel() { X = 1, Y = 0 }); // 右
        //        validDirections.Add(new CarModel() { X = -1, Y = 0 }); // 左
        //        validDirections.Add(new CarModel() { X = 0, Y = 1 }); // 下
        //        validDirections.Add(new CarModel() { X = 0, Y = -1 }); // 上
        //    }
        //    if (currentLocation.Make == "1")
        //    {
        //        // 子通道
        //        // 先拆分出口
        //        var outNode = currentLocation.AisleOne;
        //        if (string.IsNullOrEmpty(outNode))
        //        {
        //            throw new Exception("当前位置没有维护出口!");
        //        }
        //        int outX = int.Parse(outNode.Substring(0, 2));
        //        int outY = int.Parse(outNode.Substring(2, 2));
        //        if (start.X == outX)
        //        {
        //            validDirections.Add(new CarModel() { X = 0, Y = 1 }); // 下
        //            validDirections.Add(new CarModel() { X = 0, Y = -1 }); // 上
        //        }
        //        else
        //        {
        //            validDirections.Add(new CarModel() { X = 1, Y = 0 }); // 右
        //            validDirections.Add(new CarModel() { X = -1, Y = 0 }); // 左
        //        }
        //    }
        //    foreach (var dir in validDirections)
        //    {
        //        CarModel neighbor = new CarModel() { X = start.X + dir.X, Y = start.Y + dir.Y, Z = layer };
        //        // 验证下一节点位置是否可通行并且判断是否被其他小车占用
        //        // 判断下一节点是否关闭
        //        if (closeSet.ContainsKey(neighbor))
        //        {
        //            closeSet[neighbor] = neighbor;
        //        }
        //        // 当前节点
        //        var currentModel = locationModels.FirstOrDefault(it => it.Row == start.X && it.Column == start.Y);
        //        // 下一节点
        //        var locationModel = locationModels.FirstOrDefault(it => it.Row == neighbor.X && it.Column == neighbor.Y);
        //        // 不存在此位置信息
        //        if (locationModel == null)
        //        {
        //            closeSet[neighbor] = neighbor;
        //            continue;
        //        }
        //        // 储位状态为损坏不可通行 储位状态为屏蔽为可通行不可存储托盘
        //        if (locationModel.Flag == "2")
        //        {
        //            closeSet[neighbor] = neighbor;
        //            continue;
        //        }
        //    }
        //}
        //catch (Exception)
        //{
        //    throw;
        //}
        //return null;
        #endregion
    }
    public static int GetTaskNo()
    {
        var list = _db.Queryable<WcsCarTasks>().ToList();
        var maxNo = list.Max(m => m.CarTaskNo);
        if (maxNo!=null && maxNo > 0)
        {
            if (maxNo++ > 65535)
            {
                return 1;
            }
            return (int)maxNo++;
        }
        return 1;
    }
    /// <summary>
@@ -494,6 +656,11 @@
    /// </summary>
    public bool IsSendPlc { get; set; }
    /// <summary>
    /// 0通道 1 储位
    /// </summary>
    public string Make { get; set; }
    public int CompareTo(CarModel other)
    {
        if (other == null)