bklLiudl
2024-09-11 5af0a043ffbbe444f7e43b6bf52a9e94c74283f2
Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -1,60 +1,470 @@

using DocumentFormat.OpenXml.Bibliography;
using Elastic.Clients.Elasticsearch.Tasks;
using Furion.Logging;
using IoTClient;
using Microsoft.AspNetCore.SignalR;
using RazorEngine.Compilation.ImpromptuInterface.Dynamic;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.ExtendedSDK.Global.Models;
using System.Data;
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)
    {
        var mod = sender as WcsDeviceDto;
        Console.WriteLine("PLC值为" + mod.Value);
        switch (mod.Type)
        try
        {
            case PLCTypeEnum.StackingMachine:
                if (mod.Value == 820)
            var mod = sender as WcsDeviceDto;
            Console.WriteLine("PLC值为" + mod.Value);
            switch (mod.Type)
            {
                case PLCTypeEnum.StackingMachine:
                    StackingMachine(mod);
                    break;
                case PLCTypeEnum.ConveyorLine:
                    ConveyorLine(mod);
                    break;
                case PLCTypeEnum.AGV:
                    AGV(mod);
                    break;
                case PLCTypeEnum.PalletMachine:
                    PalletMachine(mod);
                    break;
                default:
                    break;
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex.Message, ex);
        }
    }
    /// <summary>
    /// 跺机业务处理
    /// </summary>
    /// <param name="modDevice"></param>
    private static async void StackingMachine(WcsDeviceDto modDevice)
    {
        var plcConn = modDevice.PLCUtil;
        switch (modDevice.Value.ToString())
        {
            case "820":
                // 跺机空闲,获取出库任务、移库任务
                {
                    //测试写入830
                    var result = mod.PLCUtil.SetPlcDBValue(mod.PosType.Value, mod.DbNumber, mod.PlcPos, "830");
                    //写入是否成功
                    if (result.IsSucceed)
                    // 获取任务信息
                    var modTask = _db.Queryable<WcsTask>().OrderBy(m=>m.CreateTime).OrderBy(m=>m.Levels,OrderByType.Desc)
                        .First(s => s.Status == TaskStatusEnum.Wait && (s.TaskType == TaskTypeEnum.Out || s.TaskType == TaskTypeEnum.Move)
                        && s.StartRoadway == modDevice.StationNum);
                    if (modTask == null)
                    {
                        break;
                    }
                    // 根据目标地址和巷道获取放货工位对应的排列层
                    PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, modTask.TaskType.ToString(),
                        modTask.StartRoadway, modTask.EndRoadway);
                    // 目标工位不为null,需先判断放货工位是否空闲
                    if (!string.IsNullOrEmpty(taskInfo.EndStation))
                    {
                        // 打开对应的输送线连接
                        var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == taskInfo.Ip);
                        if (plcConveyorConn.Connected)
                        {
                            // 获取放货工位配置信息
                            var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == taskInfo.EndStation
                            && m.DeviceType == DeviceTypeEnum.Business);
                            var (result, value) = plcConveyorConn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.PlcPos);
                            if (result.IsSucceed)
                            {
                                if (value.ToString() != "720")              // 720:放货空位空闲,可放货
                                {
                                    Log.Error(string.Format("任务号:{0}:放货工位占用,稍后执行。", modTask.TaskNo));
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    // 获取转换后的起始排列层
                    PlcTaskInfo startTaskInfo = PLCCommon.GetEndPai(modTask.StartLocate.Substring(1, 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));
                    // 目标放货工位(固定排列层)
                    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))
                    {
                        // 写入跺机任务下发完成
                        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();
                        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();
                        //下发任务日志
                        _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        //修改led屏信息
                        //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
                    }
                }
                else if (mod.Value == 840)
                break;
            case "840":
                // 取货完成
                {
                    //测试批量读取
                    Dictionary<string, PLCDataTypeEnum> listaddress = new Dictionary<string, PLCDataTypeEnum>();
                    foreach (var modStation in mod.listStation)
                    {
                        listaddress.Add(modStation.PlcPos, modStation.PosType.Value);
                    }
                    var result = mod.PLCUtil.GetPlcBatchDBValue(listaddress);
                    if (!result.IsSucceed)
                    {
                        if (result.Value.Count > 0)//有错误的也有成功的
                        {
                    // 获取跺机点位配置
                    var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (res, val) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTask.PlcPos);
                    var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位");
                    var (endStationRes, endStation) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTask.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);
                        if (modTask == null)
                        {
                            Log.Error(string.Format("PLC控制字840:未找到对应的任务。"));
                            break;
                        }
                        // 记录任务明细
                        var modInsertTaskMonitor = new WcsTaskMonitor()
                        {
                            TaskNo = modTask.TaskNo,
                            PlcId = modDevice.Id,
                            PlcName = modDevice.Text,
                            PalletNo = modTask.PalletNo,
                            Status = TaskStatusEnum.Complete,
                            StartLocat = modTask.StartLocate,
                        };
                        if (modTask.TaskType == TaskTypeEnum.In)
                        {
                            // 获取跺机起始工位点位配置,读取起始工位
                            var modPosStartStation = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位");
                            var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosStartStation.PlcPos);
                            if (startStationRes.IsSucceed)
                            {
                                // 根据工位号获取对应的输送线IP
                                PlcTaskInfo taskInfo = PLCCommon.GetPlcIp(startStationVal);
                                var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == taskInfo.Ip);
                                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 modcTaskMonitor = new WcsTaskMonitor()
                                    {
                                        TaskNo = modTask.TaskNo,
                                        PlcId = ConveyorMod.Id,
                                        PlcName = ConveyorMod.Text,
                                        PalletNo = modTask.PalletNo,
                                        Status = TaskStatusEnum.Complete,
                                        StartLocat = startStationVal,
                                        EndLocat = modTask.EndLocate                  // 目标储位地址
                                    };
                                    if (!retc.IsSucceed)
                                    {
                                        modcTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0},写入取货完成640失败等待在次写入", startStationVal);
                                        // 插入交互日志
                                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                        //下发任务日志
                                        _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                        break;
                                    }
                                    modcTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0},写入取货完成640成功", startStationVal);
                                    // 插入交互日志
                                    _db.Insertable(modcTaskMonitor).ExecuteCommand();
                                    //下发任务日志
                                    _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                                }
                                // 写入流程控制字
                                var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                                if (!ret.IsSucceed)
                                {
                                    break;              // 写入失败跳出等待再次写入
                                }
                                modInsertTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0}跺机取货完成850成功", startStationVal);
                                modInsertTaskMonitor.EndLocat = modTask.EndLocate;                  // 目标储位地址
                                                                                             // 插入交互日志
                                _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                                //下发任务日志
                                _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                            }
                        }
                        else if (modTask.TaskType == TaskTypeEnum.Out)
                        {
                            // 写入流程控制字
                            var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                            if (!ret.IsSucceed)
                            {
                                break;              // 写入失败跳出等待再次写入
                            }
                            // 记录任务明细
                            modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate);
                            modInsertTaskMonitor.EndLocat = endStation;                  // 放货工位
                        }
                        else
                        {
                            // 写入流程控制字
                            var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850");
                            if (!ret.IsSucceed)
                            {
                                break;              // 写入失败跳出等待再次写入
                            }
                            modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate);
                            modInsertTaskMonitor.EndLocat = endStation;                  // 目标储位
                        }
                        // 插入交互日志
                        _db.Insertable(modInsertTaskMonitor).ExecuteCommand();
                        //下发任务日志
                        _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>());
                        //修改led屏信息
                        //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo);
                    }
                }
                break;
            case "860":
                {
                    // 获取跺机点位配置
                    var modPos860Task = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号");
                    var (res, val) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPos860Task.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);
                        if (modTask == null)
                        {
                            Log.Error(string.Format("跺机控制字860:未找到对应的任务。"));
                            break;
                        }
                        switch (modTask.TaskType)
                        {
                            case TaskTypeEnum.In:
                                {
                                    var res870 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870");
                                    if (!res870.IsSucceed)
                                    {
                                        Log.Error(string.Format("跺机控制字860写入870失败!"));
                                        break;
                                    }
                                    // 改变任务状态
                                    modTask.Status = TaskStatusEnum.Complete;
                                    modTask.FinishDate = DateTime.Now;
                                    _db.Updateable(modTask).ExecuteCommand();
                                    if (modTask.Origin == "WMS")
                                    {
                                        // 反馈WMS
                                        var requestMode = new TaskRequest()
                                        {
                                            TaskNo = modTask.TaskNo,
                                            PalletNo = modTask.PalletNo,
                                            TaskType = "1",
                                            TaskStatus = TaskStatusEnum.Complete
                                        };
                                        // 此处添加调用WMS接口 liudl
                                    }
                                    // 此处添加不空跑业务
                                }
                                break;
                            case TaskTypeEnum.Out: // 出库任务
                                {
                                }
                                break;
                            case TaskTypeEnum.Move:       // 移库任务
                                {
                                }
                                break;
                            default: break;
                        }
                    }
                }
                else if (mod.Value == 860)
                break;
            case "841":
                {
                }
                break;
            case PLCTypeEnum.ConveyorLine:
            case "843":
                {
                }
                break;
            case PLCTypeEnum.AGV:
                break;
            case PLCTypeEnum.PalletMachine:
            case "861":
                {
                }
                break;
            default:
                break;
        }
    }
    /// <summary>
    /// 输送线业务处理
    /// </summary>
    /// <param name="modDevice"></param>
    private static void ConveyorLine(WcsDeviceDto modDevice)
    {
    }
    /// <summary>
    /// AGV业务处理
    /// </summary>
    /// <param name="modDevice"></param>
    private static void AGV(WcsDeviceDto modDevice)
    {
    }
    /// <summary>
    /// 叠托机业务处理
    /// </summary>
    /// <param name="modDevice"></param>
    private static void PalletMachine(WcsDeviceDto modDevice)
    {
    }
    private static void Test(WcsDeviceDto modDevice)
    {
        //写死测试读string
        var (res, val) = modDevice.PLCUtil.GetPlcDBValue(PLCDataTypeEnum.String, "DB100", "64");
        Console.WriteLine("DB100.64----" + val);
        //测试批量读取
        Dictionary<string, PLCDataTypeEnum> listaddress = new Dictionary<string, PLCDataTypeEnum>();
        foreach (var modStation in modDevice.listStation)
        {
            listaddress.Add(modStation.PlcPos, modStation.PosType);
        }
        var result = modDevice.PLCUtil.GetPlcBatchDBValue(listaddress);
        if (result.Value.Count > 0)
        {
            foreach (var value in result.Value)
            {
                Console.WriteLine("地址" + value.Key + "----值" + value, value);
            }
        }
        if (!result.IsSucceed)
        {
            foreach (var err in result.ErrList)
            {
                Console.WriteLine(err);
            }
            if (result.Value.Count > 0)//有错误的也有成功的
            {
            }
        }
        if (modDevice.Value == 820)
        {
            //测试写入830
            //var result = mod.PLCUtil.SetPlcDBValue(mod.PosType.Value, mod.DbNumber, mod.PlcPos, "830");
            ////写入是否成功
            //if (result.IsSucceed)
            //{
            //}
        }
        else if (modDevice.Value == 840)
        {
        }
        else if (modDevice.Value == 860)
        {
        }
    }
}