kazelee
1 天以前 74ca5a83f24c53c48ad7e6f5b7739649fb411546
优化部分日志和未使用代码
1个文件已添加
9个文件已修改
472 ■■■■■ 已修改文件
HH.WCS.Mobox3.DSZSH.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/AgvController.cs 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/DebugController.cs 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
models/TN_Container.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
process/TaskProcess.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/HttpHelper.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/LogHelper.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/SqlHelper.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/WebHelper.cs 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
wms/LocationHelper.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HH.WCS.Mobox3.DSZSH.csproj
@@ -270,6 +270,7 @@
    <Compile Include="api\WMSController.cs" />
    <Compile Include="dispatch\HostToAGV.cs" />
    <Compile Include="util\LogHelper.cs" />
    <Compile Include="util\WebHelper.cs" />
    <Compile Include="wms\LocationHelper.cs" />
    <Compile Include="wms\SYSHelper.cs" />
    <Compile Include="Program.cs" />
api/AgvController.cs
@@ -29,7 +29,7 @@
        [HttpPost]
        [Route("AGVCallbackState")]
        public ReturnResult AGVCallbackState(AgvTaskState model){
            LogHelper.InfoHostToAGV("NDC任务状态回报", model);
            LogHelper.InfoHostToAGV("AGVCallbackState:NDC任务状态回报", model);
            return WCSCore.OperateAgvTaskStatus(model);
        }
@@ -41,138 +41,8 @@
        [HttpPost]
        [Route("SafetyInteraction")]
        public ReturnResult SafetyInteraction(SafetyInteractionInfo model) {
            LogHelper.InfoHostToAGV("AGV与产线进行安全交互", model);
            LogHelper.InfoHostToAGV("SafetyInteraction:AGV与产线进行安全交互", model);
            return WCSCore.SafetyInteraction(model);
        }
        // 备用:Request 请求授权 ---------------------------------------------
        // 模拟存储的AppKey和AppSecret(实际应存储在数据库或配置中)
        private static readonly Dictionary<string, string> AppSecrets = new Dictionary<string, string> {
            { "testAppKey", "7a8f9b3d2e1c6a5b4c8d7e6f" }
        };
        // 允许的时间差(秒),用于验证时间戳
        private const int AllowedTimeDiff = 300; // 5分钟
        private CheckHeadersResult CheckHeaders(System.Net.Http.Headers.HttpRequestHeaders headers) {
            // 必须字段验证
            if (!headers.Contains("AppKey") || !headers.Contains("ReqVerify") || !headers.Contains("ReqTime")) {
                return CreateCheckHeadersResult(false, HttpStatusCode.BadRequest, "缺少必要请求头参数");
            }
            var headerModel = new SecureRequest {
                AppKey = headers.GetValues("AppKey").First(),
                ReqVerify = headers.GetValues("ReqVerify").First(),
                ReqTime = long.Parse(headers.GetValues("ReqTime").First()),
            };
            // 验证Header
            var validationResult = ValidateHeaders(headerModel);
            if (validationResult != null) {
                return validationResult;
            }
            return CreateCheckHeadersResult(true);
        }
        private CheckHeadersResult ValidateHeaders(SecureRequest request) {
            // 实现所有Header验证逻辑
            // 验证AppKey是否存在
            if (!AppSecrets.TryGetValue(request.AppKey, out var appSecret)) {
                return CreateCheckHeadersResult(false, HttpStatusCode.Unauthorized, "无效的AppKey");
            }
            // 验证时间戳是否在允许范围内
            var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            if (Math.Abs(currentTime - request.ReqTime) > AllowedTimeDiff) {
                return CreateCheckHeadersResult(false, HttpStatusCode.Unauthorized, "请求已过期");
            }
            // 计算验证串
            var expectedVerify = CalculateRequestVerify(request.AppKey, appSecret, request.ReqTime);
            // 验证请求签名
            if (!string.Equals(expectedVerify, request.ReqVerify, StringComparison.OrdinalIgnoreCase)) {
                return CreateCheckHeadersResult(false, HttpStatusCode.Unauthorized, "验证失败");
            }
            return null;
        }
        /// <summary>
        /// 构造一个成功结果的ResponseMessage
        /// </summary>
        /// <example><code><![CDATA[
        /// var res = ApiHelper.OperateAgvTaskStatus(model);
        /// return CreateSuccessResponse(res);
        /// ]]></code></example>
        /// <param name="code"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private IHttpActionResult CreateSuccessResponse(HttpStatusCode code, object data) {
            return ResponseMessage(new HttpResponseMessage(code) {
                Headers = { },
                Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json")
            });
        }
        /// <summary>
        /// 构造一个失败结果的ResponseMessage
        /// </summary>
        /// <example><code><![CDATA[
        /// var headers = Request.Headers;
        /// var checkRes = CheckHeaders(headers);
        /// if (!checkRes.isSuccess) {
        ///     return CreateErrorResponse(checkRes.code, checkRes.message);
        /// }
        /// ]]></code></example>
        /// <param name="code"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private IHttpActionResult CreateErrorResponse(HttpStatusCode code, string message) {
            return ResponseMessage(new HttpResponseMessage(code) {
                Headers = { },
                Content = new StringContent(message)
            });
        }
        private CheckHeadersResult CreateCheckHeadersResult(bool isSuccess, HttpStatusCode code = HttpStatusCode.OK, string message = "") {
            return new CheckHeadersResult {
                code = code,
                message = message,
                isSuccess = isSuccess
            };
        }
        // 计算请求验证串
        private string CalculateRequestVerify(string appKey, string appSecret, long reqTime) {
            using (var md5 = MD5.Create()) {
                var input = $"{appKey}{appSecret}{reqTime}";
                var inputBytes = Encoding.UTF8.GetBytes(input);
                var hashBytes = md5.ComputeHash(inputBytes);
                // 将字节数组转换为十六进制字符串
                var sb = new StringBuilder();
                foreach (var b in hashBytes) {
                    sb.Append(b.ToString("x2"));
                }
                return sb.ToString();
            }
        }
    }
    // 请求模型
    public class SecureRequest {
        public string AppKey { get; set; }
        public long ReqTime { get; set; }
        public string ReqVerify { get; set; }
    }
    public class CheckHeadersResult {
        public bool isSuccess { get; set; }
        public HttpStatusCode code { get; set; }
        public string message { get; set; }
    }
}
api/DebugController.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Web.Http;
@@ -53,133 +54,6 @@
            returnResult.ResultList.Add(temp4);
            agvTaskState.state = 5;
            var temp5 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp5);
            agvTaskState.state = 6;
            var temp6 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp6);
            agvTaskState.state = 2;
            var temp2 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp2);
            return returnResult;
        }
        /// <summary>
        /// 模拟AGV回报任务状态(指定下一个状态,用于需要分段测试的场景)<br/>
        /// 性能相对较差,仅用于测试,一般不使用
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("AgvReports")]
        public ReturnResults AgvReports(AgvReportsInfo model) {
            var db = new SqlHelper<object>().GetInstance();
            ReturnResults returnResult = new ReturnResults();
            returnResult.ResultList = new List<ReturnResult>();
            var agvTaskState = new AgvTaskState() {
                task_no = model.TaskId,
                forklift_no = model.ForkliftNo,
            };
            var taskAction = db.Queryable<TN_Task_Action>()
                .Where(t => t.S_TASK_CODE == model.TaskId)
                .OrderBy(t => new { create = SqlFunc.Desc(t.T_CREATE) }).First(); // 最后一个Action状态
            var lastState = taskAction?.N_ACTION_CODE ?? 0;
            if (model.NextState <= 0 || model.NextState >= 7) {
                LogHelper.Info("小车回报状态不在134562的范围内");
            }
            // 0 ==> 1,3,4,5,6,2
            if (lastState == 0 && model.NextState >= 1) {
                agvTaskState.state = 1;
                var temp = WCSCore.OperateAgvTaskStatus(agvTaskState);
                returnResult.ResultList.Add(temp);
            }
            // 0,1 ==> 3,4,5,6,2
            if (lastState < 2 && model.NextState >= 2) {
                agvTaskState.state = 3;
                var temp = WCSCore.OperateAgvTaskStatus(agvTaskState);
                returnResult.ResultList.Add(temp);
            }
            // 0,1,3 ==> 4,5,6,2
            if (lastState < 4 && lastState != 2 && (model.NextState >= 3 || model.NextState == 2)) {
                agvTaskState.state = 4;
                var temp = WCSCore.OperateAgvTaskStatus(agvTaskState);
                returnResult.ResultList.Add(temp);
            }
            // 0,1,3,4 ==> 5,6,2
            if (lastState < 5 && lastState != 2 && (model.NextState >= 4 || model.NextState == 2)) {
                agvTaskState.state = 5;
                var temp = WCSCore.OperateAgvTaskStatus(agvTaskState);
                returnResult.ResultList.Add(temp);
            }
            // 0,1,3,4,5 ==> 6,2
            if (lastState < 6 && lastState != 2 && (model.NextState >= 5 || model.NextState == 2)) {
                agvTaskState.state = 6;
                var temp = WCSCore.OperateAgvTaskStatus(agvTaskState);
                returnResult.ResultList.Add(temp);
            }
            // 0,1,3,4,5,6 ==> 2
            if (lastState != 2 && model.NextState == 2) {
                agvTaskState.state = 2;
                var temp = WCSCore.OperateAgvTaskStatus(agvTaskState);
                returnResult.ResultList.Add(temp);
            }
            return returnResult;
        }
        /// <summary>
        /// AGV状态一键回报134
        /// </summary>
        /// <param name="model">容器号</param>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReports14")]
        public ReturnResults AGVSeriesReports14(UpdateTaskState model) {
            var agvTaskState = new AgvTaskState() {
                task_no = model.TaskID,
                forklift_no = model.ForkliftNo,
                state = 1
            };
            ReturnResults returnResult = new ReturnResults();
            returnResult.ResultList = new List<ReturnResult>();
            var temp1 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp1);
            agvTaskState.state = 3;
            var temp3 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp3);
            agvTaskState.state = 4;
            var temp4 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp4);
            return returnResult;
        }
        /// <summary>
        /// AGV状态一键回报562
        /// </summary>
        /// <param name="model">容器号</param>
        /// <returns></returns>
        [HttpPost]
        [Route("AGVSeriesReports62")]
        public ReturnResults AGVSeriesReports62(UpdateTaskState model) {
            var agvTaskState = new AgvTaskState() {
                task_no = model.TaskID,
                forklift_no = model.ForkliftNo,
                state = 5
            };
            ReturnResults returnResult = new ReturnResults();
            returnResult.ResultList = new List<ReturnResult>();
            var temp5 = WCSCore.OperateAgvTaskStatus(agvTaskState);
            returnResult.ResultList.Add(temp5);
models/TN_Container.cs
@@ -26,7 +26,7 @@
        [SugarColumn(IsIgnore = true)]
        [Navigate(NavigateType.OneToMany, nameof(TN_CG_Detail.S_CNTR_CODE), nameof(S_CODE))]
        public List<TN_CG_Detail> CntrItemRels { get; set; }
        public List<TN_CG_Detail> CntrItemRels { get; set; }
    }
}
process/TaskProcess.cs
@@ -23,14 +23,13 @@
            if (load) {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTR_CODE}");
                LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList());
                LocationHelper.UnbindLocCntr(mst.S_START_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
            else {
                Console.WriteLine($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                LogHelper.Info($"任务{mst.S_CODE} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTR_CODE}");
                LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTR_CODE.Split(',').ToList());
            }
        }
        /// <summary>
util/HttpHelper.cs
@@ -84,7 +84,6 @@
            Stream stream = null;
            WebResponse rsp = null;
            try {
                rsp = request.GetResponse();
                stream = rsp.GetResponseStream();
                reader = new StreamReader(stream);
@@ -101,7 +100,6 @@
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Post(string url, string postData, string contentType = "application/json", string sessionId = "") {
@@ -137,7 +135,6 @@
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Post(string url, Dictionary<string, string> dic) {
@@ -173,7 +170,6 @@
            }
            catch (Exception e)
            {
                LogHelper.Info($"PostWithCookie res={e.Message}", "API");
                return "";
            }
@@ -183,7 +179,6 @@
                if (stream != null) stream.Close();
                if (rsp != null) rsp.Close();
            }
        }
        public string Put(string url, string postData, string contentType = "application/json", string sessionId = "")
util/LogHelper.cs
@@ -83,7 +83,6 @@
            Info($"AGV任务:{taskName}" + JsonConvert.SerializeObject(model), "HosttoagvTask");
        }
        #endregion
    }
    internal class LogFactory
util/SqlHelper.cs
@@ -6,20 +6,19 @@
namespace HH.WCS.Mobox3.DSZSH.util {
    //https://www.donet5.com/Home/Doc
    public class SqlHelper<T> where T : class, new() {
        // NOTE:如果用Oracle数据库,需要包Oracle.ManagedDataAccess/21.15.0,环境netframework 4.6.2(太新了4.8有的服务器安装不上去)
        /// <summary>
        /// 如果用Oracle数据需要包Oracle.ManagedDataAccess/21.15.0,环境netframework 4.62,太新了4.8有的服务器安装不上去
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public SqlSugarClient GetInstance(string url = "") {
            //创建数据库对象
            SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() {
                ConnectionString = string.IsNullOrEmpty(url) ? Settings.SqlServer : url,
                //ConnectionString = @"Data Source=192.168.1.198\sql2008;Initial Catalog=OIMobox;User ID=sa;Password=sa@2015",
                DbType = DbType.SqlServer,
                //ConnectionString = @"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=OIMobox)));User Id=system;Password=Am123123;",
                //DbType = DbType.Oracle,
                IsAutoCloseConnection = true,
                InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息
            });
@@ -63,7 +62,5 @@
            return db;
        }
    }
}
util/WebHelper.cs
New file
@@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace HH.WCS.Mobox3.DSZSH.util {
    // 尝试优化HttpHelper
    public class WebHelper : IDisposable {
        private readonly HttpClient _httpClient;
        private readonly int _timeoutSeconds;
        public WebHelper(int timeoutSeconds = 3) {
            _httpClient = new HttpClient();
            _timeoutSeconds = timeoutSeconds;
            _httpClient.Timeout = TimeSpan.FromSeconds(_timeoutSeconds);
        }
        #region 异步方法
        public async Task<string> GetAsync(string url, Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Get, url)) {
                    AddHeaders(request, headers);
                    var response = await _httpClient.SendAsync(request);
                    response.EnsureSuccessStatusCode();
                    return await response.Content.ReadAsStringAsync();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"GET request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        public async Task<string> PostAsync(string url, string content, string contentType = "application/json", Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Post, url)) {
                    AddHeaders(request, headers);
                    request.Content = new StringContent(content, Encoding.UTF8, contentType);
                    var response = await _httpClient.SendAsync(request);
                    response.EnsureSuccessStatusCode();
                    return await response.Content.ReadAsStringAsync();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"POST request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        public async Task<string> PutAsync(string url, string content, string contentType = "application/json", Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Put, url)) {
                    AddHeaders(request, headers);
                    request.Content = new StringContent(content, Encoding.UTF8, contentType);
                    var response = await _httpClient.SendAsync(request);
                    response.EnsureSuccessStatusCode();
                    return await response.Content.ReadAsStringAsync();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"PUT request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        public async Task<string> DeleteAsync(string url, Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Delete, url)) {
                    AddHeaders(request, headers);
                    var response = await _httpClient.SendAsync(request);
                    response.EnsureSuccessStatusCode();
                    return await response.Content.ReadAsStringAsync();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"DELETE request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        #endregion
        #region 同步方法
        public string WebGet(string url, Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Get, url)) {
                    AddHeaders(request, headers);
                    var response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
                    response.EnsureSuccessStatusCode();
                    return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"GET request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        public string WebPost(string url, string postData, string contentType = "application/json", Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Post, url)) {
                    AddHeaders(request, headers);
                    request.Content = new StringContent(postData, Encoding.UTF8, contentType);
                    var response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
                    response.EnsureSuccessStatusCode();
                    return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"POST request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        public string WebPut(string url, string putData, string contentType = "application/json", Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Put, url)) {
                    AddHeaders(request, headers);
                    request.Content = new StringContent(putData, Encoding.UTF8, contentType);
                    var response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
                    response.EnsureSuccessStatusCode();
                    return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"PUT request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        public string WebDelete(string url, Dictionary<string, string> headers = null) {
            try {
                using (var request = new HttpRequestMessage(HttpMethod.Delete, url)) {
                    AddHeaders(request, headers);
                    var response = _httpClient.SendAsync(request).GetAwaiter().GetResult();
                    response.EnsureSuccessStatusCode();
                    return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                }
            }
            catch (Exception e) {
                LogHelper.Info($"DELETE request failed: {e.Message}", "API");
                return string.Empty;
            }
        }
        #endregion
        private void AddHeaders(HttpRequestMessage request, Dictionary<string, string> headers) {
            if (headers != null) {
                foreach (var header in headers) {
                    request.Headers.TryAddWithoutValidation(header.Key, header.Value);
                }
            }
        }
        public void Dispose() {
            _httpClient?.Dispose();
        }
    }
}
wms/LocationHelper.cs
@@ -143,15 +143,14 @@
        /// <param name="loc"></param>
        /// <param name="cntrs"></param>
        /// <returns></returns>
        public static string UnBindingLoc(string loc, List<string> cntrs)
        public static string UnbindLocCntr(string loc, List<string> cntrs)
        {
            var db = new SqlHelper<object>().GetInstance();
            var logs = $"货位:{loc},容器:{JsonConvert.SerializeObject(cntrs)}";
            try
            {
                var lcrList = db.Queryable<TN_Loc_Container>().Where(a => cntrs.Contains(a.S_CNTR_CODE) && a.S_LOC_CODE == loc).ToList();
                if (lcrList.Count == 0)
                {
                if (lcrList.Count == 0) {
                    LogHelper.Info($"货位无需解绑容器,在数据库中未找到{JsonConvert.SerializeObject(cntrs)}相关的货位容器关系表信息");
                }
                cntrs = lcrList.Select(a => a.S_CNTR_CODE).ToList();
@@ -180,14 +179,12 @@
                        }
                        log = JsonConvert.SerializeObject(location);
                        if (db.Updateable(location).UpdateColumns(it => new { it.N_CURRENT_NUM, it.S_LOCK_STATE, it.N_LOCK_STATE }).ExecuteCommand() > 0)
                        {
                        if (db.Updateable(location).UpdateColumns(it => new { it.N_CURRENT_NUM, it.S_LOCK_STATE, it.N_LOCK_STATE }).ExecuteCommand() > 0) {
                            tran.CommitTran();
                            LogHelper.Info($"更新货位表成功,{log}");
                        }
                        else
                        {
                        else {
                            tran.RollbackTran();
                            LogHelper.Info($"更新货位表失败,{log}");