1
zxx
2 天以前 d66d362ee6d76f02331e56df1fdec1c2114c9f3e
HH.WCS.Mobox3/HH.WCS.Mobox3.XiaoMi/process/TaskProcess.cs
@@ -27,6 +27,9 @@
using Newtonsoft.Json.Linq;
using S7.Net;
using System.Threading.Tasks;
using HH.WCS.XiaoMi.LISTA.dispatch;
using static HH.WCS.XiaoMi.LISTA.dispatch.RcsHelper;
using System.Diagnostics;
namespace HH.WCS.XiaoMi.process
{
@@ -46,32 +49,14 @@
            {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                if (mst.S_FRAME_CODE != null)
                {
                    LocationHelper.UnBindingLocHj(mst.S_START_LOC, mst.S_FRAME_CODE);
                LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList());
                }
                else
                {
                    LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList());
                }
            }
            else
            {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                //如果货架有值则绑货架
                if (mst.S_FRAME_CODE!=null)
                {
                    LocationHelper.BindingLocHj(mst.S_END_LOC, mst.S_FRAME_CODE);
                }
                else
                {
                    LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList());
                }
                LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
        }
@@ -138,9 +123,15 @@
            if (state == 7)
            {
                CacheBitCancelUpdate(mst);
                ////小米订单取消
                //CancelModel cancelModel = new CancelModel();
                //cancelModel.order_name = mst.S_CODE;
                //cancelModel.order_command_type_id = 2;
                //RcsHelper.CancelOrder(cancelModel);
            }
        }
        private static object locLocker = new object();
        /// <summary>
@@ -368,7 +359,127 @@
            else { result = true; }
            return result;
        }
        //小米推送任务
        internal static bool SendXmTask(WCSTask mst)
        {
            var result = false;
            var taskState = mst.N_B_STATE;
            if (taskState == 0)
            {
                Console.WriteLine($"任务mst {JsonConvert.SerializeObject(mst)}");
                LogHelper.Info($"任务mst {JsonConvert.SerializeObject(mst)}", "任务");
                //var startLoc = LocationHelper.GetLoc(mst.S_START_LOC);
                //var endLoc = LocationHelper.GetLoc(mst.S_END_LOC);
                if (mst.S_START_LOC != null && mst.S_END_LOC != null)
                {
                    bool res = false;
                    if (mst.S_TYPE == "大件")
                    {
                        string src = $"\"src\":\"{mst.S_START_LOC}\",";
                        string dst = $"\"dst\":\"{mst.S_END_LOC}\",";
                        string carrier_type_id = $"\"carrier_type_id\":\"1\"";
                        string parmeS = "{";
                        string parmeD = "}";
                        string parme = parmeS + src + dst + carrier_type_id + parmeD;
                        LogHelper.Info($"推送任务参数{parme}", "任务");
                        AntsTaskModel model = new AntsTaskModel();
                        model.order_name = mst.S_CODE;
                        model.priority = 1;
                        model.dead_line = DateTime.Now.ToString();
                        model.ts_name = "p2p";
                        model.parameters = parme;
                        //model.parameters = new AntsParasModel {
                        //    src = mst.S_START_LOC,
                        //    dst = mst.S_END_LOC,
                        //    carrier_type_id="-99"
                        //};
                        res = RcsHelper.CreateAntsOrder(model);
                    }
                    else if (mst.S_TYPE == "小件通用车型")
                    {
                        string src = $"\"src\":\"{mst.S_START_LOC}\",";
                        string dst = $"\"dst\":\"{mst.S_END_LOC}\",";
                        string car_type = $"\"car_type\":\"1\",";
                        string src_ort = $"\"src_ort\":\"-1\",";
                        string dst_ort = $"\"dst_ort\":\"-1\"";
                        string parmeS = "{";
                        string parmeD = "}";
                        string parme = parmeS + src + dst + car_type + src_ort + dst_ort + parmeD;
                        LogHelper.Info($"推送任务参数{parme}", "任务");
                        PickingTaskModel model = new PickingTaskModel();
                        model.order_name = mst.S_CODE;
                        model.priority = 1;
                        model.dead_line = DateTime.Now.ToString();
                        model.ts_name = "p2p";
                        model.parameters = parme;
                        //model.parameters = new AntsParasModel {
                        //    src = mst.S_START_LOC,
                        //    dst = mst.S_END_LOC,
                        //    carrier_type_id="-99"
                        //};
                        res = RcsHelper.CreatePickingOrder(model);
                    }
                    else if (mst.S_TYPE == "inbound")
                    {
                        //查出货架编码
                        var db = new SqlHelper<Object>().GetInstance();
                        var locFrameRel = db.Queryable<LocFrameRel>().Where(a => a.S_LOC_CODE == mst.S_START_LOC).First();
                        string tote_id = $"\"tote_id\":\"{locFrameRel.S_FRAME_CODE}\",";
                        string task_type = $"\"task_type\":\"{mst.S_TYPE}\",";
                        string src = $"\"src\":\"{mst.S_START_LOC}\",";
                        string dst = $"\"dst\":\"{mst.S_END_LOC}\",";
                        string extra_info = $"\"extra_info\":";
                        string layer = $"\"layer\":[1,2,3,4],";
                        string put = $"\"put\":true";
                        string parmeS = "{";
                        string parmeD = "}";
                        string parmezS = "[";
                        string parmezD = "]";
                        string parme = parmeS + tote_id + task_type + src + dst + extra_info + parmezS+ parmeS  + layer + put + parmeD + parmezD + parmeD;
                        LogHelper.Info($"推送任务参数{parme}", "任务");
                        PickingTaskModel model = new PickingTaskModel();
                        model.order_name = mst.S_CODE;
                        model.priority = 1;
                        model.dead_line = DateTime.Now.ToString();
                        model.ts_name = "picking_ts";
                        model.parameters = parme;
                        //model.parameters = new AntsParasModel {
                        //    src = mst.S_START_LOC,
                        //    dst = mst.S_END_LOC,
                        //    carrier_type_id="-99"
                        //};
                        res = RcsHelper.CreatePickingOrder(model);
                    }
                    if (res)
                    {
                        //更新任务状态
                        mst.N_B_STATE = 1;
                        //mst.S_EQ_TASK_CODE = res.ToString();
                        WCSHelper.UpdateStatus(mst);
                        WCSHelper.UpdateEQNo(mst);
                        ////推送成功,修改任务状态
                        //TaskHelper.UpdateStatus(mst, "已推送");
                        ////推送成功,修改国自ID
                        //TaskHelper.UpdateGzId(mst, res);
                        LogHelper.Info($"任务mst {mst.S_CODE}推送成功", "任务");
                        result = true;
                    }
                }
            }
            else { result = true; }
            return result;
        }
        /// <summary>
        /// 创建搬运任务
@@ -396,6 +507,28 @@
                //任务创建成功,起点货位出库锁定,终点货位入库锁定
                LocationHelper.LockLoc(start, 2);
                LocationHelper.LockLoc(end, 1);
            }
            return result;
        }
        //小米大件
        public static bool CreateTransportDj(string start, string end, string taskType, string cntrs, string orderName, int startLayer, int endLayer, int trayCarryCount = 1, int priority = 1)
        {
            var result = false;
            var trayCodes = cntrs;
            var taskNo = DateTime.Now.Ticks.ToString();
            var res = WCSHelper.CreateTaskDj(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, orderName, trayCarryCount, startLayer, endLayer);
            if (res)
            {
                result = true;
                //任务创建成功,起点货位出库锁定,终点货位入库锁定
                LocationHelper.LockLoc(start, 2);
                if (end!=null&& end != "")
                {
                    LocationHelper.LockLoc(end, 1);
                }
            }
            return result;
        }
@@ -714,6 +847,7 @@
                        result = list.OrderBy(s => s.N_ROW).ThenBy(x => x.N_COL).FirstOrDefault();
                    }
                }
            }
@@ -727,7 +861,7 @@
        /// <summary>
        /// 出库算法
        /// 出库算法 先进先出
        /// </summary>
        /// <param name="area">库区</param>
        /// <returns></returns>
@@ -766,6 +900,108 @@
                LogHelper.Error("OutWorkTransport:" + ex.Message, ex);
            }
            return result;
        }
        /// <summary>
        /// 小米出库算法 先进先出
        /// </summary>
        /// <param name="area">库区</param>
        /// <returns></returns>
        public static Location OutWorkTransportXm(string area, string issueMode)
        {
            Location result = null;
            try
            {
                var db = new SqlHelper<Object>().GetInstance();
                // 获取所有符合条件的货位
                var query = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area);
                // 根据发料方式应用不同的筛选和排序逻辑
                switch (issueMode)
                {
                    case "9": // 发满箱,数量大于0的先进先出
                        query = query.Where(a => a.N_CURRENT_NUM > 0);
                        var list9 = query.ToList()
                            .OrderBy(s => s.T_CREATE) // 先进先出
                            .ToList();
                        result = GetFirstAvailableLocation(list9);
                        break;
                    case "0": // 发空箱,数量=0的先进先出
                        query = query.Where(a => a.N_CURRENT_NUM == 0);
                        var list0 = query.ToList()
                            .OrderBy(s => s.T_CREATE) // 先进先出
                            .ToList();
                        result = GetFirstAvailableLocation(list0);
                        break;
                    case "8": // 箱子型号优先级:残箱>空箱(残内衬)>满箱>空箱>空箱(满内衬)>其它
                        var list8 = query.ToList()
                            .OrderBy(s => GetBoxTypePriority(s,new[] { "2", "4", "1", "3", "5" })) // 按指定优先级排序
                            .ThenBy(s => s.T_CREATE) // 相同优先级按先进先出
                            .ToList();
                        result = GetFirstAvailableLocation(list8);
                        break;
                    case "1": // 箱子型号优先级:残箱>空箱(残内衬)>空箱>空箱(满内衬)>满箱>其它
                        var list1 = query.ToList()
                            .OrderBy(s => GetBoxTypePriority(s,new[] { "2", "4", "3", "5", "1" })) // 按指定优先级排序
                            .ThenBy(s => s.T_CREATE) // 相同优先级按先进先出
                            .ToList();
                        result = GetFirstAvailableLocation(list1);
                        break;
                    default: // 不填-按先进先出
                        var listDefault = query.ToList()
                            .OrderBy(s => s.T_CREATE) // 先进先出
                            .ToList();
                        result = GetFirstAvailableLocation(listDefault);
                        break;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("OutWorkTransport:" + ex.Message + ex.StackTrace);
                LogHelper.Error("OutWorkTransport:" + ex.Message, ex);
            }
            return result;
        }
        // 辅助方法:根据箱子型号获取优先级
        private static int GetBoxTypePriority(Location location, string[] priorityOrder)
        {
            var db = new SqlHelper<Object>().GetInstance();
            var locCntrRel = db.Queryable<LocCntrRel>().Where(s => s.S_LOC_CODE == location.S_CODE).First();
            if (locCntrRel != null)
            {
                var container = db.Queryable<Container>().Where(c => c.S_CODE == locCntrRel.S_CNTR_CODE).First();
                if (container != null)
                {
                    // 查找箱子型号在优先级数组中的位置
                    var index = Array.IndexOf(priorityOrder, container.S_SPEC);
                    return index >= 0 ? index : priorityOrder.Length; // 不在优先级列表中的排在最后
                }
            }
            return priorityOrder.Length; // 没有关联容器的排在最后
        }
        // 辅助方法:获取第一个可用的货位
        private static Location GetFirstAvailableLocation(List<Location> locations)
        {
            var db = new SqlHelper<Object>().GetInstance();
            foreach (var location in locations)
            {
                if (location.N_LOCK_STATE == 0) // 判断货位是否被锁住
                {
                    var locCntrRel = db.Queryable<LocCntrRel>().Where(s => s.S_LOC_CODE == location.S_CODE).First();
                    if (locCntrRel != null) // 判断是否有托盘
                    {
                        return location;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// WMS出库转运
@@ -875,897 +1111,6 @@
            return result;
        }
        #region 巨石代码
        /// <summary>
        /// 常规送检缓存区货位 abc三个区 两层
        /// </summary>
        /// <param name="startloc">起点货位</param>
        /// <param name="area">库区</param>
        /// <returns></returns>
        public static Location InCgWorkTransport(string startloc, string area)
        {
            Location result = null;
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                //A,B,C3个货架上,这个要有优先级了,CX03,04优先送到A区货架,CX01,CX02优先送到B,C货架
                var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault();
                var alllist = db.Queryable<Location>().Where(a => a.S_AREA_CODE.Trim() == reservoirs.areaCode).ToList();
                // 从配置获取优先级规则
                var mapping = Settings.PriorityLocs.FirstOrDefault(m => m.Location == startloc);
                LogHelper.Info($"配置的优先级规则{JsonConvert.SerializeObject(mapping)}");
                if (mapping == null)
                {
                    LogHelper.Info($"未找到产线{startloc}的优先级配置");
                    return null;
                }
                var primaryAreas = mapping.PrimaryArea.Split(',');
                var secondaryAreas = mapping.SecondaryArea.Split(',');
                LogHelper.Info($"优先:{JsonConvert.SerializeObject(primaryAreas)}次选:{JsonConvert.SerializeObject(secondaryAreas)}");
                // 筛选未锁且有空的货位
                var availablePrimaryLocations = FilterAvailableLocations(alllist, primaryAreas);
                //优先
                result = availablePrimaryLocations.OrderBy(l => l.N_COL).ThenBy(l => l.N_LAYER).FirstOrDefault();
                // 次选
                if (result == null)
                {
                    var availableSecondaryLocations = FilterAvailableLocations(alllist, secondaryAreas);
                    result = availableSecondaryLocations.OrderBy(l => l.N_COL).ThenBy(l => l.N_LAYER).FirstOrDefault();
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("InWorkTransport:" + ex.Message + ex.StackTrace);
                LogHelper.Error("InWorkTransport:" + ex.Message, ex);
            }
            return result;
        }
        //筛选可用位置
        private static List<Location> FilterAvailableLocations(List<Location> locations, string[] targetAreas)
        {
            return locations
                .Where(l => targetAreas.Any(area => l.S_CODE.Contains(area)))
                .Where(l => l.N_LOCK_STATE == 0 && l.C_ENABLE == "Y" && l.N_CURRENT_NUM < l.N_CAPACITY)
                .ToList();
        }
        /// <summary>
        /// 紧凑型入库货位  紧急送检区 空托缓存一、二区
        /// </summary>
        /// <param name="area">库区</param>
        /// <returns></returns>
        public static Location CompactWorkTransport(string area)
        {
            Location result = null;
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                //查询每排最后一列有托盘的货位  根据行分区 再找每一行的最后一列有货的货位
                var list = db.Queryable<Location>().
                    Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE.Trim() == area).PartitionBy(a => a.N_ROW)
                    .OrderByDescending(a => a.N_COL).Take(1).ToList();
                if (list.Count > 0)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        LogHelper.Info($"有托盘排号{list[i].N_ROW},库区{area}");
                        //入货位后一位货位
                        result = db.Queryable<Location>().OrderBy(a => a.N_COL)
                            .Where(a => a.S_AREA_CODE.Trim() == area && a.N_ROW == list[i].N_ROW
                            && a.N_COL > list[i].N_COL).First();
                        if (result != null && result.N_LOCK_STATE == 0 && result.C_ENABLE == "Y")
                        {
                            return result;
                        }
                    }
                }
                //没找到说明库区是空的 入里面
                else
                {
                    result = db.Queryable<Location>().
                    Where(a => a.S_AREA_CODE.Trim() == area && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y" && a.N_CURRENT_NUM == 0)
                    .OrderBy(a => a.N_COL).OrderBy(a => a.N_ROW).First();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("InWorkTransport:" + ex.Message + ex.StackTrace);
                LogHelper.Error("InWorkTransport:" + ex.Message, ex);
            }
            return result;
        }
        /// <summary>
        /// 物料下线/送检缓存区->常规送检区
        /// </summary>
        /// <param name="model.START_LOC">起点货位</param>
        /// <param name="model.END_AREA">终点货区</param>
        /// <param name="model.S_ITEM_CODE">物料(选填)</param>
        /// <returns></returns>
        internal static Results materialOffline(GetSubmitCheck model)
        {
            var result = new Results() { Code = "0", Message = "下线任务生成成功!", Data = null };
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                //校验起点货位是否存在/锁住
                var loc = db.Queryable<Location>().Where(a => a.S_CODE == model.START_LOC).First();
                if (loc == null || loc.N_LOCK_STATE != 0 || loc.C_ENABLE != "Y")
                {
                    return new Results { Code = "1", Message = $"{model.START_LOC}库位已被锁定!", Data = null };
                }
                //计算终点货位
                if (string.IsNullOrEmpty(model.END_AREA))
                {
                    return new Results { Code = "1", Message = "出库未传终点库区!", Data = null };
                }
                //如果是紧急送检区 紧凑型
                var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault();
                //如果是送检缓存区
                var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault();
                Location OutLoc = null;
                if (model.END_AREA.Equals(reservoirs.areaCode))
                {
                    LogHelper.Info($"紧急送检区==================");
                    OutLoc = CompactWorkTransport(model.END_AREA);
                }
                else if (model.END_AREA.Equals(reservoirs2.areaCode))
                {
                    LogHelper.Info($"送检缓存区==================");
                    OutLoc = InCgWorkTransport(model.START_LOC, model.END_AREA);
                }
                else
                {
                    LogHelper.Info($"其他==================");
                    OutLoc = InWorkTransport(model.END_AREA);
                }
                //没传物料的话默认一个
                string itemCode = null;
                string wlName = null;
                if (!string.IsNullOrEmpty(model.S_ITEM_CODE))
                {
                    itemCode = model.S_ITEM_CODE;
                    wlName = "布卷";
                    //wlName = db.Queryable<TN_Material>().Where(b => b.S_ITEM_CODE == model.S_ITEM_CODE).First().S_ITEM_NAME;
                }
                //创建托盘货位绑定关系
                string trayCode = ContainerHelper.GenerateCntrNo();
                //绑定起点货位(产线)和物料      不传的话这里没有绑物料托盘表 只绑了托盘货位表
                ContainerHelper.BindLocCntrs(model.START_LOC, trayCode, itemCode, wlName);
                var reservoirs1 = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault();
                //创建任务
                LogHelper.Info($"创建任务 起点:{model.START_LOC}终点:{OutLoc.S_CODE}", OutLoc.S_CODE == reservoirs1.areaCode ? "常规送检" : "物料下线");
                var res = TaskProcess.CreateTransport(model.START_LOC, OutLoc.S_CODE, OutLoc.S_CODE == reservoirs1.areaCode ? "常规送检" : "物料下线", trayCode, 1, 1);
                if (!res)
                {
                    return new Results { Code = "1", Message = "下线任务生成失败!", Data = null };
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("materialOffline:" + ex.Message + ex.StackTrace);
                LogHelper.Error("materialOffline:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 呼叫空托
        /// </summary>
        /// <param name="model.START_LOC">起点类型(拆托机)</param>
        /// <param name="model.END_LOC">终点货位(产线)</param>
        /// <returns></returns>
        internal static Results CallEmptyTray(GetSubmitCheck model)
        {
            var result = new Results() { Code = "0", Message = "呼叫空托任务生成成功!", Data = null };
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                //必填参数校验
                if (string.IsNullOrEmpty(model.START_LOC))
                {
                    return new Results { Code = "1", Message = "呼叫空托未传起点库位!", Data = null };
                }
                if (string.IsNullOrEmpty(model.END_LOC))
                {
                    return new Results { Code = "1", Message = "呼叫空托未传终点库位!", Data = null };
                }
                //校验终点货位是否存在/锁定
                var loc = db.Queryable<Location>().Where(a => a.S_CODE == model.END_LOC).First();
                if (loc == null || loc.N_LOCK_STATE != 0 || loc.C_ENABLE != "Y")
                {
                    return new Results { Code = "1", Message = $"{model.END_LOC}库位已被锁定!", Data = null };
                }
                ////从配置根据拆托机类型找到出口货位
                //var reservoirs = Settings.linePlcInfos.Where(s => s.code == model.S_TYPE).FirstOrDefault();
                //string OutLocStr = reservoirs.outLoca;
                //如果终点和产线下线是同一个货位 终点也不绑托盘
                string trayCode = ContainerHelper.GenerateCntrNo();
                //创建任务
                LogHelper.Info($"创建任务 起点:{model.START_LOC}终点:{model.END_LOC}", "呼叫空托");
                var res = TaskProcess.CreateTransport(model.START_LOC, model.END_LOC, "呼叫空托", trayCode, 1, 1);
                if (!res)
                {
                    return new Results { Code = "1", Message = "呼叫空托任务生成失败!", Data = null };
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("CallEmptyTray:" + ex.Message + ex.StackTrace);
                LogHelper.Error("CallEmptyTray:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 送检  常规送检区-->紧急送检区
        /// </summary>
        /// <param name="model.START_LOC">起点货位(选填)</param>
        /// <param name="model.S_ITEM_CODE">物料(选填)</param>
        /// <returns></returns>
        internal static Results submitCheck(GetSubmitCheck model)
        {
            var result = new Results() { Code = "0", Message = "送检任务生成成功!", Data = null };
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                string startloc = "";
                //物料不为空则根据物料找起点货位
                if (!string.IsNullOrEmpty(model.S_ITEM_CODE))
                {
                    //根据物料找货位
                    var cgreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault();
                    startloc = getLocByMaterial(model.S_ITEM_CODE, cgreservoirs.areaCode).S_CODE;
                    if (startloc == null)
                    {
                        return new Results { Code = "1", Message = $"{model.S_ITEM_CODE}未找到该物料!", Data = null };
                    }
                }
                //如果传了起点
                if (!string.IsNullOrEmpty(model.START_LOC))
                {
                    var loc = db.Queryable<Location>().Where(a => a.S_CODE == model.START_LOC).First();
                    if (loc == null || loc.N_LOCK_STATE != 0 || loc.C_ENABLE != "Y")
                    {
                        return new Results { Code = "1", Message = $"{model.START_LOC}库位已被锁定!", Data = null };
                    }
                    startloc = loc.S_CODE;
                }
                //计算紧急送检区终点货位
                var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault();
                Location OutLoc = TaskProcess.CompactWorkTransport(reservoirs.areaCode);
                if (OutLoc == null)
                {
                    return new Results { Code = "1", Message = $"终点库区紧急送检区未找到空货位!", Data = null };
                }
                //创建送检任务
                var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == model.START_LOC).First();
                LogHelper.Info($"创建任务 起点:{startloc}终点:{OutLoc.S_CODE}", "送检");
                var res = TaskProcess.CreateTransport(startloc, OutLoc.S_CODE, "送检", locCntrRel.S_CNTR_CODE, 1, 1);
                if (!res)
                {
                    return new Results { Code = "1", Message = "送检任务生成失败!", Data = null };
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("submitCheck:" + ex.Message + ex.StackTrace);
                LogHelper.Error("submitCheck:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 根据物料找货位  根据CntrItemDetail时间 先进先出  连表查判断货位有没有锁
        /// </summary>
        /// <param name="itemCode">物料</param>
        /// <returns></returns>
        public static Location getLocByMaterial(string itemCode, string areaCode)
        {
            Location result = null;
            try
            {
                var db = new SqlHelper<object>().GetInstance();
                //两表联查查出有该物料的货位编号  (现场没有物料表)
                var locCntrs = db.Queryable<LocCntrRel>().LeftJoin<CntrItemDetail>((p, m) => p.S_CNTR_CODE == m.S_CNTR_CODE)
                .Where((p, m) => m.S_ITEM_CODE == itemCode)
                .OrderBy((p, m) => p.T_CREATE)  //按创建时间顺序
                .Select((p, m) => p.S_LOC_CODE) // 选择托盘物料表的数据
                .ToList();
                LogHelper.Info($"有物料{itemCode}的货位编号{JsonConvert.SerializeObject(locCntrs)}");
                //找常规送检区内含有查出物料货位的货位
                var locList = db.Queryable<Location>()
                    .Where(p => p.S_AREA_CODE == areaCode && p.N_LOCK_STATE == 0 && p.C_ENABLE == "Y")
                    .Where(s => locCntrs.Contains(s.S_CODE.Trim()))
                    .ToList();
                if (!locList.Any())
                {
                    return null;
                }
                result = locList.FirstOrDefault();
            }
            catch (Exception ex)
            {
                Console.WriteLine("getLocByMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("getLocByMaterial:" + ex.Message, ex);
            }
            return result;
        }
        //存摄像头调用接口空满状态   货位,空满状态
        private static string monitorStatus = null;
        /// <summary>
        /// 摄像头监测接口
        /// </summary>
        /// <param name="models.PointCode">监测货位</param>
        /// <param name="models.PointStatus">监测空满状态0空闲1占用3异常</param>
        /// <returns></returns>
        internal static Results UpdateFullStatus(List<CameraMonitor> models)
        {
            var result = new Results() { Code = "0", Message = "操作成功", Data = null };
            var db = new SqlHelper<object>().GetInstance();
            //校验与内存是否一致
            if (monitorStatus != null)
            {
                try
                {
                    //string转成list
                    var jsonList = JsonConvert.DeserializeObject<List<CameraMonitor>>(monitorStatus);
                    //找两个List的交集
                    var intersection = jsonList.Where(j => models.Any(m =>
                        m.PointCode == j.PointCode && m.PointStatus == j.PointStatus)).ToList();
                    LogHelper.Info($"摄像头与上次调用一致数据:{JsonConvert.SerializeObject(intersection)}");
                    foreach (var model in intersection)
                    {
                        //找到该点位的库区
                        var loc = db.Queryable<Location>().Where(a => a.S_CODE == model.PointCode).First();
                        //没锁再继续走
                        if (loc.N_LOCK_STATE == 0 && loc.C_ENABLE == "Y" && loc != null)
                        {
                            var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检入库区").FirstOrDefault();
                            //如果是送检入库区
                            if (reservoirs.areaCode.Equals(loc.S_AREA_CODE))
                            {
                                var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == model.PointCode).First();
                                var container = new Container();
                                if (locCntrRel == null)
                                {
                                    //第一次自己绑定一个托盘
                                    string trayCode = ContainerHelper.GenerateCntrNo();
                                    ContainerHelper.BindLocCntrs(model.PointCode, trayCode, null, null);
                                    container = db.Queryable<Container>().Where(a => a.S_CODE == trayCode).First();
                                    container.C_FULL = "2";
                                }
                                else
                                {
                                    //查数据库空满状态 跟缓存不一样则更新
                                    //找到这个货位的容器 空满状态C_FULL改成2满  0 -- 空 1 -- 有货 2 -- 满
                                    container = db.Queryable<Container>().Where(a => a.S_CODE == locCntrRel.S_CNTR_CODE).First();
                                    if (container.C_FULL != model.PointStatus.ToString())
                                    {
                                        container.C_FULL = "2";
                                    }
                                }
                                var res = db.Updateable(container).UpdateColumns(it => it.C_FULL).ExecuteCommand() > 0;
                                if (res)
                                {
                                    LogHelper.Info($"修改{model.PointCode}货位空满状态成功", "摄像头监测");
                                }
                                else
                                {
                                    LogHelper.Info($"修改{model.PointCode}货位空满状态失败", "摄像头监测");
                                }
                            }
                            else
                            {
                                //如果是空托缓存区  判断拆托机是否有空位 空托缓存区满了且拆托机入口有空则创建任务
                                var reservoirs1 = Settings.ReservoirAreas.Where(s => s.areaName == "3min空托区").FirstOrDefault();
                                var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "6min空托区").FirstOrDefault();
                                if (loc.S_AREA_CODE.Equals(reservoirs1.areaCode) || loc.S_AREA_CODE.Equals(reservoirs2.areaCode))//三寸空托
                                {
                                    ProcessEmptyTrayAreas(db, loc, reservoirs1.areaCode, reservoirs2.areaCode);
                                }
                            }
                        }
                        else
                        {
                            LogHelper.Info($"{model.PointCode}货位任务已经生成", "摄像头监测");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("UpdateFullStatus:" + ex.Message + ex.StackTrace);
                    LogHelper.Error("UpdateFullStatus:" + ex.Message, ex);
                    throw;
                }
            }
            //list转string 存到内存
            monitorStatus = JsonConvert.SerializeObject(models);
            return result;
        }
        //摄像头监测空托缓存区
        private static void ProcessEmptyTrayAreas(SqlSugar.ISqlSugarClient db, Location loc, string areaCode1, string areaCode2)
        {
            var plcDeviceTable = S7Helper.plcDeviceTables;
            if (plcDeviceTable != null)
            {
                string endLoc = null;
                bool request = false;
                if (loc.S_AREA_CODE.Equals(areaCode1))
                {
                    request = plcDeviceTable.requestPut1;
                    endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机1").FirstOrDefault().inLoca;
                }
                else if (loc.S_AREA_CODE.Equals(areaCode2))//六寸空托
                {
                    request = plcDeviceTable.requestPut2;
                    endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机2").FirstOrDefault().inLoca;
                }
                //判断是否允许放框
                if (request)
                {
                    //创建任务 从空托缓存区到拆托机
                    var list = db.Queryable<Location>().Where(a => a.S_AREA_CODE.Trim() == loc.S_AREA_CODE
                    && a.N_CURRENT_NUM > 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").OrderByDescending(a => a.N_ROW)
                    .OrderByDescending(a => a.N_COL).First();
                    var startLoc = list.S_CODE;
                    string trayCode = ContainerHelper.GenerateCntrNo();
                    LogHelper.Info($"创建任务 起点:{startLoc}终点:{endLoc}", "拆托");
                    var res = TaskProcess.CreateTransport(startLoc, endLoc, "拆托", trayCode, 1, 1);
                    if (res)
                    {
                        LogHelper.Info($"起点:{startLoc}终点:{endLoc}任务创建成功", "拆托");
                    }
                    else
                    {
                        LogHelper.Info($"起点:{startLoc}终点:{endLoc}任务创建失败", "拆托");
                    }
                }
            }
            else
            {
                LogHelper.Info($"未读取到拆托机信号", "拆托");
            }
        }
        /// <summary>
        /// 抽检主动呼叫    起点:送检缓存区
        /// </summary>
        /// <param name="model.S_ITEM_CODE">物料</param>
        /// <param name="model.END_LOC">终点货位</param>
        /// <returns></returns>
        internal static Results activeCall(GetSubmitCheck model)
        {
            var result = new Results() { Code = "0", Message = "抽检主动呼叫任务生成成功!", Data = null };
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                //根据物料找某库区的货位
                var cgreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault();
                var startloc = getLocByMaterial(model.S_ITEM_CODE, cgreservoirs.areaCode);
                if (startloc == null)
                {
                    return new Results { Code = "1", Message = $"未找到包含物料{model.S_ITEM_CODE}的货位", Data = null };
                }
                //终点
                var endloc = db.Queryable<Location>().Where(a => a.S_CODE == model.END_LOC).First();
                if (endloc == null || endloc.N_LOCK_STATE != 0 || endloc.C_ENABLE != "Y")
                {
                    return new Results { Code = "1", Message = $"{model.END_LOC}库位已被锁定!", Data = null };
                }
                //创建任务
                var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startloc.S_CODE).First();
                LogHelper.Info($"创建任务 起点:{startloc.S_CODE}终点:{endloc.S_CODE}", "抽检主动呼叫");
                var res = TaskProcess.CreateTransport(startloc.S_CODE, endloc.S_CODE, "抽检主动呼叫", locCntrRel.S_CNTR_CODE, 1, 1);
                if (!res)
                {
                    return new Results { Code = "1", Message = "抽检主动呼叫任务生成失败!", Data = null };
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("submitCheck:" + ex.Message + ex.StackTrace);
                LogHelper.Error("submitCheck:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 主动物料绑定
        /// </summary>
        /// <param name="model.S_ITEM_CODE">物料编码(选填)</param>
        /// <param name="model.BIND_LOC">绑定货位</param>
        /// <returns></returns>
        internal static Results bindMaterial(GetSubmitCheck model)
        {
            var result = new Results() { Code = "0", Message = "物料绑定成功!", Data = null };
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                var loc = db.Queryable<Location>().Where(a => a.S_CODE == model.BIND_LOC).First();
                if (loc == null || loc.N_LOCK_STATE != 0 || loc.C_ENABLE != "Y")
                {
                    return new Results { Code = "1", Message = $"绑定货位不存在或已被锁", Data = null };
                }
                string cntrStr = ContainerHelper.GenerateCntrNo();
                var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == model.BIND_LOC).First();
                if (locCntrRel != null)
                {
                    cntrStr = locCntrRel.S_CNTR_CODE;
                }
                var res = ContainerHelper.BindLocCntrs(model.BIND_LOC, cntrStr, model.S_ITEM_CODE, "布卷");
                if (!res)
                {
                    return new Results { Code = "1", Message = $"物料{model.S_ITEM_CODE}货位{model.BIND_LOC}绑定失败", Data = null };
                }
                loc.N_CURRENT_NUM++;
                var res2 = db.Updateable(loc).UpdateColumns(it => it.N_CURRENT_NUM).ExecuteCommand() > 0;
                if (!res2)
                {
                    return new Results { Code = "1", Message = $"货位{model.BIND_LOC}当前数量自增失败", Data = null };
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("bindMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("bindMaterial:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 整排物料绑定
        /// </summary>
        /// <param name="bondLoc">绑定货位</param>
        /// <returns></returns>
        internal static Results multBindMaterial(string bondLoc)
        {
            var result = new Results() { Code = "0", Message = "整排物料绑定成功!", Data = null };
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                var location = db.Queryable<Location>().Where(a => a.S_CODE == bondLoc).First();
                //查出这一排的货位
                var loclist = db.Queryable<Location>()
                    .Where(a => a.S_AREA_CODE == location.S_AREA_CODE && a.N_ROW == location.N_ROW).ToList();
                foreach (var loc in loclist)
                {
                    //没锁的且没货的才绑
                    if (loc.N_LOCK_STATE == 0 && loc.N_CURRENT_NUM < loc.N_CAPACITY)
                    {
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("multBindMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("multBindMaterial:" + ex.Message, ex);
                throw;
            }
            return result;
        }
        /// <summary>
        /// 按钮盒调用下线
        /// </summary>
        /// <param name="startLoc">起点货位</param>
        /// <param name="endArea">终点货区</param>
        /// <returns></returns>
        internal static bool tcpOffline(string startLoc, string endArea)
        {
            var db = new SqlHelper<Location>().GetInstance();
            LogHelper.Info($"tcpOffline=====参数:起点货位{startLoc}终点库区{endArea}");
            try
            {
                //校验起点货位是否存在/锁住
                var loc = db.Queryable<Location>().Where(a => a.S_CODE == startLoc).First();
                if (loc == null || loc.N_LOCK_STATE != 0 || loc.C_ENABLE != "Y")
                {
                    LogHelper.Info("起点货位不存在或已锁" + startLoc);
                    return false;
                }
                //计算终点货位
                //if (string.IsNullOrEmpty(endArea))
                //{
                //    return new Results { Code = "1", Message = "出库未传终点库区!", Data = null };
                //}
                //如果是紧凑型
                var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault();
                Location OutLoc = null;
                if (endArea.Equals(reservoirs.areaCode))
                {
                    OutLoc = CompactWorkTransport(endArea);
                }
                else
                {
                    OutLoc = InWorkTransport(endArea);
                }
                //创建托盘货位绑定关系
                string trayCode = ContainerHelper.GenerateCntrNo();
                //没传物料的话默认一个
                string itemCode = null;
                string wlName = null;
                //if (!string.IsNullOrEmpty(model.S_ITEM_CODE))
                //{
                //    itemCode = model.S_ITEM_CODE;
                //    wlName = db.Queryable<TN_Material>().Where(b => b.S_ITEM_CODE == model.S_ITEM_CODE).First().S_ITEM_NAME;
                //}
                if (OutLoc == null)
                {
                    LogHelper.Info($"终点货位不存在", "按钮盒下线");
                    return false;
                }
                ContainerHelper.BindLocCntrs(OutLoc.S_CODE, trayCode, itemCode, wlName);
                //创建任务
                LogHelper.Info($"创建任务 起点:{startLoc}终点:{OutLoc.S_CODE}", "按钮盒下线");
                return TaskProcess.CreateTransport(startLoc, OutLoc.S_CODE, "按钮盒下线", trayCode, 1, 1);
            }
            catch (Exception ex)
            {
                Console.WriteLine("tcpOffline:" + ex.Message + ex.StackTrace);
                LogHelper.Error("tcpOffline:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 按钮盒调用空托
        /// </summary>
        /// <param name="startLoc">起点货位</param>
        /// <param name="endLoc">终点货位</param>
        /// <returns></returns>
        internal static bool tcpEmptyTray(string startLoc, string endLoc)
        {
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                //校验终点货位是否锁
                var endloc = db.Queryable<Location>().Where(a => a.S_CODE == endLoc).First();
                if (endloc == null || endloc.N_LOCK_STATE != 0 || endloc.C_ENABLE != "Y")
                {
                    LogHelper.Info("终点货位已锁" + endLoc);
                    return false;
                }
                //创建托盘货位绑定关系
                string trayCode = ContainerHelper.GenerateCntrNo();
                //创建任务
                LogHelper.Info($"创建任务 起点:{startLoc}终点:{endLoc}", "按钮盒调用空托");
                return TaskProcess.CreateTransport(startLoc, endLoc, "按钮盒调用空托", trayCode, 1, 1);
            }
            catch (Exception ex)
            {
                Console.WriteLine("materialOffline:" + ex.Message + ex.StackTrace);
                LogHelper.Error("materialOffline:" + ex.Message, ex);
                throw;
            }
        }
        /// <summary>
        /// 安全交互
        /// </summary>
        /// <param name="model.STATION_NAME">请求点位</param>
        /// <param name="model.APPLY_CODE">请求码</param>
        /// <returns></returns>
        internal static safeResult safetyInteraction(SafetyInteraction model)
        {
            //0允许进入 1不允许进入
            var result = new safeResult() { code = "1", msg = "success" };
            try
            {
                var reservoirs = Settings.SafeInteractions.Where(s => s.location == model.STATION_NAME).FirstOrDefault();//y0-0000 y1-0001  on-FF00  off-0000
                //var rgvSafeInteraction = DeviceProcess.rgvSafeInteraction;
                var plcDeviceTable = S7Helper.plcDeviceTables;
                if (plcDeviceTable != null)
                {
                    //RGV
                    if (reservoirs.type.Equals("RGV"))
                    {
                        LogHelper.Info($"RGV安全交互  请求点位:{model.STATION_NAME}请求码:{model.APPLY_CODE}");
                        //处理信号
                        var res = int.Parse(plcDeviceTable.RGVAllowUnload[reservoirs.code].ToString().Substring(1, 1));
                        //根据ip读状态
                        LogHelper.Info($"RGV安全交互缓存信号{res},{JsonConvert.SerializeObject(plcDeviceTable.RGVAllowUnload)}");
                        //卸货请求进入
                        if (model.APPLY_CODE.Equals("5"))
                        {
                            //1允许卸货
                            if (res == 1)
                            {
                                LogHelper.Info($"RGV安全交互 允许卸货");
                                return new safeResult() { code = "0", msg = "success" };
                            }
                        }
                        //卸货后已离开
                        else if (model.APPLY_CODE.Equals("8"))
                        {
                            //发送卸货完成、复位信号
                            //卸货完成信号
                            S7Helper.WriteInt(50, reservoirs.code * 2 - 2, (short)(reservoirs.code * 10 + 1));
                            // 启动后台任务处理延迟复位
                            Task.Run(async () =>
                            {
                                //10秒后复位
                                await Task.Delay(10000);
                                S7Helper.WriteInt(50, reservoirs.code * 2 - 2, (short)(reservoirs.code * 10));
                                LogHelper.Info($"RGV安全交互 复位完成");
                            });
                            //10秒后复位
                            //S7Helper.WriteInt(50, reservoirs.code * 2 - 2, (short)(reservoirs.code * 10));
                            //safeAssistant(reservoirs.code, res);
                            LogHelper.Info($"RGV安全交互 卸货完成");
                            return new safeResult() { code = "0", msg = "success" };
                        }
                    }
                    //拆托机
                    else if (reservoirs.type.Equals("CTJ"))
                    {
                        LogHelper.Info($"拆托机安全交互  请求点位:{model.STATION_NAME}请求码:{model.APPLY_CODE}");
                        //找到线体 根据线体找内存里的状态
                        var reservoirs1 = Settings.ConveyorLinesInfos.Where(s => s.location == model.STATION_NAME).FirstOrDefault();
                        LogHelper.Info($"拆托机安全交互参数{JsonConvert.SerializeObject(plcDeviceTable)}");
                        if (model.APPLY_CODE.Equals("1"))
                        {
                            //0-脱机状态,1-待机状态,2-运行中    待机且有托盘且请求取框才走
                            if ((reservoirs1.deviceNo == "1" && plcDeviceTable.requestTake1) ||
                                (reservoirs1.deviceNo == "2" && plcDeviceTable.requestTake2))
                            {
                                LogHelper.Info($"拆托机安全交互 允许取框");
                                return new safeResult() { code = "0", msg = "success" };
                            }
                        }
                        else if (model.APPLY_CODE.Equals("5"))
                        {
                            //0-脱机状态,1-待机状态,2-运行中    待机且无托盘且允许放框才走
                            if ((reservoirs1.deviceNo == "1" && plcDeviceTable.requestPut1) ||
                                (reservoirs1.deviceNo == "2" && plcDeviceTable.requestPut2))
                            {
                                LogHelper.Info($"拆托机安全交互 允许放框");
                                return new safeResult() { code = "0", msg = "success" };
                            }
                        }
                        //取货离开
                        else if (model.APPLY_CODE.Equals("4"))
                        {
                            int offsetAddr = 8;
                            if (reservoirs1.deviceNo == "1")
                            {
                                offsetAddr = 1;
                            }
                            else if (reservoirs1.deviceNo == "2")
                            {
                                offsetAddr = 3;
                            }
                            LogHelper.Info($"拆托机安全交互写入{reservoirs1.deviceNo},{offsetAddr}");
                            S7Helper.WriteDouble(reservoirs1.deviceNo, 9, 182, offsetAddr, 1);
                            LogHelper.Info($"拆托机安全交互 取框离开");
                            return new safeResult() { code = "0", msg = "success" };
                        }
                        //卸货离开
                        else if (model.APPLY_CODE.Equals("8"))
                        {
                            int offsetAddr = 8;//随便给一个
                            if (reservoirs1.deviceNo == "1")
                            {
                                offsetAddr = 0;
                            }
                            else if (reservoirs1.deviceNo == "2")
                            {
                                offsetAddr = 2;
                            }
                            LogHelper.Info($"拆托机安全交互写入{reservoirs1.deviceNo},{offsetAddr}");
                            S7Helper.WriteDouble(reservoirs1.deviceNo, 9, 182, offsetAddr, 1);
                            LogHelper.Info($"拆托机安全交互 取框离开");
                            return new safeResult() { code = "0", msg = "success" };
                        }
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("safetyInteraction:" + ex.Message + ex.StackTrace);
                LogHelper.Error("safetyInteraction:" + ex.Message, ex);
                throw;
            }
        }
        //循环发送信号
        private static void safeAssistant(int code, int res)
        {
            Thread.Sleep(10000);
            S7Helper.WriteInt(50, code * 2 - 2, (short)(code * 10));
            LogHelper.Info($"RGV安全交互 复位完成");
            ////2卸货完成确认
            //if (res != 2)
            //{
            //    //卸货完成信号
            //    S7Helper.WriteInt(50, code * 2 - 2, (short)(code * 10 + 1));
            //    Thread.Sleep(3000);
            //    safeAssistant(code, res);
            //}
            //else
            //{
            //    S7Helper.WriteInt(50, code * 2 - 2, (short)(code * 10));
            //}
        }
        /// <summary>
        /// 按钮控制服务开关
        /// </summary>
        /// <param name="isusing.S_STATUS">服务状态</param>
        /// <param name="isusing.S_TYPE">服务类型</param>
        /// <returns></returns>
        internal static Results switchButton(Isusing isusing)
        {
            var db = new SqlHelper<object>().GetInstance();
            var result = new Results() { Code = "1", Message = $"服务状态失败!", Data = null };
            var isusinglist = db.Queryable<Isusing>().Where(a => a.S_TYPE == isusing.S_TYPE).First();
            isusinglist.S_STATUS = isusing.S_STATUS;
            var res = db.Updateable(isusinglist).UpdateColumns(it => it.S_STATUS).ExecuteCommand() > 0;
            if (res)
            {
                return new Results() { Code = "0", Message = $"服务状态修改成功!", Data = null };
            }
            return result;
        }
        //tcp发送信号 测试用
        internal static Results tcpSend(string str)
        {
            var reservoirs = Settings.SafeInteractions.Where(s => s.code == 1).FirstOrDefault();
            //测试用
            LogHelper.Info($"RGV安全交互发送信号{reservoirs.ip},{str}");
            //无状态信号
            bool res = PlcHelper.SendHex(reservoirs.ip, str);
            if (res)
            {
                return new Results() { Code = "0", Message = $"发送成功", Data = null };
            }
            return new Results() { Code = "1", Message = $"发送失败", Data = null };
        }
        #endregion
        /// <summary>
        /// 大件
@@ -1779,63 +1124,354 @@
            try
            {
                var startLoc = new Location();
                var endLoc = new Location();
                string endLocStr = null;
                string Message = null;
                //校验任务编号是否存在
                if (repeatTaskCode(model.order_name))
                {
                    Message = model.order_name+"任务编号已存在";
                    return new TaskResponse
                    {
                        header = new ResponseHead { code = 0, desc = Message }
                    };
                }
                switch (model.ts_name)
                {
                    case "p2p":
                        startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameter.src).First();
                        startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameters.src).First();
                        if (startLoc == null || startLoc.N_LOCK_STATE != 0 || startLoc.C_ENABLE != "Y")
                        {
                            Message = $"{model.parameter.src}库位已被锁定!";
                            Message = $"{model.parameters.src}库位已被锁定!";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        endLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameter.dst).First();
                        if (startLoc == null || startLoc.N_LOCK_STATE != 0 || startLoc.C_ENABLE != "Y")
                        {
                            Message = $"{model.parameter.dst}库位已被锁定!";
                        }
                        endLocStr = model.parameters.dst;
                        break;
                    case "p2a":
                        startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameter.src).First();
                        startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameters.src).First();
                        if (startLoc == null || startLoc.N_LOCK_STATE != 0 || startLoc.C_ENABLE != "Y")
                        {
                            Message = $"{model.parameter.src}库位已被锁定!";
                            Message = $"{model.parameters.src}库位已被锁定!";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        endLoc = InWorkTransport(model.parameter.dst);
                        if (endLoc==null)
                        var endLoc = InWorkTransport(model.parameters.dst_area);
                        if (endLoc == null)
                        {
                            Message = $"{model.parameter.dst}库区没有可入货位!";
                            //如果没找到就等第一条
                            endLocStr = db.Queryable<Location>().Where(a => a.S_AREA_CODE.Trim() == model.parameters.dst).OrderByDescending(a => a.N_ROW).ToList()[0].S_CODE;
                        }
                        break;
                    case "a2p":
                        startLoc = OutWorkTransport(model.parameter.src);
                        if (startLoc==null)
                        startLoc = OutWorkTransportXm(model.parameters.src_area, model.parameters.issueMode);
                        if (startLoc == null)
                        {
                            Message = $"{model.parameter.dst}库区没有可出货位!";
                            Message = $"{model.parameters.dst}库区没有可出货位!";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        endLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameter.dst).First();
                        endLocStr = model.parameters.dst;
                        break;
                    case "a2a":
                        startLoc = OutWorkTransportXm(model.parameters.src_area,model.parameters.issueMode);
                        if (startLoc == null)
                        {
                            Message = $"{model.parameters.src}库区没有可出货位!";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        var endLoc1 = InWorkTransport(model.parameters.dst_area);
                        if (endLoc1 == null)
                        {
                            //如果没找到就等第一条
                            endLocStr = db.Queryable<Location>().Where(a => a.S_AREA_CODE.Trim() == model.parameters.dst).OrderByDescending(a => a.N_ROW).ToList()[0].S_CODE;
                        }
                        break;
                    case "p2u":
                        startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.parameters.src).First();
                        if (startLoc == null || startLoc.N_LOCK_STATE != 0 || startLoc.C_ENABLE != "Y")
                        {
                            Message = $"{model.parameter.dst}库位已被锁定!";
                            Message = $"{model.parameters.src}库位已被锁定!";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        endLocStr = "";
                        break;
                    case "a2u":
                        startLoc = OutWorkTransportXm(model.parameters.src, model.parameters.issueMode);
                        if (startLoc == null)
                        {
                            Message = $"{model.parameters.src}库区没有可出货位!";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        endLocStr = "";
                        break;
                }
                LogHelper.Info($"bigMaterial  接收参数{JsonConvert.SerializeObject(model)}");
                //创建托盘货位绑定关系
                string trayCode = ContainerHelper.GenerateCntrNo();
                //绑定起点货位(产线)和物料
                ContainerHelper.BindLocCntrsXm(startLoc.S_CODE, trayCode, model.parameters.sku, "", model.parameters.BatchNo, model.parameters.issueMode, model.parameters.num, model.parameters.boxType);
                var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).First();
                //创建任务
                LogHelper.Info($"创建任务 起点:{startLoc.S_CODE}终点:{endLoc.S_CODE}", model.ts_name);
                var res = TaskProcess.CreateTransport(startLoc.S_CODE, endLoc.S_CODE, model.ts_name, locCntrRel.S_CNTR_CODE, 1, 1);
                if (!res)
                LogHelper.Info($"创建任务 起点:{startLoc.S_CODE}终点:{endLocStr}", "大件");
                var res = TaskProcess.CreateTransportDj(startLoc.S_CODE, endLocStr, "大件", locCntrRel.S_CNTR_CODE, model.order_name, 1, 1);
                var result = new TaskResponse();
                if (res)
                {
                    result = new TaskResponse
                    {
                        header = new ResponseHead { code = 200, desc = "SUCCESS" },
                        body = new ResponseBody
                        {
                            msg = "success",
                            app_name = "Guozi client",
                            data = new List<ResponseData> { new ResponseData { in_order_id = model.order_name } },
                            version = ""
                        }
                    };
                }
                else {
                    Message = $"创建任务 起点:{startLoc.S_CODE}终点:{endLocStr}失败";
                    result = new TaskResponse
                    {
                        header = new ResponseHead { code = 0, desc = Message }
                    };
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("bigMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("bigMaterial:" + ex.Message, ex);
                throw;
            }
        }
        //小件
        public static TaskResponse smallMaterial(smallMaterial model)
        {
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                string Message = null;
                //拆分成两条任务,一条是料架到指定的缓存区,二是料架上的托盘到指定的工位(小米wcs传)一对多
                var startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.taskList[0].parameters.src).First();
                if (startLoc == null || startLoc.N_LOCK_STATE != 0)
                {
                    return new TaskResponse
                    {
                        header = new ResponseHead { code = 1, desc = Message }
                        header = new ResponseHead { code = 0, desc = $"{model.taskList[0].parameters.src}库位已被锁定!" }
                    };
                }
                var endLoc = TaskProcess.InWorkTransport(model.shippingRoute);
                if (endLoc != null)
                {
                    ////创建到缓存区任务
                    //var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).First();
                    //找p2a的任务编码
                    var order_name = model.taskList.Find(s=>s.ts_name=="p2a").order_name;
                    //校验任务编号是否存在
                    if (repeatTaskCode(order_name))
                    {
                        Message = order_name + "任务编号已存在";
                        return new TaskResponse
                        {
                            header = new ResponseHead { code = 0, desc = Message }
                        };
                    }
                    //创建任务
                    LogHelper.Info($"创建任务 起点:{startLoc.S_CODE}终点:{endLoc.S_CODE}", "小件通用车型");
                    var res = TaskProcess.CreateTransportDj(startLoc.S_CODE, endLoc.S_CODE, "小件通用车型", model.rackNumber, order_name, 1, 1);
                    if (!res)
                    {
                        return new TaskResponse
                        {
                            header = new ResponseHead { code = 0, desc = $"创建任务 起点:{startLoc.S_CODE}终点:{endLoc.S_CODE}失败" }
                        };
                    }
                }
                var result = new TaskResponse();
                //料架上的托盘到指定的工位
                foreach (var tasklist in model.taskList)
                {
                    if (tasklist.ts_name == "p2p")
                    {
                        //校验任务编号是否存在
                        if (repeatTaskCode(tasklist.order_name))
                        {
                            Message = tasklist.order_name + "任务编号已存在";
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                        //先绑定料架和料箱位
                        ContainerHelper.BindLocCntrsXmLj(tasklist.rackPosition, model.rackNumber);
                        var startloc = db.Queryable<Location>().Where(a => a.S_CODE == tasklist.rackPosition).First();
                        if (startloc == null || startloc.N_LOCK_STATE != 0)
                        {
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = $"{startloc.S_CODE}库位已被锁定!" }
                            };
                        }
                        var endlocstr = tasklist.parameters.dst;
                        //创建托盘货位绑定关系
                        string trayCode = ContainerHelper.GenerateCntrNo();
                        //绑定起点货位(产线)和物料
                        ContainerHelper.BindLocCntrsXm(startloc.S_CODE, trayCode, tasklist.parameters.sku, "", tasklist.parameters.BatchNo, tasklist.parameters.issueMode, tasklist.parameters.num,"");
                        var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startloc.S_CODE).First();
                        //创建任务
                        LogHelper.Info($"创建任务 起点:{startloc.S_CODE}终点:{endlocstr}", "inbound");
                        var res = TaskProcess.CreateTransportDj(startloc.S_CODE, endlocstr, "inbound", locCntrRel.S_CNTR_CODE, tasklist.order_name, 1, 1);
                        if (res)
                        {
                            result = new TaskResponse
                            {
                                header = new ResponseHead { code = 200, desc = "SUCCESS" },
                                body = new ResponseBody
                                {
                                    msg = "success",
                                    app_name = "Guozi client",
                                    data = new List<ResponseData> { new ResponseData { in_order_id = tasklist.order_name } },
                                    version = ""
                                }
                            };
                        }
                        else
                        {
                            Message = $"创建任务 起点:{startloc.S_CODE}终点:{endlocstr}失败";
                            result = new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = Message }
                            };
                        }
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("smallMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("smallMaterial:" + ex.Message, ex);
                throw;
            }
        }
        //任务号重复判断
        private static bool repeatTaskCode(string orderName) {
            var db = new SqlHelper<WCSTask>().GetInstance();
            var result = db.Queryable<WCSTask>().Where(a => a.S_CODE == orderName).Count();
            return result > 0;
        }
        //传感器小件
        public static TaskResponse sensorSmallMaterial(sensorSmallMaterial model)
        {
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                string Message = null;
                ////拆分成两条任务,一条是料架到指定的缓存区,二是料架上的托盘到指定的工位(小米wcs传)一对多
                //var startLoc = db.Queryable<Location>().Where(a => a.S_CODE == model.taskList[0].parameters.src).First();
                //if (startLoc == null || startLoc.N_LOCK_STATE != 0)
                //{
                //    return new TaskResponse
                //    {
                //        header = new ResponseHead { code = 0, desc = $"{model.taskList[0].parameters.src}库位已被锁定!" }
                //    };
                //}
                //var endLoc = TaskProcess.InWorkTransport(model.shippingRoute);
                //if (endLoc != null)
                //{
                //    ////创建到缓存区任务
                //    //var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).First();
                //    //找p2a的任务编码
                //    var order_name = model.taskList.Find(s => s.ts_name == "p2a").order_name;
                //    //创建任务
                //    LogHelper.Info($"创建任务 起点:{startLoc.S_CODE}终点:{endLoc.S_CODE}", "小件通用车型");
                //    var res = TaskProcess.CreateTransportDj(startLoc.S_CODE, endLoc.S_CODE, "小件通用车型", model.rackNumber, order_name, 1, 1);
                //    if (!res)
                //    {
                //        return new TaskResponse
                //        {
                //            header = new ResponseHead { code = 0, desc = "自动上线任务创建失败" }
                //        };
                //    }
                //}
                ////料架上的托盘到指定的工位
                //foreach (var tasklist in model.taskList)
                //{
                //    if (tasklist.ts_name == "p2p")
                //    {
                //        //先绑定料架和料箱位
                //        ContainerHelper.BindLocCntrsXmLj(tasklist.rackPosition, model.rackNumber);
                //        var startloc = db.Queryable<Location>().Where(a => a.S_CODE == tasklist.rackPosition).First();
                //        if (startloc == null || startloc.N_LOCK_STATE != 0)
                //        {
                //            return new TaskResponse
                //            {
                //                header = new ResponseHead { code = 0, desc = $"{startloc.S_CODE}库位已被锁定!" }
                //            };
                //        }
                //        var endlocstr = tasklist.parameters.dst;
                //        //创建托盘货位绑定关系
                //        string trayCode = ContainerHelper.GenerateCntrNo();
                //        //绑定起点货位(产线)和物料
                //        ContainerHelper.BindLocCntrsXm(startloc.S_CODE, trayCode, tasklist.parameters.sku, "", tasklist.parameters.BatchNo, tasklist.parameters.issueMode, tasklist.parameters.num);
                //        var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startloc.S_CODE).First();
                //        //创建任务
                //        LogHelper.Info($"创建任务 起点:{startloc.S_CODE}终点:{endlocstr}", "inbound");
                //        var res = TaskProcess.CreateTransportDj(startloc.S_CODE, endlocstr, "inbound", locCntrRel.S_CNTR_CODE, tasklist.order_name, 1, 1);
                //        if (!res)
                //        {
                //            return new TaskResponse
                //            {
                //                header = new ResponseHead { code = 1, desc = Message }
                //            };
                //        }
                //    }
                //}
                var result = new TaskResponse();
                if (Message != null)
                {
@@ -1860,142 +1496,15 @@
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("bigMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("bigMaterial:" + ex.Message, ex);
                Console.WriteLine("smallMaterial:" + ex.Message + ex.StackTrace);
                LogHelper.Error("smallMaterial:" + ex.Message, ex);
                throw;
            }
        }
        //自动 拆分
        public static TaskResponse autoSmallMaterial(smallMaterial model) {
            var db = new SqlHelper<Location>().GetInstance();
            string Message = null;
            //拆分成两条任务,一条是料架到指定的缓存区,二是料架上的托盘到指定的工位(小米wcs传)一对多
            var startFrame = db.Queryable<LocFrameRel>().Where(a => a.S_LOC_CODE == model.parameters[0].src).First();
            var startLoc = db.Queryable<Location>().Where(a => a.S_CODE == startFrame.S_FRAME_CODE).First();
            if (startLoc == null || startLoc.N_LOCK_STATE != 0)
            {
                return new TaskResponse
                {
                    header = new ResponseHead { code = 0, desc = $"{model.parameters[0].src}库位已被锁定!" }
                };
            }
            var endReservoirs = Settings.ReservoirAreas.Where(s => s.areaName == model.routeType).FirstOrDefault();
            var endLoc = TaskProcess.InWorkTransport(endReservoirs.areaCode);
            if (endLoc != null)
            {
                //创建到缓存区任务
                var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).First();
                //创建任务
                LogHelper.Info($"创建任务 起点:{startLoc.S_CODE}终点:{endLoc.S_CODE}", model.ts_name);
                var res = TaskProcess.CreateTransportHj(startLoc.S_CODE, endLoc.S_CODE, model.ts_name, locCntrRel.S_FRAME_CODE, 1, 1);
                if (!res)
                {
                    return new TaskResponse
                    {
                        header = new ResponseHead { code = 0, desc = "自动上线任务创建失败" }
                    };
                }
            }
            //料架上的托盘到指定的工位
            foreach (var parameter in model.parameters)
            {
                var startLocHj = db.Queryable<Location>().Where(a => a.S_CODE == parameter.src).First();
                if (startLocHj == null || startLocHj.N_LOCK_STATE != 0)
                {
                     Message = Message==null? $"{model.parameters[0].src}库位已被锁定!": Message+ $"{model.parameters[0].src}库位已被锁定!";
                }
                else
                {
                    //货架上的货判断一下货架有没有锁
                    var startFrameParent = db.Queryable<LocFrameRel>().Where(a => a.S_LOC_CODE == parameter.src).First();
                    if (startFrameParent != null)
                    {
                        var startLocParent = db.Queryable<Location>().Where(a => a.S_CODE == startFrameParent.S_FRAME_CODE).First();
                        if (startLocParent == null || startLocParent.N_LOCK_STATE != 0)
                        {
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = $"{startFrameParent.S_FRAME_CODE}货架已被锁定!" }
                            };
                        }
                    }
                    var endLocHj = db.Queryable<Location>().Where(a => a.S_CODE == parameter.dst).First();
                    if (endLocHj == null || endLocHj.N_LOCK_STATE != 0 || endLocHj.C_ENABLE != "Y")
                    {
                        //应该绕路
                        Message = Message == null ? $"{parameter.dst}库位已被锁定!" : Message + $"{parameter.dst}库位已被锁定!";
                    }
                    else
                    {
                        //货架上的货判断一下货架有没有锁
                        var endFrameParent = db.Queryable<LocFrameRel>().Where(a => a.S_LOC_CODE == parameter.dst).First();
                        if (endFrameParent != null)
                        {
                            var endLocParent = db.Queryable<Location>().Where(a => a.S_CODE == endFrameParent.S_FRAME_CODE).First();
                            if (endLocParent == null || endLocParent.N_LOCK_STATE != 0)
                            {
                                return new TaskResponse
                                {
                                    header = new ResponseHead { code = 0, desc = $"{endFrameParent.S_FRAME_CODE}货架已被锁定!" }
                                };
                            }
                        }
                        //创建到缓存区任务
                        var locCntrRel1 = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startLocHj.S_CODE).First();
                        //创建任务
                        LogHelper.Info($"创建任务 起点:{startLocHj.S_CODE}终点:{endLocHj.S_CODE}", model.ts_name);
                        var res = TaskProcess.CreateTransport(startLocHj.S_CODE, endLocHj.S_CODE, model.ts_name, locCntrRel1.S_CNTR_CODE, 1, 1);
                        if (!res)
                        {
                            return new TaskResponse
                            {
                                header = new ResponseHead { code = 0, desc = "自动上线任务2创建失败" }
                            };
                        }
                    }
                }
            }
            var result = new TaskResponse();
            if (Message != null)
            {
                result = new TaskResponse
                {
                    header = new ResponseHead { code = 0, desc = Message }
                };
            }
            else
            {
                result = new TaskResponse
                {
                    header = new ResponseHead { code = 200, desc = "SUCCESS" },
                    body = new ResponseBody
                    {
                        msg = "success",
                        app_name = "Guozi client",
                        data = new List<ResponseData> { new ResponseData { in_order_id = model.taskID } },
                        version = ""
                    }
                };
            }
            return result;
        }
        //人工 不拆分
        public static void artificialSmallMaterial(smallMaterial model)
        {
            var db = new SqlHelper<Location>().GetInstance();
        }