Administrator
2 天以前 e533afd765bac692ed6eb5194b44a3bf6f927f17
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -9,6 +9,7 @@
using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using OnceMi.AspNetCore.OSS;
using Qiniu.Storage;
using System;
using System.Drawing.Drawing2D;
using System.Net.NetworkInformation;
@@ -52,6 +53,7 @@
    private static List<ModbusUtil> listModbusUtil = new List<ModbusUtil>();
    public static List<ModbusUtil> modbusUtilConn
    {
        get { return listModbusUtil; }
@@ -86,11 +88,12 @@
        boDrumReversal = _sysConfigService.GetConfigValue<bool>("sys_DrumReversal").Result;
        boOutLock = _sysConfigService.GetConfigValue<bool>("sys_BoOutLock").Result;
        boEnterLock = _sysConfigService.GetConfigValue<bool>("sys_BoEnterLock").Result;
    }
    /// <summary>
    /// 初始化PLC连接
    /// </summary>
    public static void Init()
    public static void Init()
    {
        cts.Cancel();
        listPlc = _db.Queryable<WcsPlc>()
@@ -209,15 +212,6 @@
                                        var (result, value) = modPlcUtil.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
                                        if (result.IsSucceed)
                                        {
                                            ////如果是穿梭车,这里发送心跳
                                            //if (modPlc.Type == PLCTypeEnum.ShuttleCar)
                                            //{
                                            //    var modHeart = listPlcPosition.Where(s => s.DeviceId == modDevice.Id && s.Text == "心跳").FirstOrDefault();
                                            //    if (modHeart != null)
                                            //    {
                                            //        modPlcUtil.SetPlcDBValue(modHeart.PosType, modHeart.PlcPos, "1");
                                            //    }
                                            //}
                                            //无流程跳出
                                            if (Convert.ToInt32(value) == 0)
                                                continue;
@@ -338,7 +332,7 @@
                        Thread.Sleep(1000);
                        Thread.Sleep(2000);
                    }
                    catch (OperationCanceledException)
                    {
@@ -363,7 +357,7 @@
        {
            while (true)
            {
                Console.WriteLine("开启四向车任务自分配");
                //Console.WriteLine("开启四向车任务自分配");
                //取消线程 关闭PLC连接
                if (cts.Token.IsCancellationRequested)
                {
@@ -376,16 +370,92 @@
                }
                try
                {
                    // 获取密集库未执行任务 根据创建时间排序
                    var waitTask = _db.Queryable<WcsTask>().Where(s => s.IsDelete == false && s.Status == TaskStatusEnum.Wait && s.Type == PLCTypeEnum.ShuttleCar).OrderBy(s => s.CreateTime).First();
                    var waitTask = _db.Queryable<WcsTask>().Where(s => s.IsDelete == false && s.Status == TaskStatusEnum.Wait && s.Type == PLCTypeEnum.ShuttleCar).OrderBy(s => new {s.Levels, s.CreateTime}).First();
                    if (waitTask == null)
                    {
                        continue;
                    }
                    var starLocate = "";
                    var endLocate = "";
                    var taskceng = 0;
                    //01010101: 01排 01列 01层 01深度-此项目不做判断
                    var taskpai = int.Parse(waitTask.StartLocate.Substring(0, 2));
                    var tasklie = int.Parse(waitTask.StartLocate.Substring(2, 2));
                    var taskceng = int.Parse(waitTask.StartLocate.Substring(4, 2));
                    if (waitTask.TaskType == TaskTypeEnum.In )
                    {
                        //入库任务起始巷道就是起始工位
                        if (string.IsNullOrWhiteSpace(waitTask.StartRoadway) || string.IsNullOrWhiteSpace(waitTask.EndLocate))
                        {
                            continue;
                        }
                        taskceng = int.Parse(waitTask.StartRoadway.Substring(4, 2));
                        starLocate = waitTask.StartRoadway;
                        endLocate = waitTask.EndLocate;
                    }
                    else if (waitTask.TaskType == TaskTypeEnum.Out)
                    {
                        taskceng = int.Parse(waitTask.StartLocate.Substring(4, 2));
                        starLocate = waitTask.StartLocate;
                        endLocate = waitTask.EndRoadway;
                        #region 添加输送线与任务验证
                        var text = "";
                        var devStation = "";
                        var ip = "";
                        var carcon = new carConverModel();
                        if (carcon.conveyorBei.Keys.Contains(endLocate))
                        {
                            text = "输送线北";
                            ip = "10.26.254.10";
                            devStation = carcon.conveyorBei[endLocate];
                        }
                        else if (carcon.conveyorNan.Keys.Contains(endLocate))
                        {
                            text = "输送线南";
                            ip = "10.26.254.11";
                            devStation = carcon.conveyorNan[endLocate];
                        }
                        if (text != "")
                        {
                            //var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Text == text);
                            //var modConn = new PLCUtil(modPlc);
                            var modConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == ip);
                            var modDevice = PLCTaskAction.plcDevices.First(s => s.StationNum == devStation);
                            var (plcResult, palletVal) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
                            if (!plcResult.IsSucceed || Convert.ToInt32(palletVal) != 720)
                            {
                                continue;//放货工位没有读取成功或不是空闲
                            }
                            var gongwei = carcon.conveyorRuKu[endLocate];
                            //判断任务
                            var convarTask = _db.Queryable<WcsTask>().First(m => m.IsDelete == false && m.StartLocate == gongwei
                            && m.Type == PLCTypeEnum.ConveyorLine && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing));
                            if (convarTask != null)
                            {
                                continue;//放货工位有任务
                            }
                        }
                        #endregion
                    }
                    else if (waitTask.TaskType == TaskTypeEnum.Move)
                    {
                        taskceng = int.Parse(waitTask.StartLocate.Substring(4, 2));
                        starLocate = waitTask.StartLocate;
                        endLocate = waitTask.EndLocate;
                    }
                    else
                    {
                        continue;
                    }
                    #region 获取当前任务所在层所有空闲小车
@@ -412,6 +482,31 @@
                            {
                                //获取工位WCSPLCPosition信息
                                var plcPosition = listPlcPosition.Where(s => s.DeviceId == modDevice.Id).ToList();
                                if (value == 3)
                                {
                                    var modCarDl = plcPosition.FirstOrDefault(s => s.Text == "电池电量");
                                    var (resultDl, valueDl) = modbusUtil.GetDBValue(modCarDl.PosType, modCarDl.PlcPos);
                                    if (resultDl.IsSucceed && valueDl> (int)FourWayCarDLEnum.Dl)
                                    {
                                        //写入结束充电命令
                                        var modCdEnd = plcPosition.FirstOrDefault(s => s.Text == "充电命令");
                                        var resultDl22 = modbusUtil.SetDBValue(modCdEnd.PosType, modCdEnd.PlcPos.ToString(), "3") ;
                                        carErr = true;
                                        break; //暂缓分配,防止同层小车关机或失联导致阻挡路径
                                    }
                                }
                                var modCarPall = plcPosition.FirstOrDefault(s => s.Text == "托盘检测");
                                var (resultPall, valuePall) = modbusUtil.GetDBValue(modCarPall.PosType, modCarPall.PlcPos);
                                //var modCarju = plcPosition.FirstOrDefault(s => s.Text == "举升位置");
                                //var (resultju, valueju) = modbusUtil.GetDBValue(modCarju.PosType, modCarju.PlcPos);
                                //if (resultPall.IsSucceed && valuePall == 1  && resultPall.IsSucceed && valuePall != 1)  //1顶货 2子通道  3主通道
                                //{
                                //    break; //暂缓分配
                                //}
                                if (resultPall.IsSucceed && valuePall == 1)  //1有托盘 2无托盘
                                {
                                    break; //暂缓分配
                                }
                                //小车空闲加入集合
                                if (value == 1)
                                {
@@ -430,7 +525,7 @@
                                        {
                                            var carVal = ((int)valuex).ToString().PadLeft(2, '0') + ((int)valuey).ToString().PadLeft(2, '0') + ((int)valuez).ToString().PadLeft(2, '0');
                                            //小车到取货储位路径  
                                            var d = FourWayCarUtil.GetCarPath(carVal, waitTask.StartLocate);
                                            var d = FourWayCarUtil.GetCarPath(carVal, starLocate);
                                            kXCarList.Add(new CarInfo()
                                            {
                                                CarPlcIp = modbusUtil.PlcIP,
@@ -460,266 +555,65 @@
                    #endregion
                    #region 获取适合执行当前任务的小车 生成路径(需考虑小车阻阻挡)
                    // 获取适合执行当前任务的小车 生成路径(需考虑小车阻阻挡)
                    var assignCar = kXCarList.OrderBy(m => m.Level).FirstOrDefault();
                    if (assignCar == null)
                    {
                        continue;//没有空闲小车
                    }
                    var data = new List<CarModel>();
                    if (assignCar.Level != 0)
                    if (assignCar.Level != 1)
                    {
                        //判断小车位置是否与任务的起始储位相同,不相同:获取小车到取货储位路径
                        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 data1 = FourWayCarUtil.GetCarPath(carLocate, starLocate);
                        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 typeStr = "1";
                    var typeStr2 = 1;
                    if (waitTask.Levels  == 888 )
                    {
                        typeStr = "0";//小车任务是充电任务
                        typeStr2 = 0;
                    }
                    //获取小车去放货储位任务路径
                    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++)
                    {
                        //路径节点
                        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 + ";";
                            }
                            else
                            {
                                executionPath2 += pathXYZ + ";";
                            }
                        }
                    var data2 = FourWayCarUtil.GetCarPath(starLocate, endLocate, typeStr);
                    var datas2 = FourWayCarUtil.GetCarPathUp(data2, typeStr2);
                    if (datas2 == null)
                    {
                        continue;
                    }
                    #endregion
                    #region 判断是否有空闲小车阻挡路径 3
                    var preId3 = "";//前置任务Id
                    foreach (var item in kXCarList)
                    else
                    {
                        if (item == assignCar)
                        var bl = FourWayCarUtil.AddCarTask(datas2,kXCarList,assignCar,waitTask,1);
                        //分配错误,删除分配信息
                        if (!bl)
                        {
                            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 + ";";
                            waitTask.Status = TaskStatusEnum.Wait;
                            _db.Updateable(waitTask).ExecuteCommand();
                            var carTask = _db.Queryable<WcsCarTasks>().Where(m=>m.IsDelete == false && m.TaskNo == waitTask.TaskNo).ToList();
                            _db.Deleteable(carTask).ExecuteCommand();
                        }
                    }
                    #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;
                    _db.Updateable(waitTask).ExecuteCommand();
                    HubUtil.PublicTask(waitTask.Adapt<WcsTaskOutput>());
                    #endregion
                    Thread.Sleep(3000);
                }