chengsc
2024-09-11 2f0e0fa257c147a223d79ff8a52118768f43eee8
修改输送线交互逻辑
7个文件已修改
1182 ■■■■■ 已修改文件
Admin.NET/WCS.Application/Hub/PlcHub.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Model/PlcTaskInfo.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Model/TaskRequest.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCCommon.cs 431 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCService.cs 434 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Util/HttpService.cs 281 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Hub/PlcHub.cs
@@ -63,7 +63,7 @@
            PLCTaskAction.boRefresh = context.BoRefresh.Value;
            await _sysConfigService.UpdateConfigValue("sys_Refresh", context.BoRefresh.Value);
        }
        await _plcHubContext.Clients.All.UpdateService(new PLCServiceModel() { BoRunningState = PLCTaskAction.boRunningState, BoRefresh = PLCTaskAction.boRefresh, BoOffline = PLCTaskAction.boOffline });
        await _plcHubContext.Clients.All.UpdateService(new PLCServiceModel() { BoRunningState = PLCTaskAction.boRunningState, BoRefresh = PLCTaskAction.boRefresh, BoOffline = PLCTaskAction.boOffline, BoDemo = PLCTaskAction.boDemo});
    }
}
public class PLCServiceModel
@@ -75,4 +75,6 @@
    public bool? BoRefresh { get; set; }
    public bool? BoDemo { get; set; }
}
Admin.NET/WCS.Application/Model/PlcTaskInfo.cs
@@ -49,3 +49,15 @@
    /// </summary>
    public string EndRoadway { get; set; }
}
/// <summary>
/// 跺机对应的起始目标固定位置
/// </summary>
public class StokInfo
{
    public string Ip { get; set; }
    public string Pai { get; set; }
    public string Lie { get; set; }
    public string Ceng { get; set; }
}
Admin.NET/WCS.Application/Model/TaskRequest.cs
@@ -16,3 +16,15 @@
    public WcsTask TaskList { get; set; }
}
/// <summary>
/// 申请入库任务  巷道或储位
/// </summary>
public class RequestAsnTask
{
    public string PalletNo { get; set; }
    public string HouseNo { get; set; }
    public string RoadWayNo { get; set; }
    public string TaskModel { get; set; }
}
Admin.NET/WCS.Application/PLC/PLCCommon.cs
@@ -323,4 +323,435 @@
        return taskInfo;
    }
    /// <summary>
    /// 根据巷道和层数确定巷道口入库工位
    /// </summary>
    /// <param name="endRoadway"></param>
    /// <param name="ceng"></param>
    /// <returns></returns>
    public static string RoadwayToStationNum(string endRoadway, string ceng)
    {
        string stationNum = "";
        switch (endRoadway)
        {
            case "R01":
                if (ceng == "1")
                {
                    stationNum = "145";
                }
                if (ceng == "2")
                {
                    stationNum = "252";
                }
                if (ceng == "3")
                {
                    stationNum = "401";
                }
                break;
            case "R02":
                if (ceng == "1")
                {
                    stationNum = "137";
                }
                if (ceng == "2")
                {
                    stationNum = "260";
                }
                if (ceng == "3")
                {
                    stationNum = "405";
                }
                break;
            case "R03":
                if (ceng == "1")
                {
                    stationNum = "127";
                }
                if (ceng == "2")
                {
                    stationNum = "270";
                }
                if (ceng == "3")
                {
                    stationNum = "409";
                }
                break;
            case "R04":
                if (ceng == "1")
                {
                    stationNum = "119";
                }
                if (ceng == "2")
                {
                    stationNum = "278";
                }
                if (ceng == "3")
                {
                    stationNum = "413";
                }
                break;
            case "R05":
                if (ceng == "1")
                {
                    stationNum = "109";
                }
                if (ceng == "2")
                {
                    stationNum = "288";
                }
                if (ceng == "3")
                {
                    stationNum = "417";
                }
                break;
            case "R06":
                if (ceng == "1")
                {
                    stationNum = "101";
                }
                if (ceng == "2")
                {
                    stationNum = "301";
                }
                if (ceng == "3")
                {
                    stationNum = "421";
                }
                break;
            case "R07":
                if (ceng == "1")
                {
                    stationNum = "091";
                }
                if (ceng == "2")
                {
                    stationNum = "307";
                }
                if (ceng == "3")
                {
                    stationNum = "425";
                }
                break;
            case "R08":
                if (ceng == "1")
                {
                    stationNum = "83";
                }
                if (ceng == "2")
                {
                    stationNum = "315";
                }
                if (ceng == "3")
                {
                    stationNum = "429";
                }
                break;
            case "R09":
                if (ceng == "1")
                {
                    stationNum = "73";
                }
                if (ceng == "2")
                {
                    stationNum = "325";
                }
                if (ceng == "3")
                {
                    stationNum = "433";
                }
                break;
            case "R10":
                if (ceng == "1")
                {
                    stationNum = "65";
                }
                if (ceng == "2")
                {
                    stationNum = "337";
                }
                if (ceng == "3")
                {
                    stationNum = "437";
                }
                break;
        }
        return stationNum;
    }
    /// <summary>
    /// 根据工位号获取对应巷道
    /// </summary>
    /// <param name="StationNum">入出工位号</param>
    /// <returns>跺机联机</returns>
    public static string GetRoadwayByStation(string StationNum)
    {
        string value = "";
        var conveyList1 = new List<string>() { "147", "145", "252", "254", "401", "402", };
        var conveyList2 = new List<string>() { "139", "137", "260", "262", "405", "406", };
        var conveyList3 = new List<string>() { "129", "127", "272", "270", "409", "410", };
        var conveyList4 = new List<string>() { "121", "119", "278", "280", "413", "414", };
        var conveyList5 = new List<string>() { "111", "109", "288", "290", "417", "418", };
        var conveyList6 = new List<string>() { "103", "101", "294", "301", "421", "422", };
        var conveyList7 = new List<string>() { "093", "091", "307", "309", "425", "426", };
        var conveyList8 = new List<string>() { "085", "083", "315", "317", "429", "430", };
        var conveyList9 = new List<string>() { "075", "073", "325", "327", "433", "434", };
        var conveyList10 = new List<string>() { "067", "065", "331", "337", "437", "438", };
        if (conveyList1.Contains(StationNum))
        {
            value = "R01";
        }
        else if (conveyList2.Contains(StationNum))
        {
            value = "R02";
        }
        else if (conveyList3.Contains(StationNum))
        {
            value = "R03";
        }
        else if (conveyList4.Contains(StationNum))
        {
            value = "R04";
        }
        else if (conveyList5.Contains(StationNum))
        {
            value = "R05";
        }
        else if (conveyList6.Contains(StationNum))
        {
            value = "R06";
        }
        else if (conveyList7.Contains(StationNum))
        {
            value = "R07";
        }
        else if (conveyList8.Contains(StationNum))
        {
            value = "R08";
        }
        else if (conveyList9.Contains(StationNum))
        {
            value = "R09";
        }
        else if (conveyList10.Contains(StationNum))
        {
            value = "R10";
        }
        return value;
    }
    /// <summary>
    /// 根据巷道口出入库工位号获取对应楼层
    /// </summary>
    /// <param name="StationNum">入出工位号</param>
    /// <returns>跺机联机</returns>
    public static string GetRoadwayByStationNew(string StationNum)
    {
        string value = "";
        var conveyList1 = new List<string>() { "147", "145", "139", "137", "129", "127", "121", "119", "111", "109", "103", "101", "093", "091", "085", "083", "075", "073", "067", "065" };
        var conveyList2 = new List<string>() { "252", "254", "260", "262", "272", "270", "278", "280", "288", "290", "294", "301", "307", "309", "315", "317", "325", "327", "331", "337" };
        var conveyList3 = new List<string>() { "401", "402", "405", "406", "409", "410", "413", "414", "417", "418", "421", "422", "425", "426", "429", "430", "433", "434", "437", "438" };
        if (conveyList1.Contains(StationNum))
        {
            value = "1";
        }
        else if (conveyList2.Contains(StationNum))
        {
            value = "2";
        }
        else if (conveyList3.Contains(StationNum))
        {
            value = "3";
        }
        else
        {
            throw new Exception("工位未查询到");
        }
        return value;
    }
    /// <summary>
    /// 根据巷道号、层数 获取对应的跺机IP及入库工位排列层信息
    /// </summary>
    /// <param name="roadway">巷道号</param>
    /// <param name="plcList">连接集合</param>
    /// <returns></returns>
    public static StokInfo GetStokePlc(string roadway, string ceng)
    {
        StokInfo sInfo = new StokInfo();
        sInfo.Pai = "2";
        switch (roadway)
        {
            case "R01":
                sInfo.Ip = "10.18.51.10";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R02":
                sInfo.Ip = "10.18.51.20";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R03":
                sInfo.Ip = "10.18.51.30";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R04":
                sInfo.Ip = "10.18.51.40";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R05":
                sInfo.Ip = "10.18.51.50";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R06":
                sInfo.Ip = "10.18.51.60";
                if (ceng == "2" || ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R07":
                sInfo.Ip = "10.18.51.70";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R08":
                sInfo.Ip = "10.18.51.80";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R09":
                sInfo.Ip = "10.18.51.90";
                if (ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
            case "R10":
                sInfo.Ip = "10.18.51.100";
                if (ceng == "2" || ceng == "1")
                {
                    sInfo.Pai = "3";
                }
                break;
        }
        sInfo.Lie = "65";
        sInfo.Ceng = "1";
        if (ceng == "2")
        {
            sInfo.Ceng = "2";
        }
        if (ceng == "3")
        {
            sInfo.Ceng = "3";
        }
        return sInfo;
    }
    /// <summary>
    /// 根据储位排获取跺机对应的地址排
    /// </summary>
    /// <param name="road">排</param>
    /// <param name="pai">排</param>
    /// <param name="dept">深度</param>
    /// <returns></returns>
    public static int GetDjAdress(string road, string pai, string dept)
    {
        var roadNum = int.Parse(road);
        var paiNum = int.Parse(pai);
        var deptNum = int.Parse(dept);
        var paiVal = 0;
        // 判断巷道奇偶数
        if (roadNum % 2 == 0)// 偶数
        {
            // 判断排奇偶数
            if (paiNum % 2 == 0)
            {
                if (deptNum == 1)
                {
                    paiVal = 3;
                }
                else
                {
                    paiVal = 4;
                }
            }
            else
            {
                if (deptNum == 1)
                {
                    paiVal = 1;
                }
                else
                {
                    paiVal = 2;
                }
            }
        }
        else   // 奇数
        {
            // 判断排奇偶数
            if (paiNum % 2 == 0)
            {
                if (deptNum == 1)
                {
                    paiVal = 3;
                }
                else
                {
                    paiVal = 4;
                }
            }
            else
            {
                if (deptNum == 1)
                {
                    paiVal = 2;
                }
                else
                {
                    paiVal = 1;
                }
            }
        }
        return paiVal;
    }
}
Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -6,6 +6,7 @@
using Microsoft.AspNetCore.SignalR;
using RazorEngine.Compilation.ImpromptuInterface.Dynamic;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.ExtendedSDK.Global.Models;
using System;
using System.Data;
namespace WCS.Application;
@@ -396,6 +397,439 @@
    /// <param name="modDevice"></param>
    private static void ConveyorLine(WcsDeviceDto modDevice)
    {
        var plcConn = modDevice.PLCUtil;
        // 获取楼层数
        var louCeng = PLCCommon.GetRoadwayByStationNew(modDevice.StationNum);
        switch (modDevice.Value.ToString())
        {
            case "320":
                {
                    // 申请巷道
                    string strMsg = "";
                    string taskModel = "";
                    // 判断是否演示模式
                    if (PLCTaskAction.boDemo)
                    {
                        taskModel = "1";// 演示模式
                    }
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    var http = new HttpService();
                    string TaskNo = "", EndLocate = "";
                    strMsg = http.RequestRoadWay(palletVal, modDevice.StationNum, taskModel, louCeng, ref EndLocate, ref TaskNo);
                    if (!strMsg.Contains("-1"))
                    {
                        // 写入330
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "330");
                        if (ret.IsSucceed)
                        {
                            // 插入任务明细
                            var modInsertTaskMonitor = new WcsTaskMonitor()
                            {
                                TaskNo = TaskNo,
                                PlcId = modDevice.Id,
                                PlcName = modDevice.Text,
                                InteractiveMsg = $"写入指令330:{modDevice.StationNum}工位申请巷道",
                                PalletNo = palletVal,
                                Status = TaskStatusEnum.Complete,
                                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);
                        }
                    }
                    else
                    {
                        // 申请巷道失败!LED显示
                        Log.Error(string.Format($"申请巷道失败:{ strMsg },读写plc错误"));
                    }
                }
                break;
            case "330":
                {
                    // 写入任务 托盘移动 340
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    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);
                    if (modTask == null)
                    {
                        // 此托盘没有对应的转移任务 led显示
                        break;
                    }
                    // 获取巷道口入库工位
                    string endLocatVlue = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, louCeng);
                    // 给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 modPosTaskType = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
                    listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, modTask.TaskType.ToString()));
                    var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码");
                    listResult.Add(plcConn.SetPlcDBValue(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));
                    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))
                    {
                        // 将任务状态变更为正在执行
                        _db.Updateable<WcsTask>()
                           .SetColumns(s => s.Status == TaskStatusEnum.Doing)
                           .Where(s => s.Id == modTask.Id)
                           .ExecuteCommand();
                        // 写入流程字 330 340
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "340");
                        if (ret.IsSucceed)
                        {
                            // 插入任务明细
                            var modInsertTaskMonitor = new WcsTaskMonitor()
                            {
                                TaskNo = modTask.TaskNo,
                                PlcId = modDevice.Id,
                                PlcName = modDevice.Text,
                                InteractiveMsg = $"写入指令340:{modDevice.StationNum}储位====》{endLocatVlue}工位",
                                PalletNo = palletVal,
                                Status = TaskStatusEnum.Complete,
                                StartLocat = modDevice.StationNum,
                                EndLocat = endLocatVlue,
                            };
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            // 通知任务界面任务已存在更新 请更新界面
                            if (PLCTaskAction.boRefresh)
                            {
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                            // led更新内容
                            //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
                        }
                    }
                }
                break;
            case "620":
                {
                    // 申请储位 更新入库任务(储位地址) 630
                    var strMsg = "";
                    var taskModel = "";
                    // 判断是否演示模式
                    if (PLCTaskAction.boDemo)
                    {
                        // 演示模式
                        taskModel = "1";
                    }
                    // 根据工位号获取巷道号
                    var roadway = PLCCommon.GetRoadwayByStation(modDevice.StationNum);
                    if (roadway == "")
                    {
                        break;
                    }
                    // 获取工位托盘码信息
                    var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码");
                    var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos);
                    var http = new HttpService();
                    string TaskNo = "";
                    // 向WMS申请储位信息
                    strMsg = http.RequestLocate(palletVal, modDevice.StationNum, taskModel, roadway, ref TaskNo);
                    if (!strMsg.Contains("-1"))
                    {
                        // 写入流程字 630
                        var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "630");
                        if (ret.IsSucceed)
                        {
                            // 插入任务明细
                            var modInsertTaskMonitor = new WcsTaskMonitor()
                            {
                                TaskNo = TaskNo,
                                PlcId = modDevice.Id,
                                PlcName = modDevice.Text,
                                InteractiveMsg = $"写入指令340:{modDevice.StationNum}工位申请储位",
                                PalletNo = palletVal,
                                Status = TaskStatusEnum.Complete,
                                StartLocat = modDevice.StationNum,
                                EndLocat = strMsg,
                            };
                            // 插入交互日志
                            _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);
                        }
                    }
                    else
                    {
                        // 申请储位失败!LED显示
                        Log.Error(string.Format($"申请储位失败:{strMsg},读写plc错误"));
                    }
                }
                break;
            case "630":
                {
                    #region 写入跺机取货任务 640
                    // 获取工位托盘码信息
                    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);
                    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);
                    if (modTask == null)
                    {
                        // 此托盘没有对应的转移任务 led显示
                        break;
                    }
                    var sInfo = PLCCommon.GetStokePlc(modTask.EndRoadway, louCeng);
                    if (string.IsNullOrWhiteSpace(sInfo.Ip))
                    {
                        throw new Exception("根据巷道获取跺机IP失败,请联系管理员");
                    }
                    // 跺机连接
                    var plcStackeConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfo.Ip);
                    if (plcStackeConn.Connected)
                    {
                        // 目标排列层
                        var endLocate = modTask.EndLocate;
                        if (string.IsNullOrWhiteSpace(modTask.EndLocate))
                        {
                            Log.Error(string.Format($"目标位置为空,请人工处理,读写plc错误"));
                            break;
                        }
                        var paiVal = PLCCommon.GetDjAdress(modTask.EndRoadway.Substring(1, 2), endLocate.Substring(0, 2), endLocate.Substring(6, 2));
                        string pai = paiVal.ToString();
                        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
                            && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false);
                        var djInfos = PLCTaskAction.plcStation.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 (djVal != "820")
                        {
                            // 跺机非空闲等待
                            break;
                        }
                        // 给PLC写入任务数据
                        var listResult = new List<Result>();
                        // 任务号、任务类型、托盘号
                        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 modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "取货排");
                        listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum));
                        //取货排、列、层
                        var modPosStrPai = djInfos.FirstOrDefault(s => s.Text == "取货排");
                        listResult.Add(plcStackeConn.SetPlcDBValue(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));
                        var modPosStrCeng = djInfos.FirstOrDefault(s => s.Text == "取货层");
                        listResult.Add(plcStackeConn.SetPlcDBValue(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));
                        var modPosEndLie = djInfos.FirstOrDefault(s => s.Text == "放货列");
                        listResult.Add(plcStackeConn.SetPlcDBValue(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));
                        if (listResult.All(s => s.IsSucceed))
                        {
                            // 写入跺机 830
                            var retc2 = plcStackeConn.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();
                                //下发任务日志
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                break;
                            }
                            modInsertTaskMonitor.InteractiveMsg = $"跺机写入指令830:{modDevice.StationNum}工位====》" + modTask.EndLocate + "储位地址!";
                            // 插入交互日志
                            _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                            if (PLCTaskAction.boRefresh)
                            {   //下发任务日志
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                        }
                    }
                    #endregion
                }
                break;
            #region 出库交互
            case "420":
                {
                    #region 托盘到达拣选工位/出库口
                    // 出库口
                    // led显示托盘信息
                    // 写入430
                    var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "430");
                    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}工位",
                            PalletNo = palletVal,
                            Status = TaskStatusEnum.Complete,
                            StartLocat = starVal,
                            EndLocat = modDevice.StationNum,
                        };
                        // 插入交互日志
                        _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);
                    }
                    // 反馈WMS出库完成
                    //TaskReques taskReques = new TaskReques();
                    //taskReques.taskNo = TaskNo;
                    //taskReques.TaskType = "1";
                    //taskReques.TaskStatus = "2";
                    //bool bl = wcsMySql.RequestTasks(taskReques);
                    #endregion
                }
                break;
            case "440":
                {
                    #region 拣选完成,托盘离开工位
                    // 写入450
                    var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "450");
                    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 = $"写入指令450:{modDevice.StationNum}拣选完成,托盘离开工位",
                            PalletNo = palletVal,
                            Status = TaskStatusEnum.Complete,
                            StartLocat = starVal,
                            EndLocat = modDevice.StationNum,
                        };
                        // 插入交互日志
                        _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);
                    }
                    #endregion
                }
                break;
            #endregion
            default: break;
        }
    }
    /// <summary>
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -13,6 +13,8 @@
    public static bool boOffline = false;
    //自刷新
    public static bool boRefresh = false;
    //演示模式
    public static bool boDemo = false;
    public static List<PlcPositionInfo> listPositionInfo = new List<PlcPositionInfo>();
@@ -38,6 +40,11 @@
    {
        get { return listPlcDevice; }
    }
    // 交互点集合
    public static List<WcsPosition> plcStation
    {
        get { return listPlcStation; }
    }
    public static event EventHandler DeviceValueChangeEvent;
    static PLCTaskAction()
@@ -47,6 +54,7 @@
        boRunningState = _sysConfigService.GetConfigValue<bool>("sys_RunningState").Result;
        boOffline = _sysConfigService.GetConfigValue<bool>("sys_Offline").Result;
        boRefresh = _sysConfigService.GetConfigValue<bool>("sys_Refresh").Result;
        boDemo = _sysConfigService.GetConfigValue<bool>("sys_demo").Result;
    }
    /// <summary>
    /// 初始化PLC连接
Admin.NET/WCS.Application/Util/HttpService.cs
@@ -1,16 +1,297 @@
using Furion.Logging;
using Furion.RemoteRequest.Extensions;
using Newtonsoft.Json;
using System.Text;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.ComponentTCBBatchCreateContainerServiceVersionResponse.Types;
namespace WCS.Application;
public class HttpService
{
    private dynamic Urls;
    private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
    public HttpService()
    {
        var _sysConfigService = App.GetService<SysConfigService>();//todo 这里需要测试下生命周期问题
        Urls = _sysConfigService.GetSystemInfo().Result;
    }
    /// <summary>
    /// 调用WMS接口申请巷道接口
    /// </summary>
    /// <param name="palletNo"></param>
    /// <param name="startLocat"></param>
    /// <param name="taskModel"></param>
    /// <param name="ceng"></param>
    /// <param name="endLocat"></param>
    /// <param name="taskNo"></param>
    /// <returns></returns>
    public string RequestRoadWay(string palletNo, string startLocat, string taskModel, string ceng, ref string endLocat, ref string taskNo)
    {
        string returnStr = "";
        var task = _db.Queryable<WcsTask>().First(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing) && m.TaskType == TaskTypeEnum.In && m.PalletNo == palletNo);
        if (task == null)
        {
            var model = new RequestAsnTask()
            {
                PalletNo = palletNo,
                HouseNo = "W01",
                TaskModel = taskModel
            };
            string url = Urls.WMSAddress + ":" + Urls.WMSPort;
            var result =  (url + "/api/DownAPi/RequestRoadWay").SetBody(model, "application/json", Encoding.UTF8).PostAsAsync<ResponseTasks>().Result;
            Log.Information("调用WMS接口反馈任务接口" + result.ToJson());
            if (result.StatusCode == "0")
            {
                var taskAdd = new WcsTask()
                {
                    TaskType = TaskTypeEnum.In,
                    Origin = "WMS",
                    StartLocate = startLocat,
                    TaskNo = result.TaskList.TaskNo,
                    EndLocate = result.TaskList.EndLocate,
                    EndRoadway = result.TaskList.EndRoadway
                };
                _db.Insertable(taskAdd).ExecuteCommand();
                endLocat = result.TaskList.EndRoadway;
                returnStr = result.TaskList.EndLocate;
            }
            else
            {
                returnStr = "-1:" + result.Message;
                return returnStr;
            }
        }
        else
        {
            returnStr = task.EndLocate;
            endLocat = task.EndRoadway;
            taskNo = task.TaskNo;
        }
        endLocat = PLCCommon.RoadwayToStationNum(endLocat, ceng);
        return returnStr;
        // 确定目标工位//需添加层数确认
        //switch (endLocat)
        //{
        //    case "R01":
        //        if (ceng == "1")
        //        {
        //            endLocat = "145";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "252";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "101";
        //        }
        //        break;
        //    case "R02":
        //        if (ceng == "1")
        //        {
        //            endLocat = "137";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "260";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "405";
        //        }
        //        break;
        //    case "R03":
        //        if (ceng == "1")
        //        {
        //            endLocat = "127";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "270";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "409";
        //        }
        //        break;
        //    case "R04":
        //        if (ceng == "1")
        //        {
        //            endLocat = "119";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "278";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "413";
        //        }
        //        break;
        //    case "R05":
        //        if (ceng == "1")
        //        {
        //            endLocat = "109";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "288";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "417";
        //        }
        //        break;
        //    case "R06":
        //        if (ceng == "1")
        //        {
        //            endLocat = "101";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "301";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "421";
        //        }
        //        break;
        //    case "R07":
        //        if (ceng == "1")
        //        {
        //            endLocat = "091";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "307";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "425";
        //        }
        //        break;
        //    case "R08":
        //        if (ceng == "1")
        //        {
        //            endLocat = "083";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "315";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "429";
        //        }
        //        break;
        //    case "R09":
        //        if (ceng == "1")
        //        {
        //            endLocat = "073";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "325";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "433";
        //        }
        //        break;
        //    case "R10":
        //        if (ceng == "1")
        //        {
        //            endLocat = "065";
        //        }
        //        else if (ceng == "2")
        //        {
        //            endLocat = "337";
        //        }
        //        else if (ceng == "3")
        //        {
        //            endLocat = "437";
        //        }
        //        break;
        //}
    }
    /// <summary>
    /// 调用WMS接口申请储位接口
    /// </summary>
    /// <param name="palletNo"></param>
    /// <param name="startLocat"></param>
    /// <param name="taskModel"></param>
    /// <param name="starRoadWay"></param>
    /// <param name="taskNo"></param>
    /// <returns></returns>
    public string RequestLocate(string palletNo, string startLocat, string taskModel, string starRoadWay, ref string taskNo)
    {
        string returnStr = "";
        var task = _db.Queryable<WcsTask>().First(m => m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing) && m.TaskType == TaskTypeEnum.In && m.PalletNo == palletNo && string.IsNullOrWhiteSpace(m.EndLocate));
        if (task == null)
        {
            var model = new RequestAsnTask()
            {
                PalletNo = palletNo,
                HouseNo = "W01",
                RoadWayNo = starRoadWay,
                TaskModel = taskModel
            };
            string url = Urls.WMSAddress + ":" + Urls.WMSPort;
            var result = (url + "/api/DownAPi/RequestLocation").SetBody(model, "application/json", Encoding.UTF8).PostAsAsync<ResponseTasks>().Result;
            Log.Information("调用WMS申请储位接口反馈任务接口" + result.ToJson());
            if (result.StatusCode == "0")
            {
                var taskAdd = new WcsTask()
                {
                    TaskType = TaskTypeEnum.In,
                    Origin = "WMS",
                    StartLocate = startLocat,
                    TaskNo = result.TaskList.TaskNo,
                    EndLocate = result.TaskList.EndLocate,
                    EndRoadway = result.TaskList.EndRoadway
                };
                _db.Updateable(taskAdd).ExecuteCommand();
                returnStr = result.TaskList.EndLocate;
                taskNo = result.TaskList.TaskNo;
            }
            else
            {
                returnStr = "-1:" + result.Message;
                return returnStr;
            }
        }
        else
        {
            returnStr = task.EndLocate;
            taskNo = task.TaskNo;
        }
        return returnStr;
    }
    /// <summary>
    /// 调用WMS接口反馈任务接口
    /// </summary>