kazelee
2025-05-20 ef839d119eec2c28fac5f5ba175d71f926afae44
Services/AgvService.cs
@@ -14,6 +14,7 @@
using static HH.WCS.Mobox3.AnGang.Dtos.Response.AgvResponse;
using HH.WCS.Mobox3.AnGang.Consts;
using HH.WCS.Mobox3.AnGang.Dispatch;
using HH.WCS.Mobox3.AnGang.Devices;
namespace HH.WCS.Mobox3.AnGang.Services {
    public class AgvService {
@@ -22,8 +23,8 @@
            try {
                switch (model.state) {
                    case 1023:
                        break;
                    case 1025:
                        break;
                    case 1012:
                        break;
@@ -45,7 +46,7 @@
                result.ResultCode = 0;
                result.ResultMsg = "success";
                LogHelper.Info(result.ResultMsg, "API");
                LogHelper.Info(result.ResultMsg + $": state {model.state}", "API");
                return result;
            }
            catch (Exception ex) {
@@ -83,10 +84,17 @@
                case AgvStateCode.取货完成:
                    WCSHelper.UpdateStatus(TN_Task, "取货完成"); // 任务状态改成取货完成
                    // TODO 拍照
                    var captureTask = Task.Run(() => {
                        if (TN_Task.S_TYPE == TaskName.产品入库 || TN_Task.S_TYPE == TaskName.产品部分回库) {
                            CapturePic(TN_Task);
                        }
                    });
                    var setEndLocTask = Task.Run(() => {
                        SetEndLoc(TN_Task);
                        // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
                        if (TN_Task.S_TYPE == TaskName.产品入库) {
                            SetEndLoc(TN_Task);
                        }
                    });
                    TaskHelper.OperateStatus(TN_Task, 4); // 起点容器货位解绑,解锁起点
@@ -113,81 +121,134 @@
            return true;
        }
        public static void CapturePic(TN_Task model) {
            var db = DbHelper.GetDbClient();
            var filepath = SnapManager.GetCapturePicturePath();
            if (string.IsNullOrEmpty(filepath)) {
                LogHelper.Info("图片地址为空");
                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;
            }
        }
        public static void SetEndLoc(TN_Task tn_task) {
            // 只要任务为产品入库(PDA),就需要重新指定终点(默认endLoc为"")
            if (tn_task.S_TYPE == "产品入库(PDA)") {
            var db = DbHelper.GetDbClient();
            var endLoc = db.Queryable<TN_Location>()
                .First(a => a.S_CODE == tn_task.S_END_LOC);
                var db = DbHelper.GetDbClient();
                var endLoc = new TN_Location();
            // 如果已经设置的终点货位,就不要再进入这个流程
            if (endLoc != null) {
                LogHelper.Info("已经设置了终点货位:" + JsonConvert.SerializeObject(endLoc));
                return;
            }
                var data = GZRobot.CustomBuf();
            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; // TODO 正式运行有国自AGV的时候恢复
            }
            else {
                var weight = float.Parse(data[0].parameter_varchar200_up);
                tn_task.F_WEIGHT= weight;
                cgDetail.F_QTY = weight;
                // 只当之前指定终点货架后,才尝试计算终点货位,否则交给人工决定
                if (tn_task.S_END_AREA != "") {
                    if (weight > 1500) {
                        // 重量超过1.5t,需要选择1-3层货架
                        endLoc = db.Queryable<TN_Location>().First(a => a.S_SHELF_CODE == tn_task.S_END_AREA && LocationHelper.IsFree(a) && a.N_CURRENT_NUM == 0 && a.N_HEIGHT <= 3);
                    }
                    else if (weight > 0) {
                        // 重量未超过1.5t,在指定货架随便选择1个
                        endLoc = db.Queryable<TN_Location>().First(a => a.S_SHELF_CODE == tn_task.S_END_AREA && LocationHelper.IsFree(a) && a.N_CURRENT_NUM == 0);
                if (db.Updateable<TN_CG_Detail>(cgDetail).UpdateColumns(it => it.F_QTY).ExecuteCommand() <= 0) {
                    LogHelper.Info("修改物料表重量失败");
                    return;
                }
            }
            // 终点货架为空时,不判断,交给人工处理
            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);
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                        .ExecuteCommand() > 0) {
                        //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        trans.CommitTran();
                        LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货位为 0空");
                    }
                    else {
                        // 没有接收到重量,或重量出错
                        endLoc = null;
                        LogHelper.Info($"错误的重量信息:{weight}");
                        return;
                        trans.RollbackTran();
                        LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货位为 0空");
                    }
                }
            }
            else {
                // 找到合适的货位,推送
                tn_task.S_END_LOC = endLoc.S_CODE;
                    // 如果没有符合条件的货位,置空,等待PDA重新确定
                    if (endLoc == null) {
                        tn_task.S_END_AREA = "";
                        tn_task.S_END_LOC = "";
                using (var trans = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC })
                        .ExecuteCommand() > 0) {
                        LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                        // 不需要再给GZ AGV传空值,一开始就没给具体货位,只给了Area
                        //var request = new UpdateInteractInfo {
                        //    interaction_info_id = 3, // 更改终点信息
                        //    info_status = "active",
                        //    return_value = "",
                        //};
                        //GZRobot.UpdateInteractInfo(request);
                        using (var trans = db.Ado.UseTran()) {
                            if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new { it.S_END_LOC, it.F_WEIGHT })
                                .ExecuteCommand() > 0) {
                                //LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                                trans.CommitTran();
                                LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改成功,修改终点货架和货位为空");
                            }
                            else {
                                trans.RollbackTran();
                                LogHelper.Info($"重新计算后没有合适货位,任务 {tn_task.S_CODE} 修改失败,修改终点货架和货位为空");
                            }
                        }
                        trans.CommitTran();
                        LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                    }
                    else {
                        // 找到合适的货位,推送
                        tn_task.S_END_LOC = endLoc.S_CODE;
                        trans.RollbackTran();
                        using (var trans = db.Ado.UseTran()) {
                            if (db.Updateable<TN_Task>(tn_task).UpdateColumns(it => new {it.S_END_LOC, it.F_WEIGHT})
                                .ExecuteCommand() > 0) {
                                LocationHelper.LockLoc(endLoc.S_CODE, 1);//终点入库锁
                                trans.CommitTran();
                                LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改成功,终点货架为 {endLoc.S_SHELF_CODE},修改终点位置为 {endLoc.S_CODE}");
                            }
                            else {
                                trans.RollbackTran();
                                LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.S_SHELF_CODE},修改终点位置为 {endLoc.S_CODE}");
                            }
                        }
                        LogHelper.Info($"计算货位成功,任务 {tn_task.S_CODE} 修改失败,终点货架为 {endLoc.N_ROW},修改终点位置为 {endLoc.S_CODE}");
                    }
                }
            }