111
cjs
2025-06-19 ad678d0d42f126e5c0d0e2f22f373d9727fb37a5
HH.WCS.Mobox3.NongFuLinZhi/process/DeviceProcess.cs
@@ -2,6 +2,7 @@
using HH.WCS.Mobox3.NFLZ.dispatch;
using HH.WCS.Mobox3.NFLZ.util;
using HH.WCS.Mobox3.NFLZ.wms;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -50,12 +51,442 @@
        private static void LinZhiAnalysisDeviceChange(string data, Settings.deviceInfo plc)
        {
            if (plc.deviceType == 1) AnalysisDoor(data, plc);//自动门处理
            //if (plc.deviceType == 2) LinJiangAnalysisProductLine(data, plc);//输送线处理 -- 成品下线
            //if (plc.deviceType == 3) LinJiangAnalysisProductLine(data, plc);//输送线处理 -- 空托上线
            if (plc.deviceType == 2) LinZhiAnalysisProductLine(data, plc);//输送线处理 -- 成品下线
            if (plc.deviceType == 3) LinZhiAnalysisProductLine(data, plc);//输送线处理 -- 空托上线
            if (plc.deviceType == 4) LinZhiAnalysisPreform(data, plc);//瓶坯机
            if (plc.deviceType == 5) LinZhiAnalysisPGDump(data, plc);//瓶盖翻斗机
            if (plc.deviceType == 6) LinZhiAnalysisPPDump(data, plc);//瓶坯翻斗机
        }
        private static void LinZhiAnalysisProductLine(string data, Settings.deviceInfo plc)
        {
            LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}", "输送线");
            if (LineState.Keys.Contains(plc.TN_Location[0]))
            {
                LineState[plc.TN_Location[0]].status = data;
                LineState[plc.TN_Location[0]].modify = DateTime.Now;
            }
            else
            {
                LineState.Add(plc.TN_Location[0], new statemodel { status = data, modify = DateTime.Now });
            }
            //状态1   满托下线或空托上线,具体任务类型需要根据TCP消息位数判断 11-满托下线  21-空托上线
            //满托下线:需要根据物料,品相,批次入库       空托上线:空托是否单独存在空托库区,待确定
            //不同产线下线库区不同,部分产线下线库区相同,但有先后顺序
            //下线库区先后顺序:入库区域顺序:3-6-2-5-4-1
            //B1~B6  双托下线--可能存在尾托为单托的情况--尾托(单托)人工PDA下发(入零头库)----满托下线
            //B1~B5  单托上线   B6  双托上线------------------------------------------------空托上线
            if (data.Length == 4)
            {
                if (data.Substring(0, 4) == "1220")
                {
                    //满托下线
                    ConveryInfoFull(plc, plc.TN_Location[0]);
                }
                if (data.Substring(0, 4) == "1021")
                {
                    //空托上线
                    ConveryInfoEmpty(plc, plc.TN_Location[0]);
                }
            }
        }
        /// <summary>
        /// 输送线空托上线
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="location"></param>
        private static void ConveryInfoEmpty(Settings.deviceInfo plc, string location)
        {
            //try
            //{
            //    if (location != "")
            //    {
            //        if (LocationHelper.CheckLocFree(location))
            //        {
            //            var db = new SqlHelper<object>().GetInstance();
            //            bool flag = true;
            //            var cgInfo = db.Queryable<CGTTable>().Where(a => a.Bit == location).First();
            //            if (cgInfo != null)
            //            {
            //                if (cgInfo.time.AddSeconds(5) > DateTime.Now)
            //                {
            //                    flag = false;
            //                }
            //
            //            }
            //            if (flag)
            //            {
            //                LogHelper.Info($"输送线:{plc.deviceName}, {location}补空信号 查询工单", "输送线");
            //                var workorder = WCSHelper.GetLinZhiWorkOrder(plc.deviceName);
            //                if (workorder != null && workorder.S_WorkState.Trim() == "执行中")
            //                {
            //                    LogHelper.Info($"输送线:{plc.deviceName}, {location}下线信号 找到工单", "输送线");
            //                    ProductLineempty(plc, location, workorder);
            //                }
            //                else
            //                {
            //                    LogHelper.Info($"输送线:{plc.deviceName} ,{location}下线信号 未找到工单", "输送线");
            //                }
            //            }
            //        }
            //        else
            //        {
            //            LogHelper.Info($"输送线:{plc.deviceName} 当前位置{location}有任务,不可触发空托上线", "输送线");
            //        }
            //    }
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine($"输送线呼叫空托异常! 异常信息={ex.Message}");
            //}
        }
        /// <summary>
        /// 输送线满托下线
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="location"></param>
        private static bool ConveryInfoFull(Settings.deviceInfo plc, string location)
        {
            var result = false;
            try
            {
                if (location != "")
                {
                    //取满,需要根据工单以及产线信息,判断当前产线应该下发到哪个库区,以及是什么托盘类型下线
                    if (LocationHelper.CheckLocFree(location))
                    {
                        var db = new SqlHelper<object>().GetInstance();
                        LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location} 查询工单", "输送线");
                        //1.查询当前产线工单信息
                        var workOrder = WCSHelper.GetLinZhiWorkOrder(plc.deviceName);
                        if (workOrder != null)
                        {
                            //workOrder.S_BatchNo = DateTime.Now.ToString("yyyy-MM-dd");
                            //db.Updateable(workOrder).UpdateColumns(a => new { a.S_BatchNo }).ExecuteCommand();
                            //
                            //workOrder = WCSHelper.GetLinJiangWorkOrder(plc.deviceName);
                            string DeviceStartTime = DateTime.Now.ToString();//当前设备第一次收到下线信号时间
                            string TrayCode = "";//托盘编码--多个编码用 英文逗号隔开
                            string BatchNo = string.IsNullOrEmpty(workOrder.S_BatchNo) ? "" : workOrder.S_BatchNo.Trim();//批次号
                            string ItemLayer = string.IsNullOrEmpty(workOrder.S_ItemLayer) ? "" : workOrder.S_ItemLayer.Trim();//物料层数
                            string ItemTrayType = workOrder.S_TrayType;//货物大小板--大板、小板、集化板(托盘类型需要变动)
                            string StartBit = plc.TN_Location[0];
                            string workNo = "";
                            //以下三个字段暂未使用
                            //string EndBit = "";
                            //string StartLayer = "1";//生产下线-起点层数默认为1
                            //string EndLayer = "";
                            //产线下线流程----正常流程下线
                            if (workOrder.S_ORDER_TYPE.Trim() != "无码入库")
                            {
                                bool full = true;
                                //判断当前货位是否存在托盘,如果存在则 无需从托盘信息中间表获取
                                var trayInfo = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == StartBit).ToList();
                                if (trayInfo.Count() > 0)
                                {
                                    BatchNo = workOrder.S_BatchNo.Trim();
                                    ItemLayer = workOrder.S_ItemLayer.Trim();
                                    trayInfo.ForEach(a =>
                                    {
                                        TrayCode = TrayCode + a.S_CNTR_CODE + ",";
                                        workNo = a.S_SRC;
                                    });
                                }
                                else
                                {
                                    //2.获取设备第一次下线时间
                                    bool IsTime = true;
                                    DeviceStartTime = ConveryInfoFullTwo(plc, DeviceStartTime);
                                    if (IsTime)
                                    {
                                        //3.处理 工单信息表数据--托规、批次号、物料层数
                                        full = ConveryInfoFullThree(plc, location, workOrder, DeviceStartTime, ref TrayCode, ref BatchNo, ref ItemLayer, ref workNo);
                                    }
                                    else full = false;
                                }
                                if (full)
                                {
                                    //5.正常产线下线
                                    ProductLineFull(plc, location, workOrder, TrayCode, BatchNo, ItemLayer, ItemTrayType, StartBit, workNo);
                                }
                                else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},托盘信息存在异常,请查询异常日志!", "输送线");
                            }
                            //无码入库流程----人工创建工单时----工单类型 应选择 无码入库
                            else
                            {
                                //判断当前设备口是否存在托盘(任务未取货完成,托盘还是绑定在设备口的),有沿用,无生成新托盘
                                var trayInfo = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == location).ToList();
                                if (trayInfo.Count() == 0) TrayCode = Guid.NewGuid().ToString("N") + "," + Guid.NewGuid().ToString("N");
                                else
                                {
                                    TrayCode = "";
                                    trayInfo.ForEach(a => { TrayCode = TrayCode + "," + a.S_CNTR_CODE.Trim(); });
                                }
                                LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location} 无码入库!", "输送线");
                                Console.WriteLine($"输送线:{plc.deviceName} 下线信号:{location} 无码入库!");
                                ProductLineFull(plc, location, workOrder, TrayCode, BatchNo, ItemLayer, workOrder.S_TrayType, StartBit, workOrder.S_WorkNo);
                            }
                        }
                        else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location} 未找到工单", "输送线");
                    }
                    else LogHelper.Info($"输送线:{plc.deviceName} 当前位置{location}有任务,不可触发满托下线", "输送线");
                }
            }
            catch (Exception ex)
            {
                LogHelper.Info($"输送线处理异常:{ex.Message}", "输送线");
            }
            return result;
        }
        private static void ProductLineFull(Settings.deviceInfo plc, string location, LinZhiWorkOrder workOrder, string TrayCode, string BatchNo, string ItemLayer, string ItemTrayType, string StartBit, string workNo = "", bool ProType = true)
        {
            //5.根据配置文件获取当前产线优先下发库区,再连同物料、大小板、批次,获取此库区 可用货位
            //      遍历库区查询-判断排锁-表名: RowLock
            var creResult = false;
            LogHelper.Info($"输送线:{plc.deviceName} 查询入库终点货位", "输送线");
            ////Console.WriteLine($"输送线:{plc.deviceName} 查询入库终点货位");
            //string ItemNameLayer = workOrder.S_ItemCode.Trim() + workOrder.S_ItemLayer.Trim();
            //var PriProLineInfo = Settings.GetDaMingShanPriProLineList().Where(a => a.deviceName == plc.deviceName && a.ItemTrayType == "满" && a.ItemName == workOrder.S_ItemCode.Trim()).FirstOrDefault();
            var db = new SqlHelper<object>().GetInstance();
            LogHelper.Info($"itemtrayType:{ItemTrayType}");
            var ipl = db.Queryable<itemPrecedenceLine>().Where(a => a.S_ITEM_CODE == workOrder.S_ItemCode.Trim() && a.S_TRAY_TYPE.Trim() == ItemTrayType.Trim()).OrderByDescending(a => a.S_PRIORITY).ToList();
            if (ipl.Count() > 0)
            {
                if (ProType)
                {
                    LogHelper.Info($"输送线:{plc.deviceName} 查询到表数据", "输送线");
                    ////Console.WriteLine($"输送线:{plc.deviceName} 查询到配置文件");
                    for (int i = 0; i < ipl.Count(); i++)
                    {
                        string areaCode = ipl[i].S_AREA_CODE;
                        if (!creResult) creResult = TaskProcess.LinZhiPlcTask(StartBit, "成品下线", TrayCode, areaCode, workOrder.S_ItemCode.Trim(), BatchNo, ItemLayer, ItemTrayType, plc.deviceName, true, workNo);
                    }
                }
                else
                {
                    for (int i = 0; i < ipl.Count(); i++)
                    {
                        string areaCode = ipl[i].S_AREA_CODE;
                        if (!creResult) creResult = TaskProcess.LinZhiPlcTask(StartBit, "零头下线", TrayCode, areaCode, workOrder.S_ItemCode.Trim(), BatchNo, ItemLayer, ItemTrayType, plc.deviceName, true, workOrder.S_WorkNo.Trim());
                    }
                }
                if (creResult)
                {
                    LogHelper.Info("绑定托盘表和托盘物料表");
                    //任务创建成功 绑定起点托盘表,托盘物料表
                    TaskProcess.BindLocCntr(StartBit, TrayCode, workOrder.S_ItemCode.Trim(), BatchNo, workNo, ItemLayer);
                }
            }
            else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location} 未获取到当前产线的优先下线库区 itemPrecedenceLine 数据。该物料不存在:{workOrder.S_ItemCode.Trim()}", "输送线");
        }
        private static bool ConveryInfoFullThree(Settings.deviceInfo plc, string location, LinZhiWorkOrder workOrder, string DeviceStartTime, ref string TrayCode, ref string BatchNo, ref string ItemLayer, ref string workNo)
        {
            bool result = true;
            var db = new SqlHelper<object>().GetInstance();
            //3.从 富勒托盘信息中间表 获取 dateTime < DeviceStartTime 的数据   ChunAnTrayInfo
            //      有两条:进入第 3-1 步
            //      小于两条:异常-连接 报警器 进行声光报警
            //3-1.判断托盘信息中 托规、批次号、物料层数 是否有值---------根据 托规 判断当前托盘是否为零头
            //      有值:判断当前值是否与 工单信息 相同,不同代表 当前产线切换了生产类型或首次下线,需同步更新 工单信息
            //      无值:判断工单是否存在对应值,不存在 即 异常
            if (!string.IsNullOrEmpty(DeviceStartTime))
            {
                var trayTableInfo = WCSHelper.GetLinZhiTrayInfoList(DeviceStartTime, plc.deviceName);
                if (trayTableInfo != null)
                {
                    if (trayTableInfo.Count == 2)// || trayTableInfo.Count == 1
                    {
                        workNo = trayTableInfo[0].workNo;
                        LogHelper.Info($"输送线:获取当前下线时间前的两个托盘数据,按时间升序。产线号:{plc.deviceName},下线时间:{DeviceStartTime}.", "输送线");
                        trayTableInfo = db.Queryable<LinZhiTrayInfo>().Where(a => Convert.ToDateTime(a.dateTime.Trim()) < Convert.ToDateTime(DeviceStartTime) && a.deviceName == plc.deviceName).OrderBy(a => a.dateTime).Take(2).ToList();
                        LogHelper.Info($"输送线:获取当前下线时间前的两个托盘数据为:{JsonConvert.SerializeObject(trayTableInfo)}。{plc.deviceName},下线时间:{DeviceStartTime}.", "输送线");
                        string trayCode = ""; string batchNo = ""; string itemLayer = "";
                        //1-首先判断工单 托规、批次号、物料层数 三个参数是否有值
                        //      有值:判断和当前值是否相同,不同 即 更新   UpdateWorkInfo
                        //      无值:更新工单对应信息
                        trayTableInfo.ForEach(a =>
                        {
                            trayCode = trayCode + "," + a.trayCode;
                            string TrayRule = "";
                            string UpdateWorkOn = "";//更新工单信息开关 默认为空 1-需要更新 托规、批次号、物料层数 信息
                            //生产下线:首托下线 必须 传输全部信息-托规、批次号、物料层数;否则 第一托就无法下线
                            //          之后如果缺少信息,可以从工单获取
                            //工单初始状态:托规、批次号、物料层数 必然有一个值为空;后续会一直有值
                            Console.WriteLine($"更改工单托盘数据:工单号:{workOrder.S_WorkNo},托规:{a.trayRule},批次号:{a.batchNo},物料层数:{a.itemLayer}");
                            if (string.IsNullOrEmpty(workOrder.S_TrayRules) || string.IsNullOrEmpty(workOrder.S_BatchNo) || string.IsNullOrEmpty(workOrder.S_ItemLayer))
                            {
                                WCSHelper.UpdateWorkInfo(workOrder, a.trayRule, a.batchNo, a.itemLayer);
                                batchNo = a.batchNo; itemLayer = a.itemLayer;
                            }
                            //处理 当前托盘 托规、批次号、物料层数 信息
                            ConveryInfoFullThreeS(plc, location, a, workOrder, DeviceStartTime, ref batchNo, ref itemLayer, ref TrayRule, ref UpdateWorkOn);
                            if (UpdateWorkOn == "1") WCSHelper.UpdateWorkInfo(workOrder, TrayRule, batchNo, itemLayer);
                            //零头物料判断
                            //if (TrayRule != a.trayNum)
                            //{
                            //    result = false;
                            //    LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},生产下线-当前物料箱数:{a.itemLayer}与标准托规:{TrayRule}不符,标准托规信息异常!", "输送线");
                            //    //正常下线-不是整托下线  连接报警器  报警
                            //    Console.WriteLine($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},生产下线-当前物料箱数:{a.itemLayer}与标准托规:{TrayRule}不符,标准托规信息异常!");
                            //    SendErrorTcpMsg(plc, DeviceStartTime);
                            //}
                        });
                        var trayAll = WCSHelper.GetLinJiangTrayInfoAllList(plc.deviceName);
                        if (trayTableInfo.Count != trayAll.Count && trayTableInfo.Count == 1)
                        {
                            result = false;
                            LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},第一次下线时间之前只获得{trayTableInfo.Count}条托盘信息,记录托盘信息为{trayAll.Count}条,托盘信息异常!", "输送线");
                            //连接报警器  进行异常报警
                            Console.WriteLine($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},第一次下线时间之前只获得{trayTableInfo.Count}条托盘信息,记录托盘信息为{trayAll.Count}条,托盘信息异常!");
                            SendErrorTcpMsg(plc, DeviceStartTime);
                            db.Deleteable<LinZhiDeviceState>().Where(a => a.DeviceName == plc.deviceName).ExecuteCommand();
                        }
                        TrayCode = trayCode; BatchNo = batchNo; ItemLayer = itemLayer;
                    }
                    else
                    {
                        result = false;
                        LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},第一次下线时间之前只获得{trayTableInfo.Count}条托盘信息,托盘信息异常!", "输送线");
                        //连接报警器  进行异常报警
                        Console.WriteLine($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},第一次下线时间之前只获得{trayTableInfo.Count}条托盘信息,托盘信息异常!");
                        SendErrorTcpMsg(plc, DeviceStartTime);
                        db.Deleteable<LinZhiDeviceState>().Where(a => a.DeviceName == plc.deviceName).ExecuteCommand();
                    }
                }
                else
                {
                    result = false;
                    LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},第一次下线时间之前只获得{trayTableInfo.Count}条托盘信息,托盘信息异常!", "输送线");
                    SendErrorTcpMsg(plc, DeviceStartTime);
                    db.Deleteable<LinZhiDeviceState>().Where(a => a.DeviceName == plc.deviceName).ExecuteCommand();
                }
            }
            else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location} ,DeviceStartTime 设备第一次下线时间为空,程序异常!", "输送线");
            return result;
        }
        /// <summary>
        /// 输送线托盘信息异常-向输送线发送异常信号
        /// 1、下线时间前的托盘数小于2
        /// 2、托规不等于当前数量
        /// </summary>
        /// <param name="plc"></param>
        public static void SendErrorTcpMsg(Settings.deviceInfo plc, string deviceStartTime)
        {
            if (DateTime.Now >= Convert.ToDateTime(deviceStartTime)) PlcHelper.SendHex(plc.address, "3F00600d0a");
        }
        private static void ConveryInfoFullThreeS(Settings.deviceInfo plc, string location, LinZhiTrayInfo a, LinZhiWorkOrder workOrder, string DeviceStartTime, ref string BatchNo, ref string ItemLayer, ref string TrayRule, ref string UpdateWorkOn)
        {
            if (string.IsNullOrEmpty(a.trayRule))
            {
                //传输缺少 标准托规信息,需要从工单获取
                if (!string.IsNullOrEmpty(workOrder.S_TrayRules)) TrayRule = workOrder.S_TrayRules;
                else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},托盘信息表无标准托规信息且工单:{workOrder.S_WorkNo}也没有标准托规信息,标准托规信息异常!", "输送线");
            }
            else
            {
                //中途切换了 生产物料,需要更新 工单信息
                if (workOrder.S_TrayRules != a.trayRule)
                {
                    TrayRule = a.trayRule;
                    UpdateWorkOn = "1";
                }
                else TrayRule = a.trayRule;
            }
            if (string.IsNullOrEmpty(a.batchNo))
            {
                //传输缺少 批次号信息,需要从工单获取
                if (!string.IsNullOrEmpty(workOrder.S_BatchNo)) BatchNo = workOrder.S_BatchNo;
                else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},托盘信息表无批次号信息且工单:{workOrder.S_WorkNo}也没有批次号信息,批次号信息异常!", "输送线");
            }
            else
            {
                //中途切换了 生产物料,需要更新 工单信息
                if (workOrder.S_BatchNo != a.batchNo)
                {
                    BatchNo = a.batchNo;
                    UpdateWorkOn = "1";
                }
                else BatchNo = a.batchNo;
            }
            if (string.IsNullOrEmpty(a.itemLayer))
            {
                //传输缺少 批次号信息,需要从工单获取
                if (!string.IsNullOrEmpty(workOrder.S_ItemLayer)) ItemLayer = workOrder.S_ItemLayer;
                else LogHelper.Info($"输送线:{plc.deviceName} 下线信号:{location},下线时间:{DeviceStartTime},托盘信息表无物料层数信息且工单:{workOrder.S_WorkNo}也没有物料层数信息,物料层数信息异常!", "输送线");
            }
            else
            {
                //中途切换了 生产物料,需要更新 工单信息
                if (workOrder.S_ItemLayer != a.itemLayer)
                {
                    ItemLayer = a.itemLayer;
                    UpdateWorkOn = "1";
                }
                else ItemLayer = a.itemLayer;
            }
        }
        private static string ConveryInfoFullTwo(Settings.deviceInfo plc, string DeviceStartTime)
        {
            //2.获取当前产线 设备中间表 对应信息   LinJiangDeviceState
            //2-1.有数据,判断当前是否为第一次收到下线信号
            //      第一次:更新 DeviceState = 1,DeviceStartTime = 当前时间
            //      第N次:判断当前 DeviceState 是否为1,不为1,更新 DeviceState 以及 DeviceStartTime
            //2-2.无数据,插入 DeviceName ,DeviceState = 1,DeviceStartTime = 当前时间 数据
            //任务创建成功会删除此表数据
            var db = new SqlHelper<object>().GetInstance();
            var workInfo = db.Queryable<LinZhiWorkOrder>().Where(a => a.S_PLineNo == plc.deviceName && a.S_ORDER_TYPE == "产线下线" && a.S_WorkState == "执行中").First();
            if (workInfo != null)
            {
                var deviceTableInfo = WCSHelper.GetLinJiangDeviceState(plc.deviceName);
                if (deviceTableInfo != null)
                {
                    if (deviceTableInfo.DeviceState.Trim() != "1")
                    {
                        WCSHelper.UpdateLinJiangDeviceState(deviceTableInfo, "1", DeviceStartTime);
                        //isTime = false;
                    }
                    else
                    {
                        DeviceStartTime = deviceTableInfo.DeviceTime;
                    }
                }
                else
                {
                    DateTime dateTime = Convert.ToDateTime(DeviceStartTime).AddMinutes(1);
                    DeviceStartTime = dateTime.ToString();
                    WCSHelper.LinJiangInsertDeviceState(new LinZhiDeviceState
                    {
                        DeviceName = plc.deviceName,
                        DeviceTime = DeviceStartTime,
                        DeviceState = "1"
                    });
                }
            }
            return DeviceStartTime;
        }
        /// <summary>
        /// 瓶坯翻斗机空托下线
        /// </summary>
@@ -83,14 +514,13 @@
            {
                LogHelper.Info($"查询到执行中的工单,工单类型:{workInfo.S_PLineNo}");
                string startArea = "";
                string endArea = "";
                string fullTaskType = "";
                string emptyTaskType = "";
                if (workInfo.S_UsingNow == "Y")
                {
                    LogHelper.Info("即产即用工单");
                    //即产即用在起点为线边
                    var bcpInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯即产即用A" && a.enable == 1).FirstOrDefault();
                    var bcpInfo = Settings.areaInfos.Where(a => a.areaName == "瓶胚即产即用满框" && a.enable == 1).FirstOrDefault();
                    if (bcpInfo != null)
                    {
                        startArea = bcpInfo.areaCode;
@@ -102,7 +532,8 @@
                {
                    LogHelper.Info("非即产即用工单");
                    //非即产即用起点为库区
                    var bcpInfo = Settings.areaInfos.Where(a => a.areaName == "瓶坯非即产即用" && a.enable == 1).FirstOrDefault();
                    string areaName = plc.deviceName.Split('-')[1].Substring(0, 1) + "号瓶胚翻斗机非即产满框";
                    var bcpInfo = Settings.areaInfos.Where(a => a.areaName == areaName && a.enable == 1).FirstOrDefault();
                    if (bcpInfo != null)
                    {
                        startArea = bcpInfo.areaCode;
@@ -110,8 +541,6 @@
                    fullTaskType = "翻斗机库存满托上线(瓶坯)";
                    emptyTaskType = "翻斗机库存空托下线(瓶坯)";
                }
                endArea = Settings.areaInfos.Where(a => a.areaName == "瓶坯翻斗机空托" && a.enable == 1).FirstOrDefault().areaCode;
                if (data.Length == 6)
                {
@@ -138,23 +567,19 @@
                                //判断当前翻斗机是否有送过满托 S_NOTE 字段默认空字符串,满托卸货完成之后会标记为满托,空托取货完成复位为空字符串
                                Location startLoca = null;
                                var locCode = plc.TN_Location[0];
                                var plcLoca = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == locCode).ToList();
                                if (plcLoca.Count <= 0)
                                var plcLoca = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == locCode).First();
                                if (plcLoca == null)
                                {
                                    LogHelper.Info($"瓶坯翻斗机上无托盘,生成满托上线任务,瓶坯翻斗机点位:{plc.TN_Location[0]}");
                                    //初始状态,无托盘,直接上满托(非即产即用需要校验 套袋完成,即产即用直接使用)
                                    if (workInfo.S_UsingNow == "Y")
                                    {
                                        LogHelper.Info($"瓶坯即产即用A库区查找");
                                        LogHelper.Info($"瓶胚即产即用满框 查找");
                                        startLoca = getFDSXArea(db, workInfo, startArea);
                                        if (startLoca == null)
                                        {
                                            LogHelper.Info($"瓶坯即产即用A库区未找到满托,去瓶坯即产即用B库区查找");
                                            startLoca = TaskProcess.BCPInOrOut(db, true, "瓶坯即产即用B", workInfo.S_ItemCode);
                                        }
                                    }
                                    else
                                    {
                                        LogHelper.Info($"瓶胚非即产库区 查找");
                                        startLoca = getFDSXArea(db, workInfo, startArea);
                                    }
@@ -169,7 +594,7 @@
                                    LogHelper.Info($"瓶坯翻斗机上有空托盘,生成空托下线任务,瓶坯翻斗机点位:{plc.TN_Location[0]}");
                                    //创建作业
                                    WMSHelper.CreateOpTask(locCode, "", "入库", emptyTaskType, plcLoca[0].S_CNTR_CODE);
                                    WMSHelper.CreateOpTask(locCode, "", "入库", emptyTaskType, plcLoca.S_CNTR_CODE);
                                }
                            }
                        }
@@ -212,12 +637,11 @@
            {
                LogHelper.Info($"查询到执行中的工单,工单类型:{workInfo.S_PLineNo}");
                string startArea = "";
                string endArea = "";
                string fullTaskType = "";
                string emptyTaskType = "";
                LogHelper.Info("非即产即用工单");
                //非即产即用起点为库区
                var bcpInfo = Settings.areaInfos.Where(a => a.areaName == "瓶盖非即产即用" && a.enable == 1).FirstOrDefault();
                var bcpInfo = Settings.areaInfos.Where(a => a.areaName == "瓶盖非即产满框" && a.enable == 1).FirstOrDefault();
                if (bcpInfo != null)
                {
                    startArea = bcpInfo.areaCode;
@@ -226,8 +650,6 @@
                fullTaskType = "翻斗机库存满托上线(瓶盖)";
                emptyTaskType = "翻斗机库存空托下线(瓶盖)";
                endArea = Settings.areaInfos.Where(a => a.areaCode == "瓶盖空托" && a.enable == 1).FirstOrDefault().areaCode;
                if (data.Length == 6)
                {
                    if (data.Substring(0, 2) == "11")
@@ -235,7 +657,6 @@
                        if (LocationHelper.CheckLocFree(plc.TN_Location[0]))
                        {
                            var bit = plc.TN_Location[0];
                            bool flag = true;
                            var cgInfo = db.Queryable<CGTTable>().Where(a => a.Bit == bit).First();
                            if (cgInfo != null)
@@ -251,8 +672,8 @@
                                Location startLoca = null;
                                var locCode = plc.TN_Location[0];
                                var plcLoca = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == locCode).ToList();
                                if (plcLoca.Count <= 0)
                                var plcLoca = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == locCode).First();
                                if (plcLoca == null)
                                {
                                    LogHelper.Info($"瓶盖翻斗机上无托盘,生成满托上线任务,瓶盖翻斗机点位:{plc.TN_Location[0]}");
                                    //初始状态,无托盘,直接上满托(非即产即用需要校验 套袋完成,即产即用直接使用)
@@ -266,9 +687,9 @@
                                }
                                else
                                {
                                    LogHelper.Info($"瓶盖翻斗机上有空托盘,生成空托下线任务,瓶盖翻斗机点位:{plc.TN_Location[0]}");
                                    LogHelper.Info($"瓶盖翻斗机上有空托盘,生成空托下线任务,瓶盖翻斗机点位:{locCode}");
                                    //创建作业
                                    WMSHelper.CreateOpTask(plc.TN_Location[0],"", "入库", emptyTaskType, startLoca.LocCntrRel.S_CNTR_CODE);
                                    WMSHelper.CreateOpTask(locCode, "", "入库", emptyTaskType, plcLoca.S_CNTR_CODE);
                                }
                            }
                        }
@@ -306,6 +727,10 @@
                    }
                }
            }
            else
            {
                LogHelper.Info($"为查询到可能满托,库区编码:{startArea}");
            }
            return result;
        }
@@ -319,6 +744,21 @@
        {
            LogHelper.Info($"{plc.deviceName}-{plc.address}-{data}", "瓶坯机");
            var db = new SqlHelper<object>().GetInstance();
            LogHelper.Info($"瓶坯机,查询任务终点:{plc.TN_Location[0]}");
            if (LineState.Keys.Contains(plc.TN_Location[0]))
            {
                LogHelper.Info("瓶坯机包含该任务终点");
                LineState[plc.TN_Location[0]].status = data;
                LineState[plc.TN_Location[0]].modify = DateTime.Now;
            }
            else
            {
                LogHelper.Info("瓶坯机未包含该任务终点");
                LineState.Add(plc.TN_Location[0], new statemodel { status = data, modify = DateTime.Now });
            }
            var workInfo = db.Queryable<LinZhiBCPWorkOrder>().Where(a => a.S_PLineNo == plc.deviceName).First();
            if (workInfo != null && workInfo.S_WorkState == "执行中")
            {
@@ -336,7 +776,6 @@
                    taskType = "注塑库存满托下线(瓶坯)";
                }
                //endArea = Settings.GetLinJiangBCPAreaList().Where(a => a.AreaName == "瓶坯满托" && a.Enable == "1").FirstOrDefault().AreaNo;
                if (data.Length == 4)
                {
                    if (data == "1122") LinZhialysisBottleCapAndPreformTwo(plc, db, workInfo, endArea, taskType, plc.TN_Location[0], "瓶坯机");
@@ -394,33 +833,32 @@
                                taskType = $"注塑库存空托上线({machine})";
                            }
                            
                            Location startLoca = TaskProcess.getMStartLoc(db);
                            //创建作业
                            WMSHelper.CreateOpTask(startLoca.S_CODE, deviceBit, "出库", taskType, startLoca.LocCntrRel.S_CNTR_CODE);
                            Location startLoca = TaskProcess.getMStartLoc(db,workInfo.S_UsingNow);
                            if (startLoca != null)
                            {
                                //创建作业
                                WMSHelper.CreateOpTask(startLoca.S_CODE, deviceBit, "出库", taskType, startLoca.LocCntrRel.S_CNTR_CODE);
                            }
                            else
                            {
                                LogHelper.Info("未查询到可出空托");
                            }
                        }
                        else
                        {
                            LogHelper.Info($"{type}注塑机上未绑定托盘,自动绑定托盘");
                            string cntrCode = Guid.NewGuid().ToString("N");
                            var cntrInfo = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == deviceBit).First();
                            if(cntrInfo == null)
                            {
                                LocCntrRel cntr = new LocCntrRel
                                {
                                    S_LOC_CODE = deviceBit,
                                    S_CNTR_CODE = cntrCode,
                                };
                                if (db.Insertable(cntr).ExecuteCommand() > 0)
                                {
                                    locInfo.N_CURRENT_NUM = locInfo.N_CURRENT_NUM + 1;
                                    db.Updateable(locInfo).UpdateColumns(a => a.N_CURRENT_NUM).ExecuteCommand();
                                    LogHelper.Info($"起点成功绑定托盘,起点:{deviceBit},托盘号:{cntrCode}");
                                }
                                LogHelper.Info($"{type}注塑机上未绑定托盘,自动绑定托盘");
                                TaskProcess.BindLocCntr(deviceBit, cntrCode, workInfo.S_ItemCode, "");
                            }
                            else
                            {
                                cntrCode = cntrInfo.S_CNTR_CODE;
                                TaskProcess.BindCntrItem(deviceBit, cntrCode, workInfo.S_ItemCode, "");
                            }
                            //创建作业
                            WMSHelper.CreateOpTask(deviceBit, "", "入库", taskType, cntrCode);
@@ -482,20 +920,35 @@
                if (mst.S_TYPE.Contains("翻斗机"))
                {
                    LogHelper.Info($"查询翻斗机允许取空信号 允许取空信号={LineState[mst.S_START_LOC.Trim()].status} 时间间隔={DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds}", "安全交互");
                    if (LineState[mst.S_START_LOC.Trim()].status == "112100" && DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds < 10)
                    if ((LineState[mst.S_START_LOC.Trim()].status == "112100" || LineState[mst.S_START_LOC.Trim()].status == "112200") && DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds < 10)
                    {
                        NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1101, 18);
                        //NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1101, 18);
                        NDCApi.ChangeOrderParam(mst.S_CODE.Trim(), 1101, "18");
                        TaskProcess.sendSing(mst, 1101);
                    }
                }
                else
                {
                    LogHelper.Info($"查询输送线允许取满信号 允许取满信号={LineState[mst.S_START_LOC.Trim()].status} 时间间隔={DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds}", "安全交互");
                    if (LineState[mst.S_START_LOC.Trim()].status == "1220" && DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds < 10)
                    if (mst.S_TYPE.Contains("满托下线"))
                    {
                        NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1101, 18);
                        TaskProcess.sendSing(mst, 1101);
                        if ((LineState[mst.S_START_LOC.Trim()].status == "1122" || LineState[mst.S_START_LOC.Trim()].status == "1221") && DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds < 10)
                        {
                            //NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1101, 18);
                            NDCApi.ChangeOrderParam(mst.S_CODE.Trim(), 1101, "18");
                            TaskProcess.sendSing(mst, 1101);
                        }
                    }
                    else
                    {
                        if (LineState[mst.S_START_LOC.Trim()].status == "1220" && DateTime.Now.Subtract(LineState[mst.S_START_LOC.Trim()].modify).TotalSeconds < 10)
                        {
                            //NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1101, 18);
                            NDCApi.ChangeOrderParam(mst.S_CODE.Trim(), 1101, "18");
                            TaskProcess.sendSing(mst, 1101);
                        }
                    }
                }
            }
            else LogHelper.Info($"字典中未找到该key的数据,key:{mst.S_START_LOC}");
@@ -512,20 +965,35 @@
                    if (mst.S_TYPE.Contains("翻斗机"))
                    {
                        LogHelper.Info($"查询翻斗机允许上满信号 允许上满信号={LineState[mst.S_END_LOC.Trim()].status} 时间间隔={DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds}", "安全交互");
                        if (LineState[mst.S_END_LOC.Trim()].status == "112100" && DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds < 10)
                        if ((LineState[mst.S_END_LOC.Trim()].status == "112100" || LineState[mst.S_END_LOC.Trim()].status == "112200") && DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds < 10)
                        {
                            NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1103, 18);
                            //NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1103, 18);
                            NDCApi.ChangeOrderParam(mst.S_CODE.Trim(), 1103, "18");
                            TaskProcess.sendSing(mst, 1103);
                        }
                    }
                    else
                    {
                        LogHelper.Info($"查询输送线允许补空信号 允许补空信号={LineState[mst.S_END_LOC.Trim()].status} 时间间隔={DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds}", "安全交互");
                        if (LineState[mst.S_END_LOC.Trim()].status == "1021" && DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds < 10)
                        if (mst.S_TYPE.Contains("空托上线"))
                        {
                            NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1103, 18);
                            TaskProcess.sendSing(mst, 1103);
                            if ((LineState[mst.S_END_LOC.Trim()].status == "1122" || LineState[mst.S_END_LOC.Trim()].status == "1221") && DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds < 10)
                            {
                                //NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1103, 18);
                                NDCApi.ChangeOrderParam(mst.S_CODE.Trim(), 1103, "18");
                                TaskProcess.sendSing(mst, 1103);
                            }
                        }
                        else
                        {
                            if (LineState[mst.S_END_LOC.Trim()].status == "1021" && DateTime.Now.Subtract(LineState[mst.S_END_LOC.Trim()].modify).TotalSeconds < 10)
                            {
                                //NDCHelper.ChangeParam(mst.S_CODE.Trim(), 1103, 18);
                                NDCApi.ChangeOrderParam(mst.S_CODE.Trim(), 1103, "18");
                                TaskProcess.sendSing(mst, 1103);
                            }
                        }
                    }
                }
                else LogHelper.Info($"字典中未包含终点的关键字,终点货位:{mst.S_END_LOC}");