feat(router): 添加托盘操作页面路由
feat(taskinfo): 实现组盘/拆盘操作页面
feat(robot): 添加机械手状态互斥锁防止并发冲突
feat(logging): 为分容柜接口添加独立日志文件
fix(redis): 修复Redis连接字符串密码配置
fix(robot): 修复机械手状态更新时的版本控制问题
refactor(robot): 重构机械手任务处理流程
perf(robot): 优化机械手消息处理性能
docs(model): 添加机械手状态模型字段注释
test: 更新相关测试用例
chore: 更新项目依赖
| | |
| | | /// <summary> |
| | | /// æè¿ä¸æ¬¡æ¾è´§å®æçä½ç½®æ°ç»ï¼JSONï¼ |
| | | /// </summary> |
| | | [SugarColumn(Length = 500, ColumnDescription = "æ¾è´§ä½ç½®æ°ç»JSON", IsNullable = true)] |
| | | [SugarColumn(Length = 5000, ColumnDescription = "æ¾è´§ä½ç½®æ°ç»JSON", IsNullable = true)] |
| | | public string? LastPutPositionsJson { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åæ¹æ¬¡ççµè¯æ¡ç å表 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// æ¯æ¬¡è¯»åæ°æ¡ç æ¶è®¾ç½®ä¸ºæ¬æ¹æ¬¡çæ¡ç ï¼ä»
ç¨äº WMS æäº¤æ¶ææ¹æ¬¡æäº¤ã |
| | | /// æ¯æ¬¡æ°æ¹æ¬¡è¯»åæ¶è¦çï¼å¨ allputfinished æ¶æ¸
空ã |
| | | /// </remarks> |
| | | [SugarColumn(Length = 5000, ColumnDescription = "å½åæ¹æ¬¡ççµè¯æ¡ç å表", IsNullable = true)] |
| | | public string? CurrentBatchBarcodes { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµæ± /è´§ä½æ¡ç å表ï¼JSONï¼ |
| | |
| | | /// </summary> |
| | | [SugarColumn(ColumnDescription = "çµè¯æ¯å¦å°ä½")] |
| | | public bool BatteryArrived { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å½åæ§è¡ä¸çæºå¨äººä»»å¡ç¼å· |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// ä¸å任塿¶ç¼åä»»å¡ç¼å·ï¼ç¨äº RobotJob å¿«éæ¥æ¾æ§è¡ä¸çä»»å¡ï¼ |
| | | /// é¿å
æ¯æ¬¡è½®è¯¢å
¨è¡¨æ«æãä»»å¡å®ææ¶æ¸
空为 nullã |
| | | /// </remarks> |
| | | [SugarColumn(ColumnDescription = "å½åæ§è¡ä¸çæºå¨äººä»»å¡ç¼å·")] |
| | | public int? CurrentTaskNum { get; set; } |
| | | } |
| | | } |
| | |
| | | }, |
| | | "RedisConfig": { |
| | | "Enabled": true, //æ¯å¦å¯ç¨Redisï¼falseæ¶ä»
使ç¨å
åç¼å |
| | | "ConnectionString": "127.0.0.1:6379,password=,defaultDatabase=0,connectTimeout=5000,abortConnect=false", //Redisè¿æ¥å符串 |
| | | "ConnectionString": "127.0.0.1:6379,password=P@ssw0rd,defaultDatabase=0,connectTimeout=5000,abortConnect=false", //Redisè¿æ¥å符串 |
| | | "InstanceName": "WIDESEAWCS:", //å®ä¾åç§°ï¼ç¨äºåºåä¸ååºç¨ |
| | | "DefaultDatabase": 0, //é»è®¤æ°æ®åºç´¢å¼ï¼0-15ï¼ |
| | | "EnableSentinel": false, //æ¯å¦å¯ç¨å¨å
µæ¨¡å¼ |
| | |
| | | { |
| | | newState.ModifyDate = DateTime.Now; |
| | | |
| | | // ä¹è§éï¼WHERE IPAddress = @ip AND Version = @expectedVersionï¼çæ¬å¹é
ææ´æ° |
| | | var affectedRows = Db.Updateable<Dt_RobotState>(newState) |
| | | // SqlSugar ç Updateable(entity).Where(x => x.Version == param) åå¨åæ°æ··æ·é®é¢ï¼ |
| | | // å®ä½ç Version 已被设为 expectedVersion+1ï¼.Where() ä¸ SqlSugar å¯è½ä½¿ç¨å®ä½ç |
| | | // Version å¼ï¼expectedVersion+1ï¼èéåæ°å¼ï¼expectedVersionï¼ï¼å¯¼è´ WHERE æ°¸è¿å¹é
ä¸ä¸ã |
| | | // ä¿®å¤ï¼å°çæ¬æ ¡éªæä¸ºç¬ç«æ¥è¯¢ï¼æ´æ°ä»
éè¿ä¸»é®æ§è¡ã |
| | | |
| | | // æ¥éª¤1ï¼æ ¡éªçæ¬å·æ¯å¦ä¸ææä¸è´ |
| | | var currentVersion = Db.Queryable<Dt_RobotState>() |
| | | .Where(x => x.IpAddress == ipAddress) |
| | | .ExecuteCommand(); |
| | | .Select(x => x.Version) |
| | | .First(); |
| | | |
| | | if (currentVersion != expectedVersion) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // æ¥éª¤2ï¼çæ¬å¹é
ï¼éè¿ä¸»é®ç´æ¥æ´æ° |
| | | var affectedRows = Db.Updateable(newState).ExecuteCommand(); |
| | | |
| | | return affectedRows > 0; |
| | | } |
| | |
| | | CurrentBatchIndex = entity.CurrentBatchIndex, |
| | | ChangePalletPhase = entity.ChangePalletPhase, |
| | | IsScanNG = entity.IsScanNG, |
| | | BatteryArrived = entity.BatteryArrived |
| | | BatteryArrived = entity.BatteryArrived, |
| | | CurrentTaskNum = entity.CurrentTaskNum, |
| | | }; |
| | | |
| | | // ååºåå夿 JSON åæ®µ |
| | | if (!string.IsNullOrEmpty(entity.RobotCraneJson)) |
| | | { |
| | | state.RobotCrane = JsonConvert.DeserializeObject<RobotCraneDevice>(entity.RobotCraneJson); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(entity.CurrentBatchBarcodes)) |
| | | { |
| | | state.CurrentBatchBarcodes = JsonConvert.DeserializeObject<List<string>>(entity.CurrentBatchBarcodes) ?? new List<string>(); |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(entity.CurrentTaskJson)) |
| | |
| | | LastPickPositionsJson = state.LastPickPositions.ToJson(), |
| | | CurrentTaskJson = state.CurrentTask.ToJson(), |
| | | LastPutPositionsJson = state.LastPutPositions.ToJson(), |
| | | CurrentBatchBarcodes = state.CurrentBatchBarcodes.ToJson(), |
| | | CurrentTaskNum = state.CurrentTaskNum, |
| | | }; |
| | | |
| | | // åºååå¤æå¯¹è±¡ä¸º JSON |
| | |
| | | entity.RobotCraneJson = JsonConvert.SerializeObject(state.RobotCrane); |
| | | } |
| | | |
| | | if (state.CurrentTask != null) |
| | | { |
| | | entity.CurrentTaskJson = JsonConvert.SerializeObject(state.CurrentTask); |
| | | } |
| | | //if (state.CurrentTask != null) |
| | | //{ |
| | | // entity.CurrentTaskJson = JsonConvert.SerializeObject(state.CurrentTask); |
| | | //} |
| | | |
| | | if (state.LastPickPositions != null) |
| | | { |
| | | entity.LastPickPositionsJson = JsonConvert.SerializeObject(state.LastPickPositions); |
| | | } |
| | | //if (state.LastPickPositions != null) |
| | | //{ |
| | | // entity.LastPickPositionsJson = JsonConvert.SerializeObject(state.LastPickPositions); |
| | | //} |
| | | |
| | | if (state.LastPutPositions != null) |
| | | { |
| | | entity.LastPutPositionsJson = JsonConvert.SerializeObject(state.LastPutPositions); |
| | | } |
| | | //if (state.LastPutPositions != null) |
| | | //{ |
| | | // entity.LastPutPositionsJson = JsonConvert.SerializeObject(state.LastPutPositions); |
| | | //} |
| | | |
| | | if (state.CellBarcode != null && state.CellBarcode.Count > 0) |
| | | { |
| | | entity.CellBarcodeJson = JsonConvert.SerializeObject(state.CellBarcode); |
| | | } |
| | | //if (state.CellBarcode != null && state.CellBarcode.Count > 0) |
| | | //{ |
| | | // entity.CellBarcodeJson = JsonConvert.SerializeObject(state.CellBarcode); |
| | | //} |
| | | |
| | | //if (state.CurrentBatchBarcodes != null && state.CurrentBatchBarcodes.Count > 0) |
| | | //{ |
| | | // entity.CurrentBatchBarcodes = JsonConvert.SerializeObject(state.CurrentBatchBarcodes); |
| | | //} |
| | | |
| | | return entity; |
| | | } |
| | |
| | | return; |
| | | } |
| | | |
| | | |
| | | // è·å该设å¤çäºæ¥éï¼ç¡®ä¿ Job æ§è¡ä¸æ¶æ¯å¤çäºæ¥ |
| | | var robotLock = _stateManager.GetOrCreateLock(ipAddress); |
| | | |
| | | // éè¢«æ¶æ¯å¤çå¨å ç¨æ¶ç´æ¥è·³è¿æ¬æ¬¡ tickï¼ç䏿¬¡è°åº¦åæ§è¡ |
| | | //if (!await robotLock.WaitAsync(TimeSpan.Zero)) |
| | | //{ |
| | | // return; |
| | | //} |
| | | |
| | | // è·å该设å¤çäºæ¥éï¼ç¡®ä¿ Job æ§è¡ä¸æ¶æ¯å¤çäºæ¥ |
| | | await robotLock.WaitAsync(); |
| | | try |
| | | { |
| | | if (state.CurrentAction == "Picking" || state.CurrentAction == "Puting") |
| | | { |
| | | return; |
| | |
| | | } |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | robotLock.Release(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // å¼å¸¸å¤çå·²å¨ç»ä»¶å
é¨è¿è¡ï¼Job å±ä¿æå
åºè¯ä¹ |
| | |
| | | public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client) |
| | | { |
| | | var state = _stateManager.GetState(client.Client.RemoteEndPoint.ToString()); |
| | | if (state.OperStatus == message) |
| | | |
| | | // 设å¤ç¶æä¸å卿¶ç´æ¥è¿åï¼é¿å
åç»ç©ºå¼ç¨ |
| | | if (state == null) |
| | | { |
| | | // å¤çæååï¼å°åæ¶æ¯ååå°å®¢æ·ç«¯ï¼ä¿æåæè¡ä¸ºï¼ |
| | | //await _socketClientGateway.SendMessageAsync(client, message); |
| | | return null; |
| | | } |
| | | |
| | | // è·å该设å¤çäºæ¥éï¼ç¡®ä¿æ¶æ¯å¤çä¸ Job æ§è¡äºæ¥ |
| | | // Job å¨å¤ç任塿¶ä¼çå¾
æ¤ééæ¾åæç»§ç»æ§è¡ |
| | | var robotLock = _stateManager.GetOrCreateLock(state.IPAddress); |
| | | await robotLock.WaitAsync(); |
| | | try |
| | | { |
| | | // è®°å½æ¥æ¶å°çæ¶æ¯æ¥å¿ |
| | | QuartzLogHelper.LogInfo(_logger, $"æ¥æ¶å°å®¢æ·ç«¯ã{state.RobotCrane?.DeviceName}ãåéæ¶æ¯ã{message}ã", state.RobotCrane?.DeviceName); |
| | | |
| | |
| | | QuartzLogHelper.LogInfo(_logger, $"æ¥æ¶å°æ¶æ¯æ¶æ¯ã{message}ãï¼çº¦å®ä¸è¿ååéæ¶æ¯ï¼ã{message}ã", state.RobotCrane?.DeviceName); |
| | | //} |
| | | |
| | | // å®å
¨æ´æ°ç¶æå°æ°æ®åº |
| | | _stateManager.TryUpdateStateSafely(state.IPAddress, state); |
| | | //// å®å
¨æ´æ°ç¶æå°æ°æ®åº |
| | | //_stateManager.TryUpdateStateSafely(state.IPAddress, state); |
| | | return null; |
| | | } |
| | | |
| | |
| | | // è°ç¨åç¼å½ä»¤å¤çå¨ |
| | | await _prefixCommandHandler.HandleAsync(message, state, client); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | robotLock.Release(); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | |
| | | using System.Collections.Concurrent; |
| | | using Newtonsoft.Json; |
| | | using Serilog; |
| | | using WIDESEAWCS_ITaskInfoRepository; |
| | |
| | | /// <remarks> |
| | | /// æ ¸å¿åè½æ¯éè¿ IRobotStateRepository ç®¡çæ°æ®åºä¸çæºæ¢°æç¶æã |
| | | /// æä¾ä¹è§å¹¶åæ§å¶ï¼éè¿ Version åæ®µé²æ¢å¹¶åæ´æ°æ¶çæ°æ®è¦çé®é¢ã |
| | | /// åæ¶æä¾åºäº SemaphoreSlim çäºæ¥éï¼ç¡®ä¿æ¶æ¯å¤çä¸ Job æ§è¡ä¸ä¼å¹¶åæä½åä¸è®¾å¤ç¶æã |
| | | /// </remarks> |
| | | public class RobotStateManager |
| | | { |
| | |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æ¯ä¸ªè®¾å¤ç弿¥äºæ¥éåå
¸ï¼ç¨äº Job æ§è¡ä¸æ¶æ¯å¤çä¹é´çäºæ¥ |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// Key ä¸ºè®¾å¤ IP å°åï¼Value 为该设å¤ä¸å±ç SemaphoreSlim(1,1)ã |
| | | /// ç¡®ä¿åä¸è®¾å¤ç Job 轮询å TCP æ¶æ¯å¤çä¸ä¼åæ¶æä½ç¶æã |
| | | /// </remarks> |
| | | private readonly ConcurrentDictionary<string, SemaphoreSlim> _robotLocks = new(); |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="repository">ä»å¨æå¡å®ä¾</param> |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå建æå®è®¾å¤ç弿¥äºæ¥é |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// ä½¿ç¨ ConcurrentDictionary ç¡®ä¿æ¯ä¸ªè®¾å¤ IP 对åºå¯ä¸ç SemaphoreSlim(1,1)ã |
| | | /// 该éç¨äº Job æ§è¡ä¸ TCP æ¶æ¯å¤çä¹é´çäºæ¥ï¼é²æ¢å¹¶åæä½åä¸è®¾å¤ç¶æã |
| | | /// </remarks> |
| | | /// <param name="ipAddress">è®¾å¤ IP å°å</param> |
| | | /// <returns>该设å¤çä¿¡å·éå®ä¾</returns> |
| | | public SemaphoreSlim GetOrCreateLock(string ipAddress) |
| | | { |
| | | return _robotLocks.GetOrAdd(ipAddress, _ => new SemaphoreSlim(1, 1)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å®å
¨æ´æ° RobotSocketStateï¼é²æ¢å¹¶åè¦ç |
| | | /// </summary> |
| | | /// <remarks> |
| | |
| | | using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; |
| | | using Serilog; |
| | | using System.Net; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_Tasks.Workflow.Abstractions; |
| | | |
| | |
| | | case "homed": |
| | | state.Homed = "Homed"; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | for (int i = 0; i < 5; i++) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, $"åéåé¶å®ææ¶æ¯ï¼IP: {state.IPAddress}ï¼æ£å¨éè¯...", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, "Homed"); |
| | | } |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"åéåé¶å®ææ¶æ¯å¤±è´¥ï¼IP: {state.IPAddress}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | // æºå¨äººæ£å¨è¿è¡ |
| | | case "running": |
| | |
| | | // æ¯å¦çµè¯å°ä½ |
| | | case "batteryarrived": |
| | | state.BatteryArrived = true; |
| | | return true; |
| | | |
| | | // æ¯å¦çµè¯å°ä½ |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | for (int i = 0; i < 5; i++) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, $"åéçµè¯å°ä½æ¶æ¯ï¼IP: {state.IPAddress}ï¼æ£å¨éè¯...", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, "batteryarrived"); |
| | | } |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"åéçµè¯æªå°ä½æ¶æ¯å¤±è´¥ï¼IP: {state.IPAddress}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | // æ¯å¦çµè¯æ²¡å°ä½ |
| | | case "batteryarrivedno": |
| | | state.BatteryArrived = false; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | for (int i = 0; i < 5; i++) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, $"åéçµè¯æªå°ä½æ¶æ¯ï¼IP: {state.IPAddress}ï¼æ£å¨éè¯...", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, "batteryarrivedno"); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"åéçµè¯æªå°ä½æ¶æ¯å¤±è´¥ï¼IP: {state.IPAddress}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | // ==================== æ¥æ¶ä»»å¡åé¦ ==================== |
| | | |
| | | // åè´§æ¥æ¶ |
| | |
| | | if (!isResult) |
| | | return false; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | for (int i = 0; i < 5; i++) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, $"åéåè´§æ¥æ¶å®æï¼IP: {state.IPAddress}ï¼æ£å¨éè¯...", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, "pickbatteryover"); |
| | | } |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"åéåè´§å®ææ¶æ¯å¤±è´¥ï¼IP: {state.IPAddress}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | // æ¾è´§æ¥æ¶ |
| | | case "putbatteryover": |
| | |
| | | if (!isResult) |
| | | return false; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | for (int i = 0; i < 5; i++) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, $"åéæ¾è´§æ¥æ¶æ¶æ¯ï¼IP: {state.IPAddress}ï¼æ£å¨éè¯...", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, "putbatteryover"); |
| | | } |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"åéæ¾è´§å®ææ¶æ¯å¤±è´¥ï¼IP: {state.IPAddress}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | // ==================== å
¨é¨å®æå½ä»¤ ==================== |
| | | |
| | |
| | | // æ¢çä»»å¡ï¼æ ¹æ®é¶æ®µåºåå¤ç |
| | | if (robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | // è°ç¨æ¹éæç确认æ¥å£ |
| | | var sourcePallet = state.CurrentTask.RobotSourceAddressPalletCode; |
| | | var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName); |
| | | if (!confirmResult.IsSuccess && !confirmResult.Data.Status) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"æ¹éæç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | if (state.ChangePalletPhase == 5) |
| | | { |
| | | // FlowB æç»é¶æ®µï¼åçµè¯åå®ï¼æºç©ºæçååº HCSC1 |
| | |
| | | return false; |
| | | } |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | |
| | | state.CurrentTask = null; |
| | | state.CurrentTaskNum = null; |
| | | state.RobotTaskTotalNum = 0; |
| | |
| | | state.ChangePalletPhase = 0; |
| | | state.CurrentBatchIndex = 1; |
| | | state.IsInFakeBatteryMode = false; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | else if (state.ChangePalletPhase != 0) |
| | | { |
| | |
| | | // return false; |
| | | //} |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | |
| | | state.ChangePalletPhase = 0; |
| | | state.CurrentBatchIndex = 1; |
| | | state.IsInFakeBatteryMode = false; |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // æçä»»å¡ï¼ç´æ¥å¤çå
¥åº |
| | |
| | | return false; |
| | | } |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | |
| | | // æ¢çä»»å¡ï¼æ ¹æ®é¶æ®µåºåå¤ç |
| | | if (robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | // è°ç¨æ¹éæç确认æ¥å£ |
| | | var sourcePallet = state.CurrentTask.RobotSourceAddressPalletCode; |
| | | var splitConfirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName); |
| | | if (!splitConfirmResult.IsSuccess && !splitConfirmResult.Data.Status) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"æ¹éæç确认失败: {splitConfirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | | // è°ç¨æ¹éç»ç确认æ¥å£ |
| | | var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; |
| | | var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName); |
| | |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | state.CurrentBatchBarcodes = new List<string>(); |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | |
| | | state.ChangePalletPhase = 0; |
| | | state.CurrentBatchIndex = 1; |
| | | state.IsInFakeBatteryMode = false; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | else if (state.ChangePalletPhase != 0) |
| | | { |
| | |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | state.CurrentBatchBarcodes = new List<string>(); |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | |
| | | state.ChangePalletPhase = 0; |
| | | state.CurrentBatchIndex = 1; |
| | | state.IsInFakeBatteryMode = false; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // ç»çä»»å¡ï¼ç´æ¥å¤çå
¥åº |
| | |
| | | state.CellBarcode = new List<string>(); // æ¸
空æ¡ç å表 |
| | | state.CurrentBatchBarcodes = new List<string>(); // æ¸
空å½åæ¹æ¬¡æ¡ç |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | |
| | | using Masuit.Tools; |
| | | using Serilog; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core.Helper; |
| | |
| | | } |
| | | return; |
| | | } |
| | | |
| | | } |
| | | |
| | | // 鿢çä»»å¡ï¼ä½¿ç¨åææ ¼å¼ |
| | |
| | | string trayBarcode1 = RobotBarcodeGenerator.GenerateTrayBarcode("DB40.1020"); |
| | | |
| | | // 妿æ¡ç çææå |
| | | if (!string.IsNullOrEmpty(trayBarcode1) && !string.IsNullOrEmpty(trayBarcode2)) |
| | | if (!trayBarcode1.IsNullOrEmpty() && !trayBarcode2.IsNullOrEmpty()) |
| | | { |
| | | //if (stateForUpdate.CellBarcode.Contains(trayBarcode1) || stateForUpdate.CellBarcode.Contains(trayBarcode2)) |
| | | //{ |
| | |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsyncï¼è¯»åççµè¯æ¡ç å¯ä¸ï¼ç»§ç»æ§è¡ï¼ä»»å¡å·: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress); |
| | | |
| | | // è®°å½æ¥å¿ï¼è¯»åæçæ¡ç æå |
| | | QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsyncï¼è¯»åçµè¯æ¡ç æå: ã{trayBarcode1}ã-----ã{trayBarcode2}ãï¼ä»»å¡å·: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress); |
| | | |
| | | // å°æ¡ç ç´¯ç§¯å° CellBarcodeï¼å»éï¼ï¼å¹¶è®¾ç½®å½åæ¹æ¬¡æ¡ç |
| | | if (!stateForUpdate.CellBarcode.Contains(trayBarcode1)) |
| | | if (!stateForUpdate.CellBarcode.Contains(trayBarcode1) || !stateForUpdate.CellBarcode.Contains(trayBarcode2)) |
| | | { |
| | | |
| | | stateForUpdate.CellBarcode.Add(trayBarcode1); |
| | | if (!stateForUpdate.CellBarcode.Contains(trayBarcode2)) |
| | | stateForUpdate.CellBarcode.Add(trayBarcode2); |
| | | |
| | | // 设置å½åæ¹æ¬¡æ¡ç ï¼ç¨äº WMS æäº¤ |
| | |
| | | trayBarcode1, trayBarcode2 |
| | | }; |
| | | } |
| | | |
| | | // è®°å½æ¥å¿ï¼è¯»åæçæ¡ç æå |
| | | QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsyncï¼è¯»åçµè¯æ¡ç æå: ã{trayBarcode1}ã-----ã{trayBarcode2}ãï¼ä»»å¡å·: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress); |
| | | } |
| | | |
| | | // åéåè´§æä»¤ |
| | | await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); |
| | |
| | | QuartzLogHelper.LogInfo(_logger, "Executeï¼è®¢é
ä»»å¡å®æäºä»¶ï¼è®¾å¤: {DeviceCode}", "订é
ä»»å¡å®æäºä»¶", _deviceCode, _deviceCode); |
| | | } |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"å¼å§æ£æ¥å åæºå®æç¶æï¼ã{_deviceCode}ã", _deviceCode); |
| | | // ========== æ£æ¥å åæºä»»å¡å®æç¶æ ========== |
| | | commonStackerCrane.CheckStackerCraneTaskCompleted(); |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"æ£æ¥å®æï¼æ£å¨çå¬å åæºä»»å¡å®æï¼ã{_deviceCode}ã", _deviceCode); |
| | | |
| | | // ========== æ£æ¥æ¯å¦å¯ä»¥åéæ°ä»»å¡ ========== |
| | | //if (!commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs)) |
| | |
| | | // å åæºä¸å¯ç¨ï¼å¦æ£å¨æ§è¡ä¸ä¸ä»»å¡ï¼ï¼ç´æ¥è¿å |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"å åæºå¯ä¸åä»»å¡ï¼ã{_deviceCode}ã", _deviceCode); |
| | | |
| | | // ========== éæ©ä»»å¡ ========== |
| | | // ä»»å¡éæ©ä¸æ²å°ä¸ç¨éæ©å¨ |
| | |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"è·åå°ä»»å¡ï¼å¼å§æå»ºä»»å¡ä¸åå½ä»¤ï¼ã{_deviceCode}ã", _deviceCode); |
| | | |
| | | // ========== æå»ºå½ä»¤ ========== |
| | | // å½ä»¤æå»ºä¸æ²å°ä¸ç¨æå»ºå¨ |
| | | object? stackerCraneTaskCommand = _commandBuilder.ConvertToStackerCraneTaskCommand(task); |
| | | if (stackerCraneTaskCommand == null) |
| | | { |
| | | // å½ä»¤æå»ºå¤±è´¥ |
| | | QuartzLogHelper.LogInfo(_logger, $"Executeï¼å½ä»¤æå»ºå¤±è´¥ï¼è®¾å¤: {_deviceCode}ï¼ä»»å¡å·: {task.TaskNum}", _deviceCode); |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"å½ä»¤æå»ºå®æï¼å¼å§ä¸åä»»å¡ï¼ã{_deviceCode}ã", _deviceCode); |
| | | |
| | | // ========== åéå½ä»¤ ========== |
| | | bool sendFlag = SendStackerCraneCommand(commonStackerCrane, stackerCraneTaskCommand); |
| | |
| | | let loadingInstance; |
| | | let loadingStatus = false; |
| | | if (process.env.NODE_ENV == 'development') { |
| | | axios.defaults.baseURL = window.webConfig.webApiBaseUrl; |
| | | axios.defaults.baseURL = window.webConfig.webApiProduction; |
| | | } |
| | | else if (process.env.NODE_ENV == 'debug') { |
| | | axios.defaults.baseURL = window.webConfig.webApiBaseUrl; |
| | |
| | | name: 'outboundTimeConfig', |
| | | component: () => import('@/views/system/outboundTimeConfig.vue') |
| | | } |
| | | , { |
| | | path: '/palletOperation', |
| | | name: 'palletOperation', |
| | | component: () => import('@/views/taskinfo/palletOperation.vue') |
| | | } |
| | | ] |
| | | |
| | | export default viewgird |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="pallet-operation-page"> |
| | | <el-card shadow="hover"> |
| | | <template #header> |
| | | <span>ç»ç/æçæä½</span> |
| | | </template> |
| | | |
| | | <el-form :model="formData" ref="formRef" label-width="100px" style="max-width: 600px"> |
| | | <el-form-item label="æä½ç±»å" prop="action" required> |
| | | <el-select v-model="formData.action" placeholder="è¯·éæ©æä½ç±»å" @change="onActionChange"> |
| | | <el-option label="ç»ç" value="ç»ç" /> |
| | | <el-option label="æç" value="æç" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æçå·" prop="palletCode" required> |
| | | <el-input v-model="formData.palletCode" placeholder="请è¾å
¥æçå·" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="线ä½ç¼å·" prop="lineId" required> |
| | | <el-input v-model="formData.lineId" placeholder="请è¾å
¥çº¿ä½ç¼å·" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æºæ¢°æåç§°" prop="robotName" required> |
| | | <el-input v-model="formData.robotName" placeholder="请è¾å
¥æºæ¢°æåç§°" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ä»åºç¼å·" prop="warehouseCode" required> |
| | | <el-input v-model="formData.warehouseCode" placeholder="请è¾å
¥ä»åºç¼å·" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ä¼å
级" prop="grade"> |
| | | <el-input-number v-model="formData.grade" :min="1" :max="99" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- çµè¯å表ï¼ç»çæ¶æ¾ç¤ºï¼ --> |
| | | <el-card v-if="formData.action === 'ç»ç'" shadow="hover" style="margin-top: 16px"> |
| | | <template #header> |
| | | <div class="cell-header"> |
| | | <span>çµè¯å表</span> |
| | | <el-button type="primary" size="small" @click="addCellRow">æ·»å è¡</el-button> |
| | | </div> |
| | | </template> |
| | | |
| | | <el-table :data="formData.cells" border style="width: 100%" max-height="400"> |
| | | <el-table-column label="åºå·" width="60" align="center"> |
| | | <template v-slot="{ $index }">{{ $index + 1 }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="çµè¯ç " min-width="200"> |
| | | <template v-slot="{ row }"> |
| | | <el-input v-model="row.sfcCode" size="small" placeholder="请è¾å
¥çµè¯ç " /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ééå·" width="160"> |
| | | <template v-slot="{ row }"> |
| | | <el-input v-model="row.channel" size="small" placeholder="请è¾å
¥ééå·" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="80" align="center"> |
| | | <template v-slot="{ $index }"> |
| | | <el-button type="danger" size="small" link @click="removeCellRow($index)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <div style="margin-top: 16px; text-align: center"> |
| | | <el-button type="primary" @click="submitForm" :loading="submitting">æäº¤</el-button> |
| | | <el-button @click="resetForm">éç½®</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { ref, reactive, getCurrentInstance } from "vue"; |
| | | |
| | | export default { |
| | | name: "PalletOperation", |
| | | setup() { |
| | | const { proxy } = getCurrentInstance(); |
| | | const formRef = ref(null); |
| | | const submitting = ref(false); |
| | | |
| | | const defaultFormData = () => ({ |
| | | action: "", |
| | | palletCode: "", |
| | | lineId: "", |
| | | robotName: "", |
| | | warehouseCode: "", |
| | | grade: 1, |
| | | cells: [], |
| | | }); |
| | | |
| | | const formData = reactive(defaultFormData()); |
| | | |
| | | /// æä½ç±»ååæ´æ¶ï¼ç»çåå§å䏿¡ç©ºè¡ï¼æçæ¸
空å表 |
| | | const onActionChange = (val) => { |
| | | if (val === "ç»ç") { |
| | | formData.cells = [{ sfcCode: "", channel: "" }]; |
| | | } else { |
| | | formData.cells = []; |
| | | } |
| | | }; |
| | | |
| | | /// æ·»å çµè¯è¡ |
| | | const addCellRow = () => { |
| | | formData.cells.push({ sfcCode: "", channel: "" }); |
| | | }; |
| | | |
| | | /// ç§»é¤çµè¯è¡ |
| | | const removeCellRow = (index) => { |
| | | formData.cells.splice(index, 1); |
| | | }; |
| | | |
| | | /// æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | if (!formData.action) return proxy.$message.error("è¯·éæ©æä½ç±»å"); |
| | | if (!formData.palletCode) return proxy.$message.error("请è¾å
¥æçå·"); |
| | | if (!formData.lineId) return proxy.$message.error("请è¾å
¥çº¿ä½ç¼å·"); |
| | | if (!formData.robotName) return proxy.$message.error("请è¾å
¥æºæ¢°æåç§°"); |
| | | if (!formData.warehouseCode) return proxy.$message.error("请è¾å
¥ä»åºç¼å·"); |
| | | |
| | | if (formData.action === "ç»ç") { |
| | | if (formData.cells.length === 0) return proxy.$message.error("ç»çæ¶è³å°éè¦ä¸ä¸ªçµè¯"); |
| | | for (let i = 0; i < formData.cells.length; i++) { |
| | | if (!formData.cells[i].sfcCode) return proxy.$message.error(`第${i + 1}è¡çµè¯ç ä¸è½ä¸ºç©º`); |
| | | if (!formData.cells[i].channel) return proxy.$message.error(`第${i + 1}è¡ééå·ä¸è½ä¸ºç©º`); |
| | | } |
| | | } |
| | | |
| | | const payload = { |
| | | action: formData.action, |
| | | palletCode: formData.palletCode, |
| | | lineId: formData.lineId, |
| | | robotName: formData.robotName, |
| | | warehouseCode: formData.warehouseCode, |
| | | grade: formData.grade, |
| | | cells: formData.action === "ç»ç" ? formData.cells : null, |
| | | }; |
| | | |
| | | submitting.value = true; |
| | | proxy.http |
| | | .post("/api/Task/PalletOperation", payload, "æäº¤ä¸...") |
| | | .then((res) => { |
| | | submitting.value = false; |
| | | if (!res.status) return proxy.$message.error(res.message); |
| | | proxy.$message.success(res.message || "æä½æå"); |
| | | }) |
| | | .catch(() => { |
| | | submitting.value = false; |
| | | }); |
| | | }; |
| | | |
| | | /// é置表å |
| | | const resetForm = () => { |
| | | Object.assign(formData, defaultFormData()); |
| | | }; |
| | | |
| | | return { |
| | | formRef, |
| | | formData, |
| | | submitting, |
| | | onActionChange, |
| | | addCellRow, |
| | | removeCellRow, |
| | | submitForm, |
| | | resetForm, |
| | | }; |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .pallet-operation-page { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .cell-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | </style> |
| | |
| | | public class ApiLogMiddleware |
| | | { |
| | | /// <summary> |
| | | /// ä¸åå
¥ Sys_Log è¡¨çæ¥å£è·¯å¾ï¼åªåæä»¶æ¥å¿ï¼ |
| | | /// </summary> |
| | | private static readonly string[] _apiLogSkipPaths = |
| | | { |
| | | "InOrOutCompleted", |
| | | "SendLocationStatus", |
| | | "RequestOutbound", |
| | | "GetPalletCodeCell", |
| | | "GetOutBoundTrayTask" |
| | | }; |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | private readonly RequestDelegate _next; |
| | |
| | | public ApiLogMiddleware(RequestDelegate next, ILogger<ApiLogMiddleware> logger) |
| | | { |
| | | _next = next; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 夿å½å请æ±è·¯å¾æ¯å¦å¨è·³è¿æ°æ®åºæ¥å¿åè¡¨ä¸ |
| | | /// </summary> |
| | | private static bool IsApiLogSkipPath(string? path) |
| | | { |
| | | if (string.IsNullOrEmpty(path)) return false; |
| | | return _apiLogSkipPaths.Any(skip => path.Contains(skip)); |
| | | } |
| | | |
| | | //todo |
| | |
| | | ms.Position = 0; |
| | | await ms.CopyToAsync(originalBody); |
| | | |
| | | if (!ignoreUrls.Any(x => context.Request.Path.Value?.Contains(x) ?? false)) |
| | | if (!ignoreUrls.Any(x => context.Request.Path.Value?.Contains(x) ?? false) |
| | | && !IsApiLogSkipPath(context.Request.Path.Value)) |
| | | { |
| | | Logger.Add(requestParam, responseParam); |
| | | } |
| | |
| | | using Mapster; |
| | | using MapsterMapper; |
| | | using Microsoft.Extensions.Configuration; |
| | | using SqlSugar; |
| | | using System.DirectoryServices.Protocols; |
| | | using System.Text.Json; |
| | | using WIDESEA_Common.Constants; |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Common.TaskEnum; |
| | | using WIDESEA_Common.WareHouseEnum; |
| | | using Microsoft.Extensions.Logging; |
| | | using Microsoft.Extensions.Options; |
| | | using SqlSugar; |
| | | using WIDESEA_Common.Constants; |
| | | using WIDESEA_Common.TaskEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Core; |
| | | using WIDESEA_Core.Enums; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_DTO.GradingMachine; |
| | | using WIDESEA_DTO.MES; |
| | | using WIDESEA_DTO.Task; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IRecordService; |
| | |
| | | private readonly IMesUploadHelper _mesUploadHelper; |
| | | private readonly ISqlSugarClient _sqlSugarClient; |
| | | private readonly IOptionsMonitor<OutboundTimeConfigOptions> _outboundTimeOptions; |
| | | private readonly ILogger<TaskService> _logger; |
| | | |
| | | public IRepository<Dt_Task> Repository => BaseDal; |
| | | |
| | |
| | | IMesLogService mesLogService, |
| | | IMesUploadHelper mesUploadHelper, |
| | | ISqlSugarClient sqlSugarClient, |
| | | IOptionsMonitor<OutboundTimeConfigOptions> outboundTimeOptions) : base(BaseDal) |
| | | IOptionsMonitor<OutboundTimeConfigOptions> outboundTimeOptions, |
| | | ILogger<TaskService> logger) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _mesUploadHelper = mesUploadHelper; |
| | | _sqlSugarClient = sqlSugarClient; |
| | | _outboundTimeOptions = outboundTimeOptions; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | // Remark 为空æ¶ï¼åéå°å··éé
ç½® |
| | | return DetermineTargetAddress(roadway, addressMap); |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | using Serilog; |
| | | using System.Text.Json; |
| | | using System.Text.Encodings.Web; |
| | | using System.Text.Unicode; |
| | | using WIDESEA_Common.Constants; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Common.TaskEnum; |
| | |
| | | { |
| | | public partial class TaskService |
| | | { |
| | | /// <summary> |
| | | /// JSONåºååé项ï¼ä¸æä¸è½¬ä¹ï¼ |
| | | /// </summary> |
| | | private static readonly JsonSerializerOptions _jsonOptions = new() |
| | | { |
| | | Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) |
| | | }; |
| | | #region åå®¹ææ¥å£ |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | public async Task<WebResponseContent> InOrOutCompletedAsync(GradingMachineInputDto input) |
| | | { |
| | | var log = Log.ForContext("SourceContext", "å容æå®æä¿¡å·"); |
| | | log.Information("[InOrOutCompleted] 请æ±åæ°: {Request}", JsonSerializer.Serialize(input, _jsonOptions)); |
| | | WebResponseContent content = new WebResponseContent(); |
| | | if (string.IsNullOrWhiteSpace(input.LocationCode)) |
| | | { |
| | | return content.Error($"è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | var errResult = content.Error($"è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | log.Warning("[InOrOutCompleted] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | |
| | | try |
| | |
| | | |
| | | int locationStatus; |
| | | if (stockInfo == null) |
| | | return content.Error("WMSæªæ¾å°åºåä¿¡æ¯"); |
| | | { |
| | | var errResult = content.Error("WMSæªæ¾å°åºåä¿¡æ¯"); |
| | | log.Warning("[InOrOutCompleted] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | locationStatus = MapLocationStatus(stockInfo.StockStatus); |
| | | |
| | | int MapLocationStatus(int stockStatus) => stockStatus switch |
| | |
| | | IsNormalProcedure = 1, |
| | | LocationStatus = locationStatus |
| | | }; |
| | | return content.OK(data: outPutDto); |
| | | var result = content.OK(data: outPutDto); |
| | | log.Information("[InOrOutCompleted] ååº: {Response}", JsonSerializer.Serialize(result, _jsonOptions)); |
| | | return result; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | content.Error(ex.Message); |
| | | log.Error(ex, "[InOrOutCompleted] å¼å¸¸"); |
| | | } |
| | | |
| | | return content; |
| | |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> SendLocationStatusAsync(GradingMachineInputDto input) |
| | | { |
| | | var log = Log.ForContext("SourceContext", "å容æç¶ææ´æ°"); |
| | | log.Information("[SendLocationStatus] 请æ±åæ°: {Request}", JsonSerializer.Serialize(input, _jsonOptions)); |
| | | WebResponseContent content = new WebResponseContent(); |
| | | if (string.IsNullOrWhiteSpace(input.LocationCode)) |
| | | { |
| | | return content.Error($"è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | var errResult = content.Error($"è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | log.Warning("[SendLocationStatus] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | |
| | | try |
| | |
| | | { |
| | | content.Error("æ´æ°å¤±è´¥"); |
| | | } |
| | | log.Information("[SendLocationStatus] ååº: {Response}", JsonSerializer.Serialize(content, _jsonOptions)); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | content.Error(ex.Message); |
| | | log.Error(ex, "[SendLocationStatus] å¼å¸¸"); |
| | | } |
| | | return content; |
| | | } |
| | |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> RequestOutboundAsync(GradingMachineInputDto input) |
| | | { |
| | | var log = Log.ForContext("SourceContext", "å容æåºåºè¯·æ±"); |
| | | log.Information("[RequestOutbound] 请æ±åæ°: {Request}", JsonSerializer.Serialize(input, _jsonOptions)); |
| | | WebResponseContent content = new WebResponseContent(); |
| | | if (string.IsNullOrWhiteSpace(input.LocationCode) || string.IsNullOrWhiteSpace(input.PalletCode)) |
| | | { |
| | | return content.Error($"æçå·æè
è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | var errResult = content.Error($"æçå·æè
è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | log.Warning("[RequestOutbound] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | try |
| | | { |
| | | var stock = await _stockInfoService.GetStockInfoAsync(input.PalletCode, input.LocationCode); |
| | | if (stock == null) |
| | | { |
| | | return content.Error("æªæ¾å°å¯¹åºçæç"); |
| | | var errResult = content.Error("æªæ¾å°å¯¹åºçæç"); |
| | | log.Warning("[RequestOutbound] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | |
| | | var taskList = new Dt_Task |
| | |
| | | var httpResponse = _httpClientHelper.Post<WebResponseContent>("http://localhost:9292/api/Task/ReceiveTask", JsonSerializer.Serialize(wmsTaskDtos)).Data; |
| | | if (result && httpResponse != null) |
| | | { |
| | | return content.OK("åºåºè¯·æ±æå"); |
| | | var okResult = content.OK("åºåºè¯·æ±æå"); |
| | | log.Information("[RequestOutbound] ååº: {Response}", JsonSerializer.Serialize(okResult, _jsonOptions)); |
| | | return okResult; |
| | | } |
| | | else |
| | | { |
| | | return content.Error("åºåºè¯·æ±å¤±è´¥"); |
| | | var errResult = content.Error("åºåºè¯·æ±å¤±è´¥"); |
| | | log.Warning("[RequestOutbound] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | content.Error(ex.Message); |
| | | log.Error(ex, "[RequestOutbound] å¼å¸¸"); |
| | | } |
| | | return content; |
| | | } |
| | |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> GetPalletCodeCellAsync(GradingMachineInputDto input) |
| | | { |
| | | var log = Log.ForContext("SourceContext", "å容æçµè¯æ¥è¯¢"); |
| | | log.Information("[GetPalletCodeCell] 请æ±åæ°: {Request}", JsonSerializer.Serialize(input, _jsonOptions)); |
| | | WebResponseContent content = new WebResponseContent(); |
| | | if (string.IsNullOrWhiteSpace(input.PalletCode) || string.IsNullOrWhiteSpace(input.LocationCode)) |
| | | { |
| | | return content.Error($"æçå·æè
è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | var errResult = content.Error($"æçå·æè
è´§ä½ç¼å·ä¸è½ä¸ºç©º"); |
| | | log.Warning("[GetPalletCodeCell] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | try |
| | | { |
| | | var stockInfo = await _stockInfoService.GetStockInfoAsync(input.PalletCode, input.LocationCode); |
| | | if (stockInfo == null) |
| | | { |
| | | return content.Error("æªæ¾å°å¯¹åºçæç"); |
| | | var errResult = content.Error("æªæ¾å°å¯¹åºçæç"); |
| | | log.Warning("[GetPalletCodeCell] ååº: {Response}", JsonSerializer.Serialize(errResult, _jsonOptions)); |
| | | return errResult; |
| | | } |
| | | |
| | | var outPutDtos = new |
| | |
| | | Channel = x.InboundOrderRowNo.ToString() |
| | | }).ToList() |
| | | }; |
| | | return content.OK(data: outPutDtos); |
| | | var result = content.OK(data: outPutDtos); |
| | | log.Information("[GetPalletCodeCell] ååº: {Response}", JsonSerializer.Serialize(result, _jsonOptions)); |
| | | return result; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error(ex, "[GetPalletCodeCell] å¼å¸¸"); |
| | | return content.Error(ex.Message); |
| | | } |
| | | } |
| | |
| | | <ProjectReference Include="..\WIDESEA_ITaskInfoService\WIDESEA_ITaskInfoService.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="Serilog" Version="4.3.1" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| | |
| | | using Newtonsoft.Json.Converters; |
| | | using Newtonsoft.Json.Serialization; |
| | | using Serilog; |
| | | using Serilog.Events; |
| | | using Serilog.Formatting.Json; |
| | | using System.Reflection; |
| | | using System.Text; |
| | |
| | | using WIDESEA_Core.Extensions; |
| | | using WIDESEA_Core.Filter; |
| | | using WIDESEA_Core.Helper; |
| | | |
| | | //using WIDESEA_Core.HostedService; |
| | | using WIDESEA_Core.Middlewares; |
| | | using WIDESEA_WMSServer.BackgroundServices; |
| | |
| | | fileSizeLimitBytes: 10 * 1024 * 1024, |
| | | shared: true |
| | | ) |
| | | // åå®¹ææ¥å£ç¬ç«æ¥å¿æä»¶ |
| | | .WriteTo.Logger(lc => lc |
| | | .Filter.ByIncludingOnly(e => e.Properties.TryGetValue("SourceContext", out var sc) && sc is ScalarValue sv && sv.Value?.ToString() == "å容æå®æä¿¡å·") |
| | | .WriteTo.File( |
| | | "logs/å容æå®æä¿¡å·-.log", |
| | | outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", |
| | | rollingInterval: RollingInterval.Day, |
| | | retainedFileCountLimit: 30, |
| | | fileSizeLimitBytes: 10 * 1024 * 1024, |
| | | shared: true)) |
| | | .WriteTo.Logger(lc => lc |
| | | .Filter.ByIncludingOnly(e => e.Properties.TryGetValue("SourceContext", out var sc) && sc is ScalarValue sv && sv.Value?.ToString() == "å容æç¶ææ´æ°") |
| | | .WriteTo.File( |
| | | "logs/å容æç¶ææ´æ°-.log", |
| | | outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", |
| | | rollingInterval: RollingInterval.Day, |
| | | retainedFileCountLimit: 30, |
| | | fileSizeLimitBytes: 10 * 1024 * 1024, |
| | | shared: true)) |
| | | .WriteTo.Logger(lc => lc |
| | | .Filter.ByIncludingOnly(e => e.Properties.TryGetValue("SourceContext", out var sc) && sc is ScalarValue sv && sv.Value?.ToString() == "å容æåºåºè¯·æ±") |
| | | .WriteTo.File( |
| | | "logs/å容æåºåºè¯·æ±-.log", |
| | | outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", |
| | | rollingInterval: RollingInterval.Day, |
| | | retainedFileCountLimit: 30, |
| | | fileSizeLimitBytes: 10 * 1024 * 1024, |
| | | shared: true)) |
| | | .WriteTo.Logger(lc => lc |
| | | .Filter.ByIncludingOnly(e => e.Properties.TryGetValue("SourceContext", out var sc) && sc is ScalarValue sv && sv.Value?.ToString() == "å容æçµè¯æ¥è¯¢") |
| | | .WriteTo.File( |
| | | "logs/å容æçµè¯æ¥è¯¢-.log", |
| | | outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}", |
| | | rollingInterval: RollingInterval.Day, |
| | | retainedFileCountLimit: 30, |
| | | fileSizeLimitBytes: 10 * 1024 * 1024, |
| | | shared: true)) |
| | | // 6. å¯éï¼è¾åºå°Seqæ¥å¿æå¡å¨ï¼ç»æåæ¥å¿æå¡å¨ï¼ |
| | | // éè¦å®è£
Serilog.Sinks.Seq NuGetå
ï¼å¹¶ç¡®ä¿Seqæå¡å¨ http://localhost:5341 è¿è¡ |
| | | // å¦ä¸éè¦Seqæ¥å¿ï¼æ³¨éæä¸æ¹ä»£ç å³å¯ |
| | |
| | | builder.Services.AddSwaggerSetup(); |
| | | |
| | | builder.Services.AddHttpContextSetup(); |
| | | |
| | | |
| | | builder.Services.AddMvc(options => |
| | | { |
| | |
| | | builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); |
| | | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); |
| | | |
| | | |
| | | var app = builder.Build(); |
| | | |
| | | // 3. é
ç½®ä¸é´ä»¶ |
| | |
| | | app.UseApiLogMiddleware(); |
| | | // todo |
| | | // app.UseRecordAccessLogsMiddle(); |
| | | |
| | | |
| | | DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); |
| | | defaultFilesOptions.DefaultFileNames.Clear(); |