kazelee
2025-05-23 c4e968254a4f1c5d538a9fd91284b4843ea08198
内部联调,修复问题,添加取消任务功能
2个文件已添加
15个文件已修改
3个文件已删除
591 ■■■■■ 已修改文件
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/3ea34f60-d704-4ad2-8e0f-2cf457081645.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/58a869dd-63a6-4ba3-b662-00952ac61ff8.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/b2175d53-106b-45a1-ad0e-0dd460928cd4.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/c1b1f263-3564-477c-bc41-41a75528f80c.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/d649a959-a553-4855-aaba-982999a405f5.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
Dispatch/GZRobot.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/TN_Task.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Program.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Properties/AssemblyInfo.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/AgvController.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiHelper.cs 123 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiModel.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/DebugController.cs 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/MoboxController.cs 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
core/Monitor.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
core/WCSCore.cs 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/SnapDevice.cs 236 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
device/SnapManager.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/Settings.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/LocationHelper.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/3ea34f60-d704-4ad2-8e0f-2cf457081645.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/58a869dd-63a6-4ba3-b662-00952ac61ff8.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/b2175d53-106b-45a1-ad0e-0dd460928cd4.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/c1b1f263-3564-477c-bc41-41a75528f80c.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/d649a959-a553-4855-aaba-982999a405f5.vsidx
Binary files differ
Dispatch/GZRobot.cs
@@ -106,6 +106,7 @@
        /// </summary>
        /// <returns></returns>
        public static GzResult orderStatusReport(orderStatusReportParme model) {
            LogHelper.Info("RCS国自AGV任务状态回报:" + JsonConvert.SerializeObject(model), "HosttoagvTask");
            GzResult result = new GzResult();
            AgvTaskState agv = new AgvTaskState();
Models/TN_Task.cs
@@ -35,13 +35,13 @@
        public string S_CNTR_CODE { get; set; } = "";
        public string S_OP_NAME { get; set; } = "";
        //public int N_CNTR_COUNT { get; internal set; }
        ///// <summary>
        ///// 任务的货物重量
        ///// </summary>
        //public float F_WEIGHT { get; set; }
        /// <summary>
        /// 任务的货物重量
        /// </summary>
        public float F_WEIGHT { get; set; } = 0f;
        internal static string GetStateStr(int state) {
            //0等待      1已推送        2执行    3完成    4错误
Program.cs
@@ -15,7 +15,7 @@
namespace HH.WCS.Mobox3.AnGang {
    internal class Program
    {
        [STAThread]
        //[STAThread] // TODO SNAP
        static void Main(string[] args)
        {
            //基础设置信息初始化
@@ -127,8 +127,7 @@
                List<Task> tasks = new List<Task>();
                // 添加任务推送线程
                tasks.Add(GetTask(WCSCore.Dispatch));
                tasks.Add(GetTask(Monitor.CheckCountOrder));
                //tasks.Add(GetTask(Monitor.CheckCountOrder));
                Task.WaitAll(tasks.ToArray());
            }
Properties/AssemblyInfo.cs
@@ -5,11 +5,11 @@
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("HH.WCS.Mobox3.DSZSH")]
[assembly: AssemblyTitle("HH.WCS.Mobox3.AnGang")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HH.WCS.Mobox3.DSZSH")]
[assembly: AssemblyProduct("HH.WCS.Mobox3.AnGang")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
api/AgvController.cs
@@ -10,7 +10,6 @@
using System.Linq;
using HH.WCS.Mobox3.AnGang.config;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
namespace HH.WCS.Mobox3.AnGang.api
@@ -42,6 +41,7 @@
        [HttpPost]
        [Route("orderStatusReport")]
        public GzResult orderStatusReport(orderStatusReportParme model) {
            //LogHelper.Info("RCS国自AGV任务状态回报:" + JsonConvert.SerializeObject(model), "HosttoagvTask");
            return GZRobot.orderStatusReport(model);
        }
api/ApiHelper.cs
@@ -31,7 +31,7 @@
                    .First();
                if (startLoc == null) {
                    return BuildSimpleResult(1, $"起点位置{model.StartLoc}不存在!");
                    return BuildSimpleResult(1, $"起点位置{model.StartLoc}不存在或不满足要求:需要(1)没有锁状态(2)当前无容器(3)属于取放货区");
                }
                // 容器 ID 和 物料 ID 未指定,由系统直接生成
@@ -45,6 +45,7 @@
                    S_LOC_CODE = startLoc.S_CODE,
                    S_CNTR_CODE = cntId,
                };
                var cgDetail = new TN_CG_Detail() {
                    S_ITEM_CODE = cgId,
                    S_CNTR_CODE = cntId,
@@ -65,7 +66,7 @@
                }
                var task = WCSHelper.BuildInboundTask(startLoc, endLocCode, cntId);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                // 无论是否选择终点货架,都等到称重之后再计算终点货位
                using (var tran = db.Ado.UseTran()) {
@@ -122,6 +123,7 @@
            try {
                // 任务号存在:终点货架和终点位置为空,且任务为产品入库(PDA)
                var task = db.Queryable<TN_Task>()
                    .Where(a => a.S_CODE == model.TaskNo)
                    .Where(a => a.S_B_STATE == "取货完成" && a.S_TYPE == TaskName.产品入库)
                    .OrderBy(a => a.T_CREATE, SqlSugar.OrderByType.Desc).First();
@@ -141,22 +143,27 @@
                }
                var endLoc = new TN_Location();
                if (cgDetail.F_QTY > 1500) {
                    // 重量超过1.5t,需要选择1-3层货架
                if (cgDetail.F_QTY > 2000) {
                    // 重量超过2t,报错
                    return BuildSimpleResult(8, $"物料重量{cgDetail.F_QTY}超过2t");
                }
                else if (cgDetail.F_QTY > 1500) {
                    // 重量超过1.5t,需要选择1-2层货架
                    endLoc = db.Queryable<TN_Location>()
                        .Where(a => a.S_CODE == model.endLoc)
                        .Where(a => a.S_CODE == model.EndLoc)
                        .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                        .Where(a => a.N_CURRENT_NUM == 0)
                        .Where(a => Settings.Areas[1].Contains(a.S_AREA_CODE))
                        .Where(a => a.N_LAYER <= 3)
                        .Where(a => a.N_LAYER <= 2)
                        .First();
                }
                else if (cgDetail.F_QTY > 0) {
                    endLoc = db.Queryable<TN_Location>()
                        .Where(a => a.S_CODE == model.endLoc)
                        .Where(a => a.S_CODE == model.EndLoc)
                        .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                        .Where(a => a.N_CURRENT_NUM == 0)
                        .Where(a => Settings.Areas[1].Contains(a.S_AREA_CODE))
                        .OrderBy(a => a.N_LAYER > 2 ? 0 : 1) // 优先取大于2的
                        //.Where(a => a.N_LAYER <= 3)
                        .First();
                }
@@ -166,7 +173,7 @@
                // 没有符合条件的货位
                if (endLoc == null) {
                    return BuildSimpleResult(6, $"货位{model.endLoc}不存在,或不满足称重放置要求");
                    return BuildSimpleResult(6, $"货位{model.EndLoc}不存在,或不满足称重放置要求");
                }
                // 修改任务终点为PDA指定终点
@@ -230,8 +237,8 @@
                var cntId = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
@@ -294,8 +301,8 @@
                var cntId = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
@@ -322,6 +329,90 @@
                    return BuildSimpleResult(0,
                        $"生成 {taskName} 成功,容器号 {cntId} ,起点 {startLoc.S_CODE} ,终点货架 {endLoc.S_CODE}");
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
            }
        }
        public static SimpleResult CancelTask(CancelTaskInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            var info = "";
            try {
                var task = db.Queryable<TN_Task>()
                    .Where(a => a.S_CODE == model.TaskNo)
                    .First();
                if (task == null) {
                    return BuildSimpleResult(2, $"任务号{model.TaskNo}不存在");
                }
                if (task.N_B_STATE == 0 && task.S_B_STATE == TN_Task.GetStateStr(0)
                    || task.N_B_STATE == 1 && task.S_B_STATE == TN_Task.GetStateStr(1)) {
                    task.N_B_STATE = 4;
                    task.S_B_STATE = "取消";
                    var starloc = db.Queryable<TN_Location>().First(a => a.S_CODE == task.S_START_LOC);
                    var endloc = db.Queryable<TN_Location>().First(a => a.S_CODE == task.S_END_LOC);
                    //var locCnt = db.Queryable<TN_Loc_Container>().First(a => a.S_CNTR_CODE == task.S_CNTR_CODE);
                    //var cg = db.Queryable<TN_CG_Detail>().First(a => a.S_CNTR_CODE == task.S_CNTR_CODE);
                    if (starloc != null) {
                        starloc.N_LOCK_STATE = 0;
                        starloc.S_LOCK_STATE = "无";
                        //starloc.N_CURRENT_NUM = 0;
                        starloc.T_MODIFY = System.DateTime.Now;
                    }
                    if (endloc != null) {
                        endloc.N_LOCK_STATE = 0;
                        endloc.S_LOCK_STATE = "无";
                        //endloc.N_CURRENT_NUM = 0;
                        endloc.T_MODIFY = System.DateTime.Now;
                    }
                    using (var tran = db.Ado.UseTran()) {
                        if (db.Updateable<TN_Location>(starloc).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            info = $"任务{task.S_CODE}取消失败";
                            return BuildSimpleResult(0, info);
                        }
                        if (endloc != null) {
                            if (db.Updateable<TN_Location>(endloc).ExecuteCommand() <= 0) {
                                tran.RollbackTran();
                                info = $"任务{task.S_CODE}取消失败";
                                return BuildSimpleResult(0, info);
                            }
                        }
                        if (db.Updateable<TN_Task>(task).ExecuteCommand() <= 0) {
                            if (db.Updateable<TN_Location>(endloc).ExecuteCommand() <= 0) {
                                tran.RollbackTran();
                                info = $"任务{task.S_CODE}取消失败";
                                return BuildSimpleResult(0, info);
                            }
                        }
                        tran.CommitTran();
                        info = $"任务{task.S_CODE}取消成功";
                        return BuildSimpleResult(0, info);
                    }
                }
                else {
                    return BuildSimpleResult(3, $"只有任务号状态为 等待 或 已推送 的任务才能取消");
                }
            }
            catch (Exception ex) {
                return BuildSimpleResult(1, $"发生了异常:{ex.Message}");
@@ -496,8 +587,8 @@
                var cntID = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntID, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
@@ -559,8 +650,8 @@
                var cntID = locCntrRel.S_CNTR_CODE;
                var task = WCSHelper.BuildTask(startLoc, endLoc, cntID, taskName);
                LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
api/ApiModel.cs
@@ -147,9 +147,11 @@
            /// <summary>
            /// AGV小车号:NOTE 后期可能省略,因为只有一辆车
            /// </summary>
            public string forklift_no { get; set; }
            //public string forklift_no { get; set; }
            public string endLoc { get; set; }
            public string TaskNo { get; set; }
            public string EndLoc { get; set; }
        }
        /// <summary>
@@ -167,6 +169,10 @@
            public string endLoc { get; set; }
        }
        public class CancelTaskInfo {
            public string TaskNo { get; set; }
        }
        /// <summary>
        /// 产品部分出库信息
        /// </summary>
api/DebugController.cs
@@ -267,16 +267,34 @@
                return "找不到对应的物料信息";
            }
            var task = db.Queryable<TN_Task>()
                .Where(t => t.S_CODE == model.TaskNo).First();
            if (cgDetail == null) {
                return "找不到对应的任务号";
            }
            cgDetail.F_QTY = model.Weight;
            task.F_WEIGHT = model.Weight;
            try {
                if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY)
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY)
                    .ExecuteCommand() <= 0) {
                    return "修改失败";
                }
                return "修改成功";
                        tran.RollbackTran();
                        return "修改失败";
                    }
                    if (db.Updateable<TN_Task>(task).UpdateColumns(it => it.F_WEIGHT).ExecuteCommand() <= 0) {
                        tran.RollbackTran();
                        return "修改失败";
                    }
                    tran.CommitTran();
                }
                LogHelper.Info($"模拟AGV传递物料重量:修改任务号{task.S_CODE}重量为{model.Weight}", "HosttoagvTask");
                return "修改成功";
            }
            catch (Exception ex) {
                return ex.Message;
api/MoboxController.cs
@@ -1,5 +1,7 @@
using System.Web.Http;
using HH.WCS.Mobox3.AnGang.wms;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
@@ -29,7 +31,7 @@
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("SelectLocation")]
        [Route("PDAFullInArea")]
        public SimpleResult SelectLocation(SelectLocationInfo model) {
            LogHelper.Info("触发API:PDA选择终点货位" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.SelectLocation(model);
@@ -60,40 +62,52 @@
        }
        /// <summary>
        /// 创建盘点计划单(WMS)
        /// 取消任务
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateCountPlan")]
        public SimpleResult CreateCountPlan(CreateCountPlanInfo model) {
            LogHelper.Info("触发API:创建盘点计划单(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CreateCountPlan(model);
        [Route("CancelTask")]
        public SimpleResult CancelTask(CancelTaskInfo model) {
            LogHelper.Info("触发API:取消任务" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CancelTask(model);
        }
        /// <summary>
        /// 创建盘点单(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CreateCountOrder")]
        public SimpleResult CreateCountOrder(CreateCountOrderInfo model) {
            LogHelper.Info("触发API:创建盘点单(PDA)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CreateCountOrder(model);
        }
        ///// <summary>
        ///// 创建盘点计划单(WMS)
        ///// </summary>
        ///// <param name="model"></param>
        ///// <returns></returns>
        //[HttpPost]
        //[Route("CreateCountPlan")]
        //public SimpleResult CreateCountPlan(CreateCountPlanInfo model) {
        //    LogHelper.Info("触发API:创建盘点计划单(WMS)" + JsonConvert.SerializeObject(model), "API");
        //    return ApiHelper.CreateCountPlan(model);
        //}
        /// <summary>
        /// 盘点理货(PDA)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CountProduct")]
        public SimpleResult CountProduct(CountProductInfo model) {
            LogHelper.Info("触发API:盘点理货(PDA)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CountProduct(model);
        }
        ///// <summary>
        ///// 创建盘点单(PDA)
        ///// </summary>
        ///// <param name="model"></param>
        ///// <returns></returns>
        //[HttpPost]
        //[Route("CreateCountOrder")]
        //public SimpleResult CreateCountOrder(CreateCountOrderInfo model) {
        //    LogHelper.Info("触发API:创建盘点单(PDA)" + JsonConvert.SerializeObject(model), "API");
        //    return ApiHelper.CreateCountOrder(model);
        //}
        ///// <summary>
        ///// 盘点理货(PDA)
        ///// </summary>
        ///// <param name="model"></param>
        ///// <returns></returns>
        //[HttpPost]
        //[Route("CountProduct")]
        //public SimpleResult CountProduct(CountProductInfo model) {
        //    LogHelper.Info("触发API:盘点理货(PDA)" + JsonConvert.SerializeObject(model), "API");
        //    return ApiHelper.CountProduct(model);
        //}
        ///// <summary>
        ///// 盘点理货出库(WMS)
@@ -107,16 +121,16 @@
        //    return ApiHelper.CheckOutbound(model);
        //}
        /// <summary>
        /// 盘点理货回库(WMS)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CheckInbound")]
        public SimpleResult CheckInbound(CheckInboundInfo model) {
            LogHelper.Info("触发API:盘点理货回库(WMS)" + JsonConvert.SerializeObject(model), "API");
            return ApiHelper.CheckInbound(model);
        }
        ///// <summary>
        ///// 盘点理货回库(WMS)
        ///// </summary>
        ///// <param name="model"></param>
        ///// <returns></returns>
        //[HttpPost]
        //[Route("CheckInbound")]
        //public SimpleResult CheckInbound(CheckInboundInfo model) {
        //    LogHelper.Info("触发API:盘点理货回库(WMS)" + JsonConvert.SerializeObject(model), "API");
        //    return ApiHelper.CheckInbound(model);
        //}
    }
}
core/Monitor.cs
@@ -87,8 +87,8 @@
                    var cntId = detail.S_CNTR_CODE;
                    var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName);
                    LocationHelper.LockLoc(ref startLoc, 1); // 起点出库锁
                    LocationHelper.LockLoc(ref endLoc, 2); // 终点入库锁
                    LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                    LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                    using (var tran = db.Ado.UseTran()) {
                        if (db.Updateable<TN_Count_CG_Detail>(detail).UpdateColumns(it => it.N_B_STATE).ExecuteCommand() <= 0) {
core/WCSCore.cs
@@ -74,7 +74,7 @@
                    if (TN_Task.S_TYPE == TaskName.产品入库 || TN_Task.S_TYPE == TaskName.产品部分回库) {
                        var captureTask = Task.Run(() => {
                            CapturePic(TN_Task);
                            LogHelper.Info("拍照Task结束");
                            LogHelper.Info($"{TN_Task}:拍照Task结束");
                        });
                    }
@@ -170,10 +170,27 @@
                else {
                    var weight = float.Parse(data[0].parameter_varchar200_up);
                    cgDetail.F_QTY = weight;
                    tn_task.F_WEIGHT = weight;
                    if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY).ExecuteCommand() <= 0) {
                        LogHelper.Info("修改物料表重量失败");
                        return;
                    using (var tran = db.Ado.UseTran()) {
                        if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info("修改物料表重量失败");
                            return;
                        }
                        if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => it.F_WEIGHT).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info("修改任务表重量失败");
                            return;
                        }
                        tran.CommitTran();
                    }
                    LogHelper.Info($"修改任务号{tn_task.S_CODE}物料重量为{weight}", "HosttoagvTask");
                    if (weight > 2000) {
                        LogHelper.Info($"物料重量超过2t", "HosttoagvTask");
                    }
                }
@@ -189,16 +206,23 @@
                }
                // 只当之前指定终点货架后,才尝试计算终点货位
                if (cgDetail.F_QTY > 1500) {
                    // 重量超过1.5t,需要选择1-3层货架
                if (cgDetail.F_QTY > 2000) {
                    // 重量超过 2t
                    endLoc = null;
                    LogHelper.Info("重量超过2t,不允许入库");
                    return;
                }
                else if (cgDetail.F_QTY > 1500) {
                    // 重量超过1.5t,需要选择1-2层货架
                    endLoc = db.Queryable<TN_Location>()
                        .First(a => a.N_ROW == row && a.N_LAYER <= 3
                        .First(a => a.N_ROW == row && a.N_LAYER <= 2
                        && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                }
                else if (cgDetail.F_QTY > 0) {
                    // 重量未超过1.5t,在指定货架随便选择1个
                    endLoc = db.Queryable<TN_Location>().First(a => a.N_ROW == row
                        && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y");
                    endLoc = db.Queryable<TN_Location>().Where(a => a.N_ROW == row
                        && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y")
                        .OrderBy(a => a.N_LAYER > 2 ? 0 : 1).First(); // 优先选层级高的
                }
                else {
                    // 没有接收到重量,或重量出错
@@ -290,6 +314,8 @@
                    return;
                }
                LogHelper.Info($"修改任务号{tn_task.S_CODE}物料重量为{weight}", "HosttoagvTask");
            }
            catch (Exception ex) {
                LogHelper.Info($"发生了错误:{ex.Message}");
device/SnapDevice.cs
@@ -7,14 +7,14 @@
using System.Text;
using System.Threading.Tasks;
using NetSDKCS;
//using NetSDKCS; // TODO SNAP
namespace HH.WCS.Mobox3.AnGang.device {
    public class SnapDevice {
        private IntPtr _LoginID = IntPtr.Zero;
        private IntPtr _PlayID = IntPtr.Zero;
        //private fSnapRevCallBack _SnapRevCallBack;
        private NET_DEVICEINFO_Ex _DeviceInfo = new NET_DEVICEINFO_Ex();
        //private NET_DEVICEINFO_Ex _DeviceInfo = new NET_DEVICEINFO_Ex(); // TODO SNAP
        private bool _IsSpanCapture = false;
        //private List<int> _channalList = new List<int>();
@@ -23,7 +23,7 @@
        public SnapDevice() {
            try {
                //_SnapRevCallBack = new fSnapRevCallBack(SnapRevCallBack);
                NETClient.Init(null, IntPtr.Zero, null);
                //NETClient.Init(null, IntPtr.Zero, null); // TODO SNAP
                //NETClient.SetSnapRevCallBack(_SnapRevCallBack, IntPtr.Zero);
            }
            catch (Exception ex) {
@@ -32,132 +32,134 @@
        }
        ~SnapDevice() {
            NETClient.Cleanup();
            //NETClient.Cleanup(); // TODO SNAP
        }
        public void LoadInfo(Config.Snap snap) {
            LoadInfo(snap.Ip, snap.Port, snap.Name, snap.Pwd);
        }
        //public void LoadInfo(Config.Snap snap) {
        //    LoadInfo(snap.Ip, snap.Port, snap.Name, snap.Pwd);
        //}
        
        public void LoadInfo(string ip, int port, string name, string pwd) {
            if (IntPtr.Zero == _LoginID) {
                ushort uPort = 0;
                try {
                    uPort = Convert.ToUInt16(port);
                }
                catch {
                    LogHelper.Info("加载Snap:端口号格式错误");
                    return;
                }
                _LoginID = NETClient.LoginWithHighLevelSecurity(ip, uPort, name, pwd, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref _DeviceInfo);
                if (IntPtr.Zero == _LoginID) {
                    LogHelper.Info("相机初始化错误:" + NETClient.GetLastError());
                    return;
                }
                //_channalList.Clear();
                //for (int i = 0; i < _DeviceInfo.nChanNum; i++) {
                //    _channalList.Add(i + 1);
                //}
                _channalMax = _DeviceInfo.nChanNum;
            }
            else {
                NETClient.Logout(_LoginID);
                _LoginID = IntPtr.Zero;
                if (_IsSpanCapture) {
                    _IsSpanCapture = false;
        // TODO SNAP
        //public void LoadInfo(string ip, int port, string name, string pwd) {
        //    if (IntPtr.Zero == _LoginID) {
        //        ushort uPort = 0;
        //        try {
        //            uPort = Convert.ToUInt16(port);
        //        }
        //        catch {
        //            LogHelper.Info("加载Snap:端口号格式错误");
        //            return;
        //        }
        //        _LoginID = NETClient.LoginWithHighLevelSecurity(ip, uPort, name, pwd, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref _DeviceInfo);
        //        if (IntPtr.Zero == _LoginID) {
        //            LogHelper.Info("相机初始化错误:" + NETClient.GetLastError());
        //            return;
        //        }
        //        //_channalList.Clear();
        //        //for (int i = 0; i < _DeviceInfo.nChanNum; i++) {
        //        //    _channalList.Add(i + 1);
        //        //}
        //        _channalMax = _DeviceInfo.nChanNum;
        //    }
        //    else {
        //        NETClient.Logout(_LoginID);
        //        _LoginID = IntPtr.Zero;
        //        if (_IsSpanCapture) {
        //            _IsSpanCapture = false;
                    
                }
            }
        }
        //        }
        //    }
        //}
        public bool SnapPictureToFileOK(ref string filePath, int channelIndex = 0) {
            if (channelIndex >= _channalMax) {
                LogHelper.Info($"通道数 '{channelIndex}' 超出通道总数 '{_channalMax}'");
                //filePath = string.Empty;
                return false;
            }
        //public bool SnapPictureToFileOK(ref string filePath, int channelIndex = 0) {
        //    if (channelIndex >= _channalMax) {
        //        LogHelper.Info($"通道数 '{channelIndex}' 超出通道总数 '{_channalMax}'");
        //        //filePath = string.Empty;
        //        return false;
        //    }
            //DateTime now = DateTime.Now;
            //string path = AppDomain.CurrentDomain.BaseDirectory + "image";
            //string fileName = string.Format("{0}{1}{2}{3}{4}{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second) + ".jpg";
            //filePath = path + "\\" + fileName;
        //    //DateTime now = DateTime.Now;
        //    //string path = AppDomain.CurrentDomain.BaseDirectory + "image";
        //    //string fileName = string.Format("{0}{1}{2}{3}{4}{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second) + ".jpg";
        //    //filePath = path + "\\" + fileName;
            NET_SNAP_PARAMS asyncSnap = new NET_SNAP_PARAMS();
            //asyncSnap.Channel = (uint)this._channalList[channelIndex];
            asyncSnap.Channel = (uint)channelIndex;
            asyncSnap.Quality = 6;
            asyncSnap.ImageSize = 2;
            asyncSnap.mode = 0;
            asyncSnap.InterSnap = 0;
        //    NET_SNAP_PARAMS asyncSnap = new NET_SNAP_PARAMS();
        //    //asyncSnap.Channel = (uint)this._channalList[channelIndex];
        //    asyncSnap.Channel = (uint)channelIndex;
        //    asyncSnap.Quality = 6;
        //    asyncSnap.ImageSize = 2;
        //    asyncSnap.mode = 0;
        //    asyncSnap.InterSnap = 0;
            NET_IN_SNAP_PIC_TO_FILE_PARAM inParam = new NET_IN_SNAP_PIC_TO_FILE_PARAM {
                dwSize = (uint)Marshal.SizeOf(typeof(NET_IN_SNAP_PIC_TO_FILE_PARAM)),
                stuParam = asyncSnap,
                szFilePath = filePath,
            };
        //    NET_IN_SNAP_PIC_TO_FILE_PARAM inParam = new NET_IN_SNAP_PIC_TO_FILE_PARAM {
        //        dwSize = (uint)Marshal.SizeOf(typeof(NET_IN_SNAP_PIC_TO_FILE_PARAM)),
        //        stuParam = asyncSnap,
        //        szFilePath = filePath,
        //    };
            NET_OUT_SNAP_PIC_TO_FILE_PARAM outParam = new NET_OUT_SNAP_PIC_TO_FILE_PARAM() {
                dwSize = (uint)Marshal.SizeOf(typeof(NET_OUT_SNAP_PIC_TO_FILE_PARAM)),
                dwPicBufLen = 1024000,
                szPicBuf = Marshal.AllocHGlobal(1024000),
            };
        //    NET_OUT_SNAP_PIC_TO_FILE_PARAM outParam = new NET_OUT_SNAP_PIC_TO_FILE_PARAM() {
        //        dwSize = (uint)Marshal.SizeOf(typeof(NET_OUT_SNAP_PIC_TO_FILE_PARAM)),
        //        dwPicBufLen = 1024000,
        //        szPicBuf = Marshal.AllocHGlobal(1024000),
        //    };
            bool ret = NETClient.SnapPictureToFile(_LoginID, ref inParam, ref outParam, 1000);
            if (!ret) {
                LogHelper.Info("抓图失败");
            }
            return ret;
        }
        //    bool ret = NETClient.SnapPictureToFile(_LoginID, ref inParam, ref outParam, 1000);
        //    if (!ret) {
        //        LogHelper.Info("抓图失败");
        //    }
        //    return ret;
        //}
        public bool SnapPictureOk(int channelIndex = 0) {
            if (channelIndex >= _channalMax) {
                LogHelper.Info($"通道数 '{channelIndex}' 超出通道总数 '{_channalMax}'");
                return false;
            }
        //public bool SnapPictureOk(int channelIndex = 0) {
        //    if (channelIndex >= _channalMax) {
        //        LogHelper.Info($"通道数 '{channelIndex}' 超出通道总数 '{_channalMax}'");
        //        return false;
        //    }
            NET_SNAP_PARAMS asyncSnap = new NET_SNAP_PARAMS();
            //asyncSnap.Channel = (uint)this._channalList[channelIndex];
            asyncSnap.Channel = (uint)channelIndex;
            asyncSnap.Quality = 6;
            asyncSnap.ImageSize = 2;
            asyncSnap.mode = 0;
            asyncSnap.InterSnap = 0;
            bool ret = NETClient.SnapPictureEx(_LoginID, asyncSnap, IntPtr.Zero);
            if (!ret) {
                LogHelper.Info(NETClient.GetLastError());
                return false;
            }
            return true;
        }
        //    NET_SNAP_PARAMS asyncSnap = new NET_SNAP_PARAMS();
        //    //asyncSnap.Channel = (uint)this._channalList[channelIndex];
        //    asyncSnap.Channel = (uint)channelIndex;
        //    asyncSnap.Quality = 6;
        //    asyncSnap.ImageSize = 2;
        //    asyncSnap.mode = 0;
        //    asyncSnap.InterSnap = 0;
        //    bool ret = NETClient.SnapPictureEx(_LoginID, asyncSnap, IntPtr.Zero);
        //    if (!ret) {
        //        LogHelper.Info(NETClient.GetLastError());
        //        return false;
        //    }
        //    return true;
        //}
        private void SnapRevCallBack(IntPtr lLoginID, IntPtr pBuf, uint RevLen, uint EncodeType, uint CmdSerial, IntPtr dwUser) {
            string path = AppDomain.CurrentDomain.BaseDirectory + "image";
            if (!Directory.Exists(path)) {
                Directory.CreateDirectory(path);
            }
            if (EncodeType == 10) //.jpg
            {
                DateTime now = DateTime.Now;
                string fileName = string.Format("{0}-{1}-{2}-{3}-{4}-{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second) + ".jpg";
                string filePath = path + "\\" + fileName;
                byte[] data = new byte[RevLen];
                Marshal.Copy(pBuf, data, 0, (int)RevLen);
                try {
                    //when the file is operate by local capture will throw expection.
                    using (FileStream stream = new FileStream(filePath, FileMode.OpenOrCreate)) {
                        stream.Write(data, 0, (int)RevLen);
                        stream.Flush();
                        stream.Dispose();
                    }
                }
                catch (Exception ex) {
                    LogHelper.Info($"发生了异常:{ex.Message}");
                    return;
                }
                // 替代Demo程序的Frame图片展示
                LogHelper.Info($"保存图片到:{filePath}");
                Process.Start(filePath);
            }
        }
        //private void SnapRevCallBack(IntPtr lLoginID, IntPtr pBuf, uint RevLen, uint EncodeType, uint CmdSerial, IntPtr dwUser) {
        //    string path = AppDomain.CurrentDomain.BaseDirectory + "image";
        //    if (!Directory.Exists(path)) {
        //        Directory.CreateDirectory(path);
        //    }
        //    if (EncodeType == 10) //.jpg
        //    {
        //        DateTime now = DateTime.Now;
        //        string fileName = string.Format("{0}-{1}-{2}-{3}-{4}-{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second) + ".jpg";
        //        string filePath = path + "\\" + fileName;
        //        byte[] data = new byte[RevLen];
        //        Marshal.Copy(pBuf, data, 0, (int)RevLen);
        //        try {
        //            //when the file is operate by local capture will throw expection.
        //            using (FileStream stream = new FileStream(filePath, FileMode.OpenOrCreate)) {
        //                stream.Write(data, 0, (int)RevLen);
        //                stream.Flush();
        //                stream.Dispose();
        //            }
        //        }
        //        catch (Exception ex) {
        //            LogHelper.Info($"发生了异常:{ex.Message}");
        //            return;
        //        }
        //        // 替代Demo程序的Frame图片展示
        //        LogHelper.Info($"保存图片到:{filePath}");
        //        Process.Start(filePath);
        //    }
        //}
    }
}
device/SnapManager.cs
@@ -11,21 +11,24 @@
            if (_snapDevice == null) {
                _snapDevice = new SnapDevice();
            }
            _snapDevice.LoadInfo(snap);
            //_snapDevice.LoadInfo(snap); // TODO SNAP
        }
        public static string GetCapturePicturePath() {
            DateTime now = DateTime.Now;
            string path = Settings.CaptureUrl;
            string fileName = string.Format("{0}{1}{2}{3}{4}{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second) + ".jpg";
            string filePath = path + "\\" + fileName;
            //DateTime now = DateTime.Now;
            //string path = Settings.CaptureUrl;
            //string fileName = string.Format("{0}{1}{2}{3}{4}{5}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second) + ".jpg";
            //string filePath = path + "\\" + fileName;
            if (_snapDevice.SnapPictureToFileOK(ref filePath)) {
                return filePath;
            }
            else {
                return string.Empty;
            }
            //if (_snapDevice.SnapPictureToFileOK(ref filePath)) {
            //    return filePath;
            //}
            //else {
            //    return string.Empty;
            //}
            // TODO SNAP
            return string.Empty;
        }
    }
}
util/Settings.cs
@@ -19,7 +19,7 @@
        public static int TCPServerPort { get; set; }
        //public static List<Config.Area> Areas { get; set; }
        public static List<List<string>> Areas { get; set; } = new List<List<string>>();
        public static List<Config.Snap> Snaps { get; set; }
        public static List<Config.Snap> Snaps { get; set; } = new List<Config.Snap>();
        public static string CaptureUrl { get; set; }
        /// <summary>
wms/LocationHelper.cs
@@ -135,11 +135,10 @@
        }
        /// <summary>
        /// 入库锁定终点,出库锁定起点
        /// 你创建任务锁定货位的时候,把锁的来源就是任务号也写上去(加锁的方法加个参数,可空的参数),解锁的时候把来源置空。
        /// 起点出库锁:2 --- 终点入库锁:1
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="lockState">1:入库锁、2:出库锁、2:其它锁</param>
        /// <param name="lockState">1:入库锁、2:出库锁、3:其它锁</param>
        /// <param name="lockSource">锁的来源=任务号</param>
        /// <returns></returns>
        public static bool LockLoc(ref TN_Location loc, int lockState, string lockSource = "") {
@@ -160,7 +159,7 @@
        /// 你创建任务锁定货位的时候,把锁的来源就是任务号也写上去(加锁的方法加个参数,可空的参数),解锁的时候把来源置空。
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="lockState">1:入库锁、2:出库锁、2:其它锁</param>
        /// <param name="lockState">1:入库锁、2:出库锁、3:其它锁</param>
        /// <param name="lockSource">锁的来源=任务号</param>
        /// <returns></returns>
        public static bool LockLoc(string loc, int lockState, string lockSource = "")