wxw
6 天以前 2f263d548dc8b9e270f5f5663e80f9d4f5880b10
Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -20,8 +20,15 @@
namespace WCS.Application;
public static class PLCService
{
    private static readonly object OLock = new object();
    private static readonly object RuKuLock = new object();
    private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
    private static decimal weight94 = 0;
    private static decimal weight160 = 0;
    private static decimal weight155 = 0;
    private static decimal weight152 = 0;
    private static decimal weight153 = 0;
    public static void OnChangeEvent(object sender, EventArgs e)
    {
@@ -54,7 +61,7 @@
        {
            Log.Error(ex.Message, ex);
        }
    }
    }
    /// <summary>
    /// 跺机业务处理
    /// </summary>
@@ -69,7 +76,7 @@
                // 跺机空闲,获取出库任务、移库任务
                {
                    // 获取任务信息
                    var modTask = _db.Queryable<WcsTask>().OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime)
                    var modTask = _db.Queryable<WcsTask>().OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime, OrderByType.Asc)
                        .First(s => s.Status == TaskStatusEnum.Wait && (s.TaskType == TaskTypeEnum.Out || s.TaskType == TaskTypeEnum.Move)
                        && s.StartRoadway == modDevice.StationNum);
                    if (modTask == null)
@@ -85,6 +92,7 @@
                    PlcTaskInfo taskInfo = new PlcTaskInfo();
                    if (modTask.TaskType == TaskTypeEnum.Move)
                    {
                        // 移库目标地址
                        taskInfo = PLCCommon.GetEndPai(modTask.EndLocate.Substring(1, 2), modTask.EndLocate.Substring(2, 2),
                                    modTask.EndLocate.Substring(0, 2), modTask.EndLocate.Substring(4, 2),
                                    modTask.EndLocate.Substring(6, 2));
@@ -92,13 +100,88 @@
                    }
                    else 
                    {
                        // 根据目标地址和巷道获取放货工位对应的排列层
                        // 根据目标地址和巷道获取出库口对应的放货工位对应的排列层
                        taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(),
                            modTask.StartRoadway, modTask.EndRoadway);
                        // 目标工位不为null,需先判断放货工位是否空闲
                        if (!string.IsNullOrEmpty(taskInfo.EndStation))
                        {
                            #region 跨跺机任务处理     ###########
                            // 判断目标位置是否是跨跺机出库工位
                            if (modTask.EndLocate == "266" && modTask.StartRoadway != "R05")
                            {
                                // 判断入库工位是否存在未完成的入库任务
                                var modInTask = _db.Queryable<WcsTask>().OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime, OrderByType.Asc)
                                    .First(s => (s.Status == TaskStatusEnum.Wait || s.Status == TaskStatusEnum.Doing) && s.TaskType == TaskTypeEnum.In
                                    && s.StartLocate == modTask.EndLocate);
                                if (modInTask != null)
                                {
                                    // 目标出库口有对应的入库任务跳出循环,等待入库任务完成。
                                    break;
                                }
                                // 根据目标工位号获取输送线链接
                                var plcCconn = PLCCommon.GetPlcIp(modTask.EndLocate);
                                // 读取目标工位当前状态
                                var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == modTask.EndLocate && m.DeviceType == DeviceTypeEnum.Business);
                                var (result, value) = plcCconn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.PlcPos);
                                if (result.IsSucceed)
                                {
                                    if (value.ToString() != "120")
                                    {
                                        // 目标工位被占用跳出循环,等待工位释放。
                                        break;
                                    }
                                }
                                string aaa = PLCCommon.RoadwayToOutStationNum(modTask.StartRoadway, "1");  // 获取1楼中专工位号
                                taskInfo.Ip = PLCCommon.GetPlcIp(aaa).PlcIP;
                                taskInfo.EndPai = "2";
                                taskInfo.EndLie = "60";
                                taskInfo.EndCeng = "1";
                                taskInfo.EndStation = aaa;
                            }
                            if (modTask.EndLocate == "265" && modTask.StartRoadway != "R05" && modTask.StartRoadway != "R06")
                            {
                                // 判断入库工位是否存在未完成的入库任务
                                var modInTask = _db.Queryable<WcsTask>().OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime, OrderByType.Asc)
                                    .First(s => (s.Status == TaskStatusEnum.Wait || s.Status == TaskStatusEnum.Doing) && s.TaskType == TaskTypeEnum.In
                                    && s.StartLocate == modTask.EndLocate);
                                if (modInTask != null)
                                {
                                    // 目标出库口有对应的入库任务跳出循环,等待入库任务完成。
                                    break;
                                }
                                // 根据目标工位号获取输送线链接
                                var plcCconn = PLCCommon.GetPlcIp(modTask.EndLocate);
                                // 读取目标工位当前状态
                                var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == modTask.EndLocate && m.DeviceType == DeviceTypeEnum.Business);
                                var (result, value) = plcCconn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.PlcPos);
                                if (result.IsSucceed)
                                {
                                    if (value.ToString() != "120")
                                    {
                                        // 目标工位被占用跳出循环,等待工位释放。
                                        break;
                                    }
                                }
                                string aaa = PLCCommon.RoadwayToOutStationNum(modTask.StartRoadway, "1");  // 获取1楼中专工位号
                                taskInfo.Ip = PLCCommon.GetPlcIp(aaa).PlcIP;
                                taskInfo.EndPai = "2";
                                taskInfo.EndLie = "60";
                                taskInfo.EndCeng = "1";
                                taskInfo.EndStation = aaa;
                            }
                            // 写入放货工位固定地址
                            #endregion
                            // 打开对应的输送线连接
                            var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == taskInfo.Ip);
                            if (plcConveyorConn.Connected)
@@ -110,15 +193,19 @@
                                var (result, value) = plcConveyorConn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.PlcPos);
                                if (result.IsSucceed)
                                {
                                    if (value.ToString() != "720")              // 720:放货空位空闲,可放货
                                    if (value.ToString() != "720")              // 720:放货空位空闲,可放货  liudl 程序调试完成后放开
                                    {
                                        Log.Error(string.Format("任务号:{0}:放货工位占用,稍后执行。", modTask.TaskNo));
                                        break;
                                    }
                                    else if (value.ToString() == "720")
                                    else if (value.ToString() == "720")
                                    {
                                        // 若空闲提前占用此工位,同工位出入公用口 放开此程序
                                        // var ret = plcConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "730");
                                        var ret = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "730");
                                        if (!ret.IsSucceed)
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
@@ -133,7 +220,7 @@
                        }
                    }
                    // 获取转换后的起始排列层 06010101
                    // 获取转换后的起始排列层 06010101    // 移库时起始排列层
                    PlcTaskInfo startTaskInfo = PLCCommon.GetEndPai(modTask.StartRoadway.Substring(1, 2), modTask.StartLocate.Substring(2, 2),
                    modTask.StartLocate.Substring(0, 2), modTask.StartLocate.Substring(4, 2),
                    modTask.StartLocate.Substring(6, 2));
@@ -142,23 +229,30 @@
                    var listResult = new List<Result>();
                    // 任务号托盘号
                    var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
                    listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                    var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码");
                    listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                    // 起始排列层
                    var modPosRow = modDevice.listStation.FirstOrDefault(s => s.Text == "取货排");
                    listResult.Add(plcConn.SetPlcDBValue(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, startTaskInfo.EndPai));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, startTaskInfo.EndPai));
                    var modPosColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "取货列");
                    listResult.Add(plcConn.SetPlcDBValue(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, startTaskInfo.EndLie));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, startTaskInfo.EndLie));
                    var modPosStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "取货层");
                    listResult.Add(plcConn.SetPlcDBValue(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, startTaskInfo.EndCeng));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, startTaskInfo.EndCeng));
                    if (modTask.TaskType == TaskTypeEnum.Out)
                    {
                        var modEndNo = modDevice.listStation.FirstOrDefault(s => s.Text == "目的工位");
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modEndNo.PosType, modDevice.DbNumber, modEndNo.PlcPos, taskInfo.EndStation));
                    }
                    // 目标放货工位(固定排列层)
                    var modPosEndRow = modDevice.listStation.FirstOrDefault(s => s.Text == "放货排");
                    listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai));
                    var modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列");
                    listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie));
                    var modPosEndStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "放货层");
                    listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng));
                    // 是否写入成功
                    if (listResult.All(s => s.IsSucceed))
@@ -225,10 +319,7 @@
                {
                    // 获取跺机点位配置
                    var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (res, val) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTask.PlcPos);
                    var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位");
                    var (endStationRes, endStation) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosEndStation.PlcPos);
                    var (res, val) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos);
                    if (res.IsSucceed)
                    {
                        // 获取任务信息
@@ -236,7 +327,7 @@
                        var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false);
                        if (modTask == null)
                        {
                            Log.Error(string.Format("PLC控制字840:未找到对应的任务。"));
                            Log.Error(string.Format($"PLC控制字840:未找到对应的任务。任务号:{tasknoVal}"));
                            break;
                        }
                        // 记录任务明细
@@ -250,19 +341,24 @@
                            StartLocat = modTask.StartLocate,
                        };
                        var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位");
                        var (endRes, endStation) = plcConn.GetPlcDBValue(modPosEndStation.PosType, modDevice.DbNumber, modPosEndStation.PlcPos);
                        var modPosStartStation = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位");
                        var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Short, modDevice.DbNumber, modPosStartStation.PlcPos);
                        if (modTask.TaskType == TaskTypeEnum.In)
                        {
                            // 获取跺机起始工位点位配置,读取起始工位
                            var modPosStartStation = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位");
                            var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Short, modDevice.DbNumber, modPosStartStation.PlcPos);
                            if (startStationRes.IsSucceed)
                            {
                                // 根据工位号获取对应的输送线IP
                                PLCUtil plcConveyorConn = PLCCommon.GetPlcIp(startStationVal.ToString());
                                PLCUtil plcConveyorConn = PLCCommon.GetPlcIp(startStationVal.ToString().PadLeft(3, '0'));
                                if (plcConveyorConn.Connected)
                                {
                                    // 向取货工位写入流程字640  取货已完成
                                    var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal.ToString()
                                    var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal.ToString().PadLeft(3, '0')
                                                            && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                                    var modcTaskMonitor = new WcsTaskMonitor()
@@ -280,75 +376,159 @@
                                    var (ress, va1s) = plcConveyorConn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos);
                                    if (va1s.ToString() == "630") 
                                    {
                                        modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成:640", startStationVal);
                                        // 插入交互日志
                                        _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                    }
                                        var retc = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "640");
                                        if (retc.IsSucceed)
                                        {
                                            modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成:640", startStationVal);
                                            // 插入交互日志
                                            _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                        }
                                        else
                                        {
                                            modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成640失败", startStationVal);
                                            // 插入交互日志
                                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                            //下发任务日志
                                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                            break;
                                        }
                                    var retc = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "640");
                                    if (!retc.IsSucceed)
                                    {
                                        modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成640失败", startStationVal);
                                        // 插入交互日志
                                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        //下发任务日志
                                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        // 读取wcs控制字
                                        var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                                        if (va1ss.ToString() == "830")
                                        {
                                            modInsertTaskMonitor.InteractiveMsg = string.Format("工位:{0}跺机取货完成写入850", startStationVal);
                                            modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                                // 插入交互日志
                                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        }
                                        // 写入流程控制字
                                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                                        if (!ret.IsSucceed)
                                        {
                                            modInsertTaskMonitor.InteractiveMsg = string.Format("工位:{0}跺机取货完成写入850失败,等待再次写入。", startStationVal);
                                            modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                                // 插入交互日志
                                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                            break;              // 写入失败跳出等待再次写入
                                        }
                                        //下发任务日志
                                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    }
                                }
                            }
                        }
                        else if (modTask.TaskType == TaskTypeEnum.Out)
                        {
                            #region 跺机转运任务处理
                            if (modTask.StartRoadway != modDevice.StationNum)
                            {// 转运任务
                                // 写入起始工位640
                                string stationFrom = startStationVal.ToString();
                                var plcItemconn = PLCCommon.GetPlcIp(stationFrom);
                                if (plcItemconn.Connected)
                                {
                                    // 写入起始工位640
                                    var modFrom = PLCTaskAction.plcDevices.First(m => m.IsDelete == false && m.StationNum == stationFrom);
                                    var retFrom = plcItemconn.SetPlcDBValue(modFrom.PosType, modFrom.DbNumber, modFrom.WcsPos, "640");
                                    if (retFrom.IsSucceed)
                                    {
                                        Log.Error(stationFrom + "中转工位写入640");
                                    }
                                    else
                                    {
                                        break;
                                    }
                                    // 读取wcs控制字
                                    var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                                    if (va1ss.ToString() == "830")
                                    {
                                        // 记录任务明细
                                        modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850", modTask.StartLocate);
                                        modInsertTaskMonitor.EndLocat = endStation.ToString();                  // 放货工位
                                    }
                                    // 写入流程控制字
                                    var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                                    if (!ret.IsSucceed)
                                    {
                                        modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850失败,等待再次写入。", modTask.StartLocate);
                                        modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                            // 插入交互日志
                                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        break;              // 写入失败跳出等待再次写入
                                    }
                                    //下发任务日志
                                    HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                }
                            }
                            else
                            {
                                //if (modTask.EndLocate == "266" && modTask.StartRoadway == "R06")
                                //{
                                //    // R06巷道单独转运任务。
                                //    // 写入起始工位640
                                //    string stationFrom = startStationVal.ToString();
                                //    var plcItemconn = PLCCommon.GetPlcIp(stationFrom);
                                //    var modFrom = PLCTaskAction.plcDevices.First(m => m.IsDelete == false && m.StationNum == stationFrom);
                                //    var retFrom = plcItemconn.SetPlcDBValue(modFrom.PosType, modFrom.DbNumber, modFrom.WcsPos, "640");
                                //    if (retFrom.IsSucceed)
                                //    {
                                //        Log.Error(stationFrom + "中转工位写入640");
                                //    }
                                //    else
                                //    {
                                //        break;
                                //    }
                                // 读取wcs控制字
                                var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                                if (va1ss.ToString() == "830")
                                {
                                    modInsertTaskMonitor.InteractiveMsg = string.Format("工位:{0}跺机取货完成写入850", startStationVal);
                                    modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                        // 插入交互日志
                                    _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                }
                                //    // 读取wcs控制字
                                //    var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                                //    if (va1ss.ToString() == "830")
                                //    {
                                //        // 记录任务明细
                                //        modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850", modTask.StartLocate);
                                //        modInsertTaskMonitor.EndLocat = endStation.ToString();                  // 放货工位
                                //    }
                                //    // 写入流程控制字
                                //    var ret11 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                                //    if (!ret11.IsSucceed)
                                //    {
                                //        modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850失败,等待再次写入。", modTask.StartLocate);
                                //        modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                //                                                                            // 插入交互日志
                                //        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                //        break;              // 写入失败跳出等待再次写入
                                //    }
                                //    //下发任务日志
                                //    HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                //    break;
                                //}
                                // 写入流程控制字
                                var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                                if (!ret.IsSucceed)
                                {
                                    modInsertTaskMonitor.InteractiveMsg = string.Format("工位:{0}跺机取货完成写入850失败,等待再次写入。", startStationVal);
                                    modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                        // 插入交互日志
                                    _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                    break;              // 写入失败跳出等待再次写入
                                }
                                modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate);
                                modInsertTaskMonitor.EndLocat = endStation;                  // 目标储位
                                // 插入交互日志
                                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                //下发任务日志
                                HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                        }
                        else if (modTask.TaskType == TaskTypeEnum.Out)
                        {
                            // 读取wcs控制字
                            var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                            if (va1ss.ToString() == "830")
                            {
                                // 记录任务明细
                                modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850", modTask.StartLocate);
                                modInsertTaskMonitor.EndLocat = endStation;                  // 放货工位
                            }
                            // 写入流程控制字
                            var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                            if (!ret.IsSucceed)
                            {
                                modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850失败,等待再次写入。", modTask.StartLocate);
                                modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                    // 插入交互日志
                                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                break;              // 写入失败跳出等待再次写入
                            }
                            //下发任务日志
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            #endregion
                        }
                        else
                        {
@@ -360,7 +540,7 @@
                            }
                            modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate);
                            modInsertTaskMonitor.EndLocat = endStation;                  // 目标储位
                            modInsertTaskMonitor.EndLocat = endStation.ToString();                  // 目标储位
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
@@ -371,11 +551,11 @@
                    }
                }
                break;
            case "860":
            case "860":         //跺机放货完成
                {
                    // 获取跺机点位配置
                    var modPos860Task = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (res, val) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPos860Task.PlcPos);
                    var (res, val) = plcConn.GetPlcDBValue(modPos860Task.PosType, modDevice.DbNumber, modPos860Task.PlcPos);
                    // 根据任务号获取任务信息
                    if (res.IsSucceed)
                    {
@@ -391,6 +571,86 @@
                        {
                            case TaskTypeEnum.In:
                                {
                                    #region 跨跺机转运任务处理#####
                                    // 判断是否跨跺机转运任务
                                    var modPos860endAddre = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位");
                                    var (ress, endVal) = plcConn.GetPlcDBValue(modPos860endAddre.PosType, modDevice.DbNumber, modPos860endAddre.PlcPos);
                                    string endValStr = endVal.ToString().PadLeft(3, '0');
                                    // 根据巷道、层数获取入库放货工位
                                    var inVal = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, "1");
                                    var inVal1 = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, "2", modTask.StartLocate.ToString());
                                    // 根据当前跺机放货工位对比目标巷道入库取货工位做对比确认是否转运任务。
                                    if (endValStr != inVal && endValStr != inVal1)
                                    {
                                        // 根据工位号获取输送线链接
                                        var plcCconn = PLCCommon.GetPlcIp(endValStr);
                                        if (plcCconn.Connected)
                                        {
                                            // 写入转运信息
                                            // 给PLC写入任务数据
                                            var listResult = new List<Result>();
                                            // 根据工位号获取工位信息
                                            var wcsDevice = PLCTaskAction.plcDevices.First(s => s.PlcId == plcCconn.PlcId && s.Level == DeviceLevelEnum.Station && s.StationNum == endValStr);
                                            // 读取当前工位各偏移量值
                                            var listPos = PLCTaskAction.plcPositions.Where(s => s.DeviceId == wcsDevice.Id).ToList();
                                            //任务号
                                            var modPosTask = listPos.FirstOrDefault(s => s.Text == "任务号");
                                            listResult.Add(plcCconn.SetPlcDBValueRepeat(modPosTask.PosType, wcsDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                                            //任务类型
                                            var modPosTaskType = listPos.FirstOrDefault(s => s.Text == "任务类型");
                                            listResult.Add(plcCconn.SetPlcDBValueRepeat(modPosTaskType.PosType, wcsDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString()));
                                            //托盘号
                                            var modPosPalletNo = listPos.FirstOrDefault(s => s.Text == "托盘码");
                                            listResult.Add(plcCconn.SetPlcDBValueRepeat(modPosPalletNo.PosType, wcsDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                                            //起始工位
                                            var modPosLocatNo = listPos.FirstOrDefault(s => s.Text == "起始工位");
                                            listResult.Add(plcCconn.SetPlcDBValueRepeat(modPosLocatNo.PosType, wcsDevice.DbNumber, modPosLocatNo.PlcPos, endValStr));
                                            // 目标工位
                                            var modPosEndLocatNo = listPos.FirstOrDefault(s => s.Text == "目的工位");
                                            listResult.Add(plcCconn.SetPlcDBValueRepeat(modPosEndLocatNo.PosType, wcsDevice.DbNumber, modPosEndLocatNo.PlcPos, inVal));
                                            // 是否写入成功
                                            if (listResult.All(s => s.IsSucceed))
                                            {
                                                var result = plcCconn.SetPlcDBValue(wcsDevice.PosType, wcsDevice.DbNumber, wcsDevice.WcsPos, "740");
                                                if (result.IsSucceed)
                                                {
                                                    // 写入跺机wcs控制字 返回垛机执行完成
                                                    result = modDevice.PLCUtil.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870");
                                                    if (result.IsSucceed)
                                                    {
                                                        var modcTaskMonitor = new WcsTaskMonitor()
                                                        {
                                                            TaskNo = modTask.TaskNo,
                                                            PlcId = wcsDevice.Id,
                                                            PlcName = wcsDevice.Text,
                                                            PalletNo = modTask.PalletNo,
                                                            Status = TaskStatusEnum.Complete,
                                                            StartLocat = "",
                                                            EndLocat = modTask.EndRoadway,
                                                            InteractiveMsg = $"写入指令:收到跺机放货完成;放货{endValStr}工位===》{inVal}工位"
                                                        };
                                                        // 插入交互日志
                                                        _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                                        //下发任务日志
                                                        HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    // 向工位写入,当前工位到目标巷道入库取货工位流程。写入流程控制字"740"
                                    #endregion
                                    var res870 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870");
                                    if (!res870.IsSucceed)
                                    {
@@ -462,15 +722,51 @@
                                    string roadway = modTask.StartRoadway;
                                    // 从出库任务获取放货工位
                                    string outCode = modTask.EndLocate;
                                    #region 跨跺机转运任务  ##########
                                    var modPosStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位");
                                    var (ress, stationNum) = plcConn.GetPlcDBValue(modPosStation.PosType, modDevice.DbNumber, modPosStation.PlcPos);
                                    if (!ress.IsSucceed)
                                    {
                                        // 获取当前托盘所在工位失败
                                        break;
                                    }
                                    // 根据目标地址和巷道获取放货工位对应的排列层
                                    PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(),
                                        modTask.StartRoadway, modTask.EndRoadway);
                                    string stationNumstr = stationNum.ToString();
                                    if (!taskInfo.EndStation.Contains(stationNumstr) && stationNumstr != "0")
                                    { // 是跺机中专工位
                                        //taskInfo.EndStation = stationNumstr;
                                        string roadwayto = "R05";
                                        // 根据出库口放货工位获取对应的中转巷道
                                        if (taskInfo.EndStation.Contains("277"))
                                        {
                                            roadwayto = "R05";
                                        }
                                        else if (taskInfo.EndStation.Contains("250"))
                                        {
                                            roadwayto = "R06";
                                        }
                                        // 根据层数和巷道数确定中专工位
                                        outCode = PLCCommon.RoadwayToStationNum(roadwayto, "1");
                                    }
                                    #endregion
                                    // 根据工位号获取对应的输送线IP
                                    var plcConveyorConn = PLCCommon.GetPlcIp(outCode);
                                    var plcConveyorConn = PLCCommon.GetPlcIp(stationNumstr);
                                    if (plcConveyorConn.Connected)
                                    {
                                        // 根据目标地址和巷道获取放货工位对应的排列层
                                        PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(),
                                            modTask.StartRoadway, modTask.EndRoadway);
                                        stationNumstr = stationNumstr.PadLeft(3, '0');
                                        // 根据工位号获取工位信息
                                        var wcsDevice = PLCTaskAction.plcDevices.First(s => s.PlcId == plcConveyorConn.PlcId && s.Level == DeviceLevelEnum.Station && s.StationNum == taskInfo.EndStation);
                                        var wcsDevice = PLCTaskAction.plcDevices.First(s => s.PlcId == plcConveyorConn.PlcId
                                                && s.Level == DeviceLevelEnum.Station && s.StationNum == stationNumstr);
                                        // 读取当前工位各偏移量值
                                        var listPos = PLCTaskAction.plcPositions.Where(s => s.DeviceId == wcsDevice.Id).ToList();
@@ -478,19 +774,19 @@
                                        var listResult = new List<Result>();
                                        //任务号
                                        var modPosTask = listPos.FirstOrDefault(s => s.Text == "任务号");
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosTask.PosType, wcsDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                                        listResult.Add(plcConveyorConn.SetPlcDBValueRepeat(modPosTask.PosType, wcsDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                                        //任务类型
                                        var modPosTaskType = listPos.FirstOrDefault(s => s.Text == "任务类型");
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosTaskType.PosType, wcsDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString()));
                                        listResult.Add(plcConveyorConn.SetPlcDBValueRepeat(modPosTaskType.PosType, wcsDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString()));
                                        //托盘号
                                        var modPosPalletNo = listPos.FirstOrDefault(s => s.Text == "托盘码");
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosPalletNo.PosType, wcsDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                                        listResult.Add(plcConveyorConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, wcsDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                                        //起始工位
                                        var modPosLocatNo = listPos.FirstOrDefault(s => s.Text == "起始工位");
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosLocatNo.PosType, wcsDevice.DbNumber, modPosLocatNo.PlcPos, taskInfo.EndStation));
                                        listResult.Add(plcConveyorConn.SetPlcDBValueRepeat(modPosLocatNo.PosType, wcsDevice.DbNumber, modPosLocatNo.PlcPos, stationNumstr));
                                        // 目标工位
                                        var modPosEndLocatNo = listPos.FirstOrDefault(s => s.Text == "目的工位");
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosEndLocatNo.PosType, wcsDevice.DbNumber, modPosEndLocatNo.PlcPos, outCode));
                                        listResult.Add(plcConveyorConn.SetPlcDBValueRepeat(modPosEndLocatNo.PosType, wcsDevice.DbNumber, modPosEndLocatNo.PlcPos, outCode));
                                        // 是否写入成功
                                        if (listResult.All(s => s.IsSucceed))
@@ -512,7 +808,7 @@
                                                        Status = TaskStatusEnum.Complete,
                                                        StartLocat = taskInfo.EndStation,
                                                        EndLocat = outCode,
                                                        InteractiveMsg = $"写入指令:收到跺机放货完成;放货{taskInfo.EndStation}工位===》{outCode}出库口"
                                                        InteractiveMsg = $"写入指令:收到跺机放货完成;放货{taskInfo.EndStation}工位===》{outCode}工位"
                                                    };
                                                    // 插入交互日志
                                                    _db.Insertable(modcTaskMonitor).ExecuteCommand();
@@ -530,7 +826,7 @@
                            case TaskTypeEnum.Move:       // 移库任务
                                {
                                    var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
                                    var result = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo);
                                    var result = plcConn.SetPlcDBValueRepeat(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo);
                                    if (!result.IsSucceed)
                                    {
                                        Log.Error($"{modDevice.Text}写入任务号失败");
@@ -685,15 +981,15 @@
                        // 给PLC写入任务数据
                        var listResult = new List<Result>();
                        // 任务号托盘号
                        listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                        listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                        // 起始排列层
                        listResult.Add(plcConn.SetPlcDBValue(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, "2"));
                        listResult.Add(plcConn.SetPlcDBValue(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, "100"));
                        listResult.Add(plcConn.SetPlcDBValue(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, "1"));
                        listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, row));
                        listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, column));
                        listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, storey));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, "2"));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, "100"));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, "1"));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, row));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, column));
                        listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, storey));
                        // 是否写入成功
                        if (listResult.All(s => s.IsSucceed))
                        {
@@ -730,6 +1026,7 @@
                break;
        }
    }
    /// <summary>
    /// 不空跑
    /// </summary>
@@ -814,25 +1111,25 @@
            var listResult = new List<Result>();
            // 任务号托盘号
            var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
            listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
            var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码");
            listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
            // 起始排列层
            var modPosRow = modDevice.listStation.FirstOrDefault(s => s.Text == "取货排");
            listResult.Add(plcConn.SetPlcDBValue(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, startTaskInfo.EndPai));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, startTaskInfo.EndPai));
            var modPosColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "取货列");
            listResult.Add(plcConn.SetPlcDBValue(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, startTaskInfo.EndLie));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, startTaskInfo.EndLie));
            var modPosStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "取货层");
            listResult.Add(plcConn.SetPlcDBValue(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, startTaskInfo.EndCeng));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, startTaskInfo.EndCeng));
            // 目标放货工位(固定排列层)
            PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(),
                        modTask.StartRoadway, modTask.EndRoadway);
            var modPosEndRow = modDevice.listStation.FirstOrDefault(s => s.Text == "放货排");
            listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai));
            var modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列");
            listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie));
            var modPosEndStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "放货层");
            listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng));
            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng));
            // 是否写入成功
            if (listResult.All(s => s.IsSucceed))
@@ -901,29 +1198,214 @@
        {
            return;
        }
        #region#实时显示重量到LED屏幕
        var modPosPalletWeightIng = modDevice.listStation.FirstOrDefault(m => m.Text == "实际重量");
        if (modPosPalletWeightIng != null)
        {
            var (resPalletWeightIng, palletWeightValIng) = plcConn.GetPlcDBValue(modPosPalletWeightIng.PosType, modDevice.DbNumber, modPosPalletWeightIng.PlcPos);
            switch (modDevice.StationNum)
            {
                case "094":
                    {
                        if (Convert.ToDecimal(palletWeightValIng) != weight94)
                        {
                            LedDisplay(modDevice.LedIP, $"当前重量(KG):{Convert.ToDecimal(palletWeightValIng)}");
                            weight94 = Convert.ToDecimal(palletWeightValIng);
                        }
                    }
                    break;
                case "160":
                    {
                        if (Convert.ToDecimal(palletWeightValIng) != weight160)
                        {
                            LedDisplay(modDevice.LedIP, $"当前重量(KG):{Convert.ToDecimal(palletWeightValIng)}");
                            weight160 = Convert.ToDecimal(palletWeightValIng);
                        }
                    }
                    break;
                case "155":
                    {
                        if (Convert.ToDecimal(palletWeightValIng) != weight155)
                        {
                            LedDisplay(modDevice.LedIP, $"当前重量(KG):{Convert.ToDecimal(palletWeightValIng)}");
                            weight155 = Convert.ToDecimal(palletWeightValIng);
                        }
                    }
                    break;
                case "152":
                    {
                        if (Convert.ToDecimal(palletWeightValIng) != weight152)
                        {
                            LedDisplay(modDevice.LedIP, $"当前重量(KG):{Convert.ToDecimal(palletWeightValIng)}");
                            weight152 = Convert.ToDecimal(palletWeightValIng);
                        }
                    }
                    break;
                case "153":
                    {
                        if (Convert.ToDecimal(palletWeightValIng) != weight153)
                        {
                            LedDisplay(modDevice.LedIP, $"当前重量(KG):{Convert.ToDecimal(palletWeightValIng)}");
                            weight153 = Convert.ToDecimal(palletWeightValIng);
                        }
                    }
                    break;
            }
        }
        #endregion
        var ledText = "";
        switch (modDevice.Value.ToString())
        {
            case "120":
                { // 120:空闲; wcs调度小车写130请求放(占住工位)
                } break;
            case "140":
                {  // 140:可放;写入任务号等交互信息最后写入150正在放;   wcs接受wms发送的小车任务完成信号后变更为:160:
                    var http = new HttpService();
                    var modResponseTask = http.IssuedAgvTask(modDevice.StationNum).Result;
                    if (modResponseTask.StatusCode == 0)
                    {
                        plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "150");
                    }
                } break;
            case "230":
                { // 230:托盘输送到位,请求小车;  WCS向WMS申请小车输送WMS返回成功;写入240  ;
                } break;
            case "310":
                //入库申请PLC出现异常(托盘超宽、超高等)
                {
                    plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "311");
                    string dbStr = "";
                    switch (modDevice.StationNum)
                    {
                        case "094":
                                dbStr = "2381";
                            break;
                        case "160":
                            dbStr = "2385";
                            break;
                        case "155":
                            dbStr = "2383";
                            break;
                        case "152":
                            dbStr = "2401";
                            break;
                        case "153":
                            dbStr = "2403";
                            break;
                    }
                    string errorStr = string.Empty;
                    //将异常信息显示到LED屏幕上
                    var (errorRes0, errorVal0) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.0", "");
                    if (errorRes0.IsSucceed && errorVal0 == true)
                    {
                        errorStr += " 扫码失败";
                    }
                    var (errorRes1, errorVal1) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.1", "");
                    if (errorRes1.IsSucceed && errorVal1 == true)
                    {
                        errorStr += " 称重失败";
                    }
                    var (errorRes2, errorVal2) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.2", "");
                    if (errorRes2.IsSucceed && errorVal2 == true)
                    {
                        errorStr += " 垛型左超宽";
                    }
                    var (errorRes3, errorVal3) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.3", "");
                    if (errorRes3.IsSucceed && errorVal3 == true)
                    {
                        errorStr += " 垛型右超宽";
                    }
                    var (errorRes4, errorVal4) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.4", "");
                    if (errorRes4.IsSucceed && errorVal4 == true)
                    {
                        errorStr += " 垛型前超长";
                    }
                    var (errorRes5, errorVal5) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.5", "");
                    if (errorRes5.IsSucceed && errorVal5 == true)
                    {
                        errorStr += " 垛型后超长";
                    }
                    var (errorRes6, errorVal6) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.6", "");
                    if (errorRes6.IsSucceed && errorVal6 == true)
                    {
                        errorStr += " 垛型后超高";
                    }
                    var (errorRes7, errorVal7) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{dbStr}.7", "");
                    if (errorRes7.IsSucceed && errorVal7 == true)
                    {
                        errorStr += " 高低位异常报警";
                    }
                    var (errorRes9, errorVal9) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Bit, $"M{Convert.ToUInt32(dbStr)-1}.1", "");
                    if (errorRes9.IsSucceed && errorVal9 == true)
                    {
                        errorStr += " 扫码仪通讯报警";
                    }
                    if (!string.IsNullOrEmpty(errorStr))
                    {
                        errorStr = "异常信息:" + errorStr;
                        ledText += $"申请入库失败\n\n";
                        ledText += $"{errorStr}";
                        LedDisplay(modDevice.LedIP, ledText);
                    }
                }
                break;
            case "320":
                {
                    //防止重复申请
                    var (res0, Val0) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                    if (res0.IsSucceed && Val0 != 0)
                    {
                        break;
                    }
                    // 申请巷道
                    string strMsg = "";
                    string taskModel = "";
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    var (res, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                    if (!res.IsSucceed)
                    {
                        break;
                    }
                    string palletStr = Convert.ToString(palletVal);
                    var modPosEndLocat = modDevice.listStation.FirstOrDefault(s => s.Text == "目的工位");
                    //获取托盘高度
                    var modPosPalletHeight = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘高度");
                    var (resPalletHeight, palletHeightVal) = plcConn.GetPlcDBValue(modPosPalletHeight.PosType, modDevice.DbNumber, modPosPalletHeight.PlcPos);
                    if (!resPalletHeight.IsSucceed)
                    {
                        break;
                    }
                    //获取托盘实际重量
                    var modPosPalletWeight = modDevice.listStation.FirstOrDefault(m => m.Text == "实际重量");
                    var (resPalletWeight, palletWeightVal) = plcConn.GetPlcDBValue(modPosPalletWeight.PosType, modDevice.DbNumber, modPosPalletWeight.PlcPos);
                    //判断入库锁定是否打开
                    if (PLCTaskAction.boEnterLock)
                    {
                        var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                        var (res350, palletVal350) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                        if (res350.IsSucceed && palletVal350 != "350") 
                        {
                            ledText += $"申请入库失败\n\n";
@@ -933,7 +1415,7 @@
                        }
                        // 写入输送线退回指令
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                        var ret = plcConn.SetPlcDBValueRepeat(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                        if (ret.IsSucceed) 
                        {
                            plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350");
@@ -944,7 +1426,7 @@
                    if (palletVal == null) 
                    {
                        var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                        var (res350, palletVal350) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                        if (res350.IsSucceed && palletVal350 != "350")
                        {
                            ledText += $"申请入库失败\n\n";
@@ -954,7 +1436,7 @@
                        }
                        // 写入输送线退回指令
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                        var ret = plcConn.SetPlcDBValueRepeat(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                        if (ret.IsSucceed)
                        {
                            plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350");
@@ -965,7 +1447,28 @@
                    var http = new HttpService();
                    string TaskNo = "", EndLocate = "";
                    strMsg = http.RequestRoadWay(palletVal, modDevice.StationNum, taskModel, louCeng, ref EndLocate, ref TaskNo);
                    //根据工位判断是否为叠托机工位申请空托盘跺入库,是:向WMS申请空托盘跺组托
                    string groupMsg = "";
                    if (modDevice.StationNum == "72")
                    {
                        groupMsg = http.BindNullPalletWcs(10, palletVal);
                        if (groupMsg.Contains("-1"))
                        {
                            // 写入输送线退回指令
                            var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                            if (ret.IsSucceed)
                            {
                                plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350");
                            }
                            break;
                        }
                    }
                    //向WMS申请巷道
                    strMsg = http.RequestRoadWay(palletVal, modDevice.StationNum, taskModel, louCeng, ref EndLocate, ref TaskNo, (int)palletHeightVal);
                    if (!strMsg.Contains("-1"))
                    {
@@ -1002,10 +1505,11 @@
                                ledText += $"任务类型:{taskInfo.TaskType.GetDescription()}\n\n";
                                ledText += $"任务号:{taskInfo.TaskNo}\n";
                                ledText += $"托盘号:{taskInfo.PalletNo}\n\n";
                                ledText += $"托盘号:{taskInfo.PalletNo}\n";
                                ledText += $"起始位:{taskInfo.StartRoadway + " " + taskInfo.StartLocate}\n";
                                ledText += $"目标位:{taskInfo.EndRoadway + " " + taskInfo.EndLocate}";
                                ledText += $"目标位:{taskInfo.EndRoadway + " " + taskInfo.EndLocate}\n";
                                ledText += $"重量(KG):{Convert.ToDecimal(palletWeightVal)}";
                                LedDisplay(modDevice.LedIP, ledText);
                                
                            }
@@ -1013,13 +1517,11 @@
                            {
                                Log.Error(ex.Message);
                            }
                        }
                    }
                    else
                    {
                        var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                        var (res350, palletVal350) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                        if (res350.IsSucceed && palletVal350 != "350")
                        {
                            ledText += $"申请入库失败\n\n";
@@ -1029,7 +1531,7 @@
                        }
                        // 写入输送线退回指令
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                        var ret = plcConn.SetPlcDBValueRepeat(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum);
                        if (ret.IsSucceed)
                        {
                            plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350");
@@ -1043,11 +1545,12 @@
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    var (res, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                    if (!res.IsSucceed)
                    {
                        break;
                    }
                    string pallet = palletVal.ToString();
                    // 获取任务信息
                    var modTask = _db.Queryable<WcsTask>().First(s => s.IsDelete == false && s.PalletNo == pallet && (s.Status == TaskStatusEnum.Wait || s.Status == TaskStatusEnum.Doing) && s.TaskType == TaskTypeEnum.In);
@@ -1063,26 +1566,79 @@
                    }
                    // 获取巷道口入库工位
                    string endLocatVlue = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, louCeng);
                    string endLocatVlue = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, louCeng, modDevice.StationNum);
                    #region 跺机转运任务处理  ##########
                    // 判断是否四楼输送线
                    if (modDevice.StationNum == "265")
                    {   // 是
                        if (modTask.EndRoadway != "R05" && modTask.EndRoadway != "R06")
                        {
                            // 根据巷道获取中转跺机IP   ### R05巷道
                            var sInfo = PLCCommon.GetStokePlc("R05", louCeng);
                            var plcStackeConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfo.Ip);
                            if (plcStackeConn.Connected)
                            {
                                var djmodel = _db.Queryable<WcsPlc>().First(m => m.IP == sInfo.Ip);
                                var djMod = PLCTaskAction.plcDevices.First(m => m.PlcId == djmodel.Id
                                    && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                                var (djRes, djVal) = plcStackeConn.GetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.PlcPos);
                                // 判断R05跺机是否空闲
                                if (djRes.IsSucceed && djVal.ToString() == "820")
                                {
                                    endLocatVlue = "253";
                                }
                            }
                            // 根据巷道获取中转跺机IP   ### R06巷道
                            var sInfoR06 = PLCCommon.GetStokePlc("R06", louCeng);
                            var plcStackeConnR06 = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfoR06.Ip);
                            if (plcStackeConnR06.Connected)
                            {
                                var djmodel = _db.Queryable<WcsPlc>().First(m => m.IP == sInfoR06.Ip);
                                var djMod = PLCTaskAction.plcDevices.First(m => m.PlcId == djmodel.Id
                                    && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                                var (djRes, djVal) = plcStackeConnR06.GetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.PlcPos);
                                // 判断R05跺机是否空闲
                                if (djRes.IsSucceed && djVal.ToString() == "820")
                                {
                                    endLocatVlue = "250";
                                }
                            }
                        }
                    }
                    if (modDevice.StationNum == "266")
                    {   // 是
                        if (modTask.EndRoadway != "R05")
                        {
                            endLocatVlue = "277";
                        }
                    }
                    #endregion
                    // 给PLC写入任务数据
                    var listResult = new List<Result>();
                    // 任务号、任务类型、托盘号
                    var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
                    listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                    var modPosTaskType = modDevice.listStation.FirstOrDefault(s => s.Text == "任务类型");
                    var taskTypeStr = (int)modTask.TaskType;
                    listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                    var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码");
                    listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                    // 起始工位、目的工位
                    var modPosStrLocat = modDevice.listStation.FirstOrDefault(s => s.Text == "起始工位");
                    listResult.Add(plcConn.SetPlcDBValue(modPosStrLocat.PosType, modDevice.DbNumber, modPosStrLocat.PlcPos, modDevice.StationNum));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosStrLocat.PosType, modDevice.DbNumber, modPosStrLocat.PlcPos, modDevice.StationNum));
                    var modPosEndLocat = modDevice.listStation.FirstOrDefault(s => s.Text == "目的工位");
                    listResult.Add(plcConn.SetPlcDBValue(modPosEndLocat.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, endLocatVlue));
                    listResult.Add(plcConn.SetPlcDBValueRepeat(modPosEndLocat.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, endLocatVlue));
                    if (listResult.All(s => s.IsSucceed))
                    {
                    {
                        Log.Information($"写入340,任务号:{modTask.TaskNo},任务类型:{taskTypeStr.ToString()},托盘码:{modTask.PalletNo},起始工位:{modDevice.StationNum},目的工位:{endLocatVlue}");
                        // 将任务状态变更为正在执行
                        _db.Updateable<WcsTask>()
                           .SetColumns(s => s.Status == TaskStatusEnum.Doing)
@@ -1118,7 +1674,6 @@
                        }
                    }
                }
                break;
            case "620":
@@ -1141,22 +1696,138 @@
                    }
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    var (res, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                    if (!res.IsSucceed)
                    {
                        break;
                    }
                    #region 跺机转运任务处理  ###########
                    // 根据任务目标巷道号获取工位号
                    var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (ress, endTaskNoVal) = plcConn.GetPlcDBValue(modPosEndStation.PosType, modDevice.DbNumber, modPosEndStation.PlcPos);
                    if (!ress.IsSucceed)
                    {
                        break;
                    }
                    string taskno = endTaskNoVal;
                    var taskInfo2 = _db.Queryable<WcsTask>().First(w => w.TaskNo == taskno);         // 根据任务号获取当前任务目标巷道
                    if (taskInfo2 == null)
                    {
                        break;
                    }
                    string roadwayNo = PLCCommon.GetRoadwayByStation(modDevice.StationNum);         // 当前工位对应的巷道号
                    // 判断是否入库转运任务
                    if (roadwayNo != taskInfo2.EndRoadway && taskInfo2.TaskType == TaskTypeEnum.In)
                    {// 是
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "630");
                        if (ret.IsSucceed)
                        {
                            var modPosTaskNo = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                            var (resss, taskNoVal) = plcConn.GetPlcDBValue(modPosEndStation.PosType, modDevice.DbNumber, modPosEndStation.PlcPos);
                            if (!resss.IsSucceed)
                            {
                                break;
                            }
                            string taskNo = taskNoVal.ToString();
                            var taskInfos = _db.Queryable<WcsTask>().First(w => w.TaskNo == taskNo);
                            modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == taskInfos.StartLocate).Select(s => s.LedIP).First();
                            // 插入任务明细
                            var modInsertTaskMonitor = new WcsTaskMonitor()
                            {
                                TaskNo = taskNo,
                                PlcId = modDevice.Id,
                                PlcName = modDevice.Text,
                                InteractiveMsg = $"写入指令630:开启跺机转运任务",
                                PalletNo = palletVal,
                                Status = TaskStatusEnum.Complete,
                                StartLocat = modDevice.StationNum,
                                EndLocat = strMsg,
                            };
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            // 通知任务界面任务已存在更新 请更新界面
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business);
                            ledText += $"任务类型:{taskInfos.TaskType.GetDescription()}\n\n";
                            ledText += $"任务号:{taskInfos.TaskNo}\n";
                            ledText += $"托盘号:{taskInfos.PalletNo}\n\n";
                            ledText += $"起始位:{taskInfos.StartRoadway + " " + taskInfos.StartLocate}\n";
                            ledText += $"目标位:{taskInfos.EndRoadway + " " + taskInfos.EndLocate}";
                            LedDisplay(modDevice.LedIP, ledText);
                        }
                        break;
                    }
                    // 判断是否出库转运任务
                    var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (res1, taskVal) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos);
                    if (res1.IsSucceed)
                    {
                        string taskNo = taskVal.ToString();
                        var taskInfos = _db.Queryable<WcsTask>().First(w => w.TaskNo == taskNo);
                        if (taskInfos.TaskType == TaskTypeEnum.Out)
                        {
                            var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "630");
                            if (!ret.IsSucceed)
                            {
                                break;
                            }
                            modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == taskInfos.EndLocate).Select(s => s.LedIP).First();
                            // 插入任务明细
                            var modInsertTaskMonitor = new WcsTaskMonitor()
                            {
                                TaskNo = taskNo,
                                PlcId = modDevice.Id,
                                PlcName = modDevice.Text,
                                InteractiveMsg = $"写入指令630:开启跺机转运任务",
                                PalletNo = palletVal,
                                Status = TaskStatusEnum.Complete,
                                StartLocat = modDevice.StationNum,
                                EndLocat = strMsg,
                            };
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            // 通知任务界面任务已存在更新 请更新界面
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business);
                            ledText += $"任务类型:{taskInfos.TaskType.GetDescription()}\n\n";
                            ledText += $"任务号:{taskInfos.TaskNo}\n";
                            ledText += $"托盘号:{taskInfos.PalletNo}\n\n";
                            ledText += $"起始位:{taskInfos.StartRoadway + " " + taskInfos.StartLocate}\n";
                            ledText += $"目标位:{taskInfos.EndRoadway + " " + taskInfos.EndLocate}";
                            LedDisplay(modDevice.LedIP, ledText);
                            break;
                        }
                    }
                    else { break; }
                    #endregion
                    var http = new HttpService();
                    string TaskNo = "";
                    // 向WMS申请储位信息
                    strMsg = http.RequestLocate(palletVal, modDevice.StationNum, taskModel, roadway, ref TaskNo);
                    string TaskNo = "";
                    lock (RuKuLock)
                    {
                        // 向WMS申请储位信息
                        strMsg = http.RequestLocate(palletVal, modDevice.StationNum, taskModel, roadway, ref TaskNo, (int)taskInfo2.PalletQty);
                    }
                    // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。
                    var taskInfo = _db.Queryable<WcsTask>().First(w => w.TaskNo == TaskNo);
                    modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == taskInfo.StartLocate).Select(s => s.LedIP).First();
                    if (!strMsg.Contains("-1"))
                    {
                    {
                        // 写入流程字 630
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "630");
@@ -1205,14 +1876,14 @@
                break;
            case "630":
                {
                    #region 写入跺机取货任务 640
                    #region 写入跺机取货任务 不用写入640垛取货完成后会写
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    var (res, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                    // 获取工位任务号信息
                    var modPosTaskNo = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (taskRes, taskNoVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTaskNo.PlcPos);
                    var (taskRes, taskNoVal) = plcConn.GetPlcDBValue(modPosTaskNo.PosType, modDevice.DbNumber, modPosTaskNo.PlcPos);
                    if (!res.IsSucceed || !taskRes.IsSucceed)
                    {
                        break;
@@ -1220,14 +1891,274 @@
                    string pallet = palletVal.ToString();
                    string taskNo = taskNoVal.ToString();
                    // 获取任务信息
                    var modTask = _db.Queryable<WcsTask>().First(s => s.IsDelete == false && s.PalletNo == pallet && s.Status == TaskStatusEnum.Doing && s.TaskType == TaskTypeEnum.In && s.TaskNo == taskNo);
                    var modTask = _db.Queryable<WcsTask>().First(s => s.IsDelete == false && s.PalletNo == pallet && s.Status == TaskStatusEnum.Doing  && s.TaskNo == taskNo);
                    if (modTask == null)
                    {
                        // 此托盘没有对应的转移任务 led显示
                        break;
                    }
                    var sInfo = PLCCommon.GetStokePlc(modTask.EndRoadway, louCeng);
                    #region 跺机转运任务处理  ###########
                    string taskno = taskNoVal;
                    string roadwayNo = PLCCommon.GetRoadwayByStation(modDevice.StationNum);         // 当前工位对应的巷道号
                    // 获取当前工位目标地址
                    var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位");
                    var (ress, endStationVal) = plcConn.GetPlcDBValue(modPosEndStation.PosType, modDevice.DbNumber, modPosEndStation.PlcPos);
                    if (!ress.IsSucceed)
                    {
                        break;
                    }
                    if (modTask.EndRoadway == null)
                    {
                        modTask.EndRoadway = "";
                    }
                    var sInfo = PLCCommon.GetStokePlc(roadwayNo, louCeng, modDevice.StationNum); // 根据当前巷道获取跺机信息
                    // 判断是否入库转运任务
                    // 判断是否入库转运任务
                    if (roadwayNo != modTask.EndRoadway && modTask.TaskType == TaskTypeEnum.In)
                    {// 是
                        // 根据当前工位号,获取对应的取货排列层
                        sInfo = PLCCommon.GetStokePlc(roadwayNo, louCeng, modDevice.StationNum);
                        // 判断1层放货工位状态是否空闲
                        var endStationNum = PLCCommon.RoadwayToOutStationNum(roadwayNo, "1");
                        var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == endStationNum
                                                            && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                        var plcConveyorConn = PLCCommon.GetPlcIp(endStationNum);
                        if (plcConveyorConn.Connected)
                        {
                            // 读取1楼放货工位状态
                            var (reouts, plcVal) = plcConveyorConn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.PlcPos);
                            if (reouts.IsSucceed)
                            {
                                //if (plcVal.ToString() != "720")
                                //{
                                //    // 1层放货工位占用,等待放货工位释放
                                //    break;
                                //}
                                // 判断跺机是否空闲
                                var plcSConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfo.Ip);
                                if (plcSConn.Connected)
                                {
                                    var djmodel = _db.Queryable<WcsPlc>().First(m => m.IP == sInfo.Ip);
                                    var djMod = PLCTaskAction.plcDevices.First(m => m.PlcId == djmodel.Id
                                        && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                                    var djInfos = PLCTaskAction.plcPositions.Where(m => m.IsDelete == false && m.DeviceId == djMod.Id).ToList();
                                    var djInfo = djInfos.First(m => m.Text == "PLC流程字");
                                    // 获取跺机当前状态
                                    var (djRess, djVal) = plcSConn.GetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.PlcPos);
                                    if (!djRess.IsSucceed || djVal.ToString() != "820")
                                    {
                                        // 跺机非空闲等待
                                        break;
                                    }
                                    var listResult = new List<Result>();
                                    // 任务号、任务类型、托盘号
                                    var modPosTask = djInfos.FirstOrDefault(s => s.Text == "任务号");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosTask.PosType, djMod.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                                    var modPosTaskType = djInfos.FirstOrDefault(s => s.Text == "任务类型");
                                    var taskTypeStr = (int)modTask.TaskType;
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                                    var modPosPalletNo = djInfos.FirstOrDefault(s => s.Text == "托盘码");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, djMod.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                                    //起始工位
                                    var modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "起始工位");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum));
                                    // 目的工位
                                    var modPosendStationNum = djInfos.FirstOrDefault(s => s.Text == "目的工位");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosendStationNum.PosType, djMod.DbNumber, modPosendStationNum.PlcPos, endStationNum));
                                    //取货排、列、层
                                    var modPosStrPai = djInfos.FirstOrDefault(s => s.Text == "取货排");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrPai.PosType, djMod.DbNumber, modPosStrPai.PlcPos, sInfo.Pai));
                                    var modPosStrLie = djInfos.FirstOrDefault(s => s.Text == "取货列");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrLie.PosType, djMod.DbNumber, modPosStrLie.PlcPos, sInfo.Lie));
                                    var modPosStrCeng = djInfos.FirstOrDefault(s => s.Text == "取货层");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrCeng.PosType, djMod.DbNumber, modPosStrCeng.PlcPos, sInfo.Ceng));
                                    //放货排、列、层
                                    var modPosEndPai = djInfos.FirstOrDefault(s => s.Text == "放货排");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosEndPai.PosType, djMod.DbNumber, modPosEndPai.PlcPos, "2"));
                                    var modPosEndLie = djInfos.FirstOrDefault(s => s.Text == "放货列");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosEndLie.PosType, djMod.DbNumber, modPosEndLie.PlcPos, "60"));
                                    var modPosEndCeng = djInfos.FirstOrDefault(s => s.Text == "放货层");
                                    listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosEndCeng.PosType, djMod.DbNumber, modPosEndCeng.PlcPos, "1"));
                                    if (listResult.All(s => s.IsSucceed))
                                    {
                                        // 写入跺机 830
                                        var retc2 = plcSConn.SetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.WcsPos, "830");
                                        // 插入任务明细 任务明细实体类
                                        var modInsertTaskMonitor = new WcsTaskMonitor()
                                        {
                                            TaskNo = modTask.TaskNo,
                                            PlcId = modDevice.Id,
                                            PlcName = modDevice.Text,
                                            PalletNo = modTask.PalletNo,
                                            Status = TaskStatusEnum.Complete,
                                            StartLocat = modDevice.StationNum,
                                            EndLocat = modTask.EndLocate                  // 目标储位地址
                                        };
                                        if (!retc2.IsSucceed)
                                        {
                                            modInsertTaskMonitor.InteractiveMsg = $"输送线取货工位:{modDevice.StationNum},写入垛机取货任务830失败等待再次写入";
                                            // 插入交互日志
                                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                            //下发任务日志
                                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                            break;
                                        }
                                        // 写入目标工位 730  : 逻辑上此处不用占用地址。
                                        var retc3 = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "730");
                                        modInsertTaskMonitor.InteractiveMsg = $"跺机写入指令830:{modDevice.StationNum}工位====》" + modTask.EndLocate + "储位地址!";
                                        // 插入交互日志
                                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        if (PLCTaskAction.boRefresh)
                                        {
                                            //下发任务日志
                                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    }
                    // 判断是否出库转运任务
                    if (modTask.TaskType == TaskTypeEnum.Out)
                    {
                        var roadWay1 = "R06";
                        if (modTask.EndLocate == "266")
                        {
                            roadWay1 = "R05";
                        }
                        var sInfo1 = PLCCommon.GetStokePlc(roadWay1, "2");              // 放货排列层信息
                        var plcSConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfo1.Ip);
                        if (plcSConn.Connected)
                        {
                            var djmodel = _db.Queryable<WcsPlc>().First(m => m.IP == sInfo1.Ip);
                            var djMod = PLCTaskAction.plcDevices.First(m => m.PlcId == djmodel.Id
                                && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                            var djInfos = PLCTaskAction.plcPositions.Where(m => m.IsDelete == false && m.DeviceId == djMod.Id).ToList();
                            var djInfo = djInfos.First(m => m.Text == "PLC流程字");
                            // 获取跺机当前状态
                            var (djRess, djVal) = plcSConn.GetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.PlcPos);
                            if (!djRess.IsSucceed || djVal.ToString() != "820")
                            {
                                // 跺机非空闲等待
                                break;
                            }
                            var listResult = new List<Result>();
                            // 任务号、任务类型、托盘号
                            var modPosTask = djInfos.FirstOrDefault(s => s.Text == "任务号");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosTask.PosType, djMod.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                            var modPosTaskType = djInfos.FirstOrDefault(s => s.Text == "任务类型");
                            var taskTypeStr = (int)modTask.TaskType;
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                            var modPosPalletNo = djInfos.FirstOrDefault(s => s.Text == "托盘码");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, djMod.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                            //起始工位
                            var modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "起始工位");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum));
                            //目的工位
                            if (modTask.EndLocate == "266")
                            {
                                modTask.EndLocate = "277";
                            }
                            if (modTask.EndLocate == "265")
                            {
                                modTask.EndLocate = "250";
                            }
                            var modPosStrend = djInfos.FirstOrDefault(s => s.Text == "目的工位");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrend.PosType, djMod.DbNumber, modPosStrend.PlcPos, modTask.EndLocate));       // 此处现在存的是出库口266。
                            //取货排、列、层
                            var modPosStrPai = djInfos.FirstOrDefault(s => s.Text == "取货排");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrPai.PosType, djMod.DbNumber, modPosStrPai.PlcPos, "3"));
                            var modPosStrLie = djInfos.FirstOrDefault(s => s.Text == "取货列");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrLie.PosType, djMod.DbNumber, modPosStrLie.PlcPos, "60"));
                            var modPosStrCeng = djInfos.FirstOrDefault(s => s.Text == "取货层");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosStrCeng.PosType, djMod.DbNumber, modPosStrCeng.PlcPos, "1"));
                            //放货排、列、层
                            var modPosEndPai = djInfos.FirstOrDefault(s => s.Text == "放货排");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosEndPai.PosType, djMod.DbNumber, modPosEndPai.PlcPos, sInfo1.Pai));
                            var modPosEndLie = djInfos.FirstOrDefault(s => s.Text == "放货列");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosEndLie.PosType, djMod.DbNumber, modPosEndLie.PlcPos, sInfo1.Lie));
                            var modPosEndCeng = djInfos.FirstOrDefault(s => s.Text == "放货层");
                            listResult.Add(plcSConn.SetPlcDBValueRepeat(modPosEndCeng.PosType, djMod.DbNumber, modPosEndCeng.PlcPos, sInfo1.Ceng));
                            if (listResult.All(s => s.IsSucceed))
                            {
                                // 写入跺机 830
                                var retc2 = plcSConn.SetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.WcsPos, "830");
                                // 插入任务明细 任务明细实体类
                                var modInsertTaskMonitor = new WcsTaskMonitor()
                                {
                                    TaskNo = modTask.TaskNo,
                                    PlcId = modDevice.Id,
                                    PlcName = modDevice.Text,
                                    PalletNo = modTask.PalletNo,
                                    Status = TaskStatusEnum.Complete,
                                    StartLocat = modTask.StartLocate,
                                    EndLocat = modTask.EndLocate                  // 目标储位地址
                                };
                                if (!retc2.IsSucceed)
                                {
                                    modInsertTaskMonitor.InteractiveMsg = $"输送线取货工位:{modDevice.StationNum},写入垛机取货任务830失败等待再次写入";
                                    // 插入交互日志
                                    _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                    //下发任务日志
                                    HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    break;
                                }
                                modInsertTaskMonitor.InteractiveMsg = $"跺机写入指令830:{modDevice.StationNum}工位====》" + modTask.EndLocate + "储位地址!";
                                // 插入交互日志
                                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                if (PLCTaskAction.boRefresh)
                                {
                                    //下发任务日志
                                    HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                }
                            }
                        }
                        break;
                    }
                    #endregion
                    // 非正常入库任务不往下执行
                    if (modTask.TaskType != TaskTypeEnum.In)
                    {
                        break;
                    }
                    if (string.IsNullOrWhiteSpace(sInfo.Ip))
                    {
                        //需加上LED显示
@@ -1272,31 +2203,35 @@
                        // 任务号、任务类型、托盘号
                        var modPosTask = djInfos.FirstOrDefault(s => s.Text == "任务号");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosTask.PosType, djMod.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosTask.PosType, djMod.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                        var modPosTaskType = djInfos.FirstOrDefault(s => s.Text == "任务类型");
                        var taskTypeStr = (int)modTask.TaskType;
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                        var modPosPalletNo = djInfos.FirstOrDefault(s => s.Text == "托盘码");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosPalletNo.PosType, djMod.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosPalletNo.PosType, djMod.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                        //起始工位
                        var modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "起始工位");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum));
                        //目的工位
                        var modPosendStationNum = djInfos.FirstOrDefault(s => s.Text == "目的工位");
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosStrStationNum.PosType, djMod.DbNumber, modPosendStationNum.PlcPos, modDevice.StationNum));     // 此处现在是139 应该为0
                        //取货排、列、层
                        var modPosStrPai = djInfos.FirstOrDefault(s => s.Text == "取货排");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrPai.PosType, djMod.DbNumber, modPosStrPai.PlcPos, sInfo.Pai));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosStrPai.PosType, djMod.DbNumber, modPosStrPai.PlcPos, sInfo.Pai));
                        var modPosStrLie = djInfos.FirstOrDefault(s => s.Text == "取货列");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrLie.PosType, djMod.DbNumber, modPosStrLie.PlcPos, sInfo.Lie));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosStrLie.PosType, djMod.DbNumber, modPosStrLie.PlcPos, sInfo.Lie));
                        var modPosStrCeng = djInfos.FirstOrDefault(s => s.Text == "取货层");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrCeng.PosType, djMod.DbNumber, modPosStrCeng.PlcPos, sInfo.Ceng));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosStrCeng.PosType, djMod.DbNumber, modPosStrCeng.PlcPos, sInfo.Ceng));
                        //放货排、列、层
                        var modPosEndPai = djInfos.FirstOrDefault(s => s.Text == "放货排");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosEndPai.PosType, djMod.DbNumber, modPosEndPai.PlcPos, pai));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosEndPai.PosType, djMod.DbNumber, modPosEndPai.PlcPos, pai));
                        var modPosEndLie = djInfos.FirstOrDefault(s => s.Text == "放货列");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosEndLie.PosType, djMod.DbNumber, modPosEndLie.PlcPos, lie));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosEndLie.PosType, djMod.DbNumber, modPosEndLie.PlcPos, lie));
                        var modPosEndCeng = djInfos.FirstOrDefault(s => s.Text == "放货层");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosEndCeng.PosType, djMod.DbNumber, modPosEndCeng.PlcPos, ceng));
                        listResult.Add(plcStackeConn.SetPlcDBValueRepeat(modPosEndCeng.PosType, djMod.DbNumber, modPosEndCeng.PlcPos, ceng));
                        if (listResult.All(s => s.IsSucceed))
                        {
@@ -1334,10 +2269,6 @@
                            }
                        }
                    }
                    #endregion
@@ -1347,27 +2278,35 @@
            #region 出库交互
            case "420":
                {
                    string plcValue = "430";
                    #region 托盘到达拣选工位/出库口
                    // 出库口
                    // led显示托盘信息
                    // 写入430
                    var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "430");
                    var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (res, taskVal) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos);
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res2, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                    var modPosStarStationNum = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位");
                    var (res3, starVal) = plcConn.GetPlcDBValue(modPosStarStationNum.PosType, modDevice.DbNumber, modPosStarStationNum.PlcPos);
                    //判断是否四楼出库口
                    //if (modDevice.StationNum == "265" || modDevice.StationNum == "266")
                    //{
                    //    var http = new HttpService();
                    //    //根据出库任务号获取出库单类型
                    //    var modResponseTask = http.GetSoOrderTypeByTaskNo(taskVal).Result;
                    //    if (modResponseTask.StatusCode == 0 && modResponseTask.Msg == "1")//1:领料出库单
                    //    {
                    //        plcValue = "230";
                    //    }
                    //}
                    var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, plcValue);
                    if (ret.IsSucceed)
                    {
                        var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                        var (res, taskVal) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos);
                        var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                        var (res2, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos);
                        var modPosStarStationNum = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位");
                        var (res3, starVal) = plcConn.GetPlcDBValue(modPosStarStationNum.PosType, modDevice.DbNumber, modPosStarStationNum.PlcPos);
                        // 插入任务明细 
                        var modInsertTaskMonitor = new WcsTaskMonitor()
                        {
                            TaskNo = taskVal,
                            PlcId = modDevice.Id,
                            PlcName = modDevice.Text,
                            InteractiveMsg = $"写入指令430:托盘到达{modDevice.StationNum}工位",
                            InteractiveMsg = $"写入指令{plcValue}:托盘到达{modDevice.StationNum}工位",
                            PalletNo = palletVal,
                            Status = TaskStatusEnum.Complete,
                            StartLocat = starVal,
@@ -1387,7 +2326,7 @@
                        // led显示内容
                        // 根据目标工位号获取对应的LEDIP地址
                        var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId == modDevice.PlcId);
                        ledText += $"出库完成\n\n";
                        ledText += $"任务号:{taskInfo.TaskNo}\n";
                        ledText += $"托盘号:{taskInfo.PalletNo}\n\n";
@@ -1490,27 +2429,38 @@
            case "50":
                // plc申请空托
                {
                    // 防止重复叫空托跺
                    var (res, palletVal) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                    if (palletVal != 0)
                    lock (OLock)
                    {
                        break;
                    }
                        // 判断是否已有向叫空托工位的出库任务
                        var modTask = _db.Queryable<WcsTask>().First(m => (m.Status == TaskStatusEnum.Doing || m.Status == TaskStatusEnum.Wait)
                        && m.EndLocate == modDevice.StationNum && m.IsDelete == false);
                        if (modTask != null)
                        {
                            Log.Error("已存在向" + modDevice.StationNum + "工位的任务。任务号:" + modTask.TaskNo);
                            break;
                        }
                    // 调用WMS空托出库接口,返回出库任务存入出库表
                    var strMsg = "";
                    var http = new HttpService();
                    strMsg = http.IssuePlnOutHouseWcs("1", "205");
                    if (!strMsg.Contains("-1"))
                    {
                        // 写入plc流程字60
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "60");
                        // 防止重复叫空托跺
                        var (res, palletVal) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                        if (palletVal != 0)
                        {
                            break;
                        }
                        // 调用WMS空托出库接口,返回出库任务存入出库表
                        var strMsg = "";
                        var http = new HttpService();
                        strMsg = http.IssuePlnOutHouseWcs("1", modDevice.StationNum);
                        if (!strMsg.Contains("-1"))
                        {
                            // 写入plc流程字60
                            var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "60");
                        }
                        else
                        {
                            // 申请巷道失败!LED显示
                            Log.Error(string.Format($"工位号:{modDevice.StationNum}申请空托跺失败:{strMsg};"));
                        }
                    }
                    else
                    {
                        // 申请巷道失败!LED显示
                        Log.Error(string.Format($"工位号:{modDevice.StationNum}申请空托跺失败:{strMsg};"));
                    }
                }
                break;
            case "80":
@@ -1583,6 +2533,59 @@
                break;
            #endregion
            #region 拆垛业务
            case "520":
                //托盘达到拆垛工位,WCS写入品种号并写入530
                {
                    // 获取托盘条码配置
                    var modPalletNo = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码" && m.IsDelete == false);
                    // 读取PLC托盘条码号
                    var (res, palletVal) = plcConn.GetPlcDBValue(modPalletNo.PosType, modDevice.DbNumber, modPalletNo.PlcPos);
                    string palletNo = palletVal.ToString();
                    if (string.IsNullOrEmpty(palletNo))
                    {
                        Log.Error(string.Format("{0},读取的托盘号为null", modDevice.Text));
                        break;
                    }
                    string pzNo = string.Empty;
                    //调用WMS接口获取托盘上物料品种信息
                    var http = new HttpService();
                    pzNo = http.GetPalletPzNo(palletNo);
                    if (!string.IsNullOrEmpty(pzNo))
                    {
                        var modAddCode = modDevice.listStation.FirstOrDefault(m => m.Text == "品种" && m.IsDelete == false);
                        // 写入拆垛品种
                        var retVal = plcConn.SetPlcDBValueRepeat(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, pzNo);
                        if (retVal.IsSucceed)
                        {
                            plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "530");
                        }
                    }
                }
                break;
            case "540":
                //拆垛完成即出库完成任务结束,WCS写入550,PLC清0
                {
                    // 获取托盘条码配置
                    var modPalletNo = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘条码" && m.IsDelete == false);
                    // 读取PLC托盘条码号
                    var (res, palletVal) = plcConn.GetPlcDBValue(modPalletNo.PosType, modDevice.DbNumber, modPalletNo.PlcPos);
                    string palletNo = palletVal.ToString();
                    if (string.IsNullOrEmpty(palletNo))
                    {
                        Log.Error(string.Format("{0},读取的托盘号为null", modDevice.Text));
                        break;
                    }
                    //调用WMS接口进行成品箱码拣货
                    var http = new HttpService();
                    var strMsg = http.BoxUnstackd(palletNo);
                    if (!strMsg.Contains("-1"))
                    {
                        plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "550");
                    }
                }
                break;
            #endregion
            default: break;
        }
@@ -1629,11 +2632,11 @@
    /// 件箱输送和码垛机器人业务处理  配置的是件箱输送
    /// </summary>
    /// <param name="modDevice"></param>
    private static async void BoxConveyorLine(WcsDeviceDto modDevice)
    private static void BoxConveyorLine(WcsDeviceDto modDevice)
    {
        var plcConn = modDevice.PLCUtil;
        if (modDevice.DbNumber == "DB101")
        if (modDevice.DbNumber == "DB101" || modDevice.DbNumber == "DB102" || modDevice.DbNumber == "DB103" || modDevice.DbNumber == "DB104" || modDevice.DbNumber == "DB105")
        {
            // 主扫交互流程
            switch (modDevice.Value.ToString())
@@ -1641,98 +2644,69 @@
                case "1":
                    // 主扫申请分道 wcs写入2
                    {
                        // 判断是否演示模式 true:演示模式   false:生产模式
                        if (PLCTaskAction.boDemo)
                        var modPosReadBox = modDevice.listStation.FirstOrDefault(m => m.Text == "读取箱码" && m.IsDelete == false);
                        var (res, boxNo) = plcConn.GetPlcDBValue(modPosReadBox.PosType, modDevice.DbNumber, modPosReadBox.PlcPos);
                        if (string.IsNullOrWhiteSpace(boxNo.ToString()))
                        {
                            // 通道号
                            var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号");
                            // 演示模式直接写入1分道
                            var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "1");
                            if (ret.IsSucceed)
                            // 写入流程控制字 2
                            var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                            if (retVal.IsSucceed)
                            {
                                // 写入流程控制字 2
                                var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                                if (!retVal.IsSucceed)
                                {
                                    Log.Error("演示模式写入分道号失败!");
                                    break;
                                }
                                Log.Error("箱码为null进行剔除");
                                break;
                            }
                        }
                        // 根据箱码获取箱内信息
                        string boxNoVal = boxNo.ToString();
                        var boxInfo = _db.Queryable<WcsBoxInfo>().First(w => w.IsDelete == false && w.BoxNo == boxNoVal && string.IsNullOrEmpty(w.PalletNo));
                        if (boxInfo == null)
                        {
                            // 写入流程控制字 2
                            var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                            if (retVal.IsSucceed)
                            {
                                Log.Error($"箱码为null或已绑定托盘,进行剔除。箱码:{boxNoVal}");
                                break;
                            }
                        }
                        // 根据箱内品种号获取码躲绑定工位及对应的分道号
                        var checkTaskInfo = _db.Queryable<WcsCheckTask>().First(w => w.SkuNo == boxInfo.SkuNo && w.SkuName == boxInfo.SkuName && w.LotNo == boxInfo.LotNo);
                        if (checkTaskInfo == null)
                        {
                            Log.Error($"测试--。箱码:{boxNoVal},箱ID:{boxInfo.Id},物料编码:{boxInfo.SkuNo},物料名称:{boxInfo.SkuName},批次:{boxInfo.LotNo}");
                            // 写入流程控制字 2
                            var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                            if (retVal.IsSucceed)
                            {
                                Log.Error($"箱码未绑定分拣任务,进行剔除。箱码:{boxNoVal}");
                                break;
                            }
                        }
                        else
                        {
                            // 通道号
                            var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号");
                            // 给PLC写入任务数据
                            var listResult = new List<Result>();
                            //批次号
                            var modPosLotNo = modDevice.listStation.FirstOrDefault(m => m.Text == "批次号" && m.IsDelete == false);
                            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosLotNo.PosType, modDevice.DbNumber, modPosLotNo.PlcPos, boxInfo.LotNo));
                            //品种
                            var modPosPZ = modDevice.listStation.FirstOrDefault(m => m.Text == "品种" && m.IsDelete == false);
                            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosPZ.PosType, modDevice.DbNumber, modPosPZ.PlcPos, checkTaskInfo.PZNo));
                            //是否尾箱
                            var modPosIsEndBox = modDevice.listStation.FirstOrDefault(m => m.Text == "是否尾箱" && m.IsDelete == false);
                            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosIsEndBox.PosType, modDevice.DbNumber, modPosIsEndBox.PlcPos, boxInfo.EndLotFlag));
                            //写入箱码
                            var modPosBox = modDevice.listStation.FirstOrDefault(m => m.Text == "写入箱码" && m.IsDelete == false);
                            listResult.Add(plcConn.SetPlcDBValueRepeat(modPosBox.PosType, modDevice.DbNumber, modPosBox.PlcPos, boxInfo.BoxNo));
                            // 读取plc箱码
                            var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱码");
                            var (res, boxNo) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos);
                            if (string.IsNullOrWhiteSpace(boxNo.ToString()))
                            // 是否写入成功
                            if (listResult.All(s => s.IsSucceed))
                            {
                                // 箱码为null写入剔除通道号
                                var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0");
                                if (ret.IsSucceed)
                                // 写入流程控制字 2
                                var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                                if (retVal.IsSucceed)
                                {
                                    // 写入流程控制字 2
                                    var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                                    if (retVal.IsSucceed)
                                    {
                                        Log.Error("箱码为null进行剔除");
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                // 根据箱码获取箱内信息
                                string boxNoVal = boxNo.ToString();
                                var boxInfo = _db.Queryable<WcsBoxInfo>().First(w => w.IsDelete == false && w.BoxNo == boxNoVal && string.IsNullOrEmpty(w.PalletNo));
                                if (boxInfo == null)
                                {
                                    // 箱信息为null写入剔除通道号
                                    var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0");
                                    if (ret.IsSucceed)
                                    {
                                        // 写入流程控制字 2
                                        var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                                        if (retVal.IsSucceed)
                                        {
                                            Log.Error("箱码为null或已绑定托盘,进行剔除。");
                                            break;
                                        }
                                    }
                                }
                                // 根据箱内品种号获取码躲绑定工位及对应的分道号
                                var checkTaskInfo = _db.Queryable<WcsCheckTask>().First(w => w.SkuNo == boxInfo.SkuNo && w.SkuName == boxInfo.SkuName && w.LotNo == boxInfo.LotNo);
                                if (checkTaskInfo == null)
                                {
                                    // 绑定信息为null写入剔除通道号
                                    var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0");
                                    if (ret.IsSucceed)
                                    {
                                        // 写入流程控制字 2
                                        var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                                        if (retVal.IsSucceed)
                                        {
                                            Log.Error("箱码未绑定分拣任务,进行剔除。");
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    // 与plc交互写入分道号和流程控制字
                                    var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, checkTaskInfo.RoboatNo);
                                    if (ret.IsSucceed)
                                    {
                                        // 写入流程控制字 2
                                        var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                                        if (retVal.IsSucceed)
                                        {
                                            break;
                                        }
                                    }
                                    break;
                                }
                            }
                        }
@@ -1740,21 +2714,21 @@
                    break;
                default: break;
            }
        }
        else
        }
        else
        {
            // 插码交互
            switch (modDevice.Value.ToString())
            switch (modDevice.Value.ToString())
            {
                case "1":
                    // 托盘条码可读
                    {
                        // 获取托盘条码配置
                        var modPalletNo = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘条码");
                        var modPalletNo = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘条码" && m.IsDelete == false);
                        // 读取PLC托盘条码号
                        var (res, palletVal) = plcConn.GetPlcDBValue(modPalletNo.PosType, modDevice.DbNumber, modPalletNo.PlcPos);
                        string palletNo = palletVal.ToString();
                        if (string.IsNullOrEmpty(palletNo))
                        if (string.IsNullOrEmpty(palletNo))
                        {
                            Log.Error(string.Format("{0},读取的托盘号为null", modDevice.Text));
                            break;
@@ -1762,18 +2736,19 @@
                        // 根据工位号将托盘号保存在分道表
                        var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false);
                        if (checkTaskMedel == null)
                        if (checkTaskMedel == null)
                        {
                            Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum));
                            break;
                        }
                        checkTaskMedel.PalletNo = palletNo;
                        checkTaskMedel.BoxCount = 0;
                        var rowCount = _db.Updateable(checkTaskMedel).ExecuteCommand();
                        if (rowCount > 0 )
                        if (rowCount > 0)
                        {
                            // plc写入读取成功表示 2
                            var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2");
                            if (retVal.IsSucceed)
                            if (retVal.IsSucceed)
                            {
                                // liudl  此处需添加
                                // 通知分拣码垛页更新
@@ -1785,199 +2760,148 @@
                    // 申请插码
                    {
                        // 获取托盘条码配置
                        var modAddCode = modDevice.listStation.FirstOrDefault(m => m.Text == "插码结果");
                        // 判断是否演示模式 true:演示模式   false:生产模式
                        if (PLCTaskAction.boDemo)
                        var modAddCode = modDevice.listStation.FirstOrDefault(m => m.Text == "插码结果" && m.IsDelete == false);
                        //获取插码箱数
                        var modAddBoxNum = modDevice.listStation.FirstOrDefault(m => m.Text == "插码箱数" && m.IsDelete == false);
                        var (boxNumRes, boxNumVal) = plcConn.GetPlcDBValue(modAddBoxNum.PosType, modDevice.DbNumber, modAddBoxNum.PlcPos);
                        int boxNum = Convert.ToInt32(boxNumVal);
                        if (boxNum != 1 && boxNum != 2)
                        {
                            // 演示模式直接写入插码结果 1:成功
                            var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1");
                            Log.Error(string.Format($"码垛工位{0},请求插码箱数不正确! boxNum:{boxNum}", modDevice.StationNum));
                            // 写入插入结果 2:插码失败
                            var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                            break;
                        }
                        else
                        // 获取当前分道托盘号
                        var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false);
                        if (checkTaskMedel == null)
                        {
                            Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum));
                            // 写入插入结果 2:插码失败
                            var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                            break;
                        }
                        string palletNo = checkTaskMedel.PalletNo;
                        if (string.IsNullOrEmpty(palletNo))
                        {
                            Log.Error(string.Format("获取码垛工位{0}上的托盘号失败!", modDevice.StationNum));
                            // 写入插入结果 2:插码失败
                            var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                            break;
                        }
                        for (int i = 1; i <= boxNum; i++)
                        {
                            // 获取箱条码
                            // 获取箱条码配置
                            var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱条码");
                            var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == $"读取箱码{i}");
                            var (res, boxVal) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos);
                            string boxNo = boxVal.ToString();
                            if (string.IsNullOrEmpty(boxNo))
                            if (string.IsNullOrEmpty(boxNo))
                            {
                                Log.Error(string.Format("码垛工位{0},箱码为null插码失败!请人工强制结批。"), modDevice.StationNum);
                                // 写入插入结果 2:插码失败
                                var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                                Log.Error(string.Format("码垛工位{0},箱码为null插码失败!请人工强制结批。", modDevice.StationNum));
                                break;
                            }
                            // 验证箱码表是否存在此箱码
                            var boxInfo = _db.Queryable<WcsBoxInfo>().First(w => w.IsDelete == false && w.BoxNo == boxNo);
                            if (boxInfo == null)
                            var boxInfo = _db.Queryable<WcsBoxInfo>().Where(w => w.IsDelete == false && w.BoxNo == boxNo).ToList();
                            if (boxInfo.Count == 0)
                            {
                                Log.Error(string.Format("码垛工位{0},箱码{1}不存在!请人工强制结批。"), modDevice.StationNum,boxNo);
                                Log.Error(string.Format("码垛工位{0},箱码{1}不存在!请人工强制结批。", modDevice.StationNum, boxNo));
                                // 写入插入结果 2:插码失败
                                var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                                break;
                            }
                            // 获取当前分道托盘号
                            var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false);
                            if (checkTaskMedel == null)
                            {
                                Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum));
                                break;
                            }
                            string palletNo = checkTaskMedel.PalletNo;
                            if (string.IsNullOrEmpty(palletNo))
                            {
                                Log.Error(string.Format("获取码垛工位{0}上的托盘号失败!",modDevice.StationNum));
                                plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                                break;
                            }
                            // 修改插码表
                            boxInfo.PalletNo = palletNo;
                            boxInfo.UpdateTime = DateTime.Now;
                            var rowCount = _db.Updateable(boxInfo).ExecuteCommand();
                            if (rowCount > 0)
                            foreach (WcsBoxInfo item in boxInfo)
                            {
                                // 插码成功
                                var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1");
                                item.PalletNo = palletNo;
                                item.UpdateTime = DateTime.Now;
                            }
                            else
                            var resultCount = _db.Updateable(boxInfo).ExecuteCommand();
                            if (resultCount <= 0)
                            {
                                // 插码失败
                                Log.Error(string.Format("箱码{0};码垛工位{1},插码失败,请强制结批"),boxNo,modDevice.StationNum);
                                var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                                Log.Error(string.Format("箱码{0};码垛工位{1},绑定托盘{2}失败,请强制结批", boxNo, modDevice.StationNum, palletNo));
                                // 写入插入结果 2:插码失败
                                plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2");
                                break;
                            }
                        }
                        // 插码成功
                        var retVal2 = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1");
                        if (retVal2.IsSucceed)
                        {
                            //更新已插码数量
                            checkTaskMedel.BoxCount += boxNum;
                            _db.Updateable(checkTaskMedel).ExecuteCommand();
                        }
                        else
                        {
                            // 写入失败
                            Log.Error(string.Format("写入PLC插码结果失败,码垛工位{1},托盘号{2}", modDevice.StationNum, palletNo));
                        }
                    }
                    break;
                case "40":
                    // 请求组托,申请入库
                    {
                        // 根据工位号,获取托盘号
                        var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false);
                        // 根据工位号获取 托盘线该工位号的配置信息
                        var numModel = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId != modDevice.PlcId);
                        var posModel = PLCTaskAction.plcPositions.First(m => m.DeviceId == numModel.Id && m.Text == "目的工位" && m.IsDelete == false);
                        if (checkTaskMedel == null)
                        lock (OLock)
                        {
                            Log.Error(string.Format("组托失败根据码垛工位{0},获取托盘号失败!", modDevice.StationNum));
                            // 写入交互工位目标地址
                            var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234");
                            if (retVal.IsSucceed)
                            // 根据工位号,获取托盘号
                            var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false);
                            // 根据工位号获取 托盘线该工位号的配置信息
                            var numModel = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId != modDevice.PlcId);
                            //var posModel = PLCTaskAction.plcPositions.First(m => m.DeviceId == numModel.Id && m.Text == "目的工位" && m.IsDelete == false);
                            if (checkTaskMedel == null)
                            {
                                Log.Error(string.Format("组托失败根据码垛工位{0},获取托盘号失败!", modDevice.StationNum));
                                // 写入组托回复流程字
                                retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50");
                            }
                            break;
                        }
                        // 码垛工位托盘号
                        string palletNo = checkTaskMedel.PalletNo;
                        // 是否演示模式
                        if (PLCTaskAction.boDemo)
                        {
                            // 直接箱wms申请巷道
                            var http = new HttpService();
                            string TaskNo = "", EndLocate = "";
                            string strMsg = http.RequestRoadWay(palletNo, modDevice.StationNum, "1", "2", ref EndLocate, ref TaskNo);
                            if (strMsg.Contains("-1"))
                            {
                                Log.Error(string.Format("申请巷道失败,码垛工位{0};原因{1}", modDevice.StationNum, strMsg));
                                var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "60");
                                break;
                            }
                            else
                            //获取托盘高度
                            //var posPalletHeightModel = PLCTaskAction.plcPositions.First(m => m.DeviceId == numModel.Id && m.Text == "托盘高度" && m.IsDelete == false);
                            //var (resPalletHeight, palletHeightVal) = plcConn.GetPlcDBValue(posPalletHeightModel.PosType, modDevice.DbNumber, posPalletHeightModel.PlcPos);
                            //if (!resPalletHeight.IsSucceed)
                            //{
                            //    break;
                            //}
                            // 码垛工位托盘号
                            string palletNo = checkTaskMedel.PalletNo;
                            //判断该托盘是否有正在执行的任务,防止重复申请
                            var taskIng = _db.Queryable<WcsTask>().First(w => w.PalletNo == palletNo && (w.Status == TaskStatusEnum.Wait || w.Status == TaskStatusEnum.Doing) && w.IsDelete == false);
                            if (taskIng != null)
                            {
                                // 获取入库任务信息
                                var taskModel = _db.Queryable<WcsTask>().First(m => m.TaskNo == TaskNo && m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing));
                                if (taskModel != null)
                                {
                                    // 获取入库取货工位
                                    string endLocatVlue = PLCCommon.RoadwayToStationNum(taskModel.EndRoadway, "2");
                                    var listResult = new List<Result>();
                                    // 写入托盘输送线码垛工位 目的工位、任务号,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息}
                                    listResult.Add(plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue));    // 目标工位
                                    var modPosTask = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务号" && s.IsDelete == false);
                                    listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, numModel.DbNumber, modPosTask.PlcPos, TaskNo));
                                    var modPosTaskType = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务类型" && s.IsDelete == false);
                                    var taskTypeStr = (int)taskModel.TaskType;
                                    listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, numModel.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                                    if (listResult.All(s => s.IsSucceed))
                                    {
                                        // 写入组托回复流程字
                                        var retVal1 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50");
                                        if (retVal1.IsSucceed)
                                        {
                                            // 将入库任务由正在执行改为正在执行
                                            taskModel.Status = TaskStatusEnum.Doing;
                                            _db.Updateable(taskModel).ExecuteCommand();
                                            // 插入任务明细
                                            var modInsertTaskMonitor = new WcsTaskMonitor()
                                            {
                                                TaskNo = TaskNo,
                                                PlcId = modDevice.Id,
                                                PlcName = modDevice.Text,
                                                InteractiveMsg = $"写入指令50:申请巷道成功",
                                                PalletNo = palletNo,
                                                Status = TaskStatusEnum.Complete,
                                                StartLocat = modDevice.StationNum,
                                                EndLocat = strMsg,
                                            };
                                            // 插入交互日志
                                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                            // 通知任务界面任务已存在更新 请更新界面
                                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        }
                                    }
                                    //// 写入托盘输送线码垛工位 目的工位,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息}
                                    //var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue);
                                    //if (retVal.IsSucceed)
                                    //{
                                    //    // 写入码垛交互-组托回复流程字
                                    //    retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50");
                                    //    // 将入库任务由正在执行改为正在执行
                                    //    taskModel.Status = TaskStatusEnum.Doing;
                                    //    _db.Updateable(taskModel).ExecuteCommand();
                                    //}
                                }
                                break;
                            }
                        }
                        else
                        {
                            // 根据托盘号,将组托信息插入boxinfolog表 并删除boxinfo表数据
                            var boxInfoList = await _db.Queryable<WcsBoxInfo>().Where(w => w.IsDelete == false && w.PalletNo == palletNo).ToListAsync();
                            var boxInfoList = _db.Queryable<WcsBoxInfo>().Where(w => w.IsDelete == false && w.PalletNo == palletNo).ToList();
                            if (boxInfoList.Count <= 0)
                            {
                                Log.Error(string.Format("申请巷道失败,码垛工位{0},箱码信息不存在", modDevice.StationNum));
                                // 写入交互工位目标地址
                                var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234");
                                if (retVal.IsSucceed)
                                {
                                    // 写入组托回复流程字
                                    retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50");
                                }
                                // 写入组托回复流程字
                                var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "60");
                                break;
                            }
                            string sqlStr = $"insert into WCSBoxInfoLog select * from WCSBoxInfo where IsDelete=0 and PalletNo='{palletNo}'";
                            int insertCount = _db.Ado.ExecuteCommand(sqlStr);
                            if (insertCount > 0)
                            {
                                string sqlStr2 = $"delete from WCSBoxInfo where  IsDelete=0 and PalletNo='{palletNo}'";
                                _db.Ado.ExecuteCommand(sqlStr2);
                            }
                            // 向WMS申请巷道
                            var http = new HttpService();
                            string TaskNo = "", EndLocate = "";
                            string strMsg = http.BindRequestRoadWay(checkTaskMedel.OrderNo,palletNo, checkTaskMedel.BoxCount.ToDecimal(),"0", checkTaskMedel.SkuNo, checkTaskMedel.LotNo, "","", boxInfoList,
                                modDevice.StationNum, "1", "2", ref EndLocate, ref TaskNo);
                            if (!strMsg.Contains("-1"))
                            string strMsg = http.BindRequestRoadWay(checkTaskMedel.OrderNo, palletNo, checkTaskMedel.BoxCount.ToDecimal(), "0", checkTaskMedel.SkuNo, checkTaskMedel.LotNo, "", "", boxInfoList,
                                modDevice.StationNum, "1", "1", ref EndLocate, ref TaskNo, (int)1351);
                            if (strMsg.Contains("-1"))
                            {
                                Log.Error(string.Format("申请巷道失败,码垛工位{0};原因{1}", modDevice.StationNum, strMsg));
                                // 写入组托回复流程字
                                var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "60");
                                break;
                            }
                            else
@@ -1986,54 +2910,61 @@
                                var taskModel = _db.Queryable<WcsTask>().First(m => m.TaskNo == TaskNo && m.IsDelete == false && m.Status == TaskStatusEnum.Wait);
                                if (taskModel != null)
                                {
                                    // 获取入库取货工位
                                    string endLocatVlue = PLCCommon.RoadwayToStationNum(taskModel.EndRoadway, "2");
                                    var listResult = new List<Result>();
                                    // 写入托盘输送线码垛工位 目的工位、任务号,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息}
                                    listResult.Add(plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue));    // 目标工位
                                    var modPosTask = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务号" && s.IsDelete == false);
                                    listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, numModel.DbNumber, modPosTask.PlcPos, TaskNo));
                                    var modPosTaskType = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务类型" && s.IsDelete == false);
                                    var taskTypeStr = (int)taskModel.TaskType;
                                    listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, numModel.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString()));
                                    if (listResult.All(s => s.IsSucceed))
                                    // 写入组托回复流程字
                                    var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50");
                                    if (retVal.IsSucceed)
                                    {
                                        // 写入组托回复流程字
                                        var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50");
                                        if (retVal.IsSucceed)
                                        {
                                            // 将入库任务由正在执行改为正在执行
                                            taskModel.Status = TaskStatusEnum.Doing;
                                            _db.Updateable(taskModel).ExecuteCommand();
                                        // 将入库任务由正在执行改为正在执行
                                        taskModel.Status = TaskStatusEnum.Doing;
                                        _db.Updateable(taskModel).ExecuteCommand();
                                            // 插入任务明细
                                            var modInsertTaskMonitor = new WcsTaskMonitor()
                                            {
                                                TaskNo = TaskNo,
                                                PlcId = modDevice.Id,
                                                PlcName = modDevice.Text,
                                                InteractiveMsg = $"写入指令50:申请巷道成功",
                                                PalletNo = palletNo,
                                                Status = TaskStatusEnum.Complete,
                                                StartLocat = modDevice.StationNum,
                                                EndLocat = strMsg,
                                            };
                                            // 插入交互日志
                                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                            // 通知任务界面任务已存在更新 请更新界面
                                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        string sqlStr = $"insert into WCSBoxInfoLog select * from WCSBoxInfo where IsDelete=0 and PalletNo='{palletNo}'";
                                        int insertCount = _db.Ado.ExecuteCommand(sqlStr);
                                        if (insertCount > 0)
                                        {
                                            string sqlStr2 = $"delete from WCSBoxInfo where  IsDelete=0 and PalletNo='{palletNo}'";
                                            _db.Ado.ExecuteCommand(sqlStr2);
                                        }
                                        // 插入任务明细
                                        var modInsertTaskMonitor = new WcsTaskMonitor()
                                        {
                                            TaskNo = TaskNo,
                                            PlcId = modDevice.Id,
                                            PlcName = modDevice.Text,
                                            InteractiveMsg = $"写入指令50:申请巷道成功",
                                            PalletNo = palletNo,
                                            Status = TaskStatusEnum.Complete,
                                            StartLocat = modDevice.StationNum,
                                            EndLocat = strMsg,
                                        };
                                        // 插入交互日志
                                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        // 通知任务界面任务已存在更新 请更新界面
                                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    }
                                }
                            }
                        }
                    }
                    break;
                default:break;
                case "100":
                    //自动结批
                    {
                        // 获取当前分道托盘号
                        var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false);
                        if (checkTaskMedel == null)
                        {
                            Log.Error(string.Format("码垛工位{0},批次{1},自动结批失败!请人工强制结批!", modDevice.StationNum, checkTaskMedel.LotNo));
                            break;
                        }
                        // 触发结批 解绑分道
                        AutoEndLot(checkTaskMedel.LotNo, plcConn, "0", modDevice);
                    }
                    break;
                default: break;
            }
        }
        }
    }
    /// <summary>
@@ -2055,19 +2986,22 @@
        }
    }
    /// <summary>
    /// Led屏展示信息
    /// </summary>
    /// <param name="ip">地址</param>
    /// <param name="top">上方区域</param>
    /// <param name="content">中间区域</param>
    /// <param name="foot">底部区域</param>
    private static void LedDisplay(string ip, string top, string content, string foot)
    private static void LedDisplay(string ip,string text,int type=0)
    {
        try
        {
            LedDll Led = new LedDll();
            Led.LEDstr(ip, top, content, foot);
            if (type == 0)
            {
                Led.ConsoleLeds(ip, text);
            }
            else
            {
                Led.LEDstr(ip, text);
            }
            // 设置实例
            //Led.ConsoleLeds("10.18.51.238", $"任务类型:{TaskTypeEnum.Move.GetDescription()}\n\n任务号:TK2024102100001\n托盘号:LN000145\n\n起始位:033\n目标位:R01-02010102");
        }
        catch (Exception ex)
        {
@@ -2075,18 +3009,74 @@
        }
    }
    private static void LedDisplay(string ip,string text)
    /// <summary>
    /// 自动结批 并 解绑分道
    /// </summary>
    /// <param name="lotNo">批次号</param>
    /// <param name="plcConn">Plc连接</param>
    /// <param name="status">是否解绑分道 0:解绑  1:绑定</param>
    private static void AutoEndLot(string lotNo, PLCUtil plcConn, string status, WcsDeviceDto modDevice)
    {
        try
        {
            LedDll Led = new LedDll();
            Led.ConsoleLeds(ip, text);
            // 设置实例
            //Led.ConsoleLeds("10.18.51.238", $"任务类型:{TaskTypeEnum.Move.GetDescription()}\n\n任务号:TK2024102100001\n托盘号:LN000145\n\n起始位:033\n目标位:R01-02010102");
            if (string.IsNullOrWhiteSpace(lotNo))
            {
                Console.WriteLine("批次号为null");
            }
            var checkTaskList = _db.Queryable<WcsCheckTask>().Where(w => w.LotNo == lotNo && w.Status == "1").ToList();
            if (checkTaskList.Count <= 0)
            {
                Console.WriteLine("未找到分道绑定信息");
            }
            var taskInfo = _db.Queryable<WcsOderTask>().First(w => w.OrderNo == checkTaskList[0].OrderNo);
            if (taskInfo != null)
            {
                taskInfo.Status= TaskStatusEnum.Complete;//已结束
                //更新任务状态
                _db.Updateable(taskInfo).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
            }
            foreach (var item in checkTaskList)
            {
                #region#给PLC写入结批批次号
                var listResult = new List<Result>();
                listResult.Add(plcConn.SetPlcDBValueRepeat(item.PosType, item.DbNumber, item.PlcPos, "0"));//品种号
                listResult.Add(plcConn.SetPlcDBValueRepeat(item.PosTypeLot, item.DbNumber, item.PosLot, ""));//批次号
                listResult.Add(plcConn.SetPlcDBValueRepeat(item.PosTypeStatus, item.DbNumber, item.PosStatus, "0"));//绑定状态 0:未绑定 1:已绑定
                if (listResult.All(s => s.IsSucceed))
                {
                    // 写入组托回复流程字
                    var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "110");
                    if (retVal.IsSucceed)
                    {
                        //写入流程字成功后更新分拣任务
                        item.OrderNo = "";
                        item.TaskNo = "";
                        item.LotNo = "";
                        item.SkuNo = "";
                        item.SkuName = "";
                        item.BoxType = "";
                        item.Qty = 0;
                        item.BoxCount = 0;
                        item.PZNo = "";
                        item.PalletNo = "";
                        item.Status = status;      // 绑定分道 0:解绑  1:绑定
                        //更新绑定信息
                        _db.Updateable(item).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                    }
                }
                else
                {
                    throw Oops.Bah("与PCL交互失败,结批失败!");
                }
                #endregion
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex.Message);
            throw;
        }
    }