kazelee
2025-06-20 7267e82ccfbea0fa03e8bc809a2d5ac6f7da84ac
优化国自AGV和ERP下发的报文处理逻辑
2个文件已添加
9个文件已修改
1个文件已删除
201 ■■■■ 已修改文件
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/26cb7641-a9ff-4b60-93af-e7b9228fb03d.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/487b627d-37f2-4def-b2fe-acf99cac927a.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/88ff7190-7304-453c-8d3d-4144359d0c9e.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
api/AgvController.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiHelper.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ApiModel.cs 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/ErpController.cs 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.comment.json 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
core/WCSCore.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dispatch/GZRobot.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
process/TaskProcess.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/HttpHelper.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/26cb7641-a9ff-4b60-93af-e7b9228fb03d.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/487b627d-37f2-4def-b2fe-acf99cac927a.vsidx
Binary files differ
.vs/HH.WCS.Mobox3.AnGang/FileContentIndex/88ff7190-7304-453c-8d3d-4144359d0c9e.vsidx
Binary files differ
api/AgvController.cs
@@ -52,7 +52,7 @@
        /// <returns></returns>
        [HttpPost]
        [Route("safetyInteraction")]
        public ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
        public gzResult SafetyInteraction(SafetyInteractionInfo model) {
            return WCSCore.SafetyInteraction(model);
        }
    }
api/ApiHelper.cs
@@ -147,6 +147,17 @@
                var endLoc = new TN_Location();
                if (cgDetail.F_QTY > 2000) {
                    // 重量超过2t,报错
                    if (GZRobot.UpdateInteractInfo(new UpdateInteractInfo {
                        type_name = "GET_DST",
                        interaction_info_id = int.Parse(task.S_EQ_TASK_CODE),
                        info_status = "error",
                    })) {
                        LogHelper.Info($"国自AGV接受超重取消信息成功", "API");
                    }
                    else {
                        LogHelper.Info($"国自AGV接受超重取消信息失败", "API");
                    }
                    return BuildSimpleResult(8, $"物料重量{cgDetail.F_QTY}超过2t");
                }
                else if (cgDetail.F_QTY > 1500) {
@@ -181,6 +192,19 @@
                // 修改任务终点为PDA指定终点
                task.S_END_LOC = endLoc.S_CODE;
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                if (GZRobot.UpdateInteractInfo(new UpdateInteractInfo {
                    type_name = "GET_DST",
                    interaction_info_id = int.Parse(task.S_EQ_TASK_CODE),
                    info_status = "invalid",
                    return_value = LocationHelper.GetAgvSite(task.S_END_LOC), // 目前使用agvsite
                })) {
                    LogHelper.Info($"国自AGV接受终点信息成功", "API");
                }
                else {
                    LogHelper.Info($"国自AGV接受终点信息失败", "API");
                }
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Task>(task).UpdateColumns(a => a.S_END_LOC).ExecuteCommand() <= 0) {
@@ -241,8 +265,6 @@
                LocationHelper.LockLoc(ref startLoc, 2); // 起点出库锁
                LocationHelper.LockLoc(ref endLoc, 1); // 终点入库锁
                var res = GZRobot.QueryInteractInfo(3);
                using (var tran = db.Ado.UseTran()) {
                    if (db.Updateable<TN_Location>(startLoc).UpdateColumns(it => new {
@@ -381,7 +403,10 @@
                    }
                    var res = GZRobot.CancelGZOrder(code);
                    if (!res) {
                        return BuildSimpleResult(2, $"国自AGV取消任务失败!");
                        LogHelper.Info($"国自AGV取消任务失败!", "API");
                    }
                    else {
                        LogHelper.Info($"国自AGV取消任务成功!", "API");
                    }
                    using (var tran = db.Ado.UseTran()) {
api/ApiModel.cs
@@ -40,7 +40,7 @@
        }
        public class SafetyInteractionInfo {
            public int station_id { get; set; }
            //public int station_id { get; set; }
            /// <summary>
            /// 请求上线/下线的的站台库位名称,例如work6、work8
@@ -51,7 +51,7 @@
            /// 请求码
            /// </summary>
            public string apply_code { get; set; }
            public string task_no { set; get; }
            //public string task_no { set; get; }
        }
        public class orderStatusReportParme {
@@ -118,6 +118,11 @@
            public string ResultMsg { get; set; }
        }
        public class gzResult {
            public int code { get; set; } = 0;
            public string msg { get; set; } = "success";
        }
        /// <summary>
        /// 返回给GZ
        /// </summary>
api/ErpController.cs
@@ -26,10 +26,13 @@
            LogHelper.Info("触发API:入库数据同步" + JsonConvert.SerializeObject(model), "API");
            //var headers = Request.Headers;
            //return ProcessInboundData(headers, model); // 如果要求对HTTP报文字段校验,使用这行代码
            //var checkRes = CheckHeaders(headers);
            //if (!checkRes.isSuccess) {
            //    return CreateErrorResponse(checkRes.code, checkRes.message);
            //}
            //return ApiHelper.InboundDataSync(model);
            return NormalProcessInboundData(model); // 暂时使用原本的逻辑
            var res = ApiHelper.InboundDataSync(model);
            return CreateSuccessResponse(res);
        }
        /// <summary>
@@ -43,32 +46,19 @@
            LogHelper.Info("触发API:出库发料同步" + JsonConvert.SerializeObject(model), "API");
            //var headers = Request.Headers;
            //return ProcessOutboundData(headers, model); // 如果要求对HTTP报文字段校验,使用这行代码
            //var checkRes = CheckHeaders(headers);
            //if (!checkRes.isSuccess) {
            //    return CreateErrorResponse(checkRes.code, checkRes.message);
            //}
            //return ApiHelper.OutboundDataSync(model);
            return NormalProcessOutboundData(model); // 暂时使用原本的逻辑
            var res = ApiHelper.OutboundDataSync(model);
            return CreateSuccessResponse(res);
        }
        private IHttpActionResult NormalProcessInboundData(InboundDataSyncInfo model) {
            var data = ApiHelper.InboundDataSync(model);
            return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) {
                Headers = { },
                Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json")
            });
        }
        private IHttpActionResult NormalProcessOutboundData(OutboundDataSyncInfo model) {
            var data = ApiHelper.OutboundDataSync(model);
            return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) {
                Headers = { },
                Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json")
            });
        }
        private IHttpActionResult ProcessInboundData(System.Net.Http.Headers.HttpRequestHeaders headers, InboundDataSyncInfo model) {
        private CheckHeadersResult CheckHeaders(System.Net.Http.Headers.HttpRequestHeaders headers) {
            // 必须字段验证
            if (!headers.Contains("sourceAppCode") || !headers.Contains("serviceId") || !headers.Contains("msgSendTime")) {
                return CreateErrorResponse("2003", "缺少必要请求头参数");
                return CreateCheckHeadersResult(false, "2003", "缺少必要请求头参数");
            }
            var headerModel = new {
@@ -79,60 +69,18 @@
                MsgSendTime = headers.GetValues("msgSendTime").First()
            };
            // 2. 验证Header
            // 验证Header
            var validationResult = ValidateHeaders(headerModel);
            if (validationResult != null) {
                return validationResult;
            }
            // 3. 读取Body
            //string requestBody = await Request.Content.ReadAsStringAsync(); // 不需要异步读取,直接用model
            // 4. 验证Body
            // 验证Body
            if (Request.Content.Headers.ContentLength > 2 * 1024 * 1024) {
                return CreateErrorResponse("2102", "消息内容过长,超过2M");
                return CreateCheckHeadersResult(false, "2102", "消息内容过长,超过2M");
            }
            // 5. 处理业务逻辑
            var result = ApiHelper.InboundDataSync(model);
            // 6. 返回成功响应
            return CreateSuccessResponse(result);
        }
        private IHttpActionResult ProcessOutboundData(System.Net.Http.Headers.HttpRequestHeaders headers, OutboundDataSyncInfo model) {
            // 必须字段验证
            if (!headers.Contains("sourceAppCode") || !headers.Contains("serviceId") || !headers.Contains("msgSendTime")) {
                return CreateErrorResponse("2003", "缺少必要请求头参数");
            }
            var headerModel = new {
                SourceAppCode = headers.GetValues("sourceAppCode").First(),
                Password = headers.Contains("password") ? headers.GetValues("password").First() : null,
                ServiceId = headers.GetValues("serviceId").First(),
                MsgToken = headers.Contains("msgToken") ? headers.GetValues("msgToken").First() : null,
                MsgSendTime = headers.GetValues("msgSendTime").First()
            };
            // 2. 验证Header
            var validationResult = ValidateHeaders(headerModel);
            if (validationResult != null) {
                return validationResult;
            }
            // 3. 读取Body
            //string requestBody = await Request.Content.ReadAsStringAsync();
            // 4. 验证Body
            if (Request.Content.Headers.ContentLength > 2 * 1024 * 1024) {
                return CreateErrorResponse("2102", "消息内容过长,超过2M");
            }
            // 5. 处理业务逻辑
            var result = ApiHelper.OutboundDataSync(model);
            // 6. 返回成功响应
            return CreateSuccessResponse(result);
            return CreateCheckHeadersResult(true);
        }
        private IHttpActionResult CreateSuccessResponse(object data) {
@@ -149,22 +97,22 @@
            });
        }
        private IHttpActionResult ValidateHeaders(dynamic headers) {
        private CheckHeadersResult ValidateHeaders(dynamic headers) {
            // 实现所有Header验证逻辑
            if (!IsRegisteredApp(headers.SourceAppCode, headers.Password)) {
                return CreateErrorResponse("2201", "源调用系统未注册");
                return CreateCheckHeadersResult(false, "2201", "源调用系统未注册");
            }
            if (!IsValidService(headers.ServiceId)) {
                return CreateErrorResponse("2202", "代理服务未注册");
                return CreateCheckHeadersResult(false, "2202", "代理服务未注册");
            }
            if (!IsValidDateTime(headers.MsgSendTime)) {
                return CreateErrorResponse("2101", "时间格式校验失败");
                return CreateCheckHeadersResult(false, "2101", "时间格式校验失败");
            }
            if (!string.IsNullOrEmpty(headers.MsgToken) && headers.MsgToken.Length > 32) {
                return CreateErrorResponse("2104", "消息令牌过长,超过32位");
                return CreateCheckHeadersResult(false, "2104", "消息令牌过长,超过32位");
            }
            return null;
@@ -181,5 +129,19 @@
        private bool IsValidDateTime(string dataTime) {
            return true;
        }
        private CheckHeadersResult CreateCheckHeadersResult(bool isSuccess, string code = "", string message = "") {
            return new CheckHeadersResult {
                code = code,
                message = message,
                isSuccess = isSuccess
            };
        }
    }
    public class CheckHeadersResult {
        public bool isSuccess { get; set; }
        public string code { get; set; }
        public string message { get; set; }
    }
}
config/config.comment.json
@@ -1,22 +1,21 @@
{
    "WebApiUrl": "http://127.0.0.1:8901",
    "RCSApiUrl": "http://127.0.0.1:6001",
    "NDCApiUrl": "http://127.0.0.1:5201/api/order/",
    "SqlServer": "Data Source=192.168.1.144;Initial Catalog=YinKouAnGan;User ID=hhuser;Password=Am123123",
    //"SqlServer": "Data Source=(local);Initial Catalog=AnGangTest;User ID=sa;Password=123456",
    "WebApiUrl": "http://127.0.0.1:8901", // 终端地址
    "RCSApiUrl": "http://127.0.0.1:6001", // 国自AGV调度
    "NDCApiUrl": "http://127.0.0.1:5201/api/order/", // 项目不使用
    "SqlServer": "Data Source=192.168.1.144;Initial Catalog=YinKouAnGan;User ID=hhuser;Password=Hh123321&&", // 数据库地址
    "TCPServerIP": "127.0.0.1",
    "TCPServerPort": 8085,
    "Areas": [
        {
            "Name": "收发区",
            "Codes": [ "SFQ" ]
            "Name": "取放货区",
            "Codes": [ "QFHQ" ]
        },
        {
            "Name": "货架区",
            "Codes": [ "HJQ" ]
        }
    ],
    "Snap": [
    "Snaps": [ // 相机拍摄的IP和账号密码信息
        {
            "Ip": "172.23.8.95",
            "Port": 37777,
@@ -24,5 +23,5 @@
            "Pwd": "123456"
        }
    ],
    "CaptureUrl": "http://127.0.0.1/"
    "CaptureUrl": "http://127.0.0.1/" // 相机保存图片的地址
}
core/WCSCore.cs
@@ -348,8 +348,11 @@
        }
        // DOC 4.    站台申请安全交互 RCS->WMS
        public static ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            var gzResult = new ReturnResult();
        public static gzResult SafetyInteraction(SafetyInteractionInfo model) {
            var gzResult = new gzResult() {
                code = 0,
                msg = "success"
            };
            // 目前该项目没有站台安全交互的功能
            return gzResult;
        }
dispatch/GZRobot.cs
@@ -7,6 +7,7 @@
using HH.WCS.Mobox3.AnGang.models;
using Newtonsoft.Json;
using static HH.WCS.Mobox3.AnGang.api.ApiModel;
using static System.Net.WebRequestMethods;
namespace HH.WCS.Mobox3.AnGang.dispatch {
    /// <summary>
@@ -41,7 +42,14 @@
            if (response != "") {
                try {
                    var dataResult = JsonConvert.DeserializeObject<gzResult<OrderInfoResult>>(response);
                    if (dataResult.code == 0) {
                    // 原代码部分
                    //if (dataResult.code == 0) {
                    //    orderId = dataResult.data[0].in_order_id;
                    //}
                    // 尊重文档的版本
                    // 返回参数中,code目前不再使用,可通过msg字段判断是否成功,如果msg为”success”则表示成功,否则为报错信息或不存在。http code为422时候的报错为系统报错,其中的msg无法全部获取。
                    // SELFNOTE: 直接调用HttpHelper.Post方法,无法获取header,暂时不考虑
                    if (dataResult.msg == "success") {
                        orderId = dataResult.data[0].in_order_id;
                    }
                }
@@ -240,7 +248,7 @@
            return list;
        }
        // DOC 备用
        // DOC 6.    交互表查询(更新终点货位)
        public static bool UpdateInteractInfo(UpdateInteractInfo interactInfo) {
            string msg = "";
            var result = false;
@@ -257,6 +265,7 @@
            }
            return result;
        }
        // DOC 5.    称重信息查询
        public static List<CustomData> CustomBuf() {
@@ -420,6 +429,7 @@
    public class UpdateInteractInfo
    {
        public int interaction_info_id { get; set; }
        public string type_name { get; set; } = "GET_DST";
        public string info_status { get; set; }
        public string return_value { get; set; }
    }
process/TaskProcess.cs
@@ -114,11 +114,11 @@
            if (mst.N_B_STATE == 0) {
                // 原代码版本
                //var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = mst.S_START_LOC, dst = mst.S_END_LOC }), "p2p");
                // 尊重文档的版本(暂不考虑修改,因为没有终点站点,不合理)
                //var startSite = LocationHelper.GetAgvSite(mst.S_START_LOC);
                //var endSite = LocationHelper.GetAgvSite(mst.S_END_LOC);
                // 尊重文档的版本
                var startSite = LocationHelper.GetAgvSite(mst.S_START_LOC);
                var endSite = LocationHelper.GetAgvSite(mst.S_END_LOC); // 如果找不到会返回0,就是假终点
                var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = mst.S_START_LOC, dst = mst.S_END_LOC }), "p2pdst", "pgapi");
                var code = GZRobot.CreateOrder(mst.S_CODE, mst.N_PRIORITY, JsonConvert.SerializeObject(new { src = startSite, dst = endSite }), "p2pdst", "pgapi");
                if (code > 0) {
                    //更新任务状态
util/HttpHelper.cs
@@ -101,7 +101,6 @@
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Post(string url, string postData, string contentType = "application/json", string sessionId = "") {