380b269f623092f371d46f718a4cdf72817d0489..034839c93e9f18d2b77105a85f65c8400798d74c
2025-05-30 zxx
巨石
034839 对比 | 目录
2025-05-27 zxx
巨石
cdf20a 对比 | 目录
2025-05-19 zxx
测试
9e694f 对比 | 目录
2025-05-19 zxx
主动绑定接口 rgv安全交互
839cd7 对比 | 目录
2025-05-19 zxx
主动绑定接口 rgv安全交互
5dade6 对比 | 目录
2个文件已添加
19个文件已修改
1695 ■■■■ 已修改文件
.gitignore 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/HH.WCS.JuShi.csproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/Program.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/api/ApiHelper.cs 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/api/MoboxController.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/api/WmsController.cs 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/config/config.json 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/core/WCSCore.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/core/WMSCore.cs 187 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/device/S7Helper.cs 290 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/device/TcpServer.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/CameraMonitor.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/CntrItemDetail.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/GetSubmitCheck.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/PlcDeviceTable.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/SafeInteraction.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/TN_ISUSING.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/process/DeviceProcess.cs 149 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/process/TaskProcess.cs 560 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/util/Settings.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/wms/ContainerHelper.cs 81 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -184,3 +184,5 @@
# Microsoft Fakes
FakesAssemblies/
/.vs/HH.WCS.JuShi/FileContentIndex/3fc4eebc-46c2-4e7f-9d3f-1120aff520d4.vsidx
/.vs/HH.WCS.JuShi/FileContentIndex/e9cb8869-a58d-4485-bb3e-8bac64b53e74.vsidx
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/HH.WCS.JuShi.csproj
@@ -217,8 +217,10 @@
    <Compile Include="dispatch\HanAo.cs" />
    <Compile Include="dispatch\NDC.cs" />
    <Compile Include="core\Monitor.cs" />
    <Compile Include="models\TN_ISUSING.cs" />
    <Compile Include="models\BaseModel.cs" />
    <Compile Include="models\Area.cs" />
    <Compile Include="models\SafeInteraction.cs" />
    <Compile Include="models\SafetyInteraction.cs" />
    <Compile Include="models\CntrItemDetail.cs" />
    <Compile Include="models\CameraMonitor.cs" />
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/Program.cs
@@ -78,10 +78,12 @@
                tasks.Add(GetTask(WCSCore.Dispatch));
                //摄像头监测满状态托盘
                tasks.Add(GetTask(WMSCore.MonitorFullStatus));
                //监测空托缓存区有没有人工绑定
                tasks.Add(GetTask(WMSCore.AutoSendMachine));
                ////常规送检空了自动从送检缓存区取一个送过去
                //tasks.Add(GetTask(WMSCore.AutoReplenish));
                tasks.Add(GetTask(WMSCore.AutoReplenish));
                //S7通讯
                //tasks.Add(GetTask(S7Helper.ReadSsxPLc));
                tasks.Add(GetTask(S7Helper.ReadSsxPLc));
                Task.WaitAll(tasks.ToArray());
            }
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/api/ApiHelper.cs
@@ -290,50 +290,50 @@
            return result;
        }
        internal static SimpleResult PalletSorting1(PalletSorting1 model)
        {
            var result = new SimpleResult();
            //校验入库单数量,不可以超,成功后插入托盘物料表,更新入库单累计数量
            //也可以直接lua查询入库单数量,做校验
            //先用bar_code读存储过程获取信息
            var codeInfo = GetCodeInfo(model.bar_code, model.org);
            var info = WMSHelper.GetPutawayOrderDetail(model.bar_code);
            if (info != null)
            {
                if (info.F_QTY - info.F_ACC_B_QTY >= model.qty)
                {
                    // 插入到托盘明细表
        //internal static SimpleResult PalletSorting1(PalletSorting1 model)
        //{
        //    var result = new SimpleResult();
        //    //校验入库单数量,不可以超,成功后插入托盘物料表,更新入库单累计数量
        //    //也可以直接lua查询入库单数量,做校验
        //    //先用bar_code读存储过程获取信息
        //    var codeInfo = GetCodeInfo(model.bar_code, model.org);
        //    var info = WMSHelper.GetPutawayOrderDetail(model.bar_code);
        //    if (info != null)
        //    {
        //        if (info.F_QTY - info.F_ACC_B_QTY >= model.qty)
        //        {
        //            // 插入到托盘明细表
                    var cntr = ContainerHelper.GetCntr(model.cntr_code, true);
                    if (cntr != null)
                    {
                        ContainerHelper.BindCntrItem(cntr, model.bar_code, info.S_BATCH_NO, model.qty, info.S_BATCH_NO);
                        //更新入库单累计绑定数量
                        info.F_ACC_B_QTY += model.qty;
                        WMSHelper.UpdatePutawayOrderDetailQty(info);
                    }
                    else
                    {
                        result.resultCode = 2;
                        result.resultMsg = "获取托盘信息失败";
                    }
        //            var cntr = ContainerHelper.GetCntr(model.cntr_code, true);
        //            if (cntr != null)
        //            {
        //                ContainerHelper.BindCntrItem(cntr, model.bar_code, info.S_BATCH_NO, model.qty, info.S_BATCH_NO);
        //                //更新入库单累计绑定数量
        //                info.F_ACC_B_QTY += model.qty;
        //                WMSHelper.UpdatePutawayOrderDetailQty(info);
        //            }
        //            else
        //            {
        //                result.resultCode = 2;
        //                result.resultMsg = "获取托盘信息失败";
        //            }
                }
                else
                {
                    result.resultCode = 1;
                    result.resultMsg = "累计码盘数量超出入库单数量";
                }
            }
            else
            {
                result.resultCode = 3;
                result.resultMsg = $"未获取到该物料{model.bar_code}的入库单明细信息";
            }
        //        }
        //        else
        //        {
        //            result.resultCode = 1;
        //            result.resultMsg = "累计码盘数量超出入库单数量";
        //        }
        //    }
        //    else
        //    {
        //        result.resultCode = 3;
        //        result.resultMsg = $"未获取到该物料{model.bar_code}的入库单明细信息";
        //    }
            return result;
        }
        //    return result;
        //}
        public class AddTaskModel
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/api/MoboxController.cs
@@ -83,10 +83,10 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public SimpleResult PalletSorting1(PalletSorting1 model) {
            return ApiHelper.PalletSorting1(model);
        }
        //[HttpPost]
        //public SimpleResult PalletSorting1(PalletSorting1 model) {
        //    return ApiHelper.PalletSorting1(model);
        //}
        /// <summary>
        /// pda入库申请
        /// </summary>
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/api/WmsController.cs
@@ -1,6 +1,7 @@

using HH.WCS.JuShi;
using HH.WCS.JuShi.api;
using HH.WCS.JuShi.device;
using HH.WCS.JuShi.process;
using Newtonsoft.Json;
using System.Collections.Generic;
@@ -73,7 +74,32 @@
            return res;
        }
        /// <summary>
        /// 主动物料绑定
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public Results BindMaterial(GetSubmitCheck model)
        {
            LogHelper.Info("BindMaterial 参数:" + JsonConvert.SerializeObject(model), "WMSAPI");
            var res = TaskProcess.bindMaterial(model);
            LogHelper.Info("BindMaterial 返回:" + JsonConvert.SerializeObject(res), "WMSAPI");
            return res;
        }
        /// <summary>
        /// 整排绑定
        /// </summary>
        /// <param name="bondLoc"></param>
        /// <returns></returns>
        [HttpPost]
        public Results MultBindMaterial(string bondLoc)
        {
            LogHelper.Info("MultBindMaterial 参数:" + JsonConvert.SerializeObject(bondLoc), "WMSAPI");
            var res = TaskProcess.multBindMaterial(bondLoc);
            LogHelper.Info("MultBindMaterial 返回:" + JsonConvert.SerializeObject(res), "WMSAPI");
            return res;
        }
        /// <summary>
        /// 摄像头监测
        /// </summary>
@@ -101,6 +127,44 @@
            return res;
        }
        /// <summary>
        /// 服务开关按钮
        /// </summary>
        /// <param name="isusing.S_STATUS">服务状态</param>
        /// <param name="isusing.S_TYPE">服务类型</param>
        /// <returns></returns>
        [HttpPost]
        public Results switchButton(Isusing isusing)
        {
            LogHelper.Info("switchButton 参数:" + JsonConvert.SerializeObject(isusing), "WMSAPI");
            var res = TaskProcess.switchButton(isusing);
            LogHelper.Info("switchButton 返回:" + JsonConvert.SerializeObject(res), "WMSAPI");
            return res;
        }
        /// <summary>
        /// tcp发送信号 测试用
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public Results tcpSend(string str)
        {
            LogHelper.Info("tcpSend 参数:" + str, "WMSAPI");
            var res = TaskProcess.tcpSend(str);
            LogHelper.Info("tcpSend 返回:" + str, "WMSAPI");
            return res;
        }
        /// <summary>
        /// S7写入信号 测试用
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public Results S7Write(Isusing offsetAddr)
        {
            LogHelper.Info("S7Write 参数:" + offsetAddr, "WMSAPI");
            var res = S7Helper.S7Write(offsetAddr);
            LogHelper.Info("S7Write 返回:" + offsetAddr, "WMSAPI");
            return res;
        }
    }
}
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/config/config.json
@@ -28,7 +28,7 @@
      "areaCode": "JJSJQ"
    },
    {
      "areaName": "RGV库区",
      "areaName": "立库入库区",
      "areaCode": "RGV"
    },
    {
@@ -191,27 +191,77 @@
      "enable": 1
    }
  ],
  //安全门
  "SafeDoor": [
  //安全交互
  "SafeInteraction": [
    {
      "pointCode": "门1",
      "pointCode": "RGV01",
      "code": 1,
      "ip": "192.168.1.133",
      "port": "8080"
      "type": "RGV",
      "location": "RGV01"
    },
    {
      "pointCode": "门2",
      "pointCode": "RGV02",
      "code": 2,
      "ip": "192.168",
      "port": "8888"
      "type": "RGV",
      "location": "RGV02"
    },
    {
      "pointCode": "门3",
      "pointCode": "RGV03",
      "code": 3,
      "ip": "192.168",
      "port": "8888"
      "type": "RGV",
      "location": "RGV03"
    },
    {
      "pointCode": "门4",
      "pointCode": "RGV04",
      "code": 4,
      "ip": "192.168",
      "port": "8888"
      "type": "RGV",
      "location": "RGV04"
    },
    {
      "pointCode": "RGV05",
      "code": 5,
      "ip": "192.168",
      "type": "RGV",
      "location": "RGV05"
    },
    {
      "pointCode": "RGV06",
      "code": 6,
      "ip": "192.168",
      "type": "RGV",
      "location": "RGV06"
    },
    {
      "pointCode": "拆托机1入口",
      "code": 7,
      "ip": "192.168",
      "type": "CTJ",
      "location": "CPJ01-R"
    },
    {
      "pointCode": "拆托机1出口",
      "code": 8,
      "ip": "192.168",
      "type": "CTJ",
      "location": "CPJ01-C"
    },
    {
      "pointCode": "拆托机2入口",
      "code": 9,
      "ip": "192.168",
      "type": "CTJ",
      "location": "CPJ02-R"
    },
    {
      "pointCode": "拆托机2出口",
      "code": 10,
      "ip": "192.168",
      "type": "CTJ",
      "location": "CPJ02-C"
    }
  ]
  ////摄像头点位配置
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/core/WCSCore.cs
@@ -10,7 +10,7 @@
namespace HH.WCS.JuShi.core
{
    internal class WCSCore
    {
    {
        public static void OperateAgvTaskStatus(AgvTaskState model)
        {
            var TN_Task = WCSHelper.GetTask(model.No);
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/core/WMSCore.cs
@@ -1,4 +1,5 @@
using HH.WCS.JuShi.api;
using HH.WCS.JuShi.device;
using HH.WCS.JuShi.process;
using HH.WCS.JuShi.util;
using HH.WCS.JuShi.wms;
@@ -172,49 +173,56 @@
        //    }
        //}
        //监测摄像头处货位(送检入库区)空满状态 满的就叉到立库
        public static void MonitorFullStatus()
        {
            //bool result = false;
            //找送检入库区满托盘的货位
            var db = new SqlHelper<Location>().GetInstance();
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检入库区").FirstOrDefault();
                var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "RGV库区").FirstOrDefault();
                //三表联查查出托盘满的 按创建时间顺序
                var locCntrs = db.Queryable<LocCntrRel>().LeftJoin<Container>((p, c) => p.S_CNTR_CODE == c.S_CODE)
                .Where((p, c) => c.C_FULL == "2")
                .OrderBy((p, c) => p.T_CREATE)
                .Select((p, c) => p.S_LOC_CODE) // 选择托盘物料表的数据
                .ToList();
                var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检入库区").FirstOrDefault();
                var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "立库入库区").FirstOrDefault();
                //三表联查查出托盘满的 按创建时间顺序
                var locCntrs = db.Queryable<LocCntrRel>().LeftJoin<Container>((p, c) => p.S_CNTR_CODE == c.S_CODE)
                .Where((p, c) => c.C_FULL == "2")
                .OrderBy((p, c) => p.T_CREATE)
                .Select((p, c) => p.S_LOC_CODE) // 选择托盘物料表的数据
                .ToList();
                //找送检入库区内托盘满了的货位
                var locList = db.Queryable<Location>()
                    .Where(p => p.S_AREA_CODE == reservoirs.areaCode && p.N_LOCK_STATE == 0)
                    .Where(s => locCntrs.Contains(s.S_CODE.Trim()))
                    .ToList();
                //找送检入库区内托盘满了的货位
                var locList = db.Queryable<Location>()
                    .Where(p => p.S_AREA_CODE == reservoirs.areaCode && p.N_LOCK_STATE == 0)
                    .Where(s => locCntrs.Contains(s.S_CODE.Trim()))
                    .ToList();
                if (locList.Any())
                {
                    //建任务
                    var startLoc = locList.FirstOrDefault();
                    var endLoc = TaskProcess.InWorkTransport(reservoirs2.areaCode);
                if (locList.Any())
                {
                    LogHelper.Info($"任务摄像头监测空满状态找到货位{JsonConvert.SerializeObject(locList)}");
                    //建任务
                    var startLoc = locList.FirstOrDefault();
                    var endLoc = TaskProcess.InWorkTransport(reservoirs2.areaCode);
                    LogHelper.Info($"任务摄像头监测找到终点货位:{JsonConvert.SerializeObject(endLoc)}");
                    if (endLoc!=null)
                    {
                        var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == startLoc.S_CODE).First();
                        LogHelper.Info($"任务摄像头监测找到托盘:{JsonConvert.SerializeObject(locCntrRel)}");
                    var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == endLoc.S_CODE).First();
                    TaskProcess.CreateTransport(startLoc.S_CODE, endLoc.S_CODE, "摄像头监测", locCntrRel.S_CNTR_CODE, 1, 1);
                        TaskProcess.CreateTransport(startLoc.S_CODE, endLoc.S_CODE, "摄像头监测", locCntrRel.S_CNTR_CODE, 1, 1);
                }
            }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("AutoReplenish:" + ex.Message + ex.StackTrace);
                LogHelper.Error("AutoReplenish:" + ex.Message, ex);
                throw;
            }
            {
                Console.WriteLine("MonitorFullStatus:" + ex.Message + ex.StackTrace);
                LogHelper.Error("MonitorFullStatus:" + ex.Message, ex);
                throw;
            }
            //return result;
@@ -222,7 +230,12 @@
        //常规送检空了自动从送检缓存区取一个送过去
        public static void AutoReplenish()
        {
            var db = new SqlHelper<Location>().GetInstance();
            var db = new SqlHelper<object>().GetInstance();
            var isusinglist = db.Queryable<Isusing>().Where(a => a.S_TYPE == "自动补货").First();
            if (isusinglist.S_STATUS == 0)
            {
                return;
            }
            try
            {
                var cgreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault();
@@ -233,17 +246,110 @@
                    var hcreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault();
                    //找送检缓存区有货的货位
                    var startloc = TaskProcess.OutWorkTransport(hcreservoirs.areaCode);
                    //LogHelper.Info($"AutoReplenish 自动补货 起点货位{JsonConvert.SerializeObject(startloc)}");
                    if (startloc != 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)
                        {
                            LogHelper.Info($"任务 起点:{startloc.S_CODE}终点:{endloc.S_CODE}创建失败", "自动补货");
                        }
                    }
                    //创建送检任务
                    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)
                    {
                        LogHelper.Info($"任务 起点:{startloc.S_CODE}终点:{endloc.S_CODE}创建失败", "自动补货");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("AutoReplenish:" + ex.Message + ex.StackTrace);
                LogHelper.Error("AutoReplenish:" + ex.Message, ex);
                throw;
            }
                }
        }
        //空托缓存区有绑定的托盘就送到拆托机
        public static void AutoSendMachine()
        {
            var db = new SqlHelper<object>().GetInstance();
            var isusinglist = db.Queryable<Isusing>().Where(a => a.S_TYPE == "自动送托").First();
            if (isusinglist.S_STATUS == 0)
            {
                return;
            }
            try
            {
                var reservoirs1 = Settings.ReservoirAreas.Where(s => s.areaName == "3min空托区").FirstOrDefault();
                var reservoirs2 = Settings.ReservoirAreas.Where(s => s.areaName == "6min空托区").FirstOrDefault();
                var linePlcInfo1 = Settings.linePlcInfos.Where(s => s.deviceNo == "1").FirstOrDefault();
                var linePlcInfo2 = Settings.linePlcInfos.Where(s => s.deviceNo == "2").FirstOrDefault();
                //找到空托缓存区的所有货位编号
                var locList = db.Queryable<Location>()
                    .Where(s => s.S_AREA_CODE == reservoirs1.areaCode || s.S_AREA_CODE == reservoirs2.areaCode)
                    .Where(s => s.N_LOCK_STATE == 0)
                    .OrderByDescending(s => s.N_ROW).OrderByDescending(s => s.N_COL).OrderBy(s => s.N_LAYER)
                    .Select(s => s.S_CODE)
                    .ToList();
                //找到绑了托盘的货位号
                var locCntrs = db.Queryable<LocCntrRel>()
                    .Where(s => locList.Contains(s.S_LOC_CODE.Trim()))
                    .Select(s => s.S_LOC_CODE)
                    .ToList();
                if (locCntrs.Any())
                {
                    //LogHelper.Info($"空托缓存区有绑定货位:{JsonConvert.SerializeObject(locCntrs)}");
                    //var loccode = locCntrs.First();
                    foreach (var loccode in locCntrs)
                    {
                        var loc = db.Queryable<Location>().Where(s => s.S_CODE == loccode).First();
                        //判断送往3寸还是6寸拆托机
                        string endLoc = null;
                        string dev = null;
                        if (loc.S_AREA_CODE == reservoirs1.areaCode)
                        {
                            endLoc = linePlcInfo1.inLoca;
                            dev = "1";
                        }
                        else if (loc.S_AREA_CODE == reservoirs2.areaCode)
                        {
                            endLoc = linePlcInfo2.inLoca;
                            dev = "2";
                        }
                        var endLocation = db.Queryable<Location>().Where(s => s.S_CODE == endLoc).First();
                        if (endLocation == null || endLocation.N_LOCK_STATE != 0)
                        {
                            //LogHelper.Info($"拆托机货位{endLoc}不存在或已被锁");
                            return;
                        }
                        //校验是否允许放货
                        var plcDeviceTable = S7Helper.plcDeviceTables;
                        LogHelper.Info($"自动送托 拆托机{dev}:{plcDeviceTable.requestPut1}");
                        if ((plcDeviceTable.requestPut1 && dev == "1") ||
                            (plcDeviceTable.requestPut2 && dev == "2"))
                        {
                            var locCntrRel = db.Queryable<LocCntrRel>().Where(a => a.S_LOC_CODE == loccode).First();
                            LogHelper.Info($"创建任务 起点:{loccode}终点:{endLoc}");
                            var res = TaskProcess.CreateTransport(loccode, endLoc, "送托", locCntrRel.S_CNTR_CODE, 1, 1);
                            if (res)
                            {
                                LogHelper.Info($"起点:{loccode}终点:{endLoc}任务创建成功");
                            }
                            else
                            {
                                LogHelper.Info($"起点:{loccode}终点:{endLoc}任务创建失败");
                            }
                        }
                        else
                        {
                            LogHelper.Info($"拆托机{endLoc}不允许放框");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
@@ -255,7 +361,6 @@
        }
    }
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/device/S7Helper.cs
@@ -3,6 +3,7 @@
using Microsoft.Owin.BuilderProperties;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Opc.Ua;
using S7.Net;
using S7.Net.Types;
using SqlSugar;
@@ -11,6 +12,7 @@
using System.Data.SqlTypes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Services.Description;
using static HH.WCS.JuShi.util.Settings;
@@ -164,6 +166,9 @@
            var result = false;
            try
            {
                var linkplc = Settings.SafeInteractions.First();
                var plc = new Plc(CpuType.S71200, linkplc.ip, 0, 1);
                Link(plc);
                if (plc.IsConnected)
                {
                    plc.Write(DataType.DataBlock, db, byteAddr, data);
@@ -285,76 +290,187 @@
        }
        public static List<PlcDeviceTable> plcDeviceTables = new List<PlcDeviceTable>();
        public static PlcDeviceTable plcDeviceTables = new PlcDeviceTable();
        /// <summary>
        /// 获取输送线数据
        /// </summary>
        public static void ReadSsxPLc()
        {
            //#region 测试写入数据
            //List<S7Model> s7Models = new List<S7Model>();
            //s7Models.Add(new S7Model() { addr = 0, value = "1", type = "Int", length = 2 });
            //s7Models.Add(new S7Model() { addr = 2, value = "2", type = "Int", length = 2 });
            //s7Models.Add(new S7Model() { addr = 4, value = "4", type = "Int", length = 2 });
            //s7Models.Add(new S7Model() { addr = 18, value = "TP24121108", type = "String", length = 20 });
            //var plcInfo = Settings.linePlcInfo.Where(a => (a.deviceNo == "2") && a.enable == 1).FirstOrDefault();
            //Write(s7Models, 100, plcInfo);
            //#endregion
            var db = new SqlHelper<WCSTask>().GetInstance();
            //两个拆托机
            var linkplcs = Settings.linePlcInfos.FindAll(a => a.enable == 1).ToList();
            foreach (var linkplc in linkplcs){
                //获取设备配置文件
                var deviceInfos = Settings.ConveyorLinesInfos.Where(a => a.enable == 1 &&a.deviceNo== linkplc.deviceNo).ToList();
                if (deviceInfos.Count > 0)
            try
            {
                var linkplc = Settings.SafeInteractions.FindAll(a => a.code == 1|| a.code == 7).ToList();
                var plc = new Plc(CpuType.S71500, linkplc[1].ip, 0, 1);
                Link(plc);
                var plc1 = new Plc(CpuType.S71200, linkplc[0].ip, 0, 1);
                Link(plc1);
                //拆托机
                //object rawValue = plc.Read(DataType.DataBlock, 8, 230, VarType.Byte, 1);
                //LogHelper.Info($"Raw value: {rawValue} (Type: {rawValue?.GetType()})");
                // 先读取整个字节
                byte data = (byte)plc.Read(DataType.DataBlock, 8, 230, VarType.Byte, 1);
                // 然后提取各个位
                bool requestPut1 = (data & 0x01) != 0;  // 230.0   1001
                bool requestTake1 = (data & 0x02) != 0;   // 230.1    1003
                bool requestPut2 = (data & 0x04) != 0;  // 230.2     1004
                bool requestTake2 = (data & 0x08) != 0;   // 230.3    1006
                LogHelper.Info($"拆托机接收信号====={requestPut1},{requestTake1},{requestPut2},{requestTake2}");
                //RGV
                //var rawValue = plc1.Read(DataType.DataBlock, 51, 0, VarType.Int, 1);
                //LogHelper.Info($"Raw value: {rawValue}, Type: {rawValue?.GetType()}");
                // RGV允许卸货状态读取 (从DB51读取)
                int rgv1AllowUnload = Convert.ToInt32(plc1.Read(DataType.DataBlock, 51, 0, VarType.Int, 1));
                int rgv2AllowUnload = Convert.ToInt32(plc1.Read(DataType.DataBlock, 51, 2, VarType.Int, 1));
                int rgv3AllowUnload = Convert.ToInt32(plc1.Read(DataType.DataBlock, 51, 4, VarType.Int, 1));
                int rgv4AllowUnload = Convert.ToInt32(plc1.Read(DataType.DataBlock, 51, 6, VarType.Int, 1));
                int rgv5AllowUnload = Convert.ToInt32(plc1.Read(DataType.DataBlock, 51, 8, VarType.Int, 1));
                int rgv6AllowUnload = Convert.ToInt32(plc1.Read(DataType.DataBlock, 51, 10, VarType.Int, 1));
                LogHelper.Info($"RGV接收信号=== 1={rgv1AllowUnload}, 2={rgv2AllowUnload}, 3={rgv3AllowUnload}, 4={rgv4AllowUnload}, 5={rgv5AllowUnload}, 6={rgv6AllowUnload}");
                //存到缓存
                if (plcDeviceTables != null)
                {
                    int slen =int.Parse(deviceInfos.Min(a => a.readAddr).ToString());
                    int elen = int.Parse(deviceInfos.Max(a => a.readAddr).ToString());
                    //读取输送线整个偏移量的byte数组 放内存里一起解析,防止过度读取
                    //PLCRead(linkplc.address, 8, slen, elen + 18, out Ssxbytes);
                    var plc = new Plc(CpuType.S71500, linkplc.address, 0, 1);
                    Link(plc);
                    //一个拆托机两个线体
                    foreach (var device in deviceInfos)
                    plcDeviceTables.requestTake1 = requestTake1;
                    plcDeviceTables.requestPut1 = requestPut1;
                    plcDeviceTables.requestTake2 = requestTake2;
                    plcDeviceTables.requestPut2 = requestPut2;
                    plcDeviceTables.RGVAllowUnload = new Dictionary<int, int>
                    {
                        //int workMode = int.Parse(GetValue(int.Parse(device.readAddr.ToString()), VarType.Int, Ssxbytes));        //工作模式
                        //int lightAction = int.Parse(GetValue(int.Parse((device.readAddr + 2).ToString()), VarType.Int, Ssxbytes));     //是否有货,光电信号
                        int workMode = (short)plc.Read(DataType.DataBlock, 8, int.Parse(device.readAddr.ToString()), VarType.Int, 1, 0);
                        int lightAction = (short)plc.Read(DataType.DataBlock, 8, int.Parse((device.readAddr + 2).ToString()), VarType.Int, 1, 0);
                        var requestTake = plc.Read("DB8.DBX"+ device.readAddr+16.0);//输送线请求取框
                        var requestPut = plc.Read("DB8.DBX"+ device.readAddr + 16.1);//输送线允许放框
                        //存到缓存
                        var task = plcDeviceTables.Find(a => a.DeviceNo == device.code);
                        if (task != null)
                        {
                            task.DeviceNo = device.code;
                            task.workMode = workMode;
                            task.lightAction = lightAction;
                            task.requestTake =bool.Parse(requestTake.ToString());
                            task.requestPut = bool.Parse(requestPut.ToString());
                        }
                        else
                        {
                            var plcDeviceTable = new PlcDeviceTable();
                            plcDeviceTable.DeviceNo = device.code;
                            plcDeviceTable.workMode = workMode;
                            plcDeviceTable.lightAction = lightAction;
                            plcDeviceTable.requestTake = bool.Parse(requestTake.ToString());
                            plcDeviceTable.requestPut = bool.Parse(requestPut.ToString());
                            plcDeviceTables.Add(plcDeviceTable);
                        }
                    }
                        {1, rgv1AllowUnload},
                        {2, rgv2AllowUnload},
                        {3, rgv3AllowUnload},
                        {4, rgv4AllowUnload},
                        {5, rgv5AllowUnload},
                        {6, rgv6AllowUnload}
                    };
                    LogHelper.Info($"S7协议第一次读取参数:{JsonConvert.SerializeObject(plcDeviceTables)}");
                }
                else
                {
                    var plcDeviceTable = new PlcDeviceTable();
                    plcDeviceTable.requestTake1 = requestTake1;
                    plcDeviceTable.requestPut1 = requestPut1;
                    plcDeviceTable.requestTake2 = requestTake2;
                    plcDeviceTable.requestPut2 = requestPut2;
                    plcDeviceTable.RGVAllowUnload = new Dictionary<int, int>
                    {
                        {1, rgv1AllowUnload},
                        {2, rgv2AllowUnload},
                        {3, rgv3AllowUnload},
                        {4, rgv4AllowUnload},
                        {5, rgv5AllowUnload},
                        {6, rgv6AllowUnload}
                    };
                    plcDeviceTables = plcDeviceTable;
                    LogHelper.Info($"S7协议读取参数:{JsonConvert.SerializeObject(plcDeviceTable)}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ReadSsxPLc:" + ex.Message + ex.StackTrace);
                LogHelper.Error("ReadSsxPLc:" + ex.Message, ex);
                throw;
            }
        }
        ///// <summary>
        ///// 获取输送线数据
        ///// </summary>
        //public static void oldReadSsxPLc()
        //{
        //    //#region 测试写入数据
        //    //List<S7Model> s7Models = new List<S7Model>();
        //    //s7Models.Add(new S7Model() { addr = 0, value = "1", type = "Int", length = 2 });
        //    //s7Models.Add(new S7Model() { addr = 2, value = "2", type = "Int", length = 2 });
        //    //s7Models.Add(new S7Model() { addr = 4, value = "4", type = "Int", length = 2 });
        //    //s7Models.Add(new S7Model() { addr = 18, value = "TP24121108", type = "String", length = 20 });
        //    //var plcInfo = Settings.linePlcInfo.Where(a => (a.deviceNo == "2") && a.enable == 1).FirstOrDefault();
        //    //Write(s7Models, 100, plcInfo);
        //    //#endregion
        //    var db = new SqlHelper<WCSTask>().GetInstance();
        //    try
        //    {
        //        //两个拆托机
        //        var linkplcs = Settings.linePlcInfos.FindAll(a => a.enable == 1).ToList();
        //        foreach (var linkplc in linkplcs)
        //        {
        //            //获取设备配置文件
        //            var deviceInfos = Settings.ConveyorLinesInfos.Where(a => a.enable == 1 && a.deviceNo == linkplc.deviceNo).ToList();
        //            if (deviceInfos.Count > 0)
        //            {
        //                int slen = int.Parse(deviceInfos.Min(a => a.readAddr).ToString());
        //                int elen = int.Parse(deviceInfos.Max(a => a.readAddr).ToString());
        //                //读取输送线整个偏移量的byte数组 放内存里一起解析,防止过度读取
        //                //PLCRead(linkplc.address, 8, slen, elen + 18, out Ssxbytes);
        //                var plc = new Plc(CpuType.S71500, linkplc.address, 0, 1);
        //                Link(plc);
        //                //一个拆托机两个线体
        //                foreach (var device in deviceInfos)
        //                {
        //                    //int workMode = int.Parse(GetValue(int.Parse(device.readAddr.ToString()), VarType.Int, Ssxbytes));        //工作模式
        //                    //int lightAction = int.Parse(GetValue(int.Parse((device.readAddr + 2).ToString()), VarType.Int, Ssxbytes));     //是否有货,光电信号
        //                    //int workMode = (short)plc.Read(DataType.DataBlock, 8, int.Parse(device.readAddr.ToString()), VarType.Int, 1, 0);
        //                    //int lightAction = (short)plc.Read(DataType.DataBlock, 8, int.Parse((device.readAddr + 2).ToString()), VarType.Int, 1, 0);
        //                    int requestTake1 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 0);
        //                    int requestPut1 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 1);
        //                    int requestTake2 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 2);
        //                    int requestPut2 = (short)plc.Read(DataType.DataBlock, 8, 230, VarType.Int, 1, 3);
        //                    LogHelper.Info($"readbool2================={requestTake1},{requestPut1},{requestTake2},{requestPut2}");
        //                    //var requestTake = plc.Read("DB8.DBX" + device.readAddr + 16.0);//输送线请求取框
        //                    //var requestPut = plc.Read("DB8.DBX" + device.readAddr + 16.1);//输送线允许放框
        //                    //存到缓存
        //                    //var task = plcDeviceTables.Find(a => a.DeviceNo == device.code);
        //                    if (task != null)
        //                    {
        //                        task.DeviceNo = device.code;
        //                        //task.workMode = workMode;
        //                        //task.lightAction = lightAction;
        //                        task.requestTake1 = requestTake1;
        //                        task.requestPut1 = requestPut1;
        //                        task.requestTake2 = requestTake2;
        //                        task.requestPut2 = requestPut2;
        //                        LogHelper.Info($"S7协议第一次读取参数:{JsonConvert.SerializeObject(task)}");
        //                    }
        //                    else
        //                    {
        //                        var plcDeviceTable = new PlcDeviceTable();
        //                        plcDeviceTable.DeviceNo = device.code;
        //                        //plcDeviceTable.workMode = workMode;
        //                        //plcDeviceTable.lightAction = lightAction;
        //                        plcDeviceTable.requestTake1 = requestTake1;
        //                        plcDeviceTable.requestPut1 = requestPut1;
        //                        plcDeviceTable.requestTake2 = requestTake2;
        //                        plcDeviceTable.requestPut2 = requestPut2;
        //                        plcDeviceTables.Add(plcDeviceTable);
        //                        LogHelper.Info($"S7协议读取参数:{JsonConvert.SerializeObject(plcDeviceTable)}");
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        Console.WriteLine("ReadSsxPLc:" + ex.Message + ex.StackTrace);
        //        LogHelper.Error("ReadSsxPLc:" + ex.Message, ex);
        //        throw;
        //    }
        //}
        ///// <summary>
        ///// 批量写入方法
        ///// </summary>
@@ -669,7 +785,7 @@
            }
        }
        internal static bool WriteDouble(string deviceNo,int db, double? byteAddr, int data)
        internal static bool WriteDouble(string deviceNo, int db, int byteAddr, int offsetAddr, int data)
        {
            var result = false;
            try
@@ -679,22 +795,47 @@
                Link(plc);
                if (plc.IsConnected)
                {
                    if (byteAddr != 0) {
                        plc.Write("DB9.DBX" + byteAddr, data);
                        //plc.Write(DataType.DataBlock, db, byteAddr, data);
                    if (byteAddr != 0)
                    {
                        plc.WriteBit(DataType.DataBlock, db, byteAddr, offsetAddr, true);
                        Console.WriteLine($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} ");
                        LogHelper.Info($"写入plc信息,ip={plc.IP} addr={byteAddr} data={data} ");
                        if (result)
                        //睡三秒 如果还继续发请求的话就重写入 否则写入false
                        Thread.Sleep(3000);
                        var plcDeviceTable = S7Helper.plcDeviceTables;
                        if (plcDeviceTable != null)
                        {
                            //写完再读一次确认
                            //var readData = (short)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, 1, 0);
                            var readData = (short)plc.Read("DB9.DBX" + byteAddr);
                            Console.WriteLine($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}");
                            LogHelper.Info($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}", "PLC");
                            result = readData == data;
                            if ((offsetAddr == 0 && plcDeviceTable.requestPut1)
                                || (offsetAddr == 1 && plcDeviceTable.requestTake1)
                                || (offsetAddr == 2 && plcDeviceTable.requestPut2)
                                || (offsetAddr == 3 && plcDeviceTable.requestTake2))
                            {
                                WriteDouble(deviceNo, db, byteAddr, offsetAddr, data);
                            }
                            else
                            {
                                plc.WriteBit(DataType.DataBlock, db, byteAddr, offsetAddr, false);
                                LogHelper.Info($"S7发送复位信号");
                            }
                        }
                        //if (result)
                        //{
                        //    //写完再读一次确认
                        //    //var readData = (short)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Int, 1, 0);
                        //    //byte data1 = (byte)plc.Read(DataType.DataBlock, db, byteAddr, VarType.Byte, 1);
                        //    //// 然后提取各个位
                        //    //bool requestPut1 = (data1 & 0x01) != 0;  // 230.0   1001
                        //    var readData = (short)plc.Read("DB9.DBX" + byteAddr);
                        //    Console.WriteLine($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}");
                        //    LogHelper.Info($"读取plc信息,ip={plc.IP} addr={byteAddr} data={data} res={string.Join(", ", readData)}", "PLC");
                        //    result = readData == data;
                        //}
                    }
                }
                else
                {
@@ -829,7 +970,18 @@
            public string value { get; set; }
        }
        //S7写入信号 测试用
        internal static Results S7Write(Isusing offsetAddr)
        {
            //var linkplcs = Settings.linePlcInfos.Find(a => a.deviceNo == "1");
            //var plc = new Plc(CpuType.S71200, linkplcs.address, 0, 1);
            var linkplc = Settings.SafeInteractions.First();
            var plc = new Plc(CpuType.S71200, linkplc.ip, 0, 1);
            Link(plc);
            S7Helper.WriteInt(50, 0, (short)(offsetAddr.S_STATUS * 10 + int.Parse(offsetAddr.S_TYPE)));
            //plc.WriteBit(DataType.DataBlock, 9, 182, offsetAddr, false);
            return new Results() { Code = "0", Message = $"写入成功", Data = null };
        }
        #region 用于模拟测试
        /// <summary>
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/device/TcpServer.cs
@@ -1,4 +1,5 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
@@ -22,6 +23,7 @@
                socket.Listen(30);
                //开始接受客户端连接请求
                socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
                //Console.ReadLine();
            }
            catch (Exception e) {
                Console.WriteLine(e.Message);
@@ -30,7 +32,11 @@
        public static Dictionary<string, Socket> clients = new Dictionary<string, Socket>();
        public static Dictionary<string, byte[]> buffers = new Dictionary<string, byte[]>();
        public static void ClientAccepted(IAsyncResult ar) {
            //try
            //{
            Console.WriteLine("ClientAccepted================");
            var socket = ar.AsyncState as Socket;
            var client = socket.EndAccept(ar);
            string remote_ip = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address.ToString();
@@ -55,11 +61,19 @@
            }
            //准备接受下一个客户端请求
            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine($"ClientAccepted 异常: {ex.ToString()}");
            //}
        }
        public static void ReceiveMessage(IAsyncResult ar) {
            try {
                //Console.WriteLine("ReceiveMessage================");
                var socket = ar.AsyncState as Socket;
                string remote_ip = ((System.Net.IPEndPoint)socket.RemoteEndPoint).Address.ToString();
                var length = socket.EndReceive(ar);
@@ -80,9 +94,12 @@
                    if (buffers.Keys.Contains(remote_ip)) {
                        //读取出来消息内容
                        var message = GetHexString(buffers[remote_ip], length);//16   10
                        Console.WriteLine(message);
                        Console.WriteLine($"ReceiveMessage接收信号:{message}");
                        LogHelper.Info($"ReceiveMessage接收信号:{message}");
                        //Console.WriteLine(message);
                        //3A 00 01 00 01 05 73 00 02 01 01 B8
                        if (message.Substring(0, 2) == "3A") {
                        //按钮盒
                        if (message.Substring(0, 2) == "3a") {
                            //显示消息
                            if (length != 24) {
                                message = message.Substring(0, 24);
@@ -90,6 +107,18 @@
                            PlcHelper.Receive(remote_ip, message);
                            Array.Clear(buffers[remote_ip], 0, buffers[remote_ip].Length);//清空当前IP Buffer
                        }
                        //3F 00 10 20 30 40 50 60 0D 0A
                        //安全交互
                        else if (message.Substring(0, 4) == "3f00")
                        {
                            //显示消息
                            if (length != 20)
                            {
                                message = message.Substring(0, 20);
                            }
                            PlcHelper.Receive(remote_ip, message);
                            Array.Clear(buffers[remote_ip], 0, buffers[remote_ip].Length);//清空当前IP Buffer
                        }
                        else {
                            Console.WriteLine($"【TCP信息协议异常】:IP:{remote_ip},MSG:{message}");
                        }
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/CameraMonitor.cs
@@ -4,12 +4,12 @@
namespace HH.WCS.JuShi
{
    public  class CameraMonitor : BaseModel
    public  class SafeInteraction : BaseModel
    {
        //摄像头货位
        public string PointCode { get; set; }
        //摄像头货位空满状态
        public int PointStatus { get; set; }
        //站点
        public string code { get; set; }
        //信号
        public string data { get; set; }
    }
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/CntrItemDetail.cs
@@ -22,21 +22,21 @@
        /// 1:合格 2:不合格 
        /// </summary>
        public int N_ITEM_STATE { get; set; }
        public int S_CK { get; set; }
        //public int S_CK { get; set; }
        public string S_BATCH_NO { get; set; }
        public string S_END_USER { get; set; } = "";
        public string S_OWNER { get; set; }
        public string S_SUPPLIER_NO { get; set; }
        public string S_PACK_TYPE { get; set; }
        public float F_PACK_QTY { get; set; }
        //public string S_PACK_TYPE { get; set; }
        //public float F_PACK_QTY { get; set; }
        public float F_QTY { get; set; }
        public string S_UOM { get; set; } = "kg";
        public string S_CNTR_CODE { get; set; }
        public string S_BS_TYPE { get; set; } = "";
        public string S_BS_NO { get; set; } = "";
        
        public string S_ITEM_ROUTE { get; set; } = "";
        //public string S_ITEM_ROUTE { get; set; } = "";
        public float F_NET_WEIGHT { get; set; }
        public float F_GROSS_WEIGHT { get; set; }
        public string S_WU { get; set; } = "kg";
@@ -45,7 +45,7 @@
        /// </summary>
        public float F_ALLOC_QTY { get; set; }
        public string C_ITEM_MERGE { get; set; } = "N";
        public string S_PUTAWAY_NO { get; set; }
        //public string S_PUTAWAY_NO { get; set; }
        /// <summary>
        /// 反向映射
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/GetSubmitCheck.cs
@@ -15,9 +15,9 @@
        public string END_LOC { get; set; }
        //物料编号
        public string S_ITEM_CODE { get; set; }
        ////解绑货位
        //public string MONITOR_LOC { get; set; }
        //绑定货位
        public string BIND_LOC { get; set; }
    }
}
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/PlcDeviceTable.cs
@@ -1,57 +1,67 @@
using HH.WCS.JuShi.models;
using SqlSugar;
using System;
using System.Collections.Generic;
namespace HH.WCS.JuShi
{
    [SugarTable("PlcDeviceTable")]
    public class PlcDeviceTable : BaseModel
    {    /// <summary>
         /// 线体编号
         /// </summary>
        public int DeviceNo { get; set; }
    {
        ///// <summary>
        // /// 线体编号
        // /// </summary>
        //public int DeviceNo { get; set; }
        ///// <summary>
        ///// 设备货位编码
        ///// </summary>
        //public string Location { get; set; }
        ///// <summary>
        ///// 工作模式 待机=1 运行中=2  脱机=0
        ///// </summary>
        //public int workMode { get; set; }
        ///// <summary>
        ///// 光电信号        有货 =1 无货=0
        ///// </summary>
        //public int lightAction { get; set; }
        ///// <summary>
        ///// 故障报警
        ///// </summary>
        //public int errorAlarm { get; set; }
        ///// <summary>
        ///// 设备状态    无状态=0 运行状态=1 手动状态=2 有料等待=3 异常报警=4
        ///// </summary>
        //public int deviceState { get; set; }
        //public string TaskNo { get; set; }
        ///// <summary>
        ///// 目标地址
        ///// </summary>
        //public int targetAddr { get; set; }
        ///// <summary>
        ///// 重量
        ///// </summary>
        //public float weight { get; set; }
        ///// <summary>
        ///// 托盘码
        ///// </summary>
        //public string trayCode { get; set; }
        /// <summary>
        /// 设备货位编码
        /// 3寸输送线请求取框
        /// </summary>
        public string Location { get; set; }
        public bool requestTake1 { get; set; }
        /// <summary>
        /// 工作模式 待机=1 运行中=2  脱机=0
        /// 3寸输送线允许放框
        /// </summary>
        public int workMode { get; set; }
        public bool requestPut1 { get; set; }
        /// <summary>
        /// 光电信号        有货 =1 无货=0
        /// 6寸输送线请求取框
        /// </summary>
        public int lightAction { get; set; }
        public bool requestTake2 { get; set; }
        /// <summary>
        /// 故障报警
        /// 6寸输送线允许放框
        /// </summary>
        public int errorAlarm { get; set; }
        /// <summary>
        /// 设备状态    无状态=0 运行状态=1 手动状态=2 有料等待=3 异常报警=4
        /// </summary>
        public int deviceState { get; set; }
        public string TaskNo { get; set; }
        /// <summary>
        /// 目标地址
        /// </summary>
        public int targetAddr { get; set; }
        /// <summary>
        /// 重量
        /// </summary>
        public float weight { get; set; }
        /// <summary>
        /// 托盘码
        /// </summary>
        public string trayCode { get; set; }
        /// <summary>
        /// 输送线请求取框
        /// </summary>
        public bool requestTake { get; set; }
        /// <summary>
        /// 输送线允许放框
        /// </summary>
        public bool requestPut { get; set; }
        public bool requestPut2 { get; set; }
        public Dictionary<int, int> RGVAllowUnload { get; internal set; }
    }
}
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/SafeInteraction.cs
New file
@@ -0,0 +1,16 @@
using HH.WCS.JuShi.models;
using System;
namespace HH.WCS.JuShi
{
    public  class CameraMonitor : BaseModel
    {
        //摄像头货位
        public string PointCode { get; set; }
        //摄像头货位空满状态
        public int PointStatus { get; set; }
    }
}
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/models/TN_ISUSING.cs
New file
@@ -0,0 +1,15 @@
using HH.WCS.JuShi.models;
using SqlSugar;
using System;
namespace HH.WCS.JuShi
{
    [SugarTable("TN_ISUSING")]
    public class Isusing: BaseModel
    {
        public int S_STATUS { get; set; }
        public string S_TYPE { get; set; }
    }
}
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/process/DeviceProcess.cs
@@ -9,6 +9,7 @@
using System.Linq;
using System.Threading;
using static HH.WCS.JuShi.LISTA.process.HttpModel;
using static HH.WCS.JuShi.util.Settings;
namespace HH.WCS.JuShi.process
{
@@ -17,57 +18,119 @@
    /// </summary>
    internal class DeviceProcess
    {
        public static string rgvSafeInteraction = null;
        internal static void Analysis(string data, string ip)
        {
            //收
            //3A 00 01 00 01 05 73 00 02 01 01 B8
            //发
            //2A 00 01 00 01 05 73 00 02 01 01 A8
            if (data != null)
            {
                //数据序号
                data = data.Substring(16, 2);
                //根据ip找到起点/终点货位
                var plc = Settings.deviceInfos.Where(a => a.address == ip).FirstOrDefault();
                var loc = plc.TN_Location;
                //1入库2常规送检3紧急送检4三寸空托5六寸空托
                bool result = false;
                if (data.Equals("01"))
                {
                    var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "RGV库区").FirstOrDefault();
                    result= TaskProcess.tcpOffline(loc, reservoirs.areaCode);
                }
                else if (data.Equals("02"))
                {
                    var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault();
                    result = TaskProcess.tcpOffline(loc, reservoirs.areaCode);
                }
                else if (data.Equals("03"))
                {
                    var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault();
                    result = TaskProcess.tcpOffline(loc, reservoirs.areaCode);
                }
                else if (data.Equals("04"))
                {
                    var reservoirs = Settings.linePlcInfos.Where(s => s.code == "拆托机1").FirstOrDefault();
                    result = TaskProcess.tcpEmptyTray(reservoirs.outLoca, loc);
                }
                else if (data.Equals("05"))
                {
                    var reservoirs = Settings.linePlcInfos.Where(s => s.code == "拆托机2").FirstOrDefault();
                    result = TaskProcess.tcpEmptyTray(reservoirs.outLoca, loc);
                }
                //按钮盒
                //收
                //3A 00 01 00 01 05 73 00 02 01 01 B8
                //发
                //2A 00 01 00 01 05 73 00 02 01 01 A8
                // 输入的十六进制字符串数组
                string[] hexValues = { "2A", "00", "01", "00", "01", "05", "73", "00", "02", data, "01" };
                // 计算总和
                int sum = hexValues.Sum(hex => Convert.ToInt32(hex, 16));
                string returndata= hexValues.ToString()+ sum;
                if (result)
                if (data.Substring(0, 2) == "3a")
                {
                    PlcHelper.SendHex(ip, returndata);
                    //数据序号
                    data = data.Substring(16, 2);
                    //根据ip找到起点/终点货位
                    var plc = Settings.deviceInfos.Where(a => a.address == ip).FirstOrDefault();
                    var loc = plc.TN_Location;
                    //1入库2常规送检3紧急送检4三寸空托5六寸空托
                    bool result = false;
                    if (data.Equals("01"))
                    {
                        var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "立库入库区").FirstOrDefault();
                        result = TaskProcess.tcpOffline(loc, reservoirs.areaCode);
                    }
                    else if (data.Equals("02"))
                    {
                        var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "常规送检区").FirstOrDefault();
                        result = TaskProcess.tcpOffline(loc, reservoirs.areaCode);
                    }
                    else if (data.Equals("03"))
                    {
                        var reservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "紧急送检区").FirstOrDefault();
                        result = TaskProcess.tcpOffline(loc, reservoirs.areaCode);
                    }
                    else if (data.Equals("04"))
                    {
                        var reservoirs = Settings.linePlcInfos.Where(s => s.code == "拆托机1").FirstOrDefault();
                        result = TaskProcess.tcpEmptyTray(reservoirs.outLoca, loc);
                    }
                    else if (data.Equals("05"))
                    {
                        var reservoirs = Settings.linePlcInfos.Where(s => s.code == "拆托机2").FirstOrDefault();
                        result = TaskProcess.tcpEmptyTray(reservoirs.outLoca, loc);
                    }
                    //2A 00 01 00 01 05 73 00 02 01 01 A8
                    // 输入的十六进制字符串数组
                    string[] hexValues = { "2a", "00", "01", "00", "01", "05", "73", "00", "02", data, "01" };
                    // 计算总和
                    int sum = hexValues.Sum(hex => Convert.ToInt32(hex, 16));
                    string returndata = hexValues.ToString() + sum;
                    if (result)
                    {
                        PlcHelper.SendHex(ip, returndata);
                    }
                }
                //rgv安全交互
                else if (data.Substring(0, 4) == "3f00")
                {
                    ////无信号不管
                    //if (data.Trim() != "3f001020304050600d0a")
                    //{
                        LogHelper.Info($"RGV安全交互接收信号{data}");
                        rgvSafeInteraction = data.Substring(4,12);
                        //var reservoirs = Settings.SafeInteractions.Where(s => s.ip == ip).FirstOrDefault();
                        ////1允许卸货  2卸货完成确认
                        //string datastr = "";
                        //switch (reservoirs.pointCode)
                        //{
                        //    case "RGV1":
                        //        datastr = data.Substring(5, 1);
                        //        break;
                        //    case "RGV2":
                        //        datastr = data.Substring(7, 1);
                        //        break;
                        //    case "RGV3":
                        //        datastr = data.Substring(9, 1);
                        //        break;
                        //    case "RGV4":
                        //        datastr = data.Substring(11, 1);
                        //        break;
                        //    case "RGV5":
                        //        datastr = data.Substring(13, 1);
                        //        break;
                        //    case "RGV6":
                        //        datastr = data.Substring(15, 1);
                        //        break;
                        //}
                        ////接受信号存到内存
                        //if (rgvSafeInteraction != null)
                        //{
                        //    //string转成list
                        //    var jsonList = JsonConvert.DeserializeObject<List<SafeInteraction>>(rgvSafeInteraction);
                        //    var list = jsonList.Where(s => s.ip == ip).First();
                        //    if (list != null)
                        //    {
                        //        //不为空就先删再加上
                        //        jsonList.Remove(list);
                        //    }
                        //    jsonList.Add(new SafeInteraction { ip = ip, data = datastr });
                        //    rgvSafeInteraction = JsonConvert.SerializeObject(jsonList);
                        //}
                        //else
                        //{
                        //    //第一次进
                        //    var safeInteractions = new List<SafeInteraction>{new SafeInteraction { ip = ip, data = datastr }};
                        //    rgvSafeInteraction = JsonConvert.SerializeObject(safeInteractions);
                        //}
                        //LogHelper.Info($"RGV安全交互 存入内存参数{rgvSafeInteraction}");
                    //}
                }
            }
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/process/TaskProcess.cs
@@ -20,6 +20,12 @@
using Opc.Ua;
using System.Collections;
using System.Xml.Linq;
using System.Threading;
using static HH.WCS.JuShi.dispatch.NDC;
using static HH.WCS.JuShi.util.Settings;
using System.ComponentModel;
using Newtonsoft.Json.Linq;
using S7.Net;
namespace HH.WCS.JuShi.process
{
@@ -99,17 +105,129 @@
        /// <param name="state"></param>
        internal static void OperateStatus(WCSTask mst, int state)
        {
            if (state == 4)
            if (state == 4)//取货完成
            {
                CacheBitUpdate(mst, true);
                //拆托机安全交互
                //ctjSafe(mst);
            }
            if (state == 6)//卸货完成
            {
                CacheBitUpdate(mst, false);
                ////rgv安全交互
                //rgvSafe(mst);
                ////拆托机安全交互
                //ctjSafe(mst);
            }
            if (state == 7)
            {
                CacheBitCancelUpdate(mst);
            }
        }
        //rgv安全交互
        private static void rgvSafe(WCSTask mst)
        {
            //rgv安全交互  根据终点货位找到是哪个rgv
            var reservoir = Settings.ReservoirAreas.Where(a => a.areaName == "立库入库区").FirstOrDefault();
            if (mst.S_END_AREA.Equals(reservoir.areaCode))
            {
                var safeInteractions = Settings.SafeInteractions.Where(a => a.location == mst.S_END_LOC).FirstOrDefault();
                var rgvSafeInteraction = DeviceProcess.rgvSafeInteraction;
                //处理信号
                var startsub = safeInteractions.code;
                var res = rgvSafeInteraction.Substring((startsub - 1) * 2 + 1, 1);
                //var safelists = JsonConvert.DeserializeObject<List<SafeInteraction>>(DeviceProcess.rgvSafeInteraction);
                LogHelper.Info($"RGV安全交互缓存信号{rgvSafeInteraction}");
                //不等于 2卸货完成确认信号 就接着发
                if (res != "2")
                {
                    string datastr = "3f001020304050600d0a";
                    string a = ((startsub - 1) * 2).ToString();
                    //返回信号处理
                    datastr = datastr.Replace(a + "0", a + "1");
                    LogHelper.Info($"RGV安全交互发送信号{safeInteractions.ip},{datastr}");
                    PlcHelper.SendHex(safeInteractions.ip, datastr);
                    //休眠3秒再调
                    Thread.Sleep(3000);
                    rgvSafe(mst);
                }
                else
                {
                    //休眠10秒再发信号 (给现场设备吸合时间说是)
                    Thread.Sleep(10000);
                    LogHelper.Info($"RGV安全交互发送信号{safeInteractions.ip},3f001020304050600d0a");
                    //无状态信号
                    PlcHelper.SendHex(safeInteractions.ip, "3f001020304050600d0a");
                }
            }
        }
        //拆托机安全交互
        private static void ctjSafe(WCSTask mst)
        {
            PlcDeviceTable plcDeviceTable = S7Helper.plcDeviceTables;
            string deviceno = null;//线体
            //找到线体 根据线体找内存里的状态
            var rkreservoirs = Settings.ConveyorLinesInfos.Where(s => s.location == mst.S_END_LOC).FirstOrDefault();
            var ckreservoirs = Settings.ConveyorLinesInfos.Where(s => s.location == mst.S_START_LOC).FirstOrDefault();
            //入口
            if (rkreservoirs != null)
            {
                if (rkreservoirs.deviceNo == "1")
                {
                    deviceno = "1";
                }
                else if (rkreservoirs.deviceNo == "2")
                {
                    deviceno = "4";
                }
            }
            //出口
            else if (ckreservoirs != null)
            {
                if (ckreservoirs.deviceNo == "1")
                {
                    deviceno = "3";
                }
                else if (rkreservoirs.deviceNo == "2")
                {
                    deviceno = "6";
                }
            }
            LogHelper.Info($"拆托机安全交互写入参数{deviceno},{JsonConvert.SerializeObject(plcDeviceTable)}");
            if (plcDeviceTable != null && deviceno != null)
            {
                //var plcDeviceTables = S7Helper.plcDeviceTables.Where(s => s.DeviceNo == plcDeviceTable.DeviceNo);
                //s7写入
                int addr = 182;         //偏移量
                int offsetAddr = 0;         //偏移量
                string deviceNo = null;//拆托机号
                if (deviceno == "3")
                {
                    offsetAddr = 1;
                    deviceNo = "1";
                }
                else if (deviceno == "6")
                {
                    offsetAddr = 3;
                    deviceNo = "2";
                }
                else if (deviceno == "1")
                {
                    offsetAddr = 0;
                    deviceNo = "1";
                }
                else if (deviceno == "4")
                {
                    offsetAddr = 2;
                    deviceNo = "2";
                }
                LogHelper.Info($"拆托机安全交互写入{deviceNo},{addr}");
                S7Helper.WriteDouble(deviceNo, 9, addr, offsetAddr, 1);
            }
        }
@@ -316,70 +434,45 @@
                    string parmeD = "}";
                    string parme = parmeS + src + dst + parmeD;
                    int res = 0;
                    if (mst.S_TYPE == "呼叫空托" || mst.S_TYPE == "按钮盒调用空托" || mst.S_TYPE == "拆托")
                    {
                        PlcDeviceTable plcDeviceTable = null;
                        //找到线体 根据线体找内存里的状态
                        var reservoirs1 = Settings.ConveyorLinesInfos.Where(s => s.location == startLoc.S_CODE).FirstOrDefault();
                        plcDeviceTable = S7Helper.plcDeviceTables.Find(a => a.DeviceNo == reservoirs1.code);
                        if (plcDeviceTable != null)
                        {
                            if (mst.S_TYPE == "呼叫空托" || mst.S_TYPE == "按钮盒调用空托")
                            {
                                LogHelper.Info($"呼叫空托状态参数{JsonConvert.SerializeObject(plcDeviceTable)}", "任务");
                                //0-脱机状态,1-待机状态,2-运行中    待机且有托盘且请求取框才走
                                if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 1 && plcDeviceTable.requestTake)
                                {
                                    LogHelper.Info($"推送任务参数{parme}", "任务");
                                    res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                                }
                            }
                            else if (mst.S_TYPE == "拆托")
                            {
                                LogHelper.Info($"拆托状态参数{JsonConvert.SerializeObject(plcDeviceTable)}", "任务");
                                //0-脱机状态,1-待机状态,2-运行中    待机且无托盘且允许放框才走
                                if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 0 && plcDeviceTable.requestPut)
                                {
                                    LogHelper.Info($"推送任务参数{parme}", "任务");
                                    res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                                }
                            }
                            //任务完成写入s7
                            if (res > 0)
                            {
                                //s7写入 agv取框完成
                                double addr = 0;         //偏移量
                                string deviceNo = null;//拆托机号
                                if (plcDeviceTable.DeviceNo == 1003)
                                {
                                    addr = 90.1;
                                    deviceNo = "1";
                                }
                                else if (plcDeviceTable.DeviceNo == 1006)
                                {
                                    addr = 180.1;
                                    deviceNo = "2";
                                }
                                else if (plcDeviceTable.DeviceNo == 1001)
                                {
                                    addr = 30.0;
                                    deviceNo = "1";
                                }
                                else if (plcDeviceTable.DeviceNo == 1004)
                                {
                                    addr = 120.0;
                                    deviceNo = "2";
                                }
                                S7Helper.WriteDouble(deviceNo, 9, addr, 1);
                            }
                        }
                    }
                    else
                    {
                        LogHelper.Info($"推送任务参数{parme}", "任务");
                        res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                    }
                    LogHelper.Info($"推送任务参数{parme}", "任务");
                    res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                    #region
                    //if (mst.S_TYPE == "呼叫空托" || mst.S_TYPE == "按钮盒调用空托" || mst.S_TYPE == "拆托")
                    //{
                    //    PlcDeviceTable plcDeviceTable = null;
                    //    //找到线体 根据线体找内存里的状态
                    //    var reservoirs1 = Settings.ConveyorLinesInfos.Where(s => s.location == startLoc.S_CODE).FirstOrDefault();
                    //    plcDeviceTable = S7Helper.plcDeviceTables.Find(a => a.DeviceNo == reservoirs1.code);
                    //    if (plcDeviceTable != null)
                    //    {
                    //        if (mst.S_TYPE == "呼叫空托" || mst.S_TYPE == "按钮盒调用空托")
                    //        {
                    //            LogHelper.Info($"呼叫空托状态参数{JsonConvert.SerializeObject(plcDeviceTable)}", "任务");
                    //            //0-脱机状态,1-待机状态,2-运行中    待机且有托盘且请求取框才走
                    //            if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 1 && plcDeviceTable.requestTake)
                    //            {
                    //                LogHelper.Info($"推送任务参数{parme}", "任务");
                    //                res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                    //            }
                    //        }
                    //        else if (mst.S_TYPE == "拆托")
                    //        {
                    //            LogHelper.Info($"拆托状态参数{JsonConvert.SerializeObject(plcDeviceTable)}", "任务");
                    //            //0-脱机状态,1-待机状态,2-运行中    待机且无托盘且允许放框才走
                    //            if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 0 && plcDeviceTable.requestPut)
                    //            {
                    //                LogHelper.Info($"推送任务参数{parme}", "任务");
                    //                res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                    //            }
                    //        }
                    //    }
                    //}
                    //else
                    //{
                    //    LogHelper.Info($"推送任务参数{parme}", "任务");
                    //    res = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, parme);
                    //}
                    #endregion
                    if (res > 0)
                    {
                        //更新任务状态
@@ -730,7 +823,6 @@
                    {
                        list.RemoveAll(s => loca.Contains(s.S_CODE));
                    }
                    //符合条件的排序选第一个  先找第一个
                    if (list.Count > 0)
                    {
@@ -1263,12 +1355,11 @@
            try
            {
                var db = new SqlHelper<object>().GetInstance();
                //三表联查查出有该物料的货位编号
                //两表联查查出有该物料的货位编号  (现场没有物料表)
                var locCntrs = db.Queryable<LocCntrRel>().LeftJoin<CntrItemDetail>((p, m) => p.S_CNTR_CODE == m.S_CNTR_CODE)
                .LeftJoin<TN_Material>((p, m, s) => m.S_ITEM_CODE == s.S_ITEM_CODE)
                .Where((p, m, s) => s.S_ITEM_CODE == itemCode)
                .OrderBy((p, m, s) => p.T_CREATE)  //按创建时间顺序
                .Select((p, m, s) => p.S_LOC_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)}");
                //找常规送检区内含有查出物料货位的货位
@@ -1302,7 +1393,7 @@
        internal static Results UpdateFullStatus(List<CameraMonitor> models)
        {
            var result = new Results() { Code = "0", Message = "操作成功", Data = null };
            var db = new SqlHelper<Location>().GetInstance();
            var db = new SqlHelper<object>().GetInstance();
            //校验与内存是否一致
            if (monitorStatus != null)
            {
@@ -1388,40 +1479,50 @@
        //摄像头监测空托缓存区
        private static void ProcessEmptyTrayAreas(SqlSugar.ISqlSugarClient db, Location loc, string areaCode1, string areaCode2)
        {
            var plcDeviceTable = new PlcDeviceTable();
            string endLoc = null;
            if (loc.S_AREA_CODE.Equals(areaCode1))
            var plcDeviceTable = S7Helper.plcDeviceTables;
            if (plcDeviceTable != null)
            {
                plcDeviceTable = S7Helper.plcDeviceTables.Find(s => s.DeviceNo == 1001);
                endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机1").FirstOrDefault().inLoca;
            }
            else if (loc.S_AREA_CODE.Equals(areaCode2))//六寸空托
            {
                plcDeviceTable = S7Helper.plcDeviceTables.Find(s => s.DeviceNo == 1004);
                endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机2").FirstOrDefault().inLoca;
            }
            //判断是否允许放框
            if (plcDeviceTable.workMode == 1 && plcDeviceTable.lightAction == 0 && plcDeviceTable.requestPut)
            {
                //创建任务 从空托缓存区叉个料到拆托机
                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).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)
                string endLoc = null;
                bool request = false;
                if (loc.S_AREA_CODE.Equals(areaCode1))
                {
                    LogHelper.Info($"起点:{startLoc}终点:{endLoc}任务创建成功", "拆托");
                    request = plcDeviceTable.requestPut1;
                    endLoc = Settings.linePlcInfos.Where(s => s.code == "拆托机1").FirstOrDefault().inLoca;
                }
                else
                else if (loc.S_AREA_CODE.Equals(areaCode2))//六寸空托
                {
                    LogHelper.Info($"起点:{startLoc}终点:{endLoc}任务创建失败", "拆托");
                    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).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>
        /// 抽检主动呼叫    起点:送检缓存区
@@ -1438,7 +1539,7 @@
                //根据物料找某库区的货位
                var cgreservoirs = Settings.ReservoirAreas.Where(s => s.areaName == "送检缓存区").FirstOrDefault();
                var startloc = getLocByMaterial(model.S_ITEM_CODE, cgreservoirs.areaCode);
                if (startloc==null)
                if (startloc == null)
                {
                    return new Results { Code = "1", Message = $"未找到包含物料{model.S_ITEM_CODE}的货位", Data = null };
                }
@@ -1467,7 +1568,86 @@
                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)
                {
                    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>
@@ -1570,40 +1750,109 @@
        {
            //0允许进入 1不允许进入
            var result = new safeResult() { code = "1", msg = "success" };
            var db = new SqlHelper<Location>().GetInstance();
            try
            {
                var reservoirs = Settings.SafeDoors.Where(s => s.pointCode == model.STATION_NAME).FirstOrDefault();//y0-0000 y1-0001  on-FF00  off-0000
                TcpClient tcpClient = new TcpClient();
                //请求进入
                if (model.APPLY_CODE.Equals("1") || model.APPLY_CODE.Equals("5"))
                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)
                {
                    //发送信号写请求开门
                    var str = tcpClient.WriteSingleRegisterRtu("01050000FF008C3A", reservoirs.ip, int.Parse(reservoirs.port));
                    //发送信号读门状态
                    var x0bool = tcpClient.ReadInputRegistersRtu("010200000001B9CA", reservoirs.ip, int.Parse(reservoirs.port));
                    //如果开门到位
                    if (x0bool)
                    //RGV
                    if (reservoirs.type.Equals("RGV"))
                    {
                        return new safeResult() { code = "0", msg = "success" };
                    }
                }
                //请求离开
                else if (model.APPLY_CODE.Equals("4") || model.APPLY_CODE.Equals("8"))
                {
                    //发送信号写请求关门
                    var str = tcpClient.WriteSingleRegisterRtu("010500000000CDCA", reservoirs.ip, int.Parse(reservoirs.port));
                    var str2 = tcpClient.WriteSingleRegisterRtu("01050001FF00DDFA", reservoirs.ip, int.Parse(reservoirs.port));
                    //发送信号读门状态
                    var x0bool = tcpClient.ReadInputRegistersRtu("010200010001E80A", reservoirs.ip, int.Parse(reservoirs.port));
                    //如果门已关
                    if (x0bool)
                    {
                        return new safeResult() { code = "0", msg = "success" };
                    }
                        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"))
                        {
                            //发送卸货完成、复位信号
                            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 null;
                return result;
            }
            catch (Exception ex)
            {
@@ -1612,6 +1861,59 @@
                throw;
            }
        }
        //循环发送信号
        private static void safeAssistant(int code,int res) {
            //2卸货完成确认
            if (res != 2)
            {
                //卸货完成信号
                S7Helper.WriteInt(50, 0, (short)(code * 10 + 1));
                Thread.Sleep(3000);
                safeAssistant(code,res);
            }
            else
            {
                S7Helper.WriteInt(50, 0, (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 };
        }
    }
}
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/util/Settings.cs
@@ -21,7 +21,7 @@
        public static List<PriorityLoc> PriorityLocs { get; set; }
        public static List<ConveyorLinesInfo> ConveyorLinesInfos { get; set; }
        public static List<linePlcInfo> linePlcInfos { get; set; }
        public static List<SafeDoor> SafeDoors { get; set; }
        public static List<SafeInteraction> SafeInteractions { get; set; }
        public static int port { get; set; }
        public static string WHCode { get; set; }
        public static string FacCode { get; set; }
@@ -110,9 +110,9 @@
                            {
                                PriorityLocs = JsonConvert.DeserializeObject<List<PriorityLoc>>(keyValue.Value.ToString());
                            }
                            if (keyValue.Name == "SafeDoor")
                            if (keyValue.Name == "SafeInteraction")
                            {
                                SafeDoors = JsonConvert.DeserializeObject<List<SafeDoor>>(keyValue.Value.ToString());
                                SafeInteractions = JsonConvert.DeserializeObject<List<SafeInteraction>>(keyValue.Value.ToString());
                            }
                        }
                    }
@@ -192,11 +192,13 @@
            public string SecondaryArea { get; set; }
        }
        public class SafeDoor
        public class SafeInteraction
        {
            public string pointCode { get; set; }
            public int code{ get; set; }
            public string ip { get; set; }
            public string port { get; set; }
            public string type { get; set; }
            public string location { get; set; }
        }
    }
HH.WCS.Mobox3/HH.WCS.Mobox3.JuShi/wms/ContainerHelper.cs
@@ -245,43 +245,43 @@
        /// <param name="batchNo"></param>
        /// <param name="qty"></param>
        /// <returns></returns>
        internal static bool BindCntrItem(Container cntr, string itemCode, string batchNo, float qty, string putawayNo)
        {
            var res = false;
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                db.BeginTran();
                //1.查看是否有相同物料批次的信息,如果有要累加,不同批次的可以分开
                var cir = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE == cntr.S_CODE && a.S_ITEM_CODE == itemCode && a.S_BATCH_NO == batchNo).First();
                if (cir != null)
                {
                    cir.F_QTY += qty;
                    db.Updateable(cir).UpdateColumns(it => new { it.F_QTY,it.S_CK }).ExecuteCommand();
                }
                else
                {
                    //2.插入新的容器物料信息(容器号不变)
                    cir = new CntrItemDetail { S_CNTR_CODE = cntr.S_CODE.Trim(), S_BATCH_NO = batchNo, F_QTY = qty, S_ITEM_CODE = itemCode, S_PUTAWAY_NO = putawayNo};
                    db.Insertable<CntrItemDetail>(cir).ExecuteCommand();
                }
                var count = db.Queryable<CntrItemDetail>().Count(a => a.S_CNTR_CODE == cntr.S_CODE);
                cntr.N_DETAIL_COUNT = count;
                cntr.C_ENABLE = "N";//码盘后将托盘设置为不可用状态,入库后变成可用
                //db.Updateable(cntr).UpdateColumns(it => new { it.N_DETAIL_COUNT, it.C_ENABLE, it.S_SRC }).ExecuteCommand();
                db.Updateable(cntr).UpdateColumns(it => new { it.N_DETAIL_COUNT, it.C_ENABLE }).ExecuteCommand();
        //internal static bool BindCntrItem(Container cntr, string itemCode, string batchNo, float qty, string putawayNo)
        //{
        //    var res = false;
        //    var db = new SqlHelper<object>().GetInstance();
        //    try
        //    {
        //        db.BeginTran();
        //        //1.查看是否有相同物料批次的信息,如果有要累加,不同批次的可以分开
        //        var cir = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE == cntr.S_CODE && a.S_ITEM_CODE == itemCode && a.S_BATCH_NO == batchNo).First();
        //        if (cir != null)
        //        {
        //            cir.F_QTY += qty;
        //            db.Updateable(cir).UpdateColumns(it => new { it.F_QTY,it.S_CK }).ExecuteCommand();
        //        }
        //        else
        //        {
        //            //2.插入新的容器物料信息(容器号不变)
        //            cir = new CntrItemDetail { S_CNTR_CODE = cntr.S_CODE.Trim(), S_BATCH_NO = batchNo, F_QTY = qty, S_ITEM_CODE = itemCode, S_PUTAWAY_NO = putawayNo};
        //            db.Insertable<CntrItemDetail>(cir).ExecuteCommand();
        //        }
        //        var count = db.Queryable<CntrItemDetail>().Count(a => a.S_CNTR_CODE == cntr.S_CODE);
        //        cntr.N_DETAIL_COUNT = count;
        //        cntr.C_ENABLE = "N";//码盘后将托盘设置为不可用状态,入库后变成可用
        //        //db.Updateable(cntr).UpdateColumns(it => new { it.N_DETAIL_COUNT, it.C_ENABLE, it.S_SRC }).ExecuteCommand();
        //        db.Updateable(cntr).UpdateColumns(it => new { it.N_DETAIL_COUNT, it.C_ENABLE }).ExecuteCommand();
                db.CommitTran();
                res = true;
            }
            catch (Exception ex)
            {
                db.RollbackTran();
                Console.WriteLine(ex.Message);
            }
        //        db.CommitTran();
        //        res = true;
        //    }
        //    catch (Exception ex)
        //    {
        //        db.RollbackTran();
        //        Console.WriteLine(ex.Message);
        //    }
            return res;
        }
        //    return res;
        //}
        ///// <summary>
        ///// 物料信息绑定到满容器上
@@ -559,16 +559,16 @@
                    if (db.Queryable<LocCntrRel>().Count(a => a.S_CNTR_CODE.Trim() == cntrCode) == 0)
                    {
                        var cir = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntrCode};
                        var con = new Container { S_CODE = cntrCode,N_DETAIL_COUNT = 1,C_FULL="0" };
                        var con = new Container { S_CODE = cntrCode,N_DETAIL_COUNT = 1,C_FULL="2" };//默认满 主动绑定服务用
                        db.Insertable<LocCntrRel>(cir).ExecuteCommand();
                        db.Insertable<Container>(con).ExecuteCommand();
                        if (!string.IsNullOrEmpty(itemCode))
                        {
                            LogHelper.Info($"绑定容器参数:{JsonConvert.SerializeObject(con)}");
                            ContainerHelper.BindCntrItem(cntrCode, itemCode, itemName);
                            //有物料的话就是满的
                            con.C_FULL = "2";
                            db.Updateable(con).UpdateColumns(it => it.C_FULL).ExecuteCommand();
                            ////有物料的话就是满的
                            //con.C_FULL = "2";
                            //db.Updateable(con).UpdateColumns(it => it.C_FULL).ExecuteCommand();
                        }
                    }
                }
@@ -621,14 +621,17 @@
            var db = new SqlHelper<object>().GetInstance();
            try
            {
                LogHelper.Info($"BindCntrItem=============");
                db.BeginTran();
                var cir = new CntrItemDetail { S_CNTR_CODE = trayCode, S_ITEM_CODE = itemCode, S_ITEM_NAME = itemName};
                db.Insertable<CntrItemDetail>(cir).ExecuteCommand();
                db.Ado.CommitTran();
                res = true;
                LogHelper.Info($"绑定容器物料表托盘:{trayCode}物料编码:{itemCode}物料名称:{itemName}");
            }
            catch (Exception ex)
            {
                LogHelper.Error("BindCntrItem:" + ex.Message, ex);
                db.Ado.RollbackTran();
            }
            return res;