| | |
| | | |
| | | using Dm.filter; |
| | | using DocumentFormat.OpenXml.Bibliography; |
| | | using Elastic.Clients.Elasticsearch.Tasks; |
| | | using Furion.Logging; |
| | |
| | | using System; |
| | | using System.Data; |
| | | using System.Reflection.Emit; |
| | | using WCS.Application.Entity; |
| | | using WCS.Application.Util; |
| | | |
| | | namespace WCS.Application; |
| | |
| | | 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.BoxConveyorLine: |
| | | BoxConveyorLine(mod); // 码垛机器人 |
| | | break; |
| | | case PLCTypeEnum.StackingRobot: |
| | | PalletMachine(mod); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 输送线业务处理 |
| | | /// </summary> |
| | |
| | | #endregion |
| | | } |
| | | break; |
| | | #region 出库交互 |
| | | |
| | | #region 出库交互 |
| | | case "420": |
| | | { |
| | | #region 托盘到达拣选工位/出库口 |
| | |
| | | |
| | | #endregion |
| | | |
| | | case "50": |
| | | // plc申请空托 |
| | | { |
| | | // 调用WMS空托出库接口,返回出库任务存入出库表 |
| | | |
| | | // 写入 |
| | | } |
| | | break; |
| | | case "80": |
| | | // 空托盘跺已到位 |
| | | { |
| | | |
| | | } |
| | | break; |
| | | default: break; |
| | | } |
| | | |
| | |
| | | /// <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 async void BoxConveyorLine(WcsDeviceDto modDevice) |
| | | { |
| | | var plcConn = modDevice.PLCUtil; |
| | | |
| | | if (modDevice.DbNumber == "DB101") |
| | | { |
| | | // 主扫交互流程 |
| | | switch (modDevice.Value.ToString()) |
| | | { |
| | | case "1": |
| | | // 主扫申请分道 wcs写入2 |
| | | { |
| | | // 判断是否演示模式 true:演示模式 false:生产模式 |
| | | if (PLCTaskAction.boDemo) |
| | | { |
| | | // 通道号 |
| | | var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号"); |
| | | |
| | | // 演示模式直接写入1分道 |
| | | var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "1"); |
| | | if (ret.IsSucceed) |
| | | { |
| | | // 写入流程控制字 2 |
| | | var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); |
| | | if (!retVal.IsSucceed) |
| | | { |
| | | Log.Error("演示模式写入分道号失败!"); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // 通道号 |
| | | var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号"); |
| | | |
| | | // 读取plc箱码 |
| | | var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱码"); |
| | | var (res, boxNo) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos); |
| | | if (string.IsNullOrWhiteSpace(boxNo.ToString())) |
| | | { |
| | | // 箱码为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; |
| | | default: break; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // 插码交互 |
| | | switch (modDevice.Value.ToString()) |
| | | { |
| | | case "1": |
| | | // 托盘条码可读 |
| | | { |
| | | // 获取托盘条码配置 |
| | | var modPalletNo = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘条码"); |
| | | // 读取PLC托盘条码号 |
| | | var (res, palletVal) = plcConn.GetPlcDBValue(modPalletNo.PosType, modDevice.DbNumber, modPalletNo.PlcPos); |
| | | string palletNo = palletVal.ToString(); |
| | | if (string.IsNullOrEmpty(palletNo)) |
| | | { |
| | | Log.Error(string.Format("{0},读取的托盘号为null", modDevice.Text)); |
| | | break; |
| | | } |
| | | |
| | | // 根据工位号将托盘号保存在分道表 |
| | | var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false); |
| | | if (checkTaskMedel == null) |
| | | { |
| | | Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum)); |
| | | break; |
| | | } |
| | | checkTaskMedel.PalletNo = palletNo; |
| | | var rowCount = _db.Updateable(checkTaskMedel).ExecuteCommand(); |
| | | if (rowCount > 0 ) |
| | | { |
| | | // plc写入读取成功表示 2 |
| | | var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); |
| | | if (retVal.IsSucceed) |
| | | { |
| | | // liudl 此处需添加 |
| | | // 通知分拣码垛页更新 |
| | | } |
| | | } |
| | | } |
| | | break; |
| | | case "20": |
| | | // 申请插码 |
| | | { |
| | | // 获取托盘条码配置 |
| | | var modAddCode = modDevice.listStation.FirstOrDefault(m => m.Text == "插码结果"); |
| | | // 判断是否演示模式 true:演示模式 false:生产模式 |
| | | if (PLCTaskAction.boDemo) |
| | | { |
| | | // 演示模式直接写入插码结果 1:成功 |
| | | var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1"); |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | // 获取箱条码 |
| | | // 获取箱条码配置 |
| | | var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱条码"); |
| | | var (res, boxVal) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos); |
| | | string boxNo = boxVal.ToString(); |
| | | if (string.IsNullOrEmpty(boxNo)) |
| | | { |
| | | Log.Error(string.Format("码垛工位{0},箱码为null插码失败!请人工强制结批。"), modDevice.StationNum); |
| | | // 写入插入结果 2:插码失败 |
| | | var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2"); |
| | | break; |
| | | } |
| | | // 验证箱码表是否存在此箱码 |
| | | var boxInfo = _db.Queryable<WcsBoxInfo>().First(w => w.IsDelete == false && w.BoxNo == boxNo); |
| | | if (boxInfo == null) |
| | | { |
| | | Log.Error(string.Format("码垛工位{0},箱码{1}不存在!请人工强制结批。"), modDevice.StationNum,boxNo); |
| | | // 写入插入结果 2:插码失败 |
| | | var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2"); |
| | | break; |
| | | } |
| | | // 获取当前分道托盘号 |
| | | var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false); |
| | | if (checkTaskMedel == null) |
| | | { |
| | | Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum)); |
| | | break; |
| | | } |
| | | string palletNo = checkTaskMedel.PalletNo; |
| | | if (string.IsNullOrEmpty(palletNo)) |
| | | { |
| | | Log.Error(string.Format("获取码垛工位{0}上的托盘号失败!",modDevice.StationNum)); |
| | | break; |
| | | } |
| | | // 修改插码表 |
| | | boxInfo.PalletNo = palletNo; |
| | | boxInfo.UpdateTime = DateTime.Now; |
| | | var rowCount = _db.Updateable(boxInfo).ExecuteCommand(); |
| | | if (rowCount > 0) |
| | | { |
| | | // 插码成功 |
| | | var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1"); |
| | | } |
| | | else |
| | | { |
| | | // 插码失败 |
| | | Log.Error(string.Format("箱码{0};码垛工位{1},插码失败,请强制结批"),boxNo,modDevice.StationNum); |
| | | var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2"); |
| | | } |
| | | } |
| | | } |
| | | break; |
| | | case "40": |
| | | // 请求组托,申请入库 |
| | | { |
| | | // 根据工位号,获取托盘号 |
| | | var checkTaskMedel = _db.Queryable<WcsCheckTask>().First(m => m.Port == modDevice.StationNum && m.IsDelete == false); |
| | | // 根据工位号获取 托盘线该工位号的配置信息 |
| | | var numModel = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId != modDevice.PlcId); |
| | | var posModel = PLCTaskAction.plcPositions.First(m => m.DeviceId == numModel.Id && m.Text == "目的工位" && m.IsDelete == false); |
| | | if (checkTaskMedel == null) |
| | | { |
| | | Log.Error(string.Format("组托失败根据码垛工位{0},获取托盘号失败!", modDevice.StationNum)); |
| | | |
| | | // 写入交互工位目标地址 |
| | | var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234"); |
| | | if (retVal.IsSucceed) |
| | | { |
| | | // 写入组托回复流程字 |
| | | retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | // 码垛工位托盘号 |
| | | string palletNo = checkTaskMedel.PalletNo; |
| | | |
| | | // 是否演示模式 |
| | | if (PLCTaskAction.boDemo) |
| | | { |
| | | // 直接箱wms申请巷道 |
| | | var http = new HttpService(); |
| | | string TaskNo = "", EndLocate = ""; |
| | | string strMsg = http.RequestRoadWay(palletNo, modDevice.StationNum, "1", "2", ref EndLocate, ref TaskNo); |
| | | if (strMsg.Contains("-1")) |
| | | { |
| | | Log.Error(string.Format("申请巷道失败,码垛工位{0};原因{1}", modDevice.StationNum, strMsg)); |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | // 获取入库任务信息 |
| | | var taskModel = _db.Queryable<WcsTask>().First(m => m.TaskNo == TaskNo && m.IsDelete == false && m.Status == TaskStatusEnum.Wait); |
| | | if (taskModel != null) |
| | | { |
| | | // 获取入库取货工位 |
| | | string endLocatVlue = PLCCommon.RoadwayToStationNum(taskModel.EndRoadway, "2"); |
| | | |
| | | // 写入托盘输送线码垛工位 目的工位,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息} |
| | | var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue); |
| | | if (retVal.IsSucceed) |
| | | { |
| | | // 写入码垛交互-组托回复流程字 |
| | | retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); |
| | | |
| | | // 将入库任务由正在执行改为正在执行 |
| | | taskModel.Status = TaskStatusEnum.Doing; |
| | | _db.Updateable(taskModel).ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // 根据托盘号,将组托信息插入boxinfolog表 并删除boxinfo表数据 |
| | | var boxInfoList = await _db.Queryable<WcsBoxInfo>().Where(w => w.IsDelete == false && w.PalletNo == palletNo).ToListAsync(); |
| | | if (boxInfoList.Count <= 0) |
| | | { |
| | | Log.Error(string.Format("申请巷道失败,码垛工位{0},箱码信息不存在", modDevice.StationNum)); |
| | | |
| | | // 写入交互工位目标地址 |
| | | var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234"); |
| | | if (retVal.IsSucceed) |
| | | { |
| | | // 写入组托回复流程字 |
| | | retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); |
| | | } |
| | | break; |
| | | } |
| | | string sqlStr = $"insert into WCSBoxInfoLog select * from WCSBoxInfo where IsDelete=0 and PalletNo='{palletNo}'"; |
| | | int insertCount = _db.Ado.ExecuteCommand(sqlStr); |
| | | if (insertCount > 0) |
| | | { |
| | | string sqlStr2 = $"delete from WCSBoxInfo where IsDelete=0 and PalletNo='{palletNo}'"; |
| | | _db.Ado.ExecuteCommand(sqlStr2); |
| | | } |
| | | // 向WMS申请巷道 |
| | | var http = new HttpService(); |
| | | string TaskNo = "", EndLocate = ""; |
| | | string strMsg = http.BindRequestRoadWay(checkTaskMedel.OrderNo,palletNo, checkTaskMedel.BoxCount.ToDecimal(),"0", checkTaskMedel.SkuNo, checkTaskMedel.LotNo, "","", boxInfoList, |
| | | modDevice.StationNum, "1", "2", ref EndLocate, ref TaskNo); |
| | | if (!strMsg.Contains("-1")) |
| | | { |
| | | Log.Error(string.Format("申请巷道失败,码垛工位{0};原因{1}", modDevice.StationNum, strMsg)); |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | // 获取入库任务信息 |
| | | var taskModel = _db.Queryable<WcsTask>().First(m => m.TaskNo == TaskNo && m.IsDelete == false && m.Status == TaskStatusEnum.Wait); |
| | | if (taskModel != null) |
| | | { |
| | | // 获取入库取货工位 |
| | | string endLocatVlue = PLCCommon.RoadwayToStationNum(taskModel.EndRoadway, "2"); |
| | | |
| | | // 写入托盘输送线码垛工位 目的工位,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息} |
| | | var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue); |
| | | if (retVal.IsSucceed) |
| | | { |
| | | // 写入组托回复流程字 |
| | | retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); |
| | | if (retVal.IsSucceed) |
| | | { |
| | | // 将入库任务由正在执行改为正在执行 |
| | | taskModel.Status = TaskStatusEnum.Doing; |
| | | _db.Updateable(taskModel).ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | break; |
| | | default:break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |