IPC-610
2024-09-24 2fa5c9b94f81fca759daee763bdf8189ec728a33
Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -10,17 +10,13 @@
using System;
using System.Data;
using System.Reflection.Emit;
using WCS.Application.Entity;
using WCS.Application.Util;
namespace WCS.Application;
public static class PLCService
{
    private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
    private static readonly IHubContext<TaskLogHub, ITaskLogHub> _taskLogHubContext;
    static PLCService()
    {
        _taskLogHubContext = App.GetService<IHubContext<TaskLogHub, ITaskLogHub>>();
    }
    public static void OnChangeEvent(object sender, EventArgs e)
    {
@@ -31,16 +27,16 @@
            switch (mod.Type)
            {
                case PLCTypeEnum.StackingMachine:
                    StackingMachine(mod);
                    StackingMachine(mod);                           // 跺机
                    break;
                case PLCTypeEnum.ConveyorLine:
                    ConveyorLine(mod);
                    ConveyorLine(mod);                              // 托盘输送线
                    break;
                case PLCTypeEnum.AGV:
                    AGV(mod);
                    AGV(mod);                                       // AGV调度
                    break;
                case PLCTypeEnum.PalletMachine:
                    PalletMachine(mod);
                case PLCTypeEnum.RobotPalletizer:
                    RobotPalletizer(mod);                             // 码垛机器人
                    break;
                case PLCTypeEnum.StackingRobot:
                    PalletMachine(mod);
@@ -76,7 +72,7 @@
                    }
                    // 根据目标地址和巷道获取放货工位对应的排列层
                    PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, modTask.TaskType.ToString(),
                    PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(),
                        modTask.StartRoadway, modTask.EndRoadway);
                    // 目标工位不为null,需先判断放货工位是否空闲
@@ -110,8 +106,8 @@
                        }
                    }
                    // 获取转换后的起始排列层
                    PlcTaskInfo startTaskInfo = PLCCommon.GetEndPai(modTask.StartLocate.Substring(1, 2),
                    // 获取转换后的起始排列层 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));
@@ -141,14 +137,14 @@
                    if (listResult.All(s => s.IsSucceed))
                    {
                        // 写入跺机任务下发完成
                        plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "830");
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "830");
                        // 将移库任务待执行改为正在执行
                        _db.Updateable<WcsTask>()
                            .SetColumns(s => s.Status == TaskStatusEnum.Doing)
                            .Where(s => s.Id == modTask.Id)
                            .ExecuteCommand();
                        _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                        HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                        WcsTaskMonitor modInsertTaskMonitor;
                        if (string.IsNullOrEmpty(taskInfo.EndStation))
                        {
@@ -184,7 +180,7 @@
                        // 插入交互日志
                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                        //下发任务日志
                        _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        //修改led屏信息
                        //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
                    }
@@ -198,12 +194,12 @@
                    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, modPosTask.PlcPos);
                    var (endStationRes, endStation) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosEndStation.PlcPos);
                    if (res.IsSucceed)
                    {
                        // 获取任务信息
                        string tasknoVal = val.ToString();
                        var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == true);
                        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:未找到对应的任务。"));
@@ -224,17 +220,17 @@
                        {
                            // 获取跺机起始工位点位配置,读取起始工位
                            var modPosStartStation = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位");
                            var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosStartStation.PlcPos);
                            var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Short, modDevice.DbNumber, modPosStartStation.PlcPos);
                            if (startStationRes.IsSucceed)
                            {
                                // 根据工位号获取对应的输送线IP
                                var plcConveyorConn = PLCCommon.GetPlcIp(startStationVal);
                                PLCUtil plcConveyorConn = PLCCommon.GetPlcIp(startStationVal.ToString());
                                if (plcConveyorConn.Connected)
                                {
                                    // 向取货工位写入流程字640  取货已完成
                                    var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal
                                                            && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == true);
                                    var retc = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "640");
                                    var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal.ToString()
                                                            && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                                    var modcTaskMonitor = new WcsTaskMonitor()
                                    {
                                        TaskNo = modTask.TaskNo,
@@ -242,53 +238,83 @@
                                        PlcName = ConveyorMod.Text,
                                        PalletNo = modTask.PalletNo,
                                        Status = TaskStatusEnum.Complete,
                                        StartLocat = startStationVal,
                                        StartLocat = startStationVal.ToString(),
                                        EndLocat = modTask.EndLocate                  // 目标储位地址
                                    };
                                    // 读取wcs控制字
                                    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);
                                        modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成640失败", startStationVal);
                                        // 插入交互日志
                                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        //下发任务日志
                                        _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        break;
                                    }
                                    modcTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0},写入取货完成640成功", startStationVal);
                                    // 插入交互日志
                                    _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                    //下发任务日志
                                    _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    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;              // 写入失败跳出等待再次写入
                                }
                                modInsertTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0}跺机取货完成850成功", startStationVal);
                                modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                                    // 插入交互日志
                                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                //下发任务日志
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                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;              // 写入失败跳出等待再次写入
                            }
                            // 记录任务明细
                            modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate);
                            modInsertTaskMonitor.EndLocat = endStation;                  // 放货工位
                            //下发任务日志
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        }
                        else
                        {
@@ -301,12 +327,13 @@
                            modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate);
                            modInsertTaskMonitor.EndLocat = endStation;                  // 目标储位
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            //下发任务日志
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        }
                        // 插入交互日志
                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                        //下发任务日志
                        _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        //修改led屏信息
                        //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
                    }
@@ -321,7 +348,7 @@
                    if (res.IsSucceed)
                    {
                        string tasknoVal = val.ToString();
                        var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == true);
                        var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false);
                        if (modTask == null)
                        {
                            Log.Error(string.Format("跺机控制字860:未找到对应的任务。"));
@@ -343,8 +370,8 @@
                                    modTask.Status = TaskStatusEnum.Complete;
                                    modTask.FinishDate = DateTime.Now;
                                    _db.Updateable(modTask).ExecuteCommand();
                                    _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                                    var modcTaskMonitor = new WcsTaskMonitor()
                                    HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                                    var modTaskMonitor = new WcsTaskMonitor()
                                    {
                                        TaskNo = modTask.TaskNo,
                                        PlcId = modDevice.Id,
@@ -358,24 +385,34 @@
                                    if (modTask.Origin == "WMS")
                                    {
                                        // 反馈WMS
                                        var requestMode = new TaskRequest()
                                        var requestMode = new TaskRequestWMS()
                                        {
                                            TaskNo = modTask.TaskNo,
                                            PalletNo = modTask.PalletNo,
                                            TaskType = TaskTypeEnum.In,
                                            TaskStatus = TaskStatusEnum.Complete
                                            TaskType = ((int)TaskTypeEnum.In).ToString(),
                                            TaskStatus = ((int)TaskStatusEnum.Complete).ToString()
                                        };
                                        HttpService httpService = new HttpService();
                                        var modResponseTask = httpService.RequestTask(requestMode).Result;
                                        if (modResponseTask.StatusCode == "0")
                                        if (modResponseTask.StatusCode == 0)
                                        {
                                            modcTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成";
                                            modTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成";
                                        }
                                        else
                                        {
                                            Log.Error(string.Format("任务反馈失败:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg));
                                        }
                                    }
                                    // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。
                                    modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == modTask.StartLocate).Select(s => s.LedIP).First();
                                    // 插入交互日志
                                    _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                    _db.Insertable(modTaskMonitor).ExecuteCommand();
                                    //下发任务日志
                                    _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    // led显示内容
                                    LedDisplay(modDevice.LedIP, "工位:" + modTask.StartLocate, "入库完成 " + $"任务完成:{modTask.TaskNo}", "托盘号:" + modTask.PalletNo);
                                    // 此处添加不空跑业务
                                }
@@ -390,7 +427,7 @@
                                    if (plcConveyorConn.Connected)
                                    {
                                        // 根据目标地址和巷道获取放货工位对应的排列层
                                        PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, modTask.TaskType.ToString(),
                                        PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(),
                                            modTask.StartRoadway, modTask.EndRoadway);
                                        // 根据工位号获取工位信息
                                        var wcsDevice = PLCTaskAction.plcDevices.First(s => s.PlcId == plcConveyorConn.PlcId && s.Level == DeviceLevelEnum.Station && s.StationNum == taskInfo.EndStation);
@@ -401,19 +438,19 @@
                                        var listResult = new List<Result>();
                                        //任务号
                                        var modPosTask = listPos.FirstOrDefault(s => s.Text == "任务号");
                                        listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosTask.PosType, wcsDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                                        //任务类型
                                        var modPosTaskType = listPos.FirstOrDefault(s => s.Text == "任务类型");
                                        listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString()));
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosTaskType.PosType, wcsDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString()));
                                        //托盘号
                                        var modPosPalletNo = listPos.FirstOrDefault(s => s.Text == "托盘码");
                                        listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosPalletNo.PosType, wcsDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                                        //起始工位
                                        var modPosLocatNo = listPos.FirstOrDefault(s => s.Text == "起始工位");
                                        listResult.Add(plcConn.SetPlcDBValue(modPosLocatNo.PosType, modDevice.DbNumber, modPosLocatNo.PlcPos, taskInfo.EndStation));
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosLocatNo.PosType, wcsDevice.DbNumber, modPosLocatNo.PlcPos, taskInfo.EndStation));
                                        // 目标工位
                                        var modPosEndLocatNo = listPos.FirstOrDefault(s => s.Text == "目的工位");
                                        listResult.Add(plcConn.SetPlcDBValue(modPosEndLocatNo.PosType, modDevice.DbNumber, modPosEndLocatNo.PlcPos, outCode));
                                        listResult.Add(plcConveyorConn.SetPlcDBValue(modPosEndLocatNo.PosType, wcsDevice.DbNumber, modPosEndLocatNo.PlcPos, outCode));
                                        // 是否写入成功
                                        if (listResult.All(s => s.IsSucceed))
@@ -440,7 +477,15 @@
                                                    // 插入交互日志
                                                    _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                                    //下发任务日志
                                                    _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                                    HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                                    // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。
                                                    var taskModel = _db.Queryable<WcsTask>().First(w => w.TaskNo == modTask.TaskNo);
                                                    modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == taskModel.StartLocate).Select(s => s.LedIP).First();
                                                    // led显示内容
                                                    LedDisplay(modDevice.LedIP, "工位:" + modDevice.StationNum, "出库中 ", "托盘号:" + modTask.PalletNo);
                                                    break;
                                                }
                                            }
@@ -469,8 +514,7 @@
                                    modTask.FinishDate = DateTime.Now;
                                    _db.Updateable(modTask).ExecuteCommand();
                                    //下发任务日志
                                    _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                                    HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                                    var modcTaskMonitor = new WcsTaskMonitor()
                                    {
                                        TaskNo = modTask.TaskNo,
@@ -485,16 +529,16 @@
                                    if (modTask.Origin == "WMS")
                                    {
                                        // 反馈WMS
                                        var requestMode = new TaskRequest()
                                        var requestMode = new TaskRequestWMS()
                                        {
                                            TaskNo = modTask.TaskNo,
                                            PalletNo = modTask.PalletNo,
                                            TaskType = TaskTypeEnum.Move,
                                            TaskStatus = TaskStatusEnum.Complete
                                            TaskType = TaskTypeEnum.Move.ToString(),
                                            TaskStatus = TaskStatusEnum.Complete.ToString()
                                        };
                                        HttpService httpService = new HttpService();
                                        var modResponseTask = httpService.RequestTask(requestMode).Result;
                                        if (modResponseTask.StatusCode == "0")
                                        if (modResponseTask.StatusCode == 0)
                                        {
                                            modcTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成";
                                            //修改储位信息 任务类型 执行状态 起始位置 目标位置
@@ -504,7 +548,7 @@
                                    // 插入交互日志
                                    _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                    //下发任务日志
                                    _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                    // 此处添加不空跑业务
                                }
@@ -538,7 +582,7 @@
                        break;
                    modTask.Status = TaskStatusEnum.Exception;
                    _db.Updateable(modTask).UpdateColumns(s => s.Status).ExecuteCommand();
                    _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                    HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                    Log.Information($"【堆垛机】wcs任务变更空取异常,任务号:{modTask.TaskNo}");
                    var modTaskRequest = modTask.Adapt<TaskRequest>();
                    HttpService httpService = new HttpService();
@@ -549,7 +593,7 @@
                        modTask.IsSuccess = TaskSuccessEnum.Success;
                        _db.Updateable(modTask).UpdateColumns(s => s.IsSuccess).ExecuteCommand();
                        //下发任务日志
                        _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                        HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                    }
                    else
                    {
@@ -557,7 +601,7 @@
                        modTask.IsSuccess = TaskSuccessEnum.Fail;
                        modTask.Information = modResponseTask.Message;
                        _db.Updateable(modTask).UpdateColumns(s => new { s.IsSuccess, s.Information }).ExecuteCommand();
                        _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                        HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                    }
                }
                break;
@@ -578,7 +622,7 @@
                    }
                    modTask.Status = TaskStatusEnum.Exception;
                    _db.Updateable(modTask).UpdateColumns(s => s.Status).ExecuteCommand();
                    _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>());
                    HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                    Log.Information($"【堆垛机】wcs任务变更满取异常,任务号:{modTask.TaskNo}");
                    var modTaskRequest = modTask.Adapt<TaskRequest>();
                    HttpService httpService = new HttpService();
@@ -632,7 +676,7 @@
                            // 插入交互日志
                            _db.Insertable(modcTaskMonitor).ExecuteCommand();
                            //下发任务日志
                            _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        }
                    }
@@ -649,6 +693,164 @@
                break;
        }
    }
    /// <summary>
    /// 堆垛机不空跑
    /// </summary>
    /// <param name="modTask">操作完成的任务</param>
    /// <param name="plcConn">plc连接</param>
    /// <param name="modDevice">设备信息</param>
    private static void ContinuousOperation(WcsTask modTask, PLCUtil plcConn, WcsDeviceDto modDevice)
    {
        // 查询所有待执行的任务
        var listTask = _db.Queryable<WcsTask>().Where(s => s.Status == TaskStatusEnum.Wait).ToList();
        WcsTask modNextTask = null;
        switch (modTask.TaskType)
        {
            case TaskTypeEnum.In:
                {
                    // 先找出对应排列层的入库任务
                    var listInTask = listTask.Where(s => s.TaskType == TaskTypeEnum.In)
                                             .Select(s => s.EndLocate.Substring(0, 6))
                                             .ToHashSet();
                    // 找出库任务,对应巷道的任务
                    var listNextTask = listTask.Where(s => s.TaskType == TaskTypeEnum.Out && s.StartRoadway == modTask.EndRoadway).ToList();
                    foreach (var modNext in listNextTask)
                    {
                        // 如果有对应排列层的入库任务,那就不能优先执行
                        if (listInTask.Contains(modNext.EndLocate.Substring(0, 6)))
                        {
                            continue;
                        }
                        // todo: 写入modNext任务信息给plc
                        Console.WriteLine($"入库任务{modTask.TaskNo}执行完成后,不空跑逻辑检测下一任务为{modNext.TaskNo}");
                        modNextTask = modNext;
                        break;
                    }
                }
                break;
            case TaskTypeEnum.Out:
                {
                    // 先找出对应排列层的出库任务
                    var listInTask = listTask.Where(s => s.TaskType == TaskTypeEnum.Out)
                                             .Select(s => s.EndLocate.Substring(0, 6))
                                             .ToHashSet();
                    // 找入库任务,对应巷道的任务
                    var listNextTask = listTask.Where(s => s.TaskType == TaskTypeEnum.In && s.StartRoadway == modTask.EndRoadway).ToList();
                    foreach (var modNext in listNextTask)
                    {
                        // 如果有对应排列层的出库任务,那就不能优先执行
                        if (listInTask.Contains(modNext.EndLocate.Substring(0, 6)))
                        {
                            continue;
                        }
                        // todo: 写入modNext任务信息给plc
                        Console.WriteLine($"出库任务{modTask.TaskNo}执行完成后,不空跑逻辑检测下一任务为{modNext.TaskNo}");
                        modNextTask = modNext;
                        break;
                    }
                }
                break;
            case TaskTypeEnum.Move:
                {
                    var modDevicePos = _db.Queryable<WcsDevice>().Where(s => s.PlcId == plcConn.PlcId && s.DeviceType == DeviceTypeEnum.Show).First();
                    var (result, value) = plcConn.GetPlcDBValue(modDevicePos.PosType, modDevicePos.DbNumber, modDevicePos.PlcPos);
                    //当前堆垛机所在位置
                    var height = Math.Round(value / 790000d * 200).ToInt();
                    //todo:这里看能不能找到堆垛机所在位置在哪个排列层,优先寻找附近的任务?
                }
                break;
        }
        if (modNextTask != null)
        {
            // 获取转换后的起始排列层 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));
            // 给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));
            var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码");
            listResult.Add(plcConn.SetPlcDBValue(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));
            var modPosColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "取货列");
            listResult.Add(plcConn.SetPlcDBValue(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));
            // 目标放货工位(固定排列层)
            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));
            var modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列");
            listResult.Add(plcConn.SetPlcDBValue(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));
            // 是否写入成功
            if (listResult.All(s => s.IsSucceed))
            {
                // 写入跺机任务下发完成
                var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "830");
                // 将移库任务待执行改为正在执行
                _db.Updateable<WcsTask>()
                    .SetColumns(s => s.Status == TaskStatusEnum.Doing)
                    .Where(s => s.Id == modTask.Id)
                    .ExecuteCommand();
                HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                WcsTaskMonitor modInsertTaskMonitor;
                if (string.IsNullOrEmpty(taskInfo.EndStation))
                {
                    // 同巷道移库
                    modInsertTaskMonitor = new WcsTaskMonitor()
                    {
                        TaskNo = modTask.TaskNo,
                        PlcId = modDevice.Id,
                        PlcName = modDevice.Text,
                        InteractiveMsg = $"写入指令:{modTask.StartLocate}储位====》{modTask.EndLocate}储位。",
                        PalletNo = modTask.PalletNo,
                        Status = TaskStatusEnum.Complete,
                        StartLocat = modTask.StartLocate,
                        EndLocat = modTask.EndLocate,
                    };
                }
                else
                {
                    // 出库任务 跨巷道移库
                    modInsertTaskMonitor = new WcsTaskMonitor()
                    {
                        TaskNo = modTask.TaskNo,
                        PlcId = modDevice.Id,
                        PlcName = modDevice.Text,
                        InteractiveMsg = $"写入指令:{modTask.StartLocate}储位====》{taskInfo.EndStation}工位。",
                        PalletNo = modTask.PalletNo,
                        Status = TaskStatusEnum.Complete,
                        StartLocat = modTask.StartLocate,
                        EndLocat = modTask.EndLocate,
                    };
                }
                // 插入交互日志
                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                //下发任务日志
                HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                //修改led屏信息
                //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
            }
        }
    }
    /// <summary>
    /// 输送线业务处理
    /// </summary>
@@ -680,12 +882,16 @@
                    var http = new HttpService();
                    string TaskNo = "", EndLocate = "";
                    strMsg = http.RequestRoadWay(palletVal, modDevice.StationNum, taskModel, louCeng, ref EndLocate, ref TaskNo);
                    if (!strMsg.Contains("-1"))
                    {
                        // 根据任务号获取起始工位地址,根据起始工位地址获取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();
                        // 写入330
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "330");
                        if (ret.IsSucceed)
                        {
                            // 插入任务明细 
@@ -700,30 +906,27 @@
                                StartLocat = modDevice.StationNum,
                                EndLocat = EndLocate,
                            };
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            // 通知任务界面任务已存在更新 请更新界面
                            if (PLCTaskAction.boRefresh)
                            {
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                            // led更新内容
                            //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and  StationNum = '{EndLocat}'")[0];
                            //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo);
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            // led显示内容
                            LedDisplay(modDevice.LedIP, "工位:" + modDevice.StationNum, "申请入库 " + $"目标巷道:{EndLocate}", "托盘号:" + palletVal);
                        }
                    }
                    else
                    {
                        // 申请巷道失败!LED显示
                        Log.Error(string.Format($"申请巷道失败:{ strMsg },读写plc错误"));
                        Log.Error(string.Format($"申请巷道失败:{strMsg},读写plc错误"));
                    }
                }
                break;
            case "330":
                {
                    // 写入任务 托盘移动 340
                    // 获取工位托盘码信息
@@ -735,13 +938,13 @@
                    }
                    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 && s.StartRoadway == modDevice.StationNum);
                    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);
                    if (modTask == null)
                    {
                        // 此托盘没有对应的转移任务 led显示
                        break;
                    }
                    // 获取巷道口入库工位
                    string endLocatVlue = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, louCeng);
                    // 给PLC写入任务数据
@@ -749,8 +952,9 @@
                    // 任务号、任务类型、托盘号
                    var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
                    listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                    var modPosTaskType = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
                    listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, modTask.TaskType.ToString()));
                    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()));
                    var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码");
                    listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo));
                    // 起始工位、目的工位
@@ -758,7 +962,7 @@
                    listResult.Add(plcConn.SetPlcDBValue(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));
                    if (listResult.All(s => s.IsSucceed))
                    {
@@ -768,10 +972,12 @@
                           .Where(s => s.Id == modTask.Id)
                           .ExecuteCommand();
                        // 写入流程字 330 340
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "340");
                        // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。
                        modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == modTask.StartLocate).Select(s => s.LedIP).First();
                        if (ret.IsSucceed)
                        {
                            // 插入任务明细 
@@ -791,13 +997,10 @@
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            // 通知任务界面任务已存在更新 请更新界面
                            if (PLCTaskAction.boRefresh)
                            {
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            // led更新内容
                            //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
                            // led显示内容
                            LedDisplay(modDevice.LedIP, "工位:" + modDevice.StationNum, "入库中 " + $"目标巷道:{endLocatVlue}", "托盘号:" + palletVal);
                        }
                    }
@@ -806,7 +1009,7 @@
            case "620":
                {
                    // 申请储位 更新入库任务(储位地址) 630
                    var strMsg = "";
                    var taskModel = "";
                    // 判断是否演示模式
@@ -832,6 +1035,11 @@
                    string TaskNo = "";
                    // 向WMS申请储位信息
                    strMsg = http.RequestLocate(palletVal, modDevice.StationNum, taskModel, roadway, ref TaskNo);
                    // 根据任务号获取起始工位地址,根据起始工位地址获取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
@@ -856,13 +1064,9 @@
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            // 通知任务界面任务已存在更新 请更新界面
                            if (PLCTaskAction.boRefresh)
                            {
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                            // led更新内容
                            //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and  StationNum = '{EndLocat}'")[0];
                            //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo);
                            HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            // led显示内容
                            LedDisplay(modDevice.LedIP, "工位:" + modDevice.StationNum, "入库中 " + $"申请储位地址:{strMsg}", "托盘号:" + palletVal);
                        }
                    }
                    else
@@ -870,7 +1074,7 @@
                        // 申请储位失败!LED显示
                        Log.Error(string.Format($"申请储位失败:{strMsg},读写plc错误"));
                    }
                }
                break;
            case "630":
@@ -880,10 +1084,10 @@
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    // 获取工位托盘码信息
                    // 获取工位任务号信息
                    var modPosTaskNo = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (taskRes, taskNoVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTaskNo.PlcPos);
                    if (!res.IsSucceed || !taskRes.IsSucceed )
                    if (!res.IsSucceed || !taskRes.IsSucceed)
                    {
                        break;
                    }
@@ -896,13 +1100,13 @@
                        // 此托盘没有对应的转移任务 led显示
                        break;
                    }
                    var sInfo = PLCCommon.GetStokePlc(modTask.EndRoadway, louCeng);
                    if (string.IsNullOrWhiteSpace(sInfo.Ip))
                    {
                        //需加上LED显示
                        Log.Error(string.Format($"根据巷道获取跺机IP失败,请联系管理员"));
                        break;
                        break;
                    }
                    // 跺机连接
                    var plcStackeConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfo.Ip);
@@ -921,15 +1125,17 @@
                        string lie = int.Parse(endLocate.Substring(2, 2)).ToString();
                        string ceng = int.Parse(endLocate.Substring(4, 2)).ToString();
                        var djMod = PLCTaskAction.plcDevices.First(m => m.StationNum == modTask.EndRoadway
                        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 (djRes, djVal) = plcStackeConn.GetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.PlcPos);
                        if (!djRes.IsSucceed || djVal != "820")
                        if (!djRes.IsSucceed || djVal.ToString() != "820")
                        {
                            // 跺机非空闲等待
                            break;
@@ -941,12 +1147,13 @@
                        var modPosTask = djInfos.FirstOrDefault(s => s.Text == "任务号");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosTask.PosType, djMod.DbNumber, modPosTask.PlcPos, modTask.TaskNo));
                        var modPosTaskType = djInfos.FirstOrDefault(s => s.Text == "任务类型");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, modTask.TaskType.ToString()));
                        var modPosPalletNo = djInfos.FirstOrDefault(s => s.Text == "托盘号");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosPallet.PosType, djMod.DbNumber, modPosPallet.PlcPos, modTask.PalletNo));
                        var taskTypeStr = (int)modTask.TaskType;
                        listResult.Add(plcStackeConn.SetPlcDBValue(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));
                        //起始工位
                        var modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "取货排");
                        var modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "起始工位");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum));
                        //取货排、列、层
@@ -986,7 +1193,7 @@
                                // 插入交互日志
                                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                //下发任务日志
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                break;
                            }
@@ -994,17 +1201,18 @@
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            if (PLCTaskAction.boRefresh)
                            {   //下发任务日志
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            {
                                //下发任务日志
                                HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                        }
                        }
                    }
                    #endregion
                }
                break;
@@ -1017,7 +1225,7 @@
                    // led显示托盘信息
                    // 写入430
                    var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "430");
                    if (ret.IsSucceed)
                    {
                        var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
@@ -1043,14 +1251,14 @@
                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                        // 通知任务界面任务已存在更新 请更新界面
                        if (PLCTaskAction.boRefresh)
                        {
                            _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        }
                        // led更新内容
                        //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and  StationNum = '{EndLocat}'")[0];
                        //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo);
                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。
                        var taskInfo = _db.Queryable<WcsTask>().First(w => w.TaskNo == modInsertTaskMonitor.TaskNo);
                        modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == taskInfo.StartLocate).Select(s => s.LedIP).First();
                        // led显示内容
                        LedDisplay(modDevice.LedIP, "到达工位:" + modDevice.StationNum, "出库完成 " + $"储位地址:{modInsertTaskMonitor.StartLocat}", "托盘号:" + palletVal);
                    }
                    // 反馈WMS出库完成
                    //TaskReques taskReques = new TaskReques();
@@ -1074,30 +1282,61 @@
                        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);
                        string tasknoVal = taskVal.ToString();
                        var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false);
                        if (modTask == null)
                        {
                            Log.Error(string.Format("输送线440:未找到对应的任务。"));
                            break;
                        }
                        // 改变任务状态
                        modTask.Status = TaskStatusEnum.Complete;
                        modTask.FinishDate = DateTime.Now;
                        _db.Updateable(modTask).ExecuteCommand();
                        HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
                        // 插入任务明细 
                        var modInsertTaskMonitor = new WcsTaskMonitor()
                        {
                            TaskNo = taskVal,
                            TaskNo = modTask.TaskNo,
                            PlcId = modDevice.Id,
                            PlcName = modDevice.Text,
                            InteractiveMsg = $"写入指令450:{modDevice.StationNum}拣选完成,托盘离开工位",
                            PalletNo = palletVal,
                            Status = TaskStatusEnum.Complete,
                            StartLocat = starVal,
                            StartLocat = starVal.ToString(),
                            EndLocat = modDevice.StationNum,
                        };
                        if (modTask.Origin == "WMS")
                        {
                            // 反馈WMS
                            var requestMode = new TaskRequestWMS()
                            {
                                TaskNo = modTask.TaskNo,
                                PalletNo = modTask.PalletNo,
                                TaskType = ((int)TaskTypeEnum.Out).ToString(),
                                TaskStatus = ((int)TaskStatusEnum.Complete).ToString()
                            };
                            HttpService httpService = new HttpService();
                            var modResponseTask = httpService.RequestTask(requestMode).Result;
                            if (modResponseTask.StatusCode == 0)
                            {
                                modInsertTaskMonitor.InteractiveMsg += ",返回给WMS任务完成";
                            }
                            else
                            {
                                Log.Error(string.Format("任务反馈失败:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg));
                            }
                        }
                        // 插入交互日志
                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                        // 通知任务界面任务已存在更新 请更新界面
                        if (PLCTaskAction.boRefresh)
                        {
                            _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        }
                        // led更新内容
                        //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and  StationNum = '{EndLocat}'")[0];
                        //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo);
                        HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        // led显示内容
                        modDevice.LedIP = _db.Queryable<WcsDevice>().Where(w => w.StationNum == modTask.StartLocate).Select(s => s.LedIP).First();
                        LedDisplay(modDevice.LedIP, "工位:" + modTask.StartLocate, $"拣选完成,托盘离开工位", "托盘号:" + modTask.PalletNo);
                    }
                    #endregion
                }
@@ -1123,14 +1362,150 @@
    /// <param name="modDevice"></param>
    private static void PalletMachine(WcsDeviceDto modDevice)
    {
        var plcConn = modDevice.PLCUtil;
        switch (modDevice.Value.ToString())
        {
            case "220":
                // 注释1
                {
                }
                break;
            case "230":
                // 注释2
                {
                }
                break;
            case "240":
                {
                }
                break;
            default: break;
        }
    }
    /// <summary>
    /// 码垛机器人业务处理
    /// </summary>
    /// <param name="modDevice"></param>
    private static void RobotPalletizer(WcsDeviceDto modDevice)
    {
        var plcConn = modDevice.PLCUtil;
        switch (modDevice.Value.ToString())
        {
            case "1":
                // 主扫申请分道 wcs写入2
                {
                    var taskModel = "";
                    // 判断是否演示模式
                    if (PLCTaskAction.boDemo)
                    {
                        // 演示模式
                        taskModel = "1";
                        // 直接
                    }
                    else
                    {
                        // 通道号
                        var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号");
                        // 读取plc箱码
                        var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱码");
                        var (res, boxNo) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modBoxNo.PlcPos);
                        if (string.IsNullOrWhiteSpace(boxNo.ToString()))
                        {
                            // 箱码为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;
                                }
                            }
                        }
                        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;
            case "230":
                // 注释2
                {
                }
                break;
            case "240":
                {
                }
                break;
            default: break;
        }
    }
    /// <summary>
    /// 拆垛机器人业务处理
    /// </summary>
    /// <param name="modDevice"></param>
    private static void StackingRobot(WcsDeviceDto modDevice)
    private static void StackingRobot(WcsDeviceDto modDevice)
    {
        var plcConn = modDevice.PLCUtil;
        switch (modDevice.Value.ToString())
@@ -1145,6 +1520,23 @@
        }
    }
    /// <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)
    {
        try
        {
            LedDll Led = new LedDll();
            Led.LEDstr(ip, top, content, foot);
        }
        catch { }
    }
    private static void Test(WcsDeviceDto modDevice)
    {
        //写死测试读string