kazelee
7 天以前 00aaf49a223be04fc58f6f7c09d95ce4b22ef087
core/WCSCore.cs
@@ -2,7 +2,6 @@
using HH.WCS.Mobox3.AnGang.dispatch;
using HH.WCS.Mobox3.AnGang.models;
using HH.WCS.Mobox3.AnGang.process;
using HH.WCS.Mobox3.AnGang.config;
using Newtonsoft.Json;
using SqlSugar;
using System;
@@ -20,7 +19,7 @@
        public static ReturnResult OperateAgvTaskStatus(AgvTaskState model) {
            var result = new ReturnResult();
            try {
                if (model.state > 0 && model.state < 1000) {
                if (model.state > 0) {
                    // AGV 执行任务的逻辑处理
                    if (!AgvTaskProcessOk(model)) {
                        // 执行不OK,说明没有找到任务
@@ -74,6 +73,7 @@
                    if (TN_Task.S_TYPE == TaskName.产品入库 || TN_Task.S_TYPE == TaskName.产品部分回库) {
                        var captureTask = Task.Run(() => {
                            CapturePic(TN_Task);
                            LogHelper.Info($"{TN_Task}:拍照Task结束");
                        });
                    }
@@ -81,6 +81,14 @@
                        var setEndLocTask = Task.Run(() => {
                            // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
                            SetEndLoc(TN_Task);
                            LogHelper.Info("设置终点Task结束");
                        });
                    }
                    if (TN_Task.S_TYPE == TaskName.产品部分回库) {
                        var weightTask = Task.Run(() => {
                            UpdateWeight(TN_Task);
                            LogHelper.Info("称重Task结束");
                        });
                    }
@@ -95,6 +103,7 @@
                    break;
                case 2: // 完成
                    WCSHelper.End(TN_Task); // 任务状态改成结束
                    break;
                case 7: // 异常
                    TaskProcess.OperateStatus(TN_Task, 7); // 异常处理
@@ -111,122 +120,249 @@
        public static void CapturePic(TN_Task model) {
            var db = new SqlHelper<object>().GetInstance();
            var filepath = SnapManager.GetCapturePicturePath();
            if (string.IsNullOrEmpty(filepath)) {
                LogHelper.Info("图片地址为空");
                return;
            try {
                var filepath = SnapManager.GetCapturePicturePath();
                if (string.IsNullOrEmpty(filepath)) {
                    LogHelper.Info("图片地址为空");
                    return;
                }
                if (db.Updateable<TN_Loc_Container>()
                    .SetColumns(d => d.S_IMG_URL == filepath)
                    .Where(d => d.S_CNTR_CODE == model.S_CNTR_CODE).ExecuteCommand() <= 0) {
                    LogHelper.Info($"图片URL '{filepath}' 写入数据库失败");
                    return;
                }
            }
            if (db.Updateable<TN_CG_Detail>()
                .SetColumns(d => d.S_IMG_URL == filepath)
                .Where(d => d.S_CNTR_CODE == model.S_CNTR_CODE).ExecuteCommand() <= 0) {
                LogHelper.Info($"图片URL '{filepath}' 写入数据库失败");
                return;
            catch (Exception ex) {
                LogHelper.Info($"发生了错误:{ex.Message}");
            }
        }
        public static void SetEndLoc(TN_Task tn_task) {
            var db = new SqlHelper<object>().GetInstance();
            var endLoc = db.Queryable<TN_Location>()
                .First(a => a.S_CODE == tn_task.S_END_LOC);
            var info = "";
            try {
                var endLoc = db.Queryable<TN_Location>()
                        .First(a => a.S_CODE == tn_task.S_END_LOC);
            // 如果已经设置的终点货位,就不要再进入这个流程
            if (endLoc != null) {
                LogHelper.Info("已经设置了终点货位:" + JsonConvert.SerializeObject(endLoc));
                return;
                // 如果已经设置的终点货位,就不要再进入这个流程
                if (endLoc != null) {
                    LogHelper.Info("已经设置了终点货位:" + JsonConvert.SerializeObject(endLoc));
                    return;
                }
                var cgDetail = db.Queryable<TN_CG_Detail>()
                    .Where(d => d.S_CNTR_CODE == tn_task.S_CNTR_CODE).First();
                if (cgDetail == null) {
                    LogHelper.Info("设置终点货位失败:当前任务的托盘号在物料表中不存在");
                    return;
                }
                var data = GZRobot.CustomBuf();
                if (data.Count == 0) {
                    LogHelper.Info("设置终点货位失败:没有接受到来自国自AGV的重量信息");
                    //cgDetail.F_QTY = 0; // 不设置为空,便于测试时预先设置一个正常值
                }
                else {
                    var weight_str = data[0].parameter_varchar200_up.Split(';')[1].Split('-')[1];
                    var weight = float.Parse(weight_str);
                    cgDetail.F_QTY = weight;
                    tn_task.F_WEIGHT = weight;
                    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");
                    }
                }
                // 终点货架为空时,不判断,交给人工处理
                if (tn_task.S_END_LOC == "0") {
                    LogHelper.Info("终点货架为空,不处理");
                    return;
                }
                if (!int.TryParse(tn_task.S_END_LOC.Trim(), out int row)) {
                    LogHelper.Info($"终点货架号 '{tn_task.S_END_LOC}' 无法转成数字");
                    return;
                }
                //row -= 100; // 111-118 => 1-8
                // 只当之前指定终点货架后,才尝试计算终点货位
                if (cgDetail.F_QTY > 2000) {
                    // 重量超过 2t
                    endLoc = null;
                    LogHelper.Info("重量超过2t,不允许入库");
                    // 传递给国自AGV
                    if (GZRobot.TryGetInteractionInfoId(tn_task.S_CODE, out var id1)) {
                        if (GZRobot.UpdateInteractInfo(new UpdateInteractInfo {
                            type_name = "GET_DST",
                            interaction_info_id = id1,
                            info_status = "error",
                        })) {
                            LogHelper.Info($"国自AGV接受超重取消信息成功", "HosttoagvTask");
                        }
                        else {
                            LogHelper.Info($"国自AGV接受超重取消信息失败", "HosttoagvTask");
                        }
                    }
                    else {
                        LogHelper.Info($"AGV:获取任务{tn_task.S_CODE}的interaction_info_id失败!", "HosttoagvTask");
                    }
                    return; // 超重会自己return,如果国自agv没接受到也不需要提前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 <= 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>().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 {
                    // 没有接收到重量,或重量出错
                    endLoc = null;
                    LogHelper.Info($"错误的重量信息:{cgDetail.F_QTY}");
                    return;
                }
                // 如果没有符合条件的货位,置空,等待PDA重新确定
                if (endLoc == null) {
                    tn_task.S_END_AREA = Settings.Areas[AreaIndex.H货架区][0]; // HJQ
                    tn_task.S_END_LOC = "0";
                    // 不需要再给GZ AGV传空值,一开始就没给具体货位,只给了Area
                    //var request = new UpdateInteractInfo {
                    //    interaction_info_id = 3, // 更改终点信息
                    //    info_status = "active",
                    //    return_value = "",
                    //};
                    //GZRobot.UpdateInteractInfo(request);
                    if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                            .ExecuteCommand() > 0) {
                        //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货位为 0空");
                    }
                    else {
                        LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货位为 0空");
                    }
                }
                else {
                    // 找到合适的货位,推送
                    tn_task.S_END_LOC = endLoc.S_CODE;
                    LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                    // 传递给国自AGV
                    if (GZRobot.TryGetInteractionInfoId(tn_task.S_CODE, out var id2)) {
                        if (GZRobot.UpdateInteractInfo(new UpdateInteractInfo {
                            type_name = "GET_DST",
                            interaction_info_id = id2,
                            info_status = "invalid",
                            return_value = LocationHelper.GetAgvSite(tn_task.S_END_LOC), // 目前使用agvsite
                        })) {
                            LogHelper.Info($"国自AGV接受终点信息成功", "HosttoagvTask");
                        }
                        else {
                            LogHelper.Info($"国自AGV接受终点信息失败", "HosttoagvTask");
                            return;
                        }
                    }
                    else {
                        LogHelper.Info($"AGV:获取任务{tn_task.S_CODE}的interaction_info_id失败!", "HosttoagvTask");
                        return;
                    }
                    using (var tran = db.Ado.UseTran()) {
                        if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                            .ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            LogHelper.Info($"计算货位成功,任务'{tn_task.S_CODE}'修改失败,终点货架为{endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                        }
                        if (db.Updateable<TN_Location>(endLoc).UpdateColumns(it => new {
                            it.N_LOCK_STATE,
                            it.S_LOCK_STATE,
                            it.S_LOCK_OP,
                            it.T_MODIFY
                        }).ExecuteCommand() <= 0) {
                            tran.RollbackTran();
                            info = $"更新终点货位锁状态失败:起点货位{endLoc.S_CODE}";
                            LogHelper.Info(info);
                        }
                        tran.CommitTran();
                    }
                }
            }
            var cgDetail = db.Queryable<TN_CG_Detail>()
                .Where(d => d.S_CNTR_CODE == tn_task.S_CNTR_CODE).First();
            if (cgDetail == null) {
                LogHelper.Info("设置终点货位失败:当前任务的托盘号在物料表中不存在");
                return;
            catch (Exception ex) {
                LogHelper.Info($"发生了错误:{ex.Message}");
            }
        }
            var data = GZRobot.CustomBuf();
        public static void UpdateWeight(TN_Task tn_task) {
            var db = new SqlHelper<object>().GetInstance();
            if (data.Count == 0) {
                LogHelper.Info("设置终点货位失败:没有接受到来自国自AGV的重量信息");
                //return; // TODO 正式运行有国自AGV的时候恢复
            }
            else {
                var weight = float.Parse(data[0].parameter_varchar200_up);
            try {
                var cgDetail = db.Queryable<TN_CG_Detail>()
                    .Where(d => d.S_CNTR_CODE == tn_task.S_CNTR_CODE).First();
                if (cgDetail == null) {
                    LogHelper.Info("更新物料重量失败:当前任务的托盘号在物料表中不存在");
                    return;
                }
                var data = GZRobot.CustomBuf();
                if (data.Count == 0) {
                    LogHelper.Info("更新物料重量失败:没有接受到来自国自AGV的重量信息");
                    return;
                }
                var weight_str = data[0].parameter_varchar200_up.Split(';')[1].Split('-')[1];
                var weight = float.Parse(weight_str);
                cgDetail.F_QTY = weight;
                if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY).ExecuteCommand() <= 0) {
                    LogHelper.Info("修改物料表重量失败");
                    return;
                }
                LogHelper.Info($"修改任务号{tn_task.S_CODE}物料重量为{weight}", "HosttoagvTask");
            }
            catch (Exception ex) {
                LogHelper.Info($"发生了错误:{ex.Message}");
            }
            // 终点货架为空时,不判断,交给人工处理
            if (tn_task.S_END_LOC == "0") {
                LogHelper.Info("终点货架为空,不处理");
                return;
            }
            if (!int.TryParse(tn_task.S_END_LOC.Trim(), out int row)) {
                LogHelper.Info($"终点货架号 '{tn_task.S_END_LOC}' 无法转成数字");
                return;
            }
            // 只当之前指定终点货架后,才尝试计算终点货位
            if (cgDetail.F_QTY > 1500) {
                // 重量超过1.5t,需要选择1-3层货架
                endLoc = db.Queryable<TN_Location>()
                    .First(a => a.N_ROW == row && a.N_LAYER <= 3
                    && 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");
            }
            else {
                // 没有接收到重量,或重量出错
                endLoc = null;
                LogHelper.Info($"错误的重量信息:{cgDetail.F_QTY}");
                return;
            }
            // 如果没有符合条件的货位,置空,等待PDA重新确定
            if (endLoc == null) {
                tn_task.S_END_AREA = "HJQ";
                tn_task.S_END_LOC = "0";
                // 不需要再给GZ AGV传空值,一开始就没给具体货位,只给了Area
                //var request = new UpdateInteractInfo {
                //    interaction_info_id = 3, // 更改终点信息
                //    info_status = "active",
                //    return_value = "",
                //};
                //GZRobot.UpdateInteractInfo(request);
                if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                        .ExecuteCommand() > 0) {
                    //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                    LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货位为 0空");
                }
                else {
                    LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货位为 0空");
                }
            }
            else {
                // 找到合适的货位,推送
                tn_task.S_END_LOC = endLoc.S_CODE;
                if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                        .ExecuteCommand() > 0) {
                    LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                    LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                }
                else {
                    LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                }
            }
        }
        /// <summary>
@@ -244,8 +380,6 @@
                {
                    //使用自定义任务推送
                    TaskProcess.SendTask(task);//调度NDC或杭奥或国自设备
                    //TaskProcess.SendGZTask(task);///调度国自设备
                });
            }
            else
@@ -254,37 +388,13 @@
            }
        }
        public static ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            var gzResult = new ReturnResult();
            //var db = new SqlHelper<object>().GetInstance();
            //ModbusHelper.Relink();
            //var productionLineInfo = Settings.ProductionLines[0];
            //var prodLineDevice = new ProductionLineDevice(productionLineInfo.PlcIp, productionLineInfo.PlcPort);
            //if (!prodLineDevice.LoadDeviceStateOk()) {
            //    LogHelper.Info("加载设备信息失败");
            //}
            //var tn_task = db.Queryable<TN_Task>().First(a => a.S_CODE == model.task_no);
            //if (tn_task == null) {
            //    LogHelper.Info($"任务号 '{model.task_no}' 不存在");
            //}
            //if (prodLineDevice.SystemState == 1
            //    && prodLineDevice.FullOffline == 1 && tn_task.S_TYPE == "成品胶下线-托盘(WMS)") {
            //    if (!prodLineDevice.SetAgvPicking(1)) {
            //        LogHelper.Info("写入输送线 PLC 失败");
            //    }
            //}
            //if (prodLineDevice.SystemState == 1
            //    && prodLineDevice.AllowAgvPlacePallet == 1 && tn_task.S_TYPE == "空托盘上线(WMS)") {
            //    if (!prodLineDevice.SetAgvPlacingPallet(1)) {
            //        LogHelper.Info("写入输送线 PLC 失败");
            //    }
            //}
            //LogHelper.Info(JsonConvert.SerializeObject(prodLineDevice, Formatting.Indented));
        // DOC 4.   站台申请安全交互 RCS->WMS
        public static gzResult SafetyInteraction(SafetyInteractionInfo model) {
            var gzResult = new gzResult() {
                code = 0,
                msg = "success"
            };
            // 目前该项目没有站台安全交互的功能
            return gzResult;
        }
    }