using HH.WCS.Mobox3.NFLZ.device; using HH.WCS.Mobox3.NFLZ.process; using HH.WCS.Mobox3.NFLZ.util; using HH.WCS.Mobox3.NFLZ.wms; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static HH.WCS.Mobox3.NFLZ.wms.WMSHelper.AddChangeModel; using static System.Runtime.CompilerServices.RuntimeHelpers; namespace HH.WCS.Mobox3.NFLZ.core { /// /// 定时轮询任务 /// internal class Monitor { internal static void CheckThirdOutWork() { //第三方读中间表 //var db= new SqlHelper().GetInstance("中间表的sql连接字符串"); // db.Queryable //读到了出库单,插入到我们的表 } internal static void CheckOutWork() { //读自己的中间表,我们自己的表有表有个字段计数,计数小于最大值,继续出库,一次生成一条任务 } internal static void CheckDevice() { //检测输送线状态 S7Helper.ReadStr("plc1", 100, 1, 8); S7Helper.ReadBit("plc1", 101, 1, 2); S7Helper.ReadInt("plc1", 102, 1, 6); //1 设备plc的ip deviceNo 自动建立连接 //2 设备对应的通讯项和线体类型(输送线入口、输送线出口、提升机的入口。。。。)起始读的偏移地址,写的偏移地址 //{ "deviceNo":"5","code":"9001","location":"F1CJ-SSX1-01","writeAddr900":0,"writeAddr905":-1,"writeAddr710":0,"readAddr901":2,"readAddr902":0,"lineType":1}, //3 通讯项自动读plc,读到的数据根据lineType做处理,自动创建任务或者更新任务状态(创建一个设备动作或任务动作,如果是任务动作有个线程去读) } /// /// 转运任务 /// internal static void BottleBlankTransportation() { var db = new SqlHelper().GetInstance(); #region 瓶盖空托入库 var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶盖非即产空框" && a.enable == 1).FirstOrDefault(); if(areaInfo != null) { var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM == a.N_CAPACITY && a.S_LOCK_STATE == "无").First(); if(locInfo != null) { string cntrCode = getCntrCode(db, locInfo); if (string.IsNullOrEmpty(cntrCode)) { //创建作业 WMSHelper.CreateOpTask(locInfo.S_CODE, "", "入库", "瓶盖空托入库", cntrCode, "瓶盖"); } else { LogHelper.Info($"【瓶盖空托转运】当前货位未绑定托盘码,货位编码:{locInfo.S_CODE}"); } } } else { LogHelper.Info("【瓶盖空托转运】瓶盖非即产空框 未配置"); } #endregion #region 瓶坯满托入库 areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯入库接驳" && a.enable == 1).FirstOrDefault(); if (areaInfo != null) { var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM == a.N_CAPACITY && a.S_LOCK_STATE == "无").First(); if (locInfo != null) { string cntrCode = getCntrCode(db, locInfo); if (!string.IsNullOrEmpty(cntrCode)) { //创建作业 WMSHelper.CreateOpTask(locInfo.S_CODE, "", "入库", "瓶坯接驳位入库", cntrCode, "瓶坯"); } else { LogHelper.Info($"【瓶坯满托转运】当前货位未绑定托盘码,货位编码:{locInfo.S_CODE}"); } } } else { LogHelper.Info("【瓶坯满托转运】瓶坯入库接驳 未配置"); } #endregion } /// /// 瓶坯翻斗机非即产满框区补满托 /// internal static void PPFDFullIn() { //产线号 : 农夫林芝-1号瓶坯翻斗机 var db = new SqlHelper().GetInstance(); var bcpWorkList = db.Queryable().Where(a => a.S_PLineNo.Contains("瓶坯翻斗机") && a.S_UsingNow == "N" && a.S_WorkState == "执行中").ToList(); if(bcpWorkList.Count > 0) { bcpWorkList.ForEach(a => { string areaName = a.S_PLineNo.Split('-')[1].Substring(0, 1) + "号瓶坯翻斗机非即产满框"; LogHelper.Info($"PPFDFullIn area:{areaName}"); var areaInfo = Settings.areaInfos.Where(b => b.areaName == areaName && b.enable == 1).FirstOrDefault(); if(areaInfo != null) { var locInfo = db.Queryable().Where(b => b.S_AREA_CODE == areaInfo.areaCode && b.N_CURRENT_NUM == 0 && b.S_LOCK_STATE == "无").First(); if(locInfo != null) { //生成任务 Location location = TaskProcess.BCPInOrOut(db, false, "瓶坯库区", a.S_ItemCode); if(location != null) { string cntrCode = getCntrCode(db,location); //创建作业 WMSHelper.CreateOpTask(location.S_CODE, locInfo.S_CODE, "入库", "瓶坯非即产补满框", cntrCode, "瓶坯"); } } } else { LogHelper.Info($"{areaName}未配置"); } }); } } private static string getCntrCode(SqlSugar.SqlSugarClient db, Location location) { string cntr = ""; var cntrList = db.Queryable().Where(a => a.S_LOC_CODE == location.S_CODE).OrderBy(a => a.T_CREATE).ToList(); if(cntrList.Count > 0) { foreach(var a in cntrList) { cntr = cntr + a.S_CNTR_CODE + ","; } } cntr = cntr.TrimEnd(','); return cntr; } internal static void PGFDFullIn() { //产线号 : 农夫林芝-1号瓶盖翻斗机 //瓶盖翻斗机共用一个库区,需要区分几种情况(注:现场已确认,三个翻斗机不会有三种物料) //1、如果三个翻斗机物料相同,则 瓶盖非即产满框 有空货位就补 //2、如果三个翻斗机有两种不同的物料,则 瓶盖非即产满框 有空位的补充 改库区没有的物料 var db = new SqlHelper().GetInstance(); string itemList = ""; var bcpWorkList = db.Queryable().Where(a => a.S_PLineNo.Contains("瓶盖翻斗机") && a.S_UsingNow == "N" && a.S_WorkState == "执行中").ToList(); if (bcpWorkList.Count > 0) { bcpWorkList.ForEach(a => { if (string.IsNullOrEmpty(itemList)) { itemList = itemList + a.S_ItemCode + ","; } else { if (!itemList.Contains(a.S_ItemCode)) { itemList = itemList + a.S_ItemCode + ","; } } }); } if (!string.IsNullOrEmpty(itemList)) { itemList = itemList.TrimEnd(','); List itemCount = itemList.Split(',').ToList(); if(itemCount.Count > 0) { var areaInfo = Settings.areaInfos.Where(b => b.areaName == "瓶盖非即产满框" && b.enable == 1).FirstOrDefault(); if (areaInfo != null) { var locInfo = db.Queryable().Where(b => b.S_AREA_CODE == areaInfo.areaCode && b.N_CURRENT_NUM == 0 && b.S_LOCK_STATE == "无").First(); if (locInfo != null) { if (itemCount.Count == 1) { //只有一种物料 //生成任务 Location location = TaskProcess.BCPInOrOut(db, false, "瓶盖库区", itemCount[0]); if (location != null) { string cntrCode = getCntrCode(db, location); //创建作业 WMSHelper.CreateOpTask(location.S_CODE, locInfo.S_CODE, "入库", "瓶盖非即产补满框大包装", cntrCode, "瓶盖"); } } if (itemCount.Count == 2) { //两种物料 //判断库区是否有货位数量大于0或者有入库锁的,如果有,则判断物料,如果没有,则生成第一个物料的任务 var locInfo2 = db.Queryable().Where(b => b.S_AREA_CODE == areaInfo.areaCode && (b.N_CURRENT_NUM > 0 || b.S_LOCK_STATE == "入库锁")).First(); if(locInfo2 != null) { string itemCode = ""; if(locInfo2.N_CURRENT_NUM > 0) { var cntrInfo = db.Queryable().Where(b => b.S_LOC_CODE == locInfo2.S_CODE).First(); if(cntrInfo != null) { var itemInfo = db.Queryable().Where(b => b.S_CNTR_CODE == cntrInfo.S_CNTR_CODE).First(); if(itemInfo != null) { itemCode = itemInfo.S_ITEM_CODE; } } } if(locInfo2.S_LOCK_STATE == "入库锁") { var taskInfo = db.Queryable().Where(b => b.S_END_LOC == locInfo2.S_CODE && b.S_STATE != "完成" && b.S_STATE != "取消").First(); if(taskInfo != null) { string cntrCode = taskInfo.S_CNTR_CODE.Split(',')[0]; var itemInfo = db.Queryable().Where(b => b.S_CNTR_CODE == cntrCode).First(); if (itemInfo != null) { itemCode = itemInfo.S_ITEM_CODE; } } } if (itemCode != "") { itemCode = itemCode == itemCount[0] ? itemCount[1] : itemCount[0]; Location location = TaskProcess.BCPInOrOut(db, false, "瓶盖库区", itemCode); if (location != null) { string cntrCode = getCntrCode(db, location); //创建作业 WMSHelper.CreateOpTask(location.S_CODE, locInfo.S_CODE, "入库", "瓶盖非即产补满框大包装", cntrCode, "瓶盖"); } } } else { Location location = TaskProcess.BCPInOrOut(db, false, "瓶盖库区", itemCount[0]); if (location != null) { string cntrCode = getCntrCode(db, location); //创建作业 WMSHelper.CreateOpTask(location.S_CODE, locInfo.S_CODE, "入库", "瓶盖非即产补满框大包装", cntrCode, "瓶盖"); } } } } } else { LogHelper.Info($"瓶盖非即产满框 未配置"); } } } } /// /// 瓶坯非即产即用库托库区补空托 /// internal static void PPFDFullInEmpty() { //瓶坯非即产空框区堆叠库区一共四个货位,如果有三个货位是满的,就开始转运到瓶坯库区 //如果满货位小于等于一就开始从满框缓存区空框区域转运,如果满框缓存区空框区域无空托,则从瓶坯库转运 var db = new SqlHelper().GetInstance(); var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯非即产空框" && a.enable == 1).FirstOrDefault(); if (areaInfo != null) { var LocList = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM > 0).ToList(); if(LocList.Count <= 1) { LogHelper.Info($"瓶坯非即产补空框 {JsonConvert.SerializeObject(LocList)}"); var taskInfo = db.Queryable().Where(a => a.S_TYPE == "瓶坯非即产补空框" && a.S_B_STATE != "完成" && a.S_B_STATE != "取消").First(); if(taskInfo == null) { //需要从库区补充空托 Location location = TaskProcess.FJCKTLoc(); var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM < a.N_CAPACITY && a.S_LOCK_STATE == "无").OrderBy(a => a.N_ROW).First(); if (location != null && locInfo != null) { string cntrCode = getCntrCode(db, location); //创建作业 WMSHelper.CreateOpTask(location.S_CODE, locInfo.S_CODE, "入库", "瓶坯非即产补空框", cntrCode, "瓶坯"); } } } LocList = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM == a.N_CAPACITY).ToList(); if (LocList.Count > 2) { LogHelper.Info($"瓶坯非即产空托入库 {JsonConvert.SerializeObject(LocList)}"); var taskInfo = db.Queryable().Where(a => a.S_TYPE == "瓶坯非即产空框入库" && a.S_B_STATE != "完成" && a.S_B_STATE != "取消" && a.S_B_STATE != "卸货完成" && a.S_B_STATE != "开始卸货" && a.S_B_STATE != "取货完成").First(); if(taskInfo == null) { //需要将空托转运到库区 foreach (var a in LocList) { if (a.S_LOCK_STATE == "无") { //生成任务 string cntrCode = getCntrCode(db, a); //创建作业 WMSHelper.CreateOpTask(a.S_CODE, "", "入库", "瓶坯非即产空框入库", cntrCode, "瓶坯"); break; } } } } } #region //var workInfo = db.Queryable().Where(a => a.S_PLineNo == "农夫林芝-瓶坯机" && a.S_UsingNow == "N" && a.S_WorkState == "执行中").First(); //if(workInfo != null) //{ // var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯非即产空框" && a.enable == 1).FirstOrDefault(); // if(areaInfo != null) // { // var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无").First(); // if(locInfo != null) // { // //生成任务 // Location location = TaskProcess.BCPInOrOut(db, false, "瓶坯库区", ""); // if (location != null) // { // string cntrCode = getCntrCode(db, location); // //创建作业 // WMSHelper.CreateOpTask(location.S_CODE, locInfo.S_CODE, "入库", "瓶坯非即产补空框", cntrCode, "瓶坯"); // } // } // } // else // { // LogHelper.Info("瓶坯非即产空框 未配置"); // } //} #endregion } internal static void PGFDFullInJC() { var db = new SqlHelper().GetInstance(); var workInfo = db.Queryable().Where(a => a.S_PLineNo == "农夫林芝-瓶坯机" && a.S_UsingNow == "Y" && a.S_WorkState == "执行中").First(); if(workInfo != null) { var areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产满框" && a.enable == 1).FirstOrDefault(); if(areaInfo != null) { var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无").First(); if (locInfo != null) { //开始转运 Location startLoca = TaskProcess.BCPInOrOut(db, false, "瓶坯即产满框缓存", workInfo.S_ItemCode); if (startLoca != null) { //创建作业 string cntrCode = getCntrCode(db, startLoca); WMSHelper.CreateOpTask(startLoca.S_CODE, locInfo.S_CODE, "出库", "瓶坯即产补满框", cntrCode, ""); } } } areaInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产空框" && a.enable == 1).FirstOrDefault(); if (areaInfo != null) { var locInfo = db.Queryable().Where(a => a.S_AREA_CODE == areaInfo.areaCode && a.N_CURRENT_NUM == 0 && a.S_LOCK_STATE == "无").ToList(); if (locInfo.Count == 2) { //开始转运 Location startLoca = TaskProcess.BCPInOrOut(db, false, "瓶坯即产满框缓存", ""); if (startLoca != null) { //创建作业 string cntrCode = getCntrCode(db, startLoca); WMSHelper.CreateOpTask(startLoca.S_CODE, locInfo[0].S_CODE, "出库", "瓶坯即产补空框", cntrCode, ""); } } } } } /// /// 瓶盖小包装盖转运 /// /// internal static void PGXBZZY() { var db = new SqlHelper().GetInstance(); Location endLoca = null; var workInfo = db.Queryable().Where(a => a.S_PLineNo.Contains("瓶盖") && a.S_ITEM_TYPE == "小包装盖" && a.S_WorkState == "执行中").ToList(); if(workInfo.Count > 0) { foreach(var it in workInfo) { LogHelper.Info($"瓶盖小包装盖转运: 查询产线号:{it.S_PLineNo},物料编码:{it.S_ItemCode}"); //查询终点货位 string endAreaName = it.S_PLineNo.Split('-')[1].Substring(0, 1) + "号瓶盖翻斗机小包装"; var areaInfo = Settings.areaInfos.Where(b => b.areaName == endAreaName && b.enable == 1).FirstOrDefault(); if(areaInfo != null) { var taskInfo = db.Queryable().Where(a => a.S_END_AREA == areaInfo.areaCode && a.S_B_STATE != "完成" && a.S_B_STATE != "取消").First(); if(taskInfo != null) { //控制一个库区只能一次一条任务 return; } var locInfo = db.Queryable().Where(b => b.S_AREA_CODE == areaInfo.areaCode && b.N_CURRENT_NUM == 0).OrderBy(b => b.N_ROW).OrderBy(b => b.N_COL).Take(1).PartitionBy(b => b.N_ROW).ToList(); if(locInfo.Count > 0) { foreach(var endloc in locInfo) { var rowInfo = db.Queryable().Where(a => a.S_AREA_CODE == endloc.S_AREA_CODE && a.S_ROW == endloc.S_ROW).First(); LogHelper.Info($"瓶盖小包装盖转运:查询锁信息,货位锁:{endloc.S_LOCK_STATE},排锁:{JsonConvert.SerializeObject(rowInfo)}"); if(rowInfo!=null && rowInfo.S_LOCK_STATE == "无" && endloc.S_LOCK_STATE == "无") { endLoca = endloc; break; } } } } else { LogHelper.Info($"{endAreaName} 未配置"); } //查询起点货位 LogHelper.Info($"瓶盖小包装盖转运:获取到终点货位信息:{JsonConvert.SerializeObject(endLoca)}"); if (endLoca != null) { Location startLoca = TaskProcess.BCPInOrOut(db,true,"瓶盖库区",it.S_ItemCode + it.S_ITEM_TYPE); if (startLoca != null) { string cntrCode = getCntrCode(db, startLoca); WMSHelper.CreateOpTask(startLoca.S_CODE, endLoca.S_CODE, "出库", "瓶盖非即产补满框小包装", cntrCode, ""); } } } } } } }