| | |
| | | Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json |
| | | Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json |
| | | /Code/WMS/WIDESEA_WMSClient/.omc |
| | | |
| | | # Local IDE and assistant environment files |
| | | **/.claude/settings.local.json |
| | | **/.vs/**/DocumentLayout.json |
| | | **/.vs/**/DocumentLayout.backup.json |
| | |
| | | using System; |
| | | using OfficeOpenXml.FormulaParsing.Excel.Functions.Numeric; |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.Collections.Generic; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | using WIDESEAWCS_Core.Helper; |
| | | |
| | | namespace WIDESEAWCS_Core.LogHelper |
| | | { |
| | | public class QuartzLogger |
| | | /// <summary> |
| | | /// æ¥å¿ç级æä¸¾ |
| | | /// </summary> |
| | | public enum LogLevel |
| | | { |
| | | static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); |
| | | static string folderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Log\\{DateTime.Now.ToString("yyyy-MM-dd")}"); |
| | | DEBUG = 0, |
| | | INFO = 1, |
| | | WARN = 2, |
| | | ERROR = 3, |
| | | FATAL = 4 |
| | | } |
| | | |
| | | public static void WriteLogToFile(string fileName, string log) |
| | | /// <summary> |
| | | /// æ¥å¿æ¡ç®ï¼å°è£
åæ¡æ¥å¿ç宿´ä¿¡æ¯ |
| | | /// </summary> |
| | | public class LogEntry |
| | | { |
| | | /// <summary> |
| | | /// æ¥å¿æ¶é´ |
| | | /// </summary> |
| | | public DateTime Time { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿ç级 |
| | | /// </summary> |
| | | public LogLevel Level { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿æ¶æ¯å
容 |
| | | /// </summary> |
| | | public string Message { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿æ¥æº/æä»¶å |
| | | /// </summary> |
| | | public string? Source { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å¼å¸¸ä¿¡æ¯ï¼å¯éï¼ |
| | | /// </summary> |
| | | public string? Exception { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ ¼å¼å为æ 忥å¿å符串 |
| | | /// </summary> |
| | | public string ToFormattedString() |
| | | { |
| | | var sb = new StringBuilder(); |
| | | sb.Append($"ã{Time:HH:mm:ss}ãã{Level}ãï¼ã{Message}ã"); |
| | | if (!string.IsNullOrEmpty(Exception)) |
| | | { |
| | | sb.AppendLine(); |
| | | sb.Append($"ãå¼å¸¸ãï¼{Exception}"); |
| | | } |
| | | return sb.ToString(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éååé䏿¥å¿åå
¥å¨ |
| | | /// 使ç¨ç产è
-æ¶è´¹è
模å¼ï¼åå°çº¿ç¨æ¹éåå
¥æä»¶ï¼æé«æ§è½ |
| | | /// </summary> |
| | | public class QueuedLogWriter : IDisposable |
| | | { |
| | | private static readonly Lazy<QueuedLogWriter> _instance = new Lazy<QueuedLogWriter>(() => new QueuedLogWriter()); |
| | | public static QueuedLogWriter Instance => _instance.Value; |
| | | |
| | | private readonly BlockingCollection<LogEntry> _logQueue; |
| | | private readonly CancellationTokenSource _cts; |
| | | private readonly Task _writeTask; |
| | | private readonly ReaderWriterLockSlim _fileLock = new ReaderWriterLockSlim(); |
| | | private readonly string _logFolder; |
| | | private readonly int _maxFileSize; |
| | | private readonly string _fileExt; |
| | | private bool _disposed; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿éååå
¥å¨åä¾ |
| | | /// </summary> |
| | | private QueuedLogWriter() |
| | | { |
| | | _logFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Log{Path.DirectorySeparatorChar}{DateTime.Now:yyyy-MM-dd}"); |
| | | _maxFileSize = 10 * 1024 * 1024; // 10MB |
| | | _fileExt = ".log"; |
| | | _logQueue = new BlockingCollection<LogEntry>(new ConcurrentQueue<LogEntry>()); |
| | | _cts = new CancellationTokenSource(); |
| | | |
| | | // ç¡®ä¿æ¥å¿ç®å½åå¨ |
| | | if (!Directory.Exists(_logFolder)) |
| | | { |
| | | Directory.CreateDirectory(_logFolder); |
| | | } |
| | | |
| | | // å¯å¨åå°åå
¥çº¿ç¨ |
| | | _writeTask = Task.Run(WriteLoop, _cts.Token); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå°åå
¥å¾ªç¯ |
| | | /// </summary> |
| | | private void WriteLoop() |
| | | { |
| | | var batch = new List<LogEntry>(); |
| | | while (!_cts.Token.IsCancellationRequested) |
| | | { |
| | | try |
| | | { |
| | | // æ¹éååºæ¥å¿ï¼æå¤100æ¡æçå¾
500ms |
| | | batch.Clear(); |
| | | if (_logQueue.TryTake(out var entry, 500)) |
| | | { |
| | | batch.Add(entry); |
| | | while (batch.Count < 100 && _logQueue.TryTake(out entry, 50)) |
| | | { |
| | | batch.Add(entry); |
| | | } |
| | | WriteBatch(batch); |
| | | } |
| | | } |
| | | catch (OperationCanceledException) |
| | | { |
| | | break; |
| | | } |
| | | catch (Exception) |
| | | { |
| | | // 忽ç¥åå
¥å¼å¸¸ï¼é²æ¢åå°çº¿ç¨å´©æº |
| | | } |
| | | } |
| | | |
| | | // åæ¶åå°å©ä½æ¥å¿ååº |
| | | while (_logQueue.TryTake(out var remainingEntry, 100)) |
| | | { |
| | | batch.Add(remainingEntry); |
| | | } |
| | | if (batch.Count > 0) |
| | | { |
| | | WriteBatch(batch); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¹éåå
¥æ¥å¿å°æä»¶ |
| | | /// </summary> |
| | | private void WriteBatch(List<LogEntry> entries) |
| | | { |
| | | if (entries.Count == 0) return; |
| | | |
| | | try |
| | | { |
| | | // è¿å
¥åé |
| | | LogWriteLock.EnterWriteLock(); |
| | | |
| | | // 妿æä»¶å¤¹ä¸åå¨ï¼åå建æä»¶å¤¹ |
| | | if (!Directory.Exists(folderPath)) |
| | | _fileLock.EnterWriteLock(); |
| | | foreach (var entry in entries) |
| | | { |
| | | Directory.CreateDirectory(folderPath); |
| | | string fileName = GetLogFileName(entry.Source); |
| | | string filePath = Path.Combine(_logFolder, fileName); |
| | | string content = entry.ToFormattedString() + Environment.NewLine; |
| | | ConsoleHelper.WriteInfoLine(content); |
| | | File.AppendAllText(filePath, content); |
| | | } |
| | | // è·åæ¥å¿æä»¶è·¯å¾ |
| | | string logFilePath = Path.Combine(folderPath, GetLastAccessFileName(fileName)); |
| | | // è·åå½åæ¶é´ |
| | | DateTime now = DateTime.Now; |
| | | // æé æ¥å¿å
容 |
| | | string logContent = $"ã{now}ã{Environment.NewLine}{log}"; |
| | | |
| | | // å°æ¥å¿å
容追å å°æ¥å¿æä»¶ä¸ |
| | | File.AppendAllText(logFilePath, logContent); |
| | | } |
| | | catch { } |
| | | catch (Exception) |
| | | { |
| | | // éé»å¤çï¼é²æ¢æä»¶IOå¼å¸¸å½±åä¸»çº¿ç¨ |
| | | } |
| | | finally |
| | | { |
| | | // éåºåé |
| | | LogWriteLock.ExitWriteLock(); |
| | | _fileLock.ExitWriteLock(); |
| | | } |
| | | } |
| | | static int size = 10 * 1024 * 1024; |
| | | static string ext = ".log"; |
| | | private static string GetLogFilePath(string folderPath, string fileName) |
| | | { |
| | | // è·åæå®æä»¶å¤¹ä¸çæææä»¶ |
| | | var allFiles = new DirectoryInfo(folderPath); |
| | | // è·åç¬¦åæ¡ä»¶çæä»¶ï¼ææä»¶åéåºæå |
| | | var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(fileName.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList(); |
| | | |
| | | FileInfo? file = selectFiles.FirstOrDefault(); |
| | | // 妿æç¬¦åæ¡ä»¶çæä»¶ï¼è¿å第ä¸ä¸ªæä»¶ç宿´è·¯å¾ |
| | | if (file != null) |
| | | /// <summary> |
| | | /// è·åæå建ä¸ä¸ªæ¥å¿æä»¶è·¯å¾ï¼æå¤§å°åæä»¶ï¼ |
| | | /// </summary> |
| | | private string GetLogFileName(string? source) |
| | | { |
| | | string prefix = string.IsNullOrEmpty(source) ? "WCS" : source; |
| | | string searchPattern = $"{prefix}*.log"; |
| | | |
| | | if (!Directory.Exists(_logFolder)) |
| | | { |
| | | return file.FullName; |
| | | Directory.CreateDirectory(_logFolder); |
| | | } |
| | | |
| | | // å¦ææ²¡æç¬¦åæ¡ä»¶çæä»¶ï¼è¿åä¸ä¸ªæ°çæä»¶è·¯å¾ï¼æä»¶å为åæä»¶åå ä¸å½åæ¶é´ |
| | | return Path.Combine(folderPath, $@"{fileName}_{DateTime.Now.ToString("HH-mm-ss")}.log"); |
| | | } |
| | | var files = Directory.GetFiles(_logFolder, searchPattern) |
| | | .Select(f => new FileInfo(f)) |
| | | .Where(f => f.Extension.Equals(_fileExt, StringComparison.OrdinalIgnoreCase)) |
| | | .OrderByDescending(f => f.Name) |
| | | .ToList(); |
| | | |
| | | private static string GetLastAccessFileName(string fileName) |
| | | { |
| | | foreach (var m in GetExistLogFileNames(fileName)) |
| | | // æ¥æ¾æç©ºé´çç°ææä»¶ |
| | | foreach (var file in files) |
| | | { |
| | | FileInfo fileInfo = new FileInfo(m); |
| | | if (fileInfo.Length < size) |
| | | if (file.Length < _maxFileSize) |
| | | { |
| | | return m; |
| | | return file.Name; |
| | | } |
| | | } |
| | | |
| | | // è¿åä¸ä¸ªæ°çé»è®¤å½åæ¶é´çæ¥å¿åç§° |
| | | return $@"{fileName}_{DateTime.Now.ToString("HH-mm-ss")}.log"; |
| | | // åå»ºæ°æä»¶ |
| | | return $"{prefix}_{DateTime.Now:HH-mm-ss}{_fileExt}"; |
| | | } |
| | | |
| | | public static string[] GetExistLogFileNames(string fileName) |
| | | /// <summary> |
| | | /// åå
¥æ¥å¿ï¼çäº§ç«¯ï¼ |
| | | /// </summary> |
| | | public void Enqueue(LogEntry entry) |
| | | { |
| | | string[] fileNames = Directory.GetFiles(folderPath, fileName + "*.log"); |
| | | return fileNames; |
| | | if (_disposed) return; |
| | | _logQueue.Add(entry); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå
¥æ¥å¿çä¾¿æ·æ¹æ³ |
| | | /// </summary> |
| | | public void Log(LogLevel level, string message, string? source = null, string? exception = null) |
| | | { |
| | | if (_disposed) return; |
| | | var entry = new LogEntry |
| | | { |
| | | Time = DateTime.Now, |
| | | Level = level, |
| | | Message = message, |
| | | Source = source, |
| | | Exception = exception |
| | | }; |
| | | _logQueue.Add(entry); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å
³éæ¥å¿åå
¥å¨ |
| | | /// </summary> |
| | | public void Dispose() |
| | | { |
| | | if (_disposed) return; |
| | | _disposed = true; |
| | | _cts.Cancel(); |
| | | try |
| | | { |
| | | _writeTask.Wait(3000); |
| | | } |
| | | catch (AggregateException) { } |
| | | _cts.Dispose(); |
| | | _logQueue.Dispose(); |
| | | _fileLock.Dispose(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éææ¥å¿å·¥å
·ç±»ï¼å
¼å®¹åææ¥å£ï¼ |
| | | /// æä¾å¤ç§æ ¼å¼åæ¹æ³åéåååå
¥ |
| | | /// </summary> |
| | | public class QuartzLogger |
| | | { |
| | | private static readonly QueuedLogWriter _writer = QueuedLogWriter.Instance; |
| | | |
| | | /// <summary> |
| | | /// å
¼å®¹æ§æ¥å£ï¼å°æ¥å¿åå
¥æä»¶ |
| | | /// </summary> |
| | | /// <param name="fileName">æ¥å¿æä»¶åï¼ä½ä¸ºSourceï¼</param> |
| | | /// <param name="log">æ¥å¿å
容</param> |
| | | public static void WriteLogToFile(string fileName, string log) |
| | | { |
| | | _writer.Log(LogLevel.INFO, log, fileName); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå
¥è°è¯æ¥å¿ |
| | | /// </summary> |
| | | public static void Debug(string message, string? source = null) |
| | | { |
| | | _writer.Log(LogLevel.DEBUG, message, source); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå
¥ä¿¡æ¯æ¥å¿ |
| | | /// </summary> |
| | | public static void Info(string message, string? source = null) |
| | | { |
| | | _writer.Log(LogLevel.INFO, message, source); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå
¥è¦åæ¥å¿ |
| | | /// </summary> |
| | | public static void Warn(string message, string? source = null) |
| | | { |
| | | _writer.Log(LogLevel.WARN, message, source); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå
¥é误æ¥å¿ |
| | | /// </summary> |
| | | public static void Error(string message, string? source = null, Exception? exception = null) |
| | | { |
| | | _writer.Log(LogLevel.ERROR, message, source, exception?.ToString()); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// åå
¥è´å½é误æ¥å¿ |
| | | /// </summary> |
| | | public static void Fatal(string message, string? source = null, Exception? exception = null) |
| | | { |
| | | _writer.Log(LogLevel.FATAL, message, source, exception?.ToString()); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä½¿ç¨æå®æ ¼å¼åå
¥æ¥å¿ |
| | | /// </summary> |
| | | /// <param name="format">æ ¼å¼åå符串</param> |
| | | /// <param name="args">æ ¼å¼ååæ°</param> |
| | | public static void WriteFormatted(string format, params object[] args) |
| | | { |
| | | string message = string.Format(format, args); |
| | | _writer.Log(LogLevel.INFO, message); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ç´æ¥åå
¥ä¸ä¸ªæ¥å¿æ¡ç®ï¼æçµæ´»ï¼ |
| | | /// </summary> |
| | | public static void WriteLogEntry(LogEntry entry) |
| | | { |
| | | _writer.Enqueue(entry); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// éæ¾èµæºï¼åºç¨å
³éæ¶è°ç¨ï¼ |
| | | /// </summary> |
| | | public static void Shutdown() |
| | | { |
| | | _writer.Dispose(); |
| | | } |
| | | } |
| | | } |
| | |
| | | <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.3.8" /> |
| | | <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> |
| | | <PackageReference Include="OfficeOpenXml.Core.ExcelPackage" Version="1.0.0" /> |
| | | <PackageReference Include="Serilog" Version="4.3.1" /> |
| | | <PackageReference Include="Serilog.AspNetCore" Version="6.0.0" /> |
| | | <PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" /> |
| | | <PackageReference Include="SkiaSharp" Version="2.88.8" /> |
| | | <PackageReference Include="SqlSugarCore" Version="5.1.4.152" /> |
| | | <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> |
| | |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.Caches; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_QuartzJob.DTO; |
| | | using WIDESEAWCS_QuartzJob.Service; |
| | | |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine("è°åº¦æå¡å¼å¯å¼å¸¸" + ex.ToString()); |
| | | QuartzLogger.Error($"è°åº¦æå¡å¼å¯å¼å¸¸", "QuartzNetExtension", ex); |
| | | } |
| | | } |
| | | else |
| | |
| | | _ => targetDevice.Device |
| | | }; |
| | | WebResponseContent responseContent = await _schedulerCenter.AddScheduleJobAsync(dispatches[i]); |
| | | if (responseContent.Status) ConsoleHelper.WriteSuccessLine(dispatches[i].Name + "è°åº¦æå¡æ·»å æå"); else ConsoleHelper.WriteErrorLine(dispatches[i].Name + "è°åº¦æå¡æ·»å 失败"); |
| | | if (responseContent.Status) |
| | | { |
| | | QuartzLogger.Info($"{dispatches[i].Name}è°åº¦æå¡æ·»å æå", "QuartzNetExtension"); |
| | | ConsoleHelper.WriteSuccessLine(dispatches[i].Name + "è°åº¦æå¡æ·»å æå"); |
| | | } |
| | | else |
| | | { |
| | | QuartzLogger.Error($"{dispatches[i].Name}è°åº¦æå¡æ·»å 失败", "QuartzNetExtension"); |
| | | ConsoleHelper.WriteErrorLine(dispatches[i].Name + "è°åº¦æå¡æ·»å 失败"); |
| | | } |
| | | } |
| | | //await _schedulerCenter.StartScheduleAsync(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine("è°åº¦æå¡å¼å¯å¼å¸¸" + ex.ToString()); |
| | | QuartzLogger.Error($"è°åº¦æå¡å¼å¯å¼å¸¸", "QuartzNetExtension", ex); |
| | | throw; |
| | | } |
| | | } |
| | |
| | | using WIDESEAWCS_QuartzJob.DTO; |
| | | using WIDESEAWCS_QuartzJob.CustomException; |
| | | using Quartz.Impl.Matchers; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | |
| | | namespace WIDESEAWCS_QuartzJob |
| | | { |
| | |
| | | { |
| | | //çå¾
ä»»å¡è¿è¡å®æ |
| | | await this._scheduler.Start(); |
| | | await Console.Out.WriteLineAsync(QuartzJobInfoMessage.StartJobSuccess); |
| | | QuartzLogger.Info(QuartzJobInfoMessage.StartJobSuccess); |
| | | result = WebResponseContent.Instance.OK(QuartzJobInfoMessage.StartJobSuccess); |
| | | return result; |
| | | } |
| | |
| | | /// </summary> |
| | | /// <param name="startPosi">èµ·ç¹/å½åä½ç½®</param> |
| | | /// <returns>è¿åä¸ä¸ä¸ªè·¯ç±èç¹ï¼å¦ææ²¡æåè¿ånull</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi); |
| | | Dt_Router QueryNextRoute(string startPosi); |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®èµ·ç¹/å½åä½ç½®åè·¯ç±ç±»åè·åä¸ä¸ä¸ªå个åèç¹è·¯ç± |
| | |
| | | /// <param name="startPosi">èµ·ç¹/å½åä½ç½®</param> |
| | | /// <param name="routeType">è·¯ç±ç±»å</param> |
| | | /// <returns>è¿åä¸ä¸ä¸ªè·¯ç±èç¹ï¼å¦ææ²¡æåè¿ånull</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi, int routeType); |
| | | Dt_Router QueryNextRoute(string startPosi, int routeType); |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®èµ·ç¹/å½åä½ç½®ãç»ç¹æ¹ååè·¯ç±ç±»åè·åä¸ä¸ä¸ªå个åèç¹è·¯ç±ï¼æºè½éæ©æåç»ç¹çè·¯ç±ï¼ |
| | |
| | | /// <param name="endPosi">ç»ç¹ä½ç½®ï¼ç¨äºæ¹å夿ï¼</param> |
| | | /// <param name="routeType">è·¯ç±ç±»å</param> |
| | | /// <returns>è¿åä¸ä¸ä¸ªè·¯ç±èç¹ï¼ä¼å
è¿åæåç»ç¹çè·¯ç±ï¼å¦ææ²¡æåè¿ånull</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi, string endPosi, int routeType); |
| | | Dt_Router QueryNextRoute(string startPosi, string endPosi, int routeType); |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®èµ·ç¹/å½åä½ç½®ãç»ç¹æ¹ååè·¯ç±ç±»åè·åä¸ä¸ä¸ªå个åèç¹è·¯ç±ï¼æºè½éæ©æåç»ç¹çè·¯ç±ï¼ |
| | |
| | | /// <param name="startPosi">èµ·ç¹/å½åä½ç½®</param> |
| | | /// <param name="endPosi">ç»ç¹ä½ç½®ï¼ç¨äºæ¹å夿ï¼</param> |
| | | /// <returns>è¿åä¸ä¸ä¸ªè·¯ç±èç¹ï¼ä¼å
è¿åæåç»ç¹çè·¯ç±ï¼å¦ææ²¡æåè¿ånull</returns> |
| | | public Dt_Router QueryNextRoute(string startPosi, string endPosi); |
| | | Dt_Router QueryNextRoute(string startPosi, string endPosi); |
| | | |
| | | /// <summary> |
| | | /// è·åä»èµ·ç¹å°ç»ç¹ç宿´è·¯å¾ï¼æé¡ºåºè¿åæ¯ä¸ªåèç¹è·¯ç±ï¼ |
| | |
| | | /// <param name="endPosi">ç»ç¹ä½ç½®</param> |
| | | /// <param name="routeType">è·¯ç±ç±»å</param> |
| | | /// <returns>è¿åæåºçè·¯ç±å表ï¼å¦ææ¾ä¸å°è·¯å¾åè¿å空å表</returns> |
| | | public List<Dt_Router> QueryRoutePath(string startPosi, string endPosi, int routeType); |
| | | List<Dt_Router> QueryRoutePath(string startPosi, string endPosi, int routeType); |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®è®¾å¤ç¼å·è·å对åºçè·¯ç±ç¹ä½ç¼å·(è¾é线ç«å°ç¼å·)ä¿¡æ¯ |
| | |
| | | /// <param name="routerType">è·¯ç±ç±»å</param> |
| | | /// <returns></returns> |
| | | WebResponseContent AddRouters(List<RoutersAddDTO> routersAddDTOs, int routerType); |
| | | |
| | | /// <summary> |
| | | /// æ¸
é¤è·¯ç±ç¼å |
| | | /// </summary> |
| | | void ClearRouterCache(); |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®è®¾å¤ç¼å·æ¥è¯¢ç»è¿è¯¥è®¾å¤çææè·¯ç± |
| | | /// </summary> |
| | | /// <param name="deviceCode">设å¤ç¼å·</param> |
| | | /// <returns>è¿åç»è¿è¯¥è®¾å¤çææè·¯ç±å表</returns> |
| | | List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode); |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ï¼å
¨ç±»åï¼ |
| | | /// </summary> |
| | | /// <param name="startPosi">èµ·ç¹ä½ç½®</param> |
| | | /// <param name="endPosi">ç»ç¹ä½ç½®</param> |
| | | /// <returns>åå¨è¿åtrueï¼ä¸åå¨è¿åfalse</returns> |
| | | bool ExistsRouter(string startPosi, string endPosi); |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦å卿å®ç±»åçè·¯ç± |
| | | /// </summary> |
| | | /// <param name="startPosi">èµ·ç¹ä½ç½®</param> |
| | | /// <param name="endPosi">ç»ç¹ä½ç½®</param> |
| | | /// <param name="routeType">è·¯ç±ç±»å</param> |
| | | /// <returns>åå¨è¿åtrueï¼ä¸åå¨è¿åfalse</returns> |
| | | bool ExistsRouter(string startPosi, string endPosi, int routeType); |
| | | |
| | | /// <summary> |
| | | /// è·åå
¨éè·¯ç±æ°éï¼å
¥å£+åºå£åè®¡ï¼ |
| | | /// </summary> |
| | | /// <returns>è¿åå
¨éè·¯ç±æ°é</returns> |
| | | int GetRouterCount(); |
| | | |
| | | /// <summary> |
| | | /// è·åæå®ç±»åè·¯ç±æ°é |
| | | /// </summary> |
| | | /// <param name="routeType">è·¯ç±ç±»å</param> |
| | | /// <returns>è¿åæå®ç±»åçè·¯ç±æ°é</returns> |
| | | int GetRouterCount(int routeType); |
| | | |
| | | /// <summary> |
| | | /// æ¹éå é¤è·¯ç± |
| | | /// </summary> |
| | | /// <param name="routerIds">è¦å é¤çè·¯ç±IDå表</param> |
| | | /// <returns>è¿åå 餿ä½çç»æ</returns> |
| | | WebResponseContent DeleteRouters(List<long> routerIds); |
| | | } |
| | | } |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.BaseServices; |
| | | using WIDESEAWCS_Core.Enums; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ä»ç¼åè·åæå®ç±»åçå
¨éè·¯ç±æ°æ®ï¼ç¼åä¸å卿¶èªå¨ä»æ°æ®åºå 载并åå
¥ç¼å |
| | | /// </summary> |
| | | /// <param name="routeType">è·¯ç±ç±»åï¼å
¥å£/åºå£ï¼</param> |
| | | /// <returns>该类åçå
¨é¨è·¯ç±å表</returns> |
| | | private List<Dt_Router> GetAllRoutersFromCache(int routeType) |
| | | { |
| | | // æ ¹æ®è·¯ç±ç±»åæå»ºç¼åKeyï¼Inç±»å对åº"In"ï¼Outç±»å对åº"Out" |
| | | string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | // éè¿ç¼åæå¡è·åæ°æ®ï¼ç¼åæªå½ä¸æ¶è°ç¨å·¥åæ¹æ³ä»æ°æ®åºæ¥è¯¢å¹¶åå
¥ç¼å |
| | | return _cacheService.GetOrAdd( |
| | | cacheKey, |
| | | _ => BaseDal.QueryData(x => x.InOutType == routeType) |
| | | ); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¸
餿æè·¯ç±ç¼åï¼å
¥å£ååºå£ç±»åï¼ |
| | | /// </summary> |
| | | public void ClearRouterCache() |
| | | { |
| | | _cacheService.Remove("Router:AllRouters:In"); |
| | | _cacheService.Remove("Router:AllRouters:Out"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®è®¾å¤ç¼å·æ¥è¯¢ç»è¿è¯¥è®¾å¤çææè·¯ç±ï¼åå¹¶å
¥å£+åºå£ç±»åï¼ |
| | | /// </summary> |
| | | /// <param name="deviceCode">设å¤ç¼å·</param> |
| | | /// <returns>ç»è¿è¯¥è®¾å¤çè·¯ç±å表</returns> |
| | | public List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode) |
| | | { |
| | | // ä»ç¼åè·åå
¥å£ç±»åååºå£ç±»åçå
¨éè·¯ç±æ°æ® |
| | | List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | // åå¹¶åçéåºç»è¿æå®è®¾å¤çè·¯ç±ï¼ChildPosiDeviceCodeå¹é
ï¼ |
| | | return inRouters.Concat(outRouters) |
| | | .Where(x => x.ChildPosiDeviceCode == deviceCode) |
| | | .ToList(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ï¼å
¨ç±»åï¼ |
| | | /// </summary> |
| | | public bool ExistsRouter(string startPosi, string endPosi) |
| | | { |
| | | // ä»ç¼åè·åå
¥å£ç±»åååºå£ç±»åçå
¨éè·¯ç±æ°æ®å¹¶åå¹¶ |
| | | List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | var allRouters = inRouters.Concat(outRouters).ToList(); |
| | | // å¨å
å䏿¥æ¾ä»èµ·ç¹å°ç»ç¹çè·¯ç± |
| | | var routes = FindRoutesInMemory(startPosi, endPosi, allRouters, null); |
| | | return routes.Count > 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦å卿å®ç±»åçè·¯ç± |
| | | /// </summary> |
| | | public bool ExistsRouter(string startPosi, string endPosi, int routeType) |
| | | { |
| | | // ä»ç¼åè·åæå®ç±»åçå
¨éè·¯ç±æ°æ® |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); |
| | | // å¨å
å䏿¥æ¾ä»èµ·ç¹å°ç»ç¹çè·¯ç± |
| | | var routes = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); |
| | | return routes.Count > 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åå
¨éè·¯ç±æ°éï¼å
¥å£+åºå£åè®¡ï¼ |
| | | /// </summary> |
| | | public int GetRouterCount() |
| | | { |
| | | // åå«è·åå
¥å£ç±»åååºå£ç±»åçè·¯ç±æ°éå¹¶ç¸å |
| | | int inCount = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()).Count; |
| | | int outCount = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()).Count; |
| | | return inCount + outCount; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå®ç±»åè·¯ç±æ°é |
| | | /// </summary> |
| | | public int GetRouterCount(int routeType) |
| | | { |
| | | // è·åæå®ç±»åçå
¨éè·¯ç±æ°æ®å¹¶è¿åæ°é |
| | | return GetAllRoutersFromCache(routeType).Count; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¹éå 餿å®IDçè·¯ç±ï¼å é¤å忥æ¸
é¤å¯¹åºç±»åçç¼å |
| | | /// </summary> |
| | | /// <param name="routerIds">å¾
å é¤çè·¯ç±IDå表</param> |
| | | /// <returns>è¿åå¤çç»æ</returns> |
| | | public WebResponseContent DeleteRouters(List<long> routerIds) |
| | | { |
| | | WebResponseContent content = new WebResponseContent(); |
| | | try |
| | | { |
| | | if (routerIds == null || routerIds.Count == 0) |
| | | { |
| | | return content = WebResponseContent.Instance.Error("å¾
å é¤çè·¯ç±IDå表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // æ¥è¯¢å¾
å é¤è·¯ç±çç±»åï¼ç¨äºåç»æ¸
é¤ç¼åï¼ |
| | | var routersToDelete = BaseDal.QueryData(x => routerIds.Contains(x.Id)); |
| | | if (routersToDelete.Count == 0) |
| | | { |
| | | return content = WebResponseContent.Instance.Error("æªæ¾å°å¾
å é¤çè·¯ç±"); |
| | | } |
| | | |
| | | // è®°å½æ¶åçç±»åï¼å»éï¼ |
| | | var affectedTypes = routersToDelete.Select(x => x.InOutType).Distinct().ToList(); |
| | | |
| | | // æ§è¡æ¹éå é¤ |
| | | BaseDal.DeleteData(routersToDelete); |
| | | |
| | | // æ¸
é¤åå½±åç±»åçç¼å |
| | | foreach (var routeType in affectedTypes) |
| | | { |
| | | string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | _cacheService.Remove(cacheKey); |
| | | } |
| | | |
| | | content = WebResponseContent.Instance.OK(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | content = WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | return content; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®èµ·ç¹/å½åä½ç½®ãç»ç¹è·åä¸ä¸ä¸ªåèç¹ã |
| | | /// </summary> |
| | | /// <param name="startPosi">èµ·ç¹/å½åä½ç½®ã</param> |
| | |
| | | List<Dt_Router> routers = new List<Dt_Router>(); |
| | | try |
| | | { |
| | | // 䏿¬¡æ§æ¥è¯¢ææè·¯ç±æ°æ®å°å
å |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => true); |
| | | // ä»ç¼åå è½½å
¥å£ç±»åååºå£ç±»åçè·¯ç±æ°æ®å¹¶åå¹¶ï¼å建æ°å表ï¼é¿å
ä¿®æ¹ç¼åå¼ç¨ï¼ |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()) |
| | | .Concat(GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt())) |
| | | .ToList(); |
| | | |
| | | // å¨å
åä¸è¿è¡è·¯å¾æç´¢ |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null); |
| | |
| | | List<Dt_Router> routers = new List<Dt_Router>(); |
| | | try |
| | | { |
| | | // 䏿¬¡æ§æ¥è¯¢æå®ç±»åçææè·¯ç±æ°æ®å°å
å |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); |
| | | // ä»ç¼åå è½½æå®ç±»åçææè·¯ç±æ°æ® |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); |
| | | |
| | | // å¨å
åä¸è¿è¡è·¯å¾æç´¢ |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); |
| | |
| | | { |
| | | try |
| | | { |
| | | // æ¥è¯¢ä»èµ·ç¹åºåçææè·¯ç± |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, |
| | | new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | // ä»ç¼åè·åå
¥å£ç±»åçææè·¯ç±æ°æ®ï¼åºäºèµ·ç¹çéåæIsEndéåºæåº |
| | | List<Dt_Router> routes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | |
| | | // è¿å第ä¸ä¸ªè·¯ç± |
| | | return routes.FirstOrDefault(); |
| | |
| | | { |
| | | try |
| | | { |
| | | // æ¥è¯¢ä»èµ·ç¹åºåçæå®ç±»åè·¯ç± |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, |
| | | new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | // ä»ç¼åè·åæå®ç±»åçææè·¯ç±æ°æ®ï¼çéèµ·ç¹åæIsEndéåºæå |
| | | List<Dt_Router> routes = GetAllRoutersFromCache(routeType) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | |
| | | // è¿å第ä¸ä¸ªè·¯ç± |
| | | return routes.FirstOrDefault(); |
| | |
| | | { |
| | | try |
| | | { |
| | | // æ¥è¯¢ä»èµ·ç¹åºåçæå®ç±»åè·¯ç± |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, |
| | | new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | // ä»ç¼åè·åæå®ç±»åçææè·¯ç±æ°æ®ï¼çéèµ·ç¹åæIsEndéåºæå |
| | | List<Dt_Router> routes = GetAllRoutersFromCache(routeType) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | |
| | | if (routes.Count == 0) |
| | | return null; |
| | |
| | | if (directRoute != null) |
| | | return directRoute; |
| | | |
| | | // å¦ææ²¡æç´æ¥è·¯ç±ï¼ä½¿ç¨æ¥æ¾ç®æ³æ¾å°æåç»ç¹çè·¯ç± |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); |
| | | // å¦ææ²¡æç´æ¥è·¯ç±ï¼ä½¿ç¨ç¼åä¸çå
¨éè·¯ç±æ°æ®æ¥æ¾æåç»ç¹çè·¯ç± |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); |
| | | foreach (var route in routes) |
| | | { |
| | | // æ£æ¥ä»è¿ä¸ªè·¯ç±çä¸ä¸ä¸ªä½ç½®æ¯å¦è½å°è¾¾ç»ç¹ |
| | |
| | | { |
| | | try |
| | | { |
| | | // æ¥è¯¢ä»èµ·ç¹åºåçæå®ç±»åè·¯ç± |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, |
| | | new Dictionary<string, OrderByType> { { nameof(Dt_Router.IsEnd), OrderByType.Desc } }); |
| | | // ä»ç¼åè·åå
¥å£ååºå£ç±»åçææè·¯ç±æ°æ®ï¼çéèµ·ç¹åæIsEndéåºæåº |
| | | List<Dt_Router> inRoutes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRoutes = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | List<Dt_Router> routes = inRoutes.Concat(outRoutes) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | |
| | | if (routes.Count == 0) |
| | | return null; |
| | |
| | | Dt_Router directRoute = routes.FirstOrDefault(x => x.NextPosi == endPosi || x.ChildPosi == endPosi); |
| | | if (directRoute != null) |
| | | return directRoute; |
| | | |
| | | //// å¦ææ²¡æç´æ¥è·¯ç±ï¼ä½¿ç¨æ¥æ¾ç®æ³æ¾å°æåç»ç¹çè·¯ç± |
| | | //List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); |
| | | //foreach (var route in routes) |
| | | //{ |
| | | // // æ£æ¥ä»è¿ä¸ªè·¯ç±çä¸ä¸ä¸ªä½ç½®æ¯å¦è½å°è¾¾ç»ç¹ |
| | | // var pathToEnd = FindRoutesInMemory(route.NextPosi, endPosi, allRouters, routeType); |
| | | // if (pathToEnd.Count > 0) |
| | | // return route; |
| | | //} |
| | | |
| | | // 妿é½ä¸è½å°è¾¾ç»ç¹ï¼è¿å第ä¸ä¸ªè·¯ç± |
| | | return routes.FirstOrDefault(); |
| | |
| | | // è¿åå»éåçä½ç½®å表 |
| | | return positions.GroupBy(x => x).Select(x => x.Key).ToList(); |
| | | } |
| | | catch |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | ConsoleHelper.WriteErrorLine($"RouterService.QueryAllPositions æ¥è¯¢å¤±è´¥: {ex.Message}"); |
| | | } |
| | | finally |
| | | { |
| | | _cacheService.TryAdd($"{RedisPrefix.System}:{RedisName.DevicePositions}:{deviceCode}", positions); |
| | | } |
| | | } |
| | | else |
| | | else |
| | | positions = device; |
| | | // è¿åä½ç½®å表 |
| | | return positions; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åè·¯ç±è¡¨ä¸ææå®æ´çè·¯ç±ä¿¡æ¯(å端è°ç¨å±ç¤ºæ°æ®)ã |
| | | /// </summary> |
| | |
| | | public List<object> GetAllWholeRouters() |
| | | { |
| | | List<object> data = new List<object>(); |
| | | // æ¥è¯¢ææè·¯ç± |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => true); |
| | | // ä»ç¼åå è½½å
¥å£ç±»åååºå£ç±»åçå
¨éè·¯ç±æ°æ®å¹¶åå¹¶ |
| | | List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | List<Dt_Router> allRouters = inRouters.Concat(outRouters).ToList(); |
| | | // æ¥è¯¢ææç»æçè·¯ç±ï¼å¹¶æIdæåº |
| | | List<Dt_Router> dt_Routers = allRouters.Where(x => x.IsEnd).OrderBy(x => x.Id).ToList(); |
| | | |
| | |
| | | |
| | | // æ·»å æ°çè·¯ç±ä¿¡æ¯ |
| | | BaseDal.AddData(routers); |
| | | |
| | | // éæ°æ¥è¯¢å
¨éè·¯ç±ï¼æ¤æ¶æå
嫿°å¢çè·¯ç±ï¼ï¼ååå
¥ç¼å |
| | | List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); |
| | | string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | |
| | | try |
| | | { |
| | | _cacheService.AddOrUpdate(cacheKey, updatedRouters); |
| | | } |
| | | catch |
| | | { |
| | | // ç¼åæ´æ°å¤±è´¥æ¶éé»å¿½ç¥ï¼ä¸æ¬¡æ¥è¯¢ä¼ä»DBèªå¨é建ç¼å |
| | | } |
| | | |
| | | content = WebResponseContent.Instance.OK(); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | return content; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using StackExchange.Redis; |
| | | using System.Linq; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_RedisService.Options; |
| | | |
| | | namespace WIDESEAWCS_RedisService.Connection |
| | |
| | | |
| | | var connection = ConnectionMultiplexer.Connect(configOptions); |
| | | connection.ConnectionFailed += (_, e) => |
| | | ConsoleHelper.WriteErrorLine($"Redisè¿æ¥å¤±è´¥: {e.FailureType}"); |
| | | QuartzLogger.Info($"Redisè¿æ¥å¤±è´¥: {e.FailureType}"); |
| | | connection.ConnectionRestored += (_, e) => |
| | | ConsoleHelper.WriteSuccessLine($"Redisè¿æ¥æ¢å¤: {e.EndPoint}"); |
| | | QuartzLogger.Info($"Redisè¿æ¥æ¢å¤: {e.EndPoint}"); |
| | | |
| | | ConsoleHelper.WriteSuccessLine($"Redisè¿æ¥æå: {string.Join(",", configOptions.EndPoints)}"); |
| | | QuartzLogger.Info($"Redisè¿æ¥æå: {string.Join(",", configOptions.EndPoints)}"); |
| | | return connection; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ConsoleHelper.WriteErrorLine($"Redisè¿æ¥å建失败:{ex.Message}"); |
| | | QuartzLogger.Error($"Redisè¿æ¥å建失败:{ex.Message}",null, ex); |
| | | throw; |
| | | } |
| | | } |
| | |
| | | .ReadFrom.Configuration(context.Configuration) // ä»åºç¨ç¨åºé
ç½®ä¸è¯»åSerilogç¸å
³è®¾ç½®ï¼å¦appsettings.jsonï¼ |
| | | .ReadFrom.Services(services) // ä»ä¾èµæ³¨å
¥å®¹å¨ä¸è¯»åæå¡é
ç½®ï¼å
许å¨é
ç½®ä¸ä½¿ç¨å·²æ³¨åçæå¡ |
| | | .Enrich.FromLogContext() // å¯ç¨æ¥å¿ä¸ä¸æï¼å¯ä»¥å¨æ¥å¿ä¸å
å«å¦è¯·æ±IDãç¨æ·IDç卿屿§ |
| | | |
| | | .Enrich.WithProperty("Application", "WCS") |
| | | // 设置Microsoftå½å空é´çæ¥å¿çº§å«ä¸ºInformation |
| | | // è¿æ ·å¯ä»¥åå°Microsoftæ¡æ¶æ¬èº«çè¯¦ç»æ¥å¿ï¼é¿å
è¿å¤çDebugæ¥å¿ |
| | | .MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
| | |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="Serilog.AspNetCore" Version="8.0.3" /> |
| | | <PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" /> |
| | | <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" /> |
| | | <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> |
| | | <PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" /> |
| | | <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> |
| | | </ItemGroup> |
| | | |
| | |
| | | using MapsterMapper; |
| | | using Microsoft.Extensions.Configuration; |
| | | using Microsoft.Extensions.Logging; |
| | | using Quartz; |
| | | using SqlSugar; |
| | | using System.Text.Json; |
| | |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_DTO.TaskInfo; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | |
| | | private readonly HttpClientHelper _httpClientHelper; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger<CommonConveyorLineNewJob> _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="taskService">任塿å¡</param> |
| | |
| | | /// <param name="routerService">è·¯ç±æå¡</param> |
| | | /// <param name="mapper">对象æ å°å¨</param> |
| | | /// <param name="httpClientHelper">HTTP 客æ·ç«¯å¸®å©ç±»</param> |
| | | public CommonConveyorLineNewJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, HttpClientHelper httpClientHelper) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public CommonConveyorLineNewJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, HttpClientHelper httpClientHelper, ILogger<CommonConveyorLineNewJob> logger) |
| | | { |
| | | _taskService = taskService; |
| | | _taskExecuteDetailService = taskExecuteDetailService; |
| | | _routerService = routerService; |
| | | _mapper = mapper; |
| | | _httpClientHelper = httpClientHelper; |
| | | _logger = logger; |
| | | |
| | | // åå§åè°åº¦å¤çå¨ |
| | | _conveyorLineDispatch = new ConveyorLineDispatchHandler(_taskService, _taskExecuteDetailService, _routerService, _mapper); |
| | | _conveyorLineDispatch = new ConveyorLineDispatchHandler(_taskService, _taskExecuteDetailService, _routerService, _mapper, _logger); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | if (childDeviceCodes == null || childDeviceCodes.Count == 0) |
| | | { |
| | | // 没æå设å¤ï¼ç´æ¥è¿å |
| | | Console.WriteLine($"è¾é线 {conveyorLine.DeviceCode} 没æå设å¤"); |
| | | _logger.LogInformation("è¾é线 {DeviceCode} 没æå设å¤", conveyorLine.DeviceCode); |
| | | QuartzLogger.Info($"è¾é线 {conveyorLine.DeviceCode} 没æå设å¤", conveyorLine.DeviceCode); |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | |
| | | // éå¶å¹¶åæ°ï¼åè®¾å¤æ°éå CPU æ ¸å¿æ°*2 çè¾å°å¼ |
| | | MaxDegreeOfParallelism = Math.Min(childDeviceCodes.Count, Environment.ProcessorCount * 2), |
| | | }; |
| | | |
| | | _logger.LogDebug("Executeï¼å¼å§å¹¶è¡å¤çè¾é线 {DeviceCode}ï¼åè®¾å¤æ°é: {Count}", conveyorLine.DeviceCode, childDeviceCodes.Count); |
| | | QuartzLogger.Debug($"å¼å§å¹¶è¡å¤çè¾é线ï¼åè®¾å¤æ°é: {childDeviceCodes.Count}", conveyorLine.DeviceCode); |
| | | |
| | | // å¹¶è¡å¤çæ¯ä¸ªåè®¾å¤ |
| | | Parallel.For(0, childDeviceCodes.Count, parallelOptions, i => |
| | |
| | | // 妿å½ä»¤ä¸ºç©ºï¼è·³è¿ |
| | | if (command == null) |
| | | { |
| | | _logger.LogDebug("Executeï¼åè®¾å¤ {ChildDeviceCode} å½ä»¤ä¸ºç©ºï¼è·³è¿", childDeviceCode); |
| | | QuartzLogger.Debug($"åè®¾å¤ {childDeviceCode} å½ä»¤ä¸ºç©ºï¼è·³è¿", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | |
| | | { |
| | | // 没æä»»å¡ï¼å WMS 请æ±åºåºæçä»»å¡ |
| | | var position = checkPalletPositions.FirstOrDefault(x => x.Code == childDeviceCode); |
| | | _logger.LogInformation("Executeï¼æ£æ¥æçä½ç½® {ChildDeviceCode}ï¼è¯·æ±WMSåºåºæçä»»å¡", childDeviceCode); |
| | | QuartzLogger.Info($"æ£æ¥æçä½ç½® {childDeviceCode}ï¼è¯·æ±WMSåºåºæçä»»å¡", conveyorLine.DeviceCode); |
| | | |
| | | var responseResult = _httpClientHelper.Post<WebResponseContent>("GetOutBoundTrayTaskAsync", new CreateTaskDto() |
| | | { |
| | | WarehouseId = position.WarehouseId, |
| | |
| | | |
| | | // ========== æ£æ¥ PLC_STB æ å¿ ========== |
| | | // åªæå½ PLC_STB 为 1 æ¶æå¤çä»»å¡ |
| | | if (command.PLC_STB != 1) return; |
| | | if (command.PLC_STB != 1) |
| | | { |
| | | _logger.LogDebug("Executeï¼åè®¾å¤ {ChildDeviceCode} PLC_STB ä¸ä¸º1ï¼è·³è¿", childDeviceCode); |
| | | QuartzLogger.Debug($"åè®¾å¤ {childDeviceCode} PLC_STB ä¸ä¸º1ï¼è·³è¿", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | | // ========== å¤çæ æçæ¡ç çæ
åµ ========== |
| | | // æ æçæ¡ç æ¶ï¼è¯·æ±åºåºä»»å¡ |
| | | if (command.Barcode.IsNullOrEmpty() || command.Barcode.Replace("\0", "") == "") |
| | | { |
| | | _logger.LogDebug("Executeï¼åè®¾å¤ {ChildDeviceCode} æ æçæ¡ç ï¼è¯·æ±åºåºä»»å¡", childDeviceCode); |
| | | QuartzLogger.Debug($"åè®¾å¤ {childDeviceCode} æ æçæ¡ç ï¼è¯·æ±åºåºä»»å¡", conveyorLine.DeviceCode); |
| | | _conveyorLineDispatch.RequestOutbound(conveyorLine, command, childDeviceCode); |
| | | return; |
| | | } |
| | |
| | | Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNo, childDeviceCode); |
| | | if (!task.IsNullOrEmpty()) |
| | | { |
| | | _logger.LogInformation("Executeï¼åè®¾å¤ {ChildDeviceCode} å¤çä»»å¡ {TaskNum}ï¼ç¶æ: {Status}", childDeviceCode, task.TaskNum, task.TaskStatus); |
| | | QuartzLogger.Info($"å¤çä»»å¡ {task.TaskNum}ï¼ç¶æ: {task.TaskStatus}", conveyorLine.DeviceCode); |
| | | // å¤çä»»å¡ç¶æï¼æ ¹æ®ç¶æååå°ä¸åæ¹æ³ï¼ |
| | | ProcessTaskState(conveyorLine, command, task, childDeviceCode); |
| | | return; |
| | |
| | | catch (Exception innerEx) |
| | | { |
| | | // è®°å½å¼å¸¸ï¼ä½ä¸å½±åå
¶ä»å设å¤çå¤ç |
| | | Console.Error.WriteLine($"{DateTime.UtcNow:O} [{childDeviceCode}] CorrelationId={correlationId} {innerEx}"); |
| | | _logger.LogError(innerEx, "Executeï¼åè®¾å¤ {ChildDeviceCode} å¤çå¼å¸¸ï¼CorrelationId: {CorrelationId}", childDeviceCode, correlationId); |
| | | QuartzLogger.Error($"å设å¤å¤çå¼å¸¸: {innerEx.Message}", conveyorLine.DeviceCode, innerEx); |
| | | } |
| | | }); |
| | | } |
| | |
| | | catch (Exception ex) |
| | | { |
| | | // è®°å½æ´ä½å¼å¸¸ |
| | | Console.Error.WriteLine(ex); |
| | | _logger.LogError(ex, "Executeï¼è¾é线 {DeviceCode} æ§è¡å¼å¸¸", ex.Message); |
| | | QuartzLogger.Error($"è¾é线æ§è¡å¼å¸¸: {ex.Message}", "CommonConveyorLineNewJob", ex); |
| | | } |
| | | return Task.CompletedTask; |
| | | } |
| | |
| | | using MapsterMapper; |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | |
| | | private readonly IMapper _mapper; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// è¾é线任å¡è¿æ»¤å¨ |
| | | /// </summary> |
| | | /// <remarks> |
| | |
| | | /// <param name="taskExecuteDetailService">任塿§è¡æç»æå¡</param> |
| | | /// <param name="routerService">è·¯ç±æå¡</param> |
| | | /// <param name="mapper">对象æ å°å¨</param> |
| | | public ConveyorLineDispatchHandler(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public ConveyorLineDispatchHandler(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, ILogger logger) |
| | | { |
| | | _taskService = taskService; |
| | | _taskExecuteDetailService = taskExecuteDetailService; |
| | | _routerService = routerService; |
| | | _mapper = mapper; |
| | | _logger = logger; |
| | | |
| | | // åå§åä»»å¡è¿æ»¤å¨åç®æ å°åéæ©å¨ |
| | | _taskFilter = new ConveyorLineTaskFilter(taskService); |
| | | _targetAddressSelector = new ConveyorLineTargetAddressSelector(); |
| | | _taskFilter = new ConveyorLineTaskFilter(taskService, _logger); |
| | | _targetAddressSelector = new ConveyorLineTargetAddressSelector(_logger); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | // æ¸
é¤ä»»å¡å·ï¼è¡¨ç¤ºå½åç©ºé² |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, 0, childDeviceCode); |
| | | _logger.LogDebug("HeartBeatï¼åè®¾å¤ {ChildDeviceCode} å¿è·³", childDeviceCode); |
| | | QuartzLogger.Debug($"HeartBeatï¼åè®¾å¤ {childDeviceCode} å¿è·³", conveyorLine.DeviceCode); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <param name="childDeviceCode">å设å¤ç¼ç </param> |
| | | public void RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode) |
| | | { |
| | | _logger.LogInformation("RequestInboundï¼åè®¾å¤ {ChildDeviceCode} 请æ±å
¥åº", childDeviceCode); |
| | | QuartzLogger.Info($"请æ±å
¥åºï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | |
| | | // å WMS è¯·æ±æ°ä»»å¡ï¼åºäºæ¡ç ï¼ |
| | | if (_taskFilter.RequestWmsTask(command.Barcode, childDeviceCode)) |
| | | { |
| | |
| | | |
| | | // æ´æ°ä»»å¡ç¶æå°ä¸ä¸é¶æ®µ |
| | | _taskService.UpdateTaskStatusToNext(task); |
| | | |
| | | _logger.LogInformation("RequestInboundï¼å
¥åºä»»å¡å·²ä¸åï¼ä»»å¡å·: {TaskNum}ï¼å设å¤: {ChildDeviceCode}", task.TaskNum, childDeviceCode); |
| | | QuartzLogger.Info($"å
¥åºä»»å¡å·²ä¸åï¼ä»»å¡å·: {task.TaskNum}ï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | } |
| | |
| | | Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode); |
| | | if (task == null) |
| | | { |
| | | _logger.LogDebug("RequestInNextAddressï¼ä»»å¡ {TaskNo} ä¸åå¨", command.TaskNo); |
| | | QuartzLogger.Debug($"RequestInNextAddressï¼ä»»å¡ {command.TaskNo} ä¸åå¨", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | | _logger.LogInformation("RequestInNextAddressï¼å
¥åºä¸ä¸å°åï¼ä»»å¡å·: {TaskNum}ï¼å设å¤: {ChildDeviceCode}", task.TaskNum, childDeviceCode); |
| | | QuartzLogger.Info($"RequestInNextAddressï¼å
¥åºä¸ä¸å°åï¼ä»»å¡å·: {task.TaskNum}ï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | |
| | | // 妿䏿¯ç©ºæçä»»å¡ï¼å¤çç®æ å°åï¼ä¸æææº/ææéæºäº¤äºï¼ |
| | | if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty) |
| | |
| | | |
| | | // æ´æ°ä»»å¡ç¶æå°ä¸ä¸é¶æ®µï¼é常æ¯å®æï¼ |
| | | WebResponseContent content = _taskService.UpdateTaskStatusToNext(task); |
| | | Console.Out.WriteLine(content.Serialize()); |
| | | |
| | | _logger.LogInformation("ConveyorLineInFinishï¼å
¥åºå®æï¼ä»»å¡å·: {TaskNum}ï¼å设å¤: {ChildDeviceCode}", task.TaskNum, childDeviceCode); |
| | | QuartzLogger.Info($"å
¥åºå®æï¼ä»»å¡å·: {task.TaskNum}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | // æ´æ°ä»»å¡ç¶æ |
| | | _taskService.UpdateTaskStatusToNext(task); |
| | | |
| | | _logger.LogInformation("RequestOutboundï¼åºåºä»»å¡å·²ä¸åï¼ä»»å¡å·: {TaskNum}ï¼å设å¤: {ChildDeviceCode}", task.TaskNum, childDeviceCode); |
| | | QuartzLogger.Info($"åºåºä»»å¡å·²ä¸åï¼ä»»å¡å·: {task.TaskNum}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | |
| | |
| | | Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode); |
| | | if (task == null) |
| | | { |
| | | _logger.LogDebug("RequestOutNextAddressï¼ä»»å¡ {TaskNo} ä¸åå¨", command.TaskNo); |
| | | QuartzLogger.Debug($"RequestOutNextAddressï¼ä»»å¡ {command.TaskNo} ä¸åå¨", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | | _logger.LogInformation("RequestOutNextAddressï¼åºåºä¸ä¸å°åï¼ä»»å¡å·: {TaskNum}ï¼å设å¤: {ChildDeviceCode}", task.TaskNum, childDeviceCode); |
| | | QuartzLogger.Info($"RequestOutNextAddressï¼åºåºä¸ä¸å°åï¼ä»»å¡å·: {task.TaskNum}ï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | |
| | | // 妿䏿¯ç©ºæçä»»å¡ï¼å¤çç®æ å°å |
| | | if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty) |
| | |
| | | |
| | | // æ´æ°ä»»å¡ç¶æå°ä¸ä¸é¶æ®µï¼é常æ¯å®æï¼ |
| | | WebResponseContent content = _taskService.UpdateTaskStatusToNext(task); |
| | | Console.Out.WriteLine(content.Serialize()); |
| | | |
| | | _logger.LogInformation("ConveyorLineOutFinishï¼åºåºå®æï¼ä»»å¡å·: {TaskNum}ï¼å设å¤: {ChildDeviceCode}", task.TaskNum, childDeviceCode); |
| | | QuartzLogger.Info($"åºåºå®æï¼ä»»å¡å·: {task.TaskNum}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_QuartzJob; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | |
| | | private static readonly List<string> PinMachineCodes = new List<string> { "10190", "20100" }; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public ConveyorLineTargetAddressSelector(ILogger logger) |
| | | { |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å¤çå
¥åºåºæ¯çä¸ä¸å°åè¯·æ± |
| | | /// </summary> |
| | | /// <remarks> |
| | |
| | | /// <param name="childDeviceCode">å½åå设å¤ç¼ç </param> |
| | | public void HandleInboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode) |
| | | { |
| | | _logger.LogDebug("HandleInboundNextAddressï¼å
¥åºä¸ä¸å°åï¼å设å¤: {ChildDeviceCode}ï¼ç®æ å°å: {NextAddress}", childDeviceCode, nextAddress); |
| | | QuartzLogger.Debug($"HandleInboundNextAddressï¼å
¥åºä¸ä¸å°åï¼å设å¤: {childDeviceCode}ï¼ç®æ å°å: {nextAddress}", conveyorLine.DeviceCode); |
| | | // è°ç¨éç¨å¤çæ¹æ³ï¼isUpper = true 表示å¤çä¸å± |
| | | HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, isUpper: true); |
| | | } |
| | |
| | | /// <param name="childDeviceCode">å½åå设å¤ç¼ç </param> |
| | | public void HandleOutboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode) |
| | | { |
| | | _logger.LogDebug("HandleOutboundNextAddressï¼åºåºä¸ä¸å°åï¼å设å¤: {ChildDeviceCode}ï¼ç®æ å°å: {NextAddress}", childDeviceCode, nextAddress); |
| | | QuartzLogger.Debug($"HandleOutboundNextAddressï¼åºåºä¸ä¸å°åï¼å设å¤: {childDeviceCode}ï¼ç®æ å°å: {nextAddress}", conveyorLine.DeviceCode); |
| | | // è°ç¨éç¨å¤çæ¹æ³ï¼isUpper = false 表示å¤çä¸å± |
| | | HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, isUpper: false); |
| | | } |
| | |
| | | ConstraintMachine? constraint = devices.OfType<ConstraintMachine>().FirstOrDefault(d => d.DeviceName == ConstraintMachineName); |
| | | if (constraint == null) |
| | | { |
| | | _logger.LogDebug("HandleDeviceRequestï¼æªæ¾å°æææºè®¾å¤"); |
| | | QuartzLogger.Debug("HandleDeviceRequestï¼æªæ¾å°æææºè®¾å¤", conveyorLine.DeviceCode); |
| | | // æªæ¾å°æææºè®¾å¤ï¼ç´æ¥è¿å |
| | | return; |
| | | } |
| | |
| | | { |
| | | constraint.SetValue(ConstraintMachineDBName.ConstraintTrayOutputReadyLower, outputReq ? 1 : 0); |
| | | } |
| | | }); |
| | | }, |
| | | "æææº"); |
| | | } |
| | | else if (PinMachineCodes.Contains(nextAddress)) |
| | | { |
| | |
| | | PinMachine? pinMachine = devices.OfType<PinMachine>().FirstOrDefault(d => d.DeviceName == PinMachineName); |
| | | if (pinMachine == null) |
| | | { |
| | | _logger.LogDebug("HandleDeviceRequestï¼æªæ¾å°ææéæºè®¾å¤"); |
| | | QuartzLogger.Debug("HandleDeviceRequestï¼æªæ¾å°ææéæºè®¾å¤", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | |
| | | { |
| | | pinMachine.SetValue(PinMachineDBName.PlugPinTrayOutputReadyLower, outputReq ? 1 : 0); |
| | | } |
| | | }); |
| | | }, |
| | | "ææéæº"); |
| | | } |
| | | } |
| | | |
| | |
| | | /// <param name="getMaterialRequest">è·åç©æè¯·æ±ç¶æçå§æ</param> |
| | | /// <param name="getOutputRequest">è·ååºæè¯·æ±ç¶æçå§æ</param> |
| | | /// <param name="setOutputReady">设置è¾åºå°±ç»ªæ å¿çå§æ</param> |
| | | private static void ProcessDeviceRequest( |
| | | /// <param name="deviceType">设å¤ç±»åæè¿°</param> |
| | | private void ProcessDeviceRequest( |
| | | CommonConveyorLine conveyorLine, |
| | | string childDeviceCode, |
| | | Func<bool> getMaterialRequest, |
| | | Func<bool> getOutputRequest, |
| | | Action<bool> setOutputReady) |
| | | Action<bool> setOutputReady, |
| | | string deviceType) |
| | | { |
| | | // è·åç©æè¯·æ±ç¶æ |
| | | bool materialReq = getMaterialRequest(); |
| | | |
| | | // è·ååºæè¯·æ±ç¶æ |
| | | bool outputReq = getOutputRequest(); |
| | | |
| | | _logger.LogDebug("ProcessDeviceRequestï¼{DeviceType}ï¼å设å¤: {ChildDeviceCode}ï¼ç©æè¯·æ±: {MaterialReq}ï¼åºæè¯·æ±: {OutputReq}", |
| | | deviceType, childDeviceCode, materialReq, outputReq); |
| | | QuartzLogger.Debug($"ProcessDeviceRequestï¼{deviceType}ï¼å设å¤: {childDeviceCode}ï¼ç©æè¯·æ±: {materialReq}ï¼åºæè¯·æ±: {outputReq}", conveyorLine.DeviceCode); |
| | | |
| | | // å¦æè®¾å¤éè¦ç©æ |
| | | if (materialReq) |
| | |
| | | |
| | | // åå¤ ACK ç¡®è®¤ä¿¡å· |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode); |
| | | |
| | | _logger.LogInformation("ProcessDeviceRequestï¼{DeviceType} éè¦ç©æï¼å·²è®¾ç½®ç®æ å°ååACK", deviceType); |
| | | QuartzLogger.Info($"ProcessDeviceRequestï¼{deviceType} éè¦ç©æï¼å·²è®¾ç½®ç®æ å°ååACK", conveyorLine.DeviceCode); |
| | | } |
| | | else |
| | | { |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | |
| | |
| | | private readonly ITaskService _taskService; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="taskService">任塿å¡å®ä¾</param> |
| | | public ConveyorLineTaskFilter(ITaskService taskService) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public ConveyorLineTaskFilter(ITaskService taskService, ILogger logger) |
| | | { |
| | | _taskService = taskService; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <returns>å¾
å¤ççä»»å¡å¯¹è±¡ï¼å¦ææ²¡æåè¿å null</returns> |
| | | public Dt_Task? QueryPendingTask(string deviceCode, string childDeviceCode) |
| | | { |
| | | return _taskService.QueryConveyorLineTask(deviceCode, childDeviceCode); |
| | | var task = _taskService.QueryConveyorLineTask(deviceCode, childDeviceCode); |
| | | _logger.LogDebug("QueryPendingTaskï¼è®¾å¤ {DeviceCode}ï¼åè®¾å¤ {ChildDeviceCode}ï¼æ¥è¯¢ç»æ: {TaskNum}", deviceCode, childDeviceCode, task?.TaskNum); |
| | | QuartzLogger.Debug($"QueryPendingTaskï¼è®¾å¤ {deviceCode}ï¼åè®¾å¤ {childDeviceCode}ï¼æ¥è¯¢ç»æ: {task?.TaskNum}", deviceCode); |
| | | return task; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <returns>æ§è¡ä¸çä»»å¡å¯¹è±¡ï¼å¦ææ²¡æåè¿å null</returns> |
| | | public Dt_Task? QueryExecutingTask(int taskNo, string childDeviceCode) |
| | | { |
| | | return _taskService.QueryExecutingConveyorLineTask(taskNo, childDeviceCode); |
| | | var task = _taskService.QueryExecutingConveyorLineTask(taskNo, childDeviceCode); |
| | | _logger.LogDebug("QueryExecutingTaskï¼ä»»å¡å· {TaskNo}ï¼åè®¾å¤ {ChildDeviceCode}ï¼æ¥è¯¢ç»æ: {Found}", taskNo, childDeviceCode, task != null); |
| | | QuartzLogger.Debug($"QueryExecutingTaskï¼ä»»å¡å· {taskNo}ï¼åè®¾å¤ {childDeviceCode}ï¼æ¥è¯¢ç»æ: {(task != null)}", childDeviceCode); |
| | | return task; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <returns>è¯·æ±æ¯å¦æå</returns> |
| | | public bool RequestWmsTask(string barcode, string childDeviceCode) |
| | | { |
| | | return _taskService.RequestWMSTask(barcode, childDeviceCode).Status; |
| | | _logger.LogInformation("RequestWmsTaskï¼åWMS请æ±ä»»å¡ï¼æ¡ç : {Barcode}ï¼å设å¤: {ChildDeviceCode}", barcode, childDeviceCode); |
| | | QuartzLogger.Info($"åWMS请æ±ä»»å¡ï¼æ¡ç : {barcode}", childDeviceCode); |
| | | var result = _taskService.RequestWMSTask(barcode, childDeviceCode); |
| | | return result.Status; |
| | | } |
| | | } |
| | | } |
| | |
| | | using System.Collections.Concurrent; |
| | | using System.Net.Sockets; |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_Tasks.SocketServer; |
| | |
| | | /// æºæ¢°æç¶æç®¡çå¨ï¼ç¨äºè¯»å设å¤ç¶æ |
| | | /// </summary> |
| | | private readonly RobotStateManager _stateManager; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// è·è¸ªå·²å¯å¨æ¶æ¯å¤çç客æ·ç«¯ï¼é¿å
éå¤å¯å¨ |
| | |
| | | /// </summary> |
| | | /// <param name="tcpSocket">TCP Socket æå¡å¨å®ä¾</param> |
| | | /// <param name="stateManager">ç¶æç®¡çå¨å®ä¾</param> |
| | | public RobotClientManager(TcpSocketServer tcpSocket, RobotStateManager stateManager) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public RobotClientManager(TcpSocketServer tcpSocket, RobotStateManager stateManager, ILogger logger) |
| | | { |
| | | _tcpSocket = tcpSocket; |
| | | _stateManager = stateManager; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | // æ¸
ç该客æ·ç«¯ç HandleClientAsync å¯å¨æ å¿ |
| | | // ä»¥ä¾¿ä¸æ¬¡éè¿æ¶å¯ä»¥éæ°å¯å¨å¤ç |
| | | _handleClientStarted.TryRemove(ipAddress, out _); |
| | | _logger.LogDebug("客æ·ç«¯æªè¿æ¥ï¼IP: {IpAddress}", ipAddress); |
| | | QuartzLogger.Debug($"客æ·ç«¯æªè¿æ¥ï¼IP: {ipAddress}", robotCrane.DeviceName); |
| | | return false; |
| | | } |
| | | |
| | |
| | | { |
| | | // ç»å®å®¢æ·ç«¯æå¼è¿æ¥çäºä»¶å¤ç |
| | | _tcpSocket.RobotReceived += OnRobotReceived; |
| | | // è®°å½æ¥å¿ï¼æ³¨æï¼æ¥å¿å
容为"客æ·ç«¯å·²æå¼è¿æ¥"ï¼å¯è½æ¯éççå 使æ¬ï¼ |
| | | QuartzLogger.Error($"客æ·ç«¯å·²æå¼è¿æ¥", robotCrane.DeviceName); |
| | | // è®°å½æ¥å¿ï¼äºä»¶è®¢é
æå |
| | | _logger.LogInformation("æºæ¢°æTCPæ¶æ¯äºä»¶å·²è®¢é
ï¼è®¾å¤: {DeviceName}", robotCrane.DeviceName); |
| | | QuartzLogger.Info($"æºæ¢°æTCPæ¶æ¯äºä»¶å·²è®¢é
", robotCrane.DeviceName); |
| | | } |
| | | |
| | | // ä» TCP æå¡å¨ç客æ·ç«¯åå
¸ä¸è·å TcpClient 对象 |
| | |
| | | { |
| | | // ç§»é¤å¯å¨æ å¿ï¼è¿å false 表示客æ·ç«¯ä¸å¯ç¨ |
| | | _handleClientStarted.TryRemove(ipAddress, out _); |
| | | _logger.LogWarning("è·åTcpClient失败ï¼IP: {IpAddress}", ipAddress); |
| | | QuartzLogger.Warn($"è·åTcpClient失败ï¼IP: {ipAddress}", robotCrane.DeviceName); |
| | | return false; |
| | | } |
| | | |
| | |
| | | // 妿尿ªå¯å¨ï¼åå¯å¨æ¶æ¯å¤çå¾ªç¯ |
| | | if (!alreadyStarted) |
| | | { |
| | | // è®°å½æ¥å¿ |
| | | QuartzLogger.Error($"å¯å¨å®¢æ·ç«¯æ¶æ¯å¤ç", robotCrane.DeviceName); |
| | | // è®°å½æ¥å¿ï¼å¯å¨æ¶æ¯å¤ç |
| | | _logger.LogInformation("å¯å¨å®¢æ·ç«¯æ¶æ¯å¤çï¼IP: {IpAddress}", ipAddress); |
| | | QuartzLogger.Info($"å¯å¨å®¢æ·ç«¯æ¶æ¯å¤ç", robotCrane.DeviceName); |
| | | |
| | | // è·åææ°çç¶æå¯¹è±¡ |
| | | var latestStateForSubscribe = _stateManager.GetState(ipAddress); |
| | |
| | | if (t.IsFaulted) |
| | | { |
| | | // è®°å½é误æ¥å¿ |
| | | QuartzLogger.Error($"çå¬å®¢æ·ç«¯æ¶æ¯äºä»¶å¼å¸¸", robotCrane.DeviceName); |
| | | Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] HandleClientAsync error: {t.Exception?.GetBaseException().Message}"); |
| | | _logger.LogError(t.Exception, "çå¬å®¢æ·ç«¯æ¶æ¯äºä»¶å¼å¸¸ï¼IP: {IpAddress}", ipAddress); |
| | | QuartzLogger.Error($"çå¬å®¢æ·ç«¯æ¶æ¯äºä»¶å¼å¸¸", robotCrane.DeviceName, t.Exception); |
| | | // åçé误æ¶ï¼ç§»é¤å¯å¨æ å¿ï¼å
è®¸ä¸æ¬¡éè¯ |
| | | _handleClientStarted.TryRemove(ipAddress, out _); |
| | | } |
| | |
| | | // ç§»é¤è¯¥å®¢æ·ç«¯ç HandleClientAsync å¯å¨æ å¿ |
| | | _handleClientStarted.TryRemove(clientId, out _); |
| | | |
| | | // è®°å½æ¥å¿ï¼å®¢æ·ç«¯æå¼è¿æ¥ |
| | | _logger.LogInformation("客æ·ç«¯æå¼è¿æ¥ï¼IP: {ClientId}", clientId); |
| | | QuartzLogger.Info($"客æ·ç«¯æå¼è¿æ¥", clientId); |
| | | |
| | | // é置该客æ·ç«¯çç¶æä¿¡æ¯ |
| | | _stateManager.TryUpdateStateSafely(clientId, state => |
| | | { |
| | |
| | | ILogger<RobotJob> logger) |
| | | { |
| | | // åå§åç¶æç®¡çå¨ï¼ä¼ å
¥ç¼åæå¡ |
| | | _stateManager = new RobotStateManager(cache); |
| | | _stateManager = new RobotStateManager(cache, _logger); |
| | | _logger = logger; |
| | | |
| | | // å建 Socket ç½å
³ï¼å°è£
TcpSocketServer çè®¿é® |
| | |
| | | ISocketClientGateway socketGateway = new SocketClientGateway(tcpSocket); |
| | | |
| | | // åå§åä»»å¡å¤çå¨ |
| | | _taskProcessor = new RobotTaskProcessor(socketGateway, _stateManager, robotTaskService, taskService, httpClientHelper); |
| | | _taskProcessor = new RobotTaskProcessor(socketGateway, _stateManager, robotTaskService, taskService, httpClientHelper, _logger); |
| | | |
| | | // åå§å客æ·ç«¯ç®¡çå¨ |
| | | _clientManager = new RobotClientManager(tcpSocket, _stateManager); |
| | | _clientManager = new RobotClientManager(tcpSocket, _stateManager, _logger); |
| | | |
| | | // åå§åå½ä»¤å¤çå¨ |
| | | // ç®åå½ä»¤å¤çå¨ï¼å¤çç¶ææ´æ°çç®åå½ä»¤ |
| | |
| | | _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, cache, simpleCommandHandler, prefixCommandHandler, logger); |
| | | |
| | | // åå§å工使µç¼æå¨ |
| | | _workflowOrchestrator = new RobotWorkflowOrchestrator(_stateManager, _clientManager, _taskProcessor, robotTaskService); |
| | | _workflowOrchestrator = new RobotWorkflowOrchestrator(_stateManager, _clientManager, _taskProcessor, robotTaskService, _logger); |
| | | |
| | | // 订é
客æ·ç«¯æå¼è¿æ¥äºä»¶ |
| | | _clientManager.OnClientDisconnected += OnClientDisconnected; |
| | |
| | | { |
| | | // è®°å½æ¥æ¶å°çæ¶æ¯æ¥å¿ |
| | | _logger.LogInformation($"æ¥æ¶å°å®¢æ·ç«¯ã{state.RobotCrane.DeviceName}ãåéæ¶æ¯ã{message}ã"); |
| | | QuartzLogger.Error($"æ¥æ¶å°å®¢æ·ç«¯æ¶æ¯ã{message}ã", state.RobotCrane.DeviceName); |
| | | QuartzLogger.Info($"æ¥æ¶å°å®¢æ·ç«¯æ¶æ¯ã{message}ã", state.RobotCrane.DeviceName); |
| | | |
| | | // æå»ºç¼åé®ï¼æ£æ¥ Redis 䏿¯å¦åå¨è¯¥è®¾å¤çç¶æ |
| | | var cacheKey = $"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}"; |
| | |
| | | // å¤çæååï¼å°åæ¶æ¯ååå°å®¢æ·ç«¯ï¼ä¿æåæè¡ä¸ºï¼ |
| | | await _socketClientGateway.SendMessageAsync(client, message); |
| | | _logger.LogInformation($"åéæ¶æ¯ã{message}ã"); |
| | | QuartzLogger.Error($"åéæ¶æ¯ï¼ã{message}ã", state.RobotCrane.DeviceName); |
| | | QuartzLogger.Info($"åéæ¶æ¯ï¼ã{message}ã", state.RobotCrane.DeviceName); |
| | | |
| | | // å®å
¨æ´æ°ç¶æå° Redis |
| | | _stateManager.TryUpdateStateSafely(activeState.IPAddress, activeState); |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Newtonsoft.Json; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Core.Caches; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_QuartzJob; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | |
| | | private readonly ICacheService _cache; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="cache">ç¼åæå¡å®ä¾ï¼é常为 HybridCacheServiceï¼</param> |
| | | public RobotStateManager(ICacheService cache) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public RobotStateManager(ICacheService cache, ILogger logger) |
| | | { |
| | | _cache = cache; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | newState.Version = DateTime.UtcNow.Ticks; |
| | | // ç´æ¥æ·»å å°ç¼å |
| | | _cache.AddObject(cacheKey, newState); |
| | | _logger.LogDebug("TryUpdateStateSafelyï¼å建æ°ç¶æï¼IP: {IpAddress}", ipAddress); |
| | | QuartzLogger.Debug($"å建æ°ç¶æï¼IP: {ipAddress}", ipAddress); |
| | | return true; |
| | | } |
| | | |
| | |
| | | newState.Version = DateTime.UtcNow.Ticks; |
| | | |
| | | // å°è¯å®å
¨æ´æ°ï¼å¦æçæ¬å²çªåè¿å false |
| | | return _cache.TrySafeUpdate( |
| | | bool success = _cache.TrySafeUpdate( |
| | | cacheKey, |
| | | newState, |
| | | expectedVersion, |
| | | s => s.Version |
| | | ); |
| | | |
| | | if (!success) |
| | | { |
| | | _logger.LogWarning("TryUpdateStateSafelyï¼çæ¬å²çªï¼æ´æ°å¤±è´¥ï¼IP: {IpAddress}ï¼ææçæ¬: {ExpectedVersion}", ipAddress, expectedVersion); |
| | | QuartzLogger.Warn($"çæ¬å²çªï¼æ´æ°å¤±è´¥ï¼IP: {ipAddress}", ipAddress); |
| | | } |
| | | |
| | | return success; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Newtonsoft.Json; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common; |
| | |
| | | private readonly HttpClientHelper _httpClientHelper; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="socketClientGateway">Socket ç½å
³</param> |
| | |
| | | /// <param name="robotTaskService">æºå¨äººä»»å¡æå¡</param> |
| | | /// <param name="taskService">éç¨ä»»å¡æå¡</param> |
| | | /// <param name="httpClientHelper">HTTP 客æ·ç«¯å¸®å©ç±»</param> |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public RobotTaskProcessor( |
| | | ISocketClientGateway socketClientGateway, |
| | | RobotStateManager stateManager, |
| | | IRobotTaskService robotTaskService, |
| | | ITaskService taskService, |
| | | HttpClientHelper httpClientHelper) |
| | | HttpClientHelper httpClientHelper, |
| | | ILogger logger) |
| | | { |
| | | _socketClientGateway = socketClientGateway; |
| | | _stateManager = stateManager; |
| | | _robotTaskService = robotTaskService; |
| | | _taskService = taskService; |
| | | _httpClientHelper = httpClientHelper; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | |
| | | if (result) |
| | | { |
| | | // åéæåï¼è®°å½æ¥å¿ |
| | | QuartzLogger.Error($"ä¸ååè´§æä»¤ï¼æä»¤: {taskString}", state.RobotCrane.DeviceName); |
| | | // åéæåï¼è®°å½ Info æ¥å¿ |
| | | _logger.LogInformation("ä¸ååè´§æä»¤æåï¼æä»¤: {TaskString}ï¼è®¾å¤: {DeviceName}", taskString, state.RobotCrane?.DeviceName); |
| | | QuartzLogger.Info($"ä¸ååè´§æä»¤æåï¼æä»¤: {taskString}", state.RobotCrane?.DeviceName); |
| | | |
| | | // æ´æ°ä»»å¡ç¶æä¸º"æºå¨äººæ§è¡ä¸" |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | |
| | | { |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // åé失败ï¼è®°å½ Error æ¥å¿ |
| | | _logger.LogError("ä¸ååè´§æä»¤å¤±è´¥ï¼æä»¤: {TaskString}ï¼è®¾å¤: {DeviceName}", taskString, state.RobotCrane?.DeviceName); |
| | | QuartzLogger.Error($"ä¸ååè´§æä»¤å¤±è´¥ï¼æä»¤: {taskString}", state.RobotCrane?.DeviceName); |
| | | } |
| | | } |
| | | |
| | |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | _logger.LogDebug("HandleInboundTaskAsyncï¼å½åä»»å¡ä¸ºç©º"); |
| | | QuartzLogger.Debug($"HandleInboundTaskAsyncï¼å½åä»»å¡ä¸ºç©º", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | |
| | | { |
| | | case RobotTaskTypeEnum.GroupPallet: |
| | | // ç»çä»»å¡ä¸ä½¿ç¨æºå°åï¼ç´æ¥è¿å false |
| | | _logger.LogDebug("HandleInboundTaskAsyncï¼ç»çä»»å¡ä¸ä½¿ç¨æºå°å"); |
| | | QuartzLogger.Debug($"HandleInboundTaskAsyncï¼ç»çä»»å¡ä¸ä½¿ç¨æºå°å", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | |
| | | case RobotTaskTypeEnum.ChangePallet: |
| | |
| | | |
| | | case RobotTaskTypeEnum.SplitPallet: |
| | | // æçä»»å¡ä¸ä½¿ç¨ç®æ å°å |
| | | _logger.LogDebug("HandleInboundTaskAsyncï¼æçä»»å¡ä¸ä½¿ç¨ç®æ å°å"); |
| | | QuartzLogger.Debug($"HandleInboundTaskAsyncï¼æçä»»å¡ä¸ä½¿ç¨ç®æ å°å", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | TaskType = taskType // ä»»å¡ç±»åï¼å
¥åº/空æçå
¥åºï¼ |
| | | }; |
| | | |
| | | // è®°å½æ¥å¿ï¼å¼å§è°ç¨ WMS å建å
¥åºä»»å¡ |
| | | _logger.LogInformation("HandleInboundTaskAsyncï¼è°ç¨WMSå建å
¥åºä»»å¡ï¼æçç : {PalletCode}ï¼ä»»å¡ç±»å: {TaskType}", PalletCode, taskType); |
| | | QuartzLogger.Info($"è°ç¨WMSå建å
¥åºä»»å¡ï¼æçç : {PalletCode}ï¼ä»»å¡ç±»å: {taskType}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | |
| | | // è°ç¨ WMS æ¥å£å建å
¥åºä»»å¡ |
| | | var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.CreateTaskInboundAsync), taskDto.ToJson()); |
| | | |
| | | // 妿è°ç¨å¤±è´¥æè¿åéè¯¯ç¶æ |
| | | if (!result.Data.Status && result.IsSuccess) |
| | | { |
| | | _logger.LogError("HandleInboundTaskAsyncï¼WMSè¿åéè¯¯ç¶æï¼Status: {Status}", result.Data.Status); |
| | | QuartzLogger.Error($"HandleInboundTaskAsyncï¼WMSè¿åéè¯¯ç¶æ", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | |
| | | var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO }); |
| | | if (!content.Status) |
| | | { |
| | | _logger.LogError("HandleInboundTaskAsyncï¼æ¥æ¶WMSä»»å¡å¤±è´¥"); |
| | | QuartzLogger.Error($"HandleInboundTaskAsyncï¼æ¥æ¶WMSä»»å¡å¤±è´¥", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | | } |
| | | |
| | |
| | | // æ´æ°ä»»å¡ç¶æå°ä¸ä¸é¶æ®µ |
| | | if (_taskService.UpdateTaskStatusToNext(taskInfo).Status) |
| | | { |
| | | _logger.LogInformation("HandleInboundTaskAsyncï¼å
¥åºä»»å¡å¤çæåï¼ä»»å¡å·: {TaskNum}", taskInfo.TaskNum); |
| | | QuartzLogger.Info($"HandleInboundTaskAsyncï¼å
¥åºä»»å¡å¤çæåï¼ä»»å¡å·: {taskInfo.TaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | |
| | | private readonly IRobotTaskService _robotTaskService; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="stateManager">ç¶æç®¡çå¨</param> |
| | | /// <param name="clientManager">客æ·ç«¯ç®¡çå¨</param> |
| | | /// <param name="taskProcessor">ä»»å¡å¤çå¨</param> |
| | | /// <param name="robotTaskService">任塿å¡</param> |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public RobotWorkflowOrchestrator( |
| | | RobotStateManager stateManager, |
| | | RobotClientManager clientManager, |
| | | RobotTaskProcessor taskProcessor, |
| | | IRobotTaskService robotTaskService) |
| | | IRobotTaskService robotTaskService, |
| | | ILogger logger) |
| | | { |
| | | _stateManager = stateManager; |
| | | _clientManager = clientManager; |
| | | _taskProcessor = taskProcessor; |
| | | _robotTaskService = robotTaskService; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | && latestState.RobotArmObject == 1 |
| | | && task.RobotTaskState == TaskRobotStatusEnum.RobotPickFinish.GetHashCode()) |
| | | { |
| | | _logger.LogInformation("ExecuteAsyncï¼æ»¡è¶³æ¾è´§æ¡ä»¶ï¼å¼å§å¤çåè´§å®æï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); |
| | | QuartzLogger.Info($"ExecuteAsyncï¼æ»¡è¶³æ¾è´§æ¡ä»¶ï¼å¼å§å¤çåè´§å®æ", latestState.RobotCrane?.DeviceName ?? ipAddress); |
| | | // åéæ¾è´§æä»¤ |
| | | await HandlePickFinishedStateAsync(task, ipAddress); |
| | | } |
| | |
| | | && (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode() |
| | | || task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode())) |
| | | { |
| | | _logger.LogInformation("ExecuteAsyncï¼æ»¡è¶³åè´§æ¡ä»¶ï¼å¼å§å¤çæ¾è´§å®æï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); |
| | | QuartzLogger.Info($"ExecuteAsyncï¼æ»¡è¶³åè´§æ¡ä»¶ï¼å¼å§å¤çæ¾è´§å®æ", latestState.RobotCrane?.DeviceName ?? ipAddress); |
| | | // åéåè´§æä»¤ |
| | | await HandlePutFinishedStateAsync(task, ipAddress); |
| | | } |
| | |
| | | |
| | | if (result) |
| | | { |
| | | // åéæåï¼è®°å½æ¥å¿ |
| | | QuartzLogger.Error($"ä¸åæ¾è´§æä»¤ï¼æï¿½?: {taskString}", task.RobotRoadway); |
| | | // åéæåï¼è®°å½ Info æ¥å¿ |
| | | _logger.LogInformation("HandlePickFinishedStateAsyncï¼ä¸åæ¾è´§æä»¤æåï¼æä»¤: {TaskString}ï¼ä»»å¡å·: {TaskNum}", taskString, task.RobotTaskNum); |
| | | QuartzLogger.Info($"ä¸åæ¾è´§æä»¤æåï¼æä»¤: {taskString}", task.RobotRoadway); |
| | | |
| | | // æ´æ°ä»»å¡ç¶æä¸º"æºå¨äººæ§è¡ä¸" |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // åé失败ï¼è®°å½ Error æ¥å¿ |
| | | _logger.LogError("HandlePickFinishedStateAsyncï¼ä¸åæ¾è´§æä»¤å¤±è´¥ï¼æä»¤: {TaskString}ï¼ä»»å¡å·: {TaskNum}", taskString, task.RobotTaskNum); |
| | | QuartzLogger.Error($"ä¸åæ¾è´§æä»¤å¤±è´¥ï¼æä»¤: {taskString}", task.RobotRoadway); |
| | | } |
| | | } |
| | | |
| | |
| | | var stateForUpdate = _stateManager.GetState(ipAddress); |
| | | if (stateForUpdate == null) |
| | | { |
| | | _logger.LogWarning("HandlePutFinishedStateAsyncï¼è·åç¶æå¤±è´¥ï¼IP: {IpAddress}", ipAddress); |
| | | QuartzLogger.Warn($"HandlePutFinishedStateAsyncï¼è·åç¶æå¤±è´¥ï¼IP: {ipAddress}", ipAddress); |
| | | return; |
| | | } |
| | | |
| | |
| | | stateForUpdate.CellBarcode.Add(trayBarcode1); |
| | | stateForUpdate.CellBarcode.Add(trayBarcode2); |
| | | |
| | | // è®°å½æ¥å¿ |
| | | QuartzLogger.Error($"ȡ�������о�ţ���о: {trayBarcode1}+{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName); |
| | | // è®°å½æ¥å¿ï¼çææçæ¡ç æå |
| | | _logger.LogInformation("HandlePutFinishedStateAsyncï¼çææçæ¡ç æå: {Barcode1}+{Barcode2}ï¼ä»»å¡å·: {TaskNum}", trayBarcode1, trayBarcode2, task.RobotTaskNum); |
| | | QuartzLogger.Info($"çææçæ¡ç æå: {trayBarcode1}+{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName); |
| | | |
| | | // åéåè´§æä»¤ |
| | | await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); |
| | | } |
| | | else |
| | | { |
| | | // æ¡ç çæå¤±è´¥ï¼è®°å½é误æ¥å¿ |
| | | _logger.LogError("HandlePutFinishedStateAsyncï¼çææçæ¡ç 失败ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); |
| | | QuartzLogger.Error($"çææçæ¡ç 失败", stateForUpdate.RobotCrane.DeviceName); |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Quartz; |
| | | using System; |
| | | using System.Diagnostics.CodeAnalysis; |
| | |
| | | using WIDESEAWCS_QuartzJob.StackerCrane; |
| | | using WIDESEAWCS_Tasks.StackerCraneJob; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_QuartzJob.Service; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | |
| | | private readonly StackerCraneCommandBuilder _commandBuilder; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger<CommonStackerCraneJob> _logger; |
| | | |
| | | /// <summary> |
| | | /// å åæºè®¾å¤ç¼ç |
| | | /// </summary> |
| | | private string _deviceCode = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="taskService">任塿å¡</param> |
| | |
| | | /// <param name="taskRepository">ä»»å¡ä»å¨</param> |
| | | /// <param name="routerService">è·¯ç±æå¡</param> |
| | | /// <param name="httpClientHelper">HTTP 客æ·ç«¯å¸®å©ç±»</param> |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public CommonStackerCraneJob( |
| | | ITaskService taskService, |
| | | ITaskExecuteDetailService taskExecuteDetailService, |
| | | ITaskRepository taskRepository, |
| | | IRouterService routerService, |
| | | HttpClientHelper httpClientHelper) |
| | | HttpClientHelper httpClientHelper, |
| | | ILogger<CommonStackerCraneJob> logger) |
| | | { |
| | | _taskService = taskService; |
| | | _taskExecuteDetailService = taskExecuteDetailService; |
| | | _taskRepository = taskRepository; |
| | | _logger = logger; |
| | | |
| | | // å è½½é
ç½®æä»¶ |
| | | _config = LoadConfig(); |
| | | |
| | | // åå§åä»»å¡éæ©å¨ |
| | | _taskSelector = new StackerCraneTaskSelector(taskService, routerService, httpClientHelper); |
| | | _taskSelector = new StackerCraneTaskSelector(taskService, routerService, httpClientHelper, _logger); |
| | | |
| | | // åå§åå½ä»¤æå»ºå¨ |
| | | _commandBuilder = new StackerCraneCommandBuilder(taskService, routerService, _config); |
| | | _commandBuilder = new StackerCraneCommandBuilder(taskService, routerService, _config, _logger); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | if (!flag || value is not IStackerCrane commonStackerCrane) |
| | | { |
| | | // åæ°æ æï¼ç´æ¥è¿å |
| | | _logger.LogWarning("Executeï¼åæ°æ æ"); |
| | | QuartzLogger.Warn("Executeï¼åæ°æ æ", "CommonStackerCraneJob"); |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | | _deviceCode = commonStackerCrane.DeviceCode; |
| | | |
| | | // ========== 订é
ä»»å¡å®æäºä»¶ï¼å
¨å±åªè®¢é
䏿¬¡ï¼ ========== |
| | | if (!commonStackerCrane.IsEventSubscribed) |
| | | { |
| | | // ç»å®ä»»å¡å®æäºä»¶å¤çæ¹æ³ |
| | | commonStackerCrane.StackerCraneTaskCompletedEventHandler += CommonStackerCrane_StackerCraneTaskCompletedEventHandler; |
| | | _logger.LogInformation("Executeï¼è®¢é
ä»»å¡å®æäºä»¶ï¼è®¾å¤: {DeviceCode}", _deviceCode); |
| | | QuartzLogger.Info($"订é
ä»»å¡å®æäºä»¶", _deviceCode); |
| | | } |
| | | |
| | | // ========== æ£æ¥å åæºä»»å¡å®æç¶æ ========== |
| | | commonStackerCrane.CheckStackerCraneTaskCompleted(); |
| | | _logger.LogDebug("Executeï¼æ£æ¥ä»»å¡å®æç¶æï¼è®¾å¤: {DeviceCode}", _deviceCode); |
| | | QuartzLogger.Debug($"æ£æ¥ä»»å¡å®æç¶æï¼è®¾å¤: {_deviceCode}", _deviceCode); |
| | | |
| | | // ========== æ£æ¥æ¯å¦å¯ä»¥åéæ°ä»»å¡ ========== |
| | | if (!commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs)) |
| | | { |
| | | // å åæºä¸å¯ç¨ï¼å¦æ£å¨æ§è¡ä¸ä¸ä»»å¡ï¼ï¼ç´æ¥è¿å |
| | | _logger.LogDebug("Executeï¼å åæºä¸å¯ç¨ï¼è®¾å¤: {DeviceCode}", _deviceCode); |
| | | QuartzLogger.Debug($"å åæºä¸å¯ç¨ï¼è®¾å¤: {_deviceCode}", _deviceCode); |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | |
| | | if (task == null) |
| | | { |
| | | // 没æå¯ç¨ä»»å¡ |
| | | _logger.LogDebug("Executeï¼æ²¡æå¯ç¨ä»»å¡ï¼è®¾å¤: {DeviceCode}", _deviceCode); |
| | | QuartzLogger.Debug($"没æå¯ç¨ä»»å¡ï¼è®¾å¤: {_deviceCode}", _deviceCode); |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | | _logger.LogInformation("Executeï¼éæ©ä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", _deviceCode, task.TaskNum); |
| | | QuartzLogger.Info($"鿩任å¡ï¼ä»»å¡å·: {task.TaskNum}", _deviceCode); |
| | | |
| | | // ========== æå»ºå½ä»¤ ========== |
| | | // å½ä»¤æå»ºä¸æ²å°ä¸ç¨æå»ºå¨ |
| | |
| | | if (stackerCraneTaskCommand == null) |
| | | { |
| | | // å½ä»¤æå»ºå¤±è´¥ |
| | | _logger.LogWarning("Executeï¼å½ä»¤æå»ºå¤±è´¥ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", _deviceCode, task.TaskNum); |
| | | QuartzLogger.Warn($"å½ä»¤æå»ºå¤±è´¥ï¼ä»»å¡å·: {task.TaskNum}", _deviceCode); |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | |
| | | // åéæåï¼æ´æ°ç¶æ |
| | | commonStackerCrane.LastTaskType = task.TaskType; |
| | | _taskService.UpdateTaskStatusToNext(task.TaskNum); |
| | | |
| | | _logger.LogInformation("Executeï¼å½ä»¤åéæåï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", _deviceCode, task.TaskNum); |
| | | QuartzLogger.Info($"å½ä»¤åéæåï¼ä»»å¡å·: {task.TaskNum}", _deviceCode); |
| | | } |
| | | else |
| | | { |
| | | _logger.LogError("Executeï¼å½ä»¤åé失败ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", _deviceCode, task.TaskNum); |
| | | QuartzLogger.Error($"å½ä»¤åé失败", _deviceCode); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // è®°å½å¼å¸¸ |
| | | Console.WriteLine($"CommonStackerCraneJob Error: {ex.Message}"); |
| | | _logger.LogError(ex, "Executeï¼æ§è¡å¼å¸¸ï¼è®¾å¤: {DeviceCode}", _deviceCode); |
| | | QuartzLogger.Error($"æ§è¡å¼å¸¸: {ex.Message}", _deviceCode, ex); |
| | | } |
| | | |
| | | return Task.CompletedTask; |
| | |
| | | if (stackerCrane != null) |
| | | { |
| | | // è®°å½æ¥å¿ |
| | | Console.Out.WriteLine("TaskCompleted" + e.TaskNum); |
| | | _logger.LogInformation("CommonStackerCrane_StackerCraneTaskCompletedEventHandlerï¼ä»»å¡å®æï¼ä»»å¡å·: {TaskNum}", e.TaskNum); |
| | | QuartzLogger.Info($"ä»»å¡å®æï¼ä»»å¡å·: {e.TaskNum}", stackerCrane.DeviceCode); |
| | | |
| | | // æ´æ°ä»»å¡ç¶æä¸ºå®æ |
| | | _taskService.StackCraneTaskCompleted(e.TaskNum); |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using System; |
| | | using System.Diagnostics.CodeAnalysis; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob.Models; |
| | |
| | | private readonly StackerCraneCommandConfig _config; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="taskService">任塿å¡</param> |
| | | /// <param name="routerService">è·¯ç±æå¡</param> |
| | | /// <param name="config">å½ä»¤é
ç½®</param> |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public StackerCraneCommandBuilder( |
| | | ITaskService taskService, |
| | | IRouterService routerService, |
| | | StackerCraneCommandConfig config) |
| | | StackerCraneCommandConfig config, |
| | | ILogger logger) |
| | | { |
| | | _taskService = taskService; |
| | | _routerService = routerService; |
| | | _config = config; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | // æ ¹æ®å··éè·åå½ä»¤ç±»å |
| | | string commandType = GetCommandType(task.Roadway); |
| | | |
| | | _logger.LogInformation("ConvertToStackerCraneTaskCommandï¼æå»ºå½ä»¤ï¼ä»»å¡å·: {TaskNum}ï¼å··é: {Roadway}ï¼å½ä»¤ç±»å: {CommandType}", task.TaskNum, task.Roadway, commandType); |
| | | QuartzLogger.Info($"æå»ºå½ä»¤ï¼ä»»å¡å·: {task.TaskNum}ï¼å··é: {task.Roadway}ï¼å½ä»¤ç±»å: {commandType}", task.Roadway); |
| | | |
| | | // æ ¹æ®å½ä»¤ç±»åè°ç¨ç¸åºçæå»ºæ¹æ³ |
| | | return commandType switch |
| | |
| | | { |
| | | if (roadway.Contains(mapping.Key)) |
| | | { |
| | | _logger.LogDebug("GetCommandTypeï¼å¹é
å··é {Roadway}ï¼å½ä»¤ç±»å: {CommandType}", roadway, mapping.Value); |
| | | QuartzLogger.Debug($"GetCommandTypeï¼å¹é
å··é {roadway}ï¼å½ä»¤ç±»å: {mapping.Value}", roadway); |
| | | return mapping.Value; |
| | | } |
| | | } |
| | | |
| | | _logger.LogDebug("GetCommandTypeï¼å··é {Roadway} æªå¹é
ï¼ä½¿ç¨é»è®¤å½ä»¤ç±»å: {DefaultType}", roadway, _config.DefaultCommandType); |
| | | QuartzLogger.Debug($"GetCommandTypeï¼å··é {roadway} æªå¹é
ï¼ä½¿ç¨é»è®¤å½ä»¤ç±»å: {_config.DefaultCommandType}", roadway); |
| | | return _config.DefaultCommandType; |
| | | } |
| | | |
| | |
| | | // è·åä»»å¡ç±»ååç» |
| | | TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup(); |
| | | |
| | | _logger.LogDebug("BuildCommandï¼ä»»å¡å·: {TaskNum}ï¼ä»»å¡ç±»ååç»: {TaskTypeGroup}", task.TaskNum, taskTypeGroup); |
| | | QuartzLogger.Debug($"BuildCommandï¼ä»»å¡å·: {task.TaskNum}ï¼ä»»å¡ç±»ååç»: {taskTypeGroup}", task.Roadway); |
| | | |
| | | // æ ¹æ®ä»»å¡ç±»åååæå»º |
| | | return taskTypeGroup switch |
| | | { |
| | |
| | | /// <returns>å¡«å
好çå½ä»¤å¯¹è±¡</returns> |
| | | private T? BuildInboundCommand<T>(Dt_Task task, T command) where T : class |
| | | { |
| | | _logger.LogInformation("BuildInboundCommandï¼æå»ºå
¥åºå½ä»¤ï¼ä»»å¡å·: {TaskNum}", task.TaskNum); |
| | | QuartzLogger.Info($"BuildInboundCommandï¼æå»ºå
¥åºå½ä»¤ï¼ä»»å¡å·: {task.TaskNum}", task.Roadway); |
| | | |
| | | // ç¡®å®ä»»å¡ç±»åï¼ç©ºæçç¨ç¹æ®ç±»å 100ï¼ |
| | | int taskType = 0; |
| | | if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty) |
| | |
| | | if (router == null) |
| | | { |
| | | // æªæ¾å°ç«å°ï¼æ´æ°å¼å¸¸ä¿¡æ¯ |
| | | _logger.LogError("BuildInboundCommandï¼æªæ¾å°ç«å°ã{CurrentAddress}ãä¿¡æ¯ï¼ä»»å¡å·: {TaskNum}", task.CurrentAddress, task.TaskNum); |
| | | QuartzLogger.Error($"BuildInboundCommandï¼æªæ¾å°ç«å°ã{task.CurrentAddress}ãä¿¡æ¯", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"æªæ¾å°ç«å°ã{task.CurrentAddress}ãä¿¡æ¯ï¼æ æ³è·å对åºçå åæºåè´§ç«å°ä¿¡æ¯"); |
| | | return null; |
| | | } |
| | |
| | | // è§£æç®æ å°åï¼åºä½å°åï¼ |
| | | if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer)) |
| | | { |
| | | _logger.LogError("BuildInboundCommandï¼å
¥åºä»»å¡ç»ç¹å°åè§£æå¤±è´¥ï¼ç»ç¹: {NextAddress}ï¼ä»»å¡å·: {TaskNum}", task.NextAddress, task.TaskNum); |
| | | QuartzLogger.Error($"BuildInboundCommandï¼å
¥åºä»»å¡ç»ç¹å°åè§£æå¤±è´¥ï¼ç»ç¹: {task.NextAddress}", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"å
¥åºä»»å¡ç»ç¹é误ï¼ç»ç¹ï¼ã{task.NextAddress}ã"); |
| | | return null; |
| | | } |
| | |
| | | SetCommandProperty(command, "EndRow", endRow); |
| | | SetCommandProperty(command, "EndColumn", endColumn); |
| | | SetCommandProperty(command, "EndLayer", endLayer); |
| | | |
| | | _logger.LogInformation("BuildInboundCommandï¼å
¥åºå½ä»¤æå»ºæåï¼èµ·ç¹: {StartRow}-{StartColumn}-{StartLayer}ï¼ç»ç¹: {EndRow}-{EndColumn}-{EndLayer}ï¼ä»»å¡å·: {TaskNum}", |
| | | router.SrmRow, router.SrmColumn, router.SrmLayer, endRow, endColumn, endLayer, task.TaskNum); |
| | | QuartzLogger.Info($"BuildInboundCommandï¼å
¥åºå½ä»¤æå»ºæåï¼èµ·ç¹: {router.SrmRow}-{router.SrmColumn}-{router.SrmLayer}ï¼ç»ç¹: {endRow}-{endColumn}-{endLayer}", task.Roadway); |
| | | |
| | | return command; |
| | | } |
| | |
| | | /// <returns>å¡«å
好çå½ä»¤å¯¹è±¡</returns> |
| | | private T? BuildOutboundCommand<T>(Dt_Task task, T command) where T : class |
| | | { |
| | | _logger.LogInformation("BuildOutboundCommandï¼æå»ºåºåºå½ä»¤ï¼ä»»å¡å·: {TaskNum}", task.TaskNum); |
| | | QuartzLogger.Info($"BuildOutboundCommandï¼æå»ºåºåºå½ä»¤ï¼ä»»å¡å·: {task.TaskNum}", task.Roadway); |
| | | |
| | | // ç¡®å®ä»»å¡ç±»å |
| | | int taskType = 0; |
| | | if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty) |
| | |
| | | Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.TargetAddress, taskType); |
| | | if (router == null) |
| | | { |
| | | _logger.LogError("BuildOutboundCommandï¼æªæ¾å°ç«å°ã{TargetAddress}ãä¿¡æ¯ï¼ä»»å¡å·: {TaskNum}", task.TargetAddress, task.TaskNum); |
| | | QuartzLogger.Error($"BuildOutboundCommandï¼æªæ¾å°ç«å°ã{task.TargetAddress}ãä¿¡æ¯", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"æªæ¾å°ç«å°ã{task.TargetAddress}ãä¿¡æ¯ï¼æ æ³è·å对åºçå åæºæ¾è´§ç«å°ä¿¡æ¯"); |
| | | return null; |
| | | } |
| | |
| | | // è§£æèµ·å§å°åï¼åºä½å°åï¼ |
| | | if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer)) |
| | | { |
| | | _logger.LogError("BuildOutboundCommandï¼åºåºä»»å¡èµ·ç¹å°åè§£æå¤±è´¥ï¼èµ·ç¹: {CurrentAddress}ï¼ä»»å¡å·: {TaskNum}", task.CurrentAddress, task.TaskNum); |
| | | QuartzLogger.Error($"BuildOutboundCommandï¼åºåºä»»å¡èµ·ç¹å°åè§£æå¤±è´¥ï¼èµ·ç¹: {task.CurrentAddress}", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"åºåºä»»å¡èµ·ç¹é误ï¼èµ·ç¹ï¼ã{task.CurrentAddress}ã"); |
| | | return null; |
| | | } |
| | |
| | | SetCommandProperty(command, "StartRow", startRow); |
| | | SetCommandProperty(command, "StartColumn", startColumn); |
| | | SetCommandProperty(command, "StartLayer", startLayer); |
| | | |
| | | _logger.LogInformation("BuildOutboundCommandï¼åºåºå½ä»¤æå»ºæåï¼èµ·ç¹: {StartRow}-{StartColumn}-{StartLayer}ï¼ç»ç¹: {EndRow}-{EndColumn}-{EndLayer}ï¼ä»»å¡å·: {TaskNum}", |
| | | startRow, startColumn, startLayer, router.SrmRow, router.SrmColumn, router.SrmLayer, task.TaskNum); |
| | | QuartzLogger.Info($"BuildOutboundCommandï¼åºåºå½ä»¤æå»ºæåï¼èµ·ç¹: {startRow}-{startColumn}-{startLayer}ï¼ç»ç¹: {router.SrmRow}-{router.SrmColumn}-{router.SrmLayer}", task.Roadway); |
| | | |
| | | return command; |
| | | } |
| | |
| | | /// <returns>å¡«å
好çå½ä»¤å¯¹è±¡</returns> |
| | | private T? BuildRelocationCommand<T>(Dt_Task task, T command) where T : class |
| | | { |
| | | _logger.LogInformation("BuildRelocationCommandï¼æå»ºç§»åºå½ä»¤ï¼ä»»å¡å·: {TaskNum}", task.TaskNum); |
| | | QuartzLogger.Info($"BuildRelocationCommandï¼æå»ºç§»åºå½ä»¤ï¼ä»»å¡å·: {task.TaskNum}", task.Roadway); |
| | | |
| | | // è§£æç®æ å°å |
| | | if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer)) |
| | | { |
| | | _logger.LogError("BuildRelocationCommandï¼ç§»åºä»»å¡ç»ç¹å°åè§£æå¤±è´¥ï¼ç»ç¹: {NextAddress}ï¼ä»»å¡å·: {TaskNum}", task.NextAddress, task.TaskNum); |
| | | QuartzLogger.Error($"BuildRelocationCommandï¼ç§»åºä»»å¡ç»ç¹å°åè§£æå¤±è´¥ï¼ç»ç¹: {task.NextAddress}", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"ç§»åºä»»å¡ç»ç¹é误ï¼ç»ç¹ï¼ã{task.NextAddress}ã"); |
| | | return null; |
| | | } |
| | |
| | | // è§£æèµ·å§å°å |
| | | if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer)) |
| | | { |
| | | _logger.LogError("BuildRelocationCommandï¼ç§»åºä»»å¡èµ·ç¹å°åè§£æå¤±è´¥ï¼èµ·ç¹: {CurrentAddress}ï¼ä»»å¡å·: {TaskNum}", task.CurrentAddress, task.TaskNum); |
| | | QuartzLogger.Error($"BuildRelocationCommandï¼ç§»åºä»»å¡èµ·ç¹å°åè§£æå¤±è´¥ï¼èµ·ç¹: {task.CurrentAddress}", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"ç§»åºä»»å¡èµ·ç¹é误ï¼èµ·ç¹ï¼ã{task.CurrentAddress}ã"); |
| | | return null; |
| | | } |
| | |
| | | SetCommandProperty(command, "StartColumn", startColumn); |
| | | SetCommandProperty(command, "StartLayer", startLayer); |
| | | |
| | | _logger.LogInformation("BuildRelocationCommandï¼ç§»åºå½ä»¤æå»ºæåï¼èµ·ç¹: {StartRow}-{StartColumn}-{StartLayer}ï¼ç»ç¹: {EndRow}-{EndColumn}-{EndLayer}ï¼ä»»å¡å·: {TaskNum}", |
| | | startRow, startColumn, startLayer, endRow, endColumn, endLayer, task.TaskNum); |
| | | QuartzLogger.Info($"BuildRelocationCommandï¼ç§»åºå½ä»¤æå»ºæåï¼èµ·ç¹: {startRow}-{startColumn}-{startLayer}ï¼ç»ç¹: {endRow}-{endColumn}-{endLayer}", task.Roadway); |
| | | |
| | | return command; |
| | | } |
| | | |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Newtonsoft.Json; |
| | | using System.Diagnostics.CodeAnalysis; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | |
| | | private readonly IRouterService _routerService; |
| | | |
| | | /// <summary> |
| | | /// æ¥å¿è®°å½å¨ |
| | | /// </summary> |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// ç§»åºæ£æ¥å§æå½æ° |
| | | /// </summary> |
| | | /// <remarks> |
| | |
| | | /// <param name="taskService">任塿å¡</param> |
| | | /// <param name="routerService">è·¯ç±æå¡</param> |
| | | /// <param name="httpClientHelper">HTTP 客æ·ç«¯å¸®å©ç±»</param> |
| | | public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, HttpClientHelper httpClientHelper) |
| | | : this(taskService, routerService, taskNum => QueryTransferTask(httpClientHelper, taskNum)) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, HttpClientHelper httpClientHelper, ILogger logger) |
| | | : this(taskService, routerService, taskNum => QueryTransferTask(httpClientHelper, taskNum), logger) |
| | | { |
| | | } |
| | | |
| | |
| | | /// <param name="taskService">任塿å¡</param> |
| | | /// <param name="routerService">è·¯ç±æå¡</param> |
| | | /// <param name="transferCheck">ç§»åºæ£æ¥å½æ°</param> |
| | | public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, Func<int, Dt_Task?> transferCheck) |
| | | /// <param name="logger">æ¥å¿è®°å½å¨</param> |
| | | public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, Func<int, Dt_Task?> transferCheck, ILogger logger) |
| | | { |
| | | _taskService = taskService; |
| | | _routerService = routerService; |
| | | _transferCheck = transferCheck; |
| | | _logger = logger; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | public Dt_Task? SelectTask(IStackerCrane commonStackerCrane) |
| | | { |
| | | Dt_Task? candidateTask; |
| | | var deviceCode = commonStackerCrane.DeviceCode; |
| | | |
| | | _logger.LogInformation("SelectTaskï¼å¼å§éæ©ä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ä¸ä¸ä»»å¡ç±»å: {LastTaskType}", deviceCode, commonStackerCrane.LastTaskType); |
| | | QuartzLogger.Info($"å¼å§éæ©ä»»å¡ï¼è®¾å¤: {deviceCode}ï¼ä¸ä¸ä»»å¡ç±»å: {commonStackerCrane.LastTaskType}", deviceCode); |
| | | |
| | | // æ ¹æ®ä¸ä¸ä»»å¡ç±»åå³å®æ¥è¯¢çç¥ |
| | | if (commonStackerCrane.LastTaskType == null) |
| | | { |
| | | // 没æä¸ä¸ä»»å¡ç±»åï¼æ¥è¯¢æ®éä»»å¡ |
| | | candidateTask = _taskService.QueryStackerCraneTask(commonStackerCrane.DeviceCode); |
| | | candidateTask = _taskService.QueryStackerCraneTask(deviceCode); |
| | | _logger.LogDebug("SelectTaskï¼æ¥è¯¢æ®éä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ç»æ: {TaskNum}", deviceCode, candidateTask?.TaskNum); |
| | | QuartzLogger.Debug($"æ¥è¯¢æ®éä»»å¡ï¼è®¾å¤: {deviceCode}ï¼ç»æ: {candidateTask?.TaskNum}", deviceCode); |
| | | } |
| | | else if (commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup) |
| | | { |
| | | // ä¸ä¸ä»»å¡æ¯åºåºï¼ä¼å
æ¥å
¥åºä»»å¡ |
| | | candidateTask = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode); |
| | | candidateTask = _taskService.QueryStackerCraneInTask(deviceCode); |
| | | // å¦ææ²¡æå
¥åºä»»å¡ï¼åæ¥ä¸ä¸åºåºä»»å¡ |
| | | candidateTask ??= _taskService.QueryStackerCraneOutTask(commonStackerCrane.DeviceCode); |
| | | candidateTask ??= _taskService.QueryStackerCraneOutTask(deviceCode); |
| | | _logger.LogDebug("SelectTaskï¼åºåºåä¼å
æ¥å
¥åºï¼è®¾å¤: {DeviceCode}ï¼ç»æ: {TaskNum}", deviceCode, candidateTask?.TaskNum); |
| | | QuartzLogger.Debug($"åºåºåä¼å
æ¥å
¥åºï¼è®¾å¤: {deviceCode}ï¼ç»æ: {candidateTask?.TaskNum}", deviceCode); |
| | | } |
| | | else |
| | | { |
| | | // ä¸ä¸ä»»å¡æ¯å
¥åºï¼éåºåºï¼ï¼ä¼å
æ¥åºåºä»»å¡ |
| | | candidateTask = _taskService.QueryStackerCraneOutTask(commonStackerCrane.DeviceCode); |
| | | candidateTask = _taskService.QueryStackerCraneOutTask(deviceCode); |
| | | _logger.LogDebug("SelectTaskï¼å
¥åºåä¼å
æ¥åºåºï¼è®¾å¤: {DeviceCode}ï¼ç»æ: {TaskNum}", deviceCode, candidateTask?.TaskNum); |
| | | QuartzLogger.Debug($"å
¥åºåä¼å
æ¥åºåºï¼è®¾å¤: {deviceCode}ï¼ç»æ: {candidateTask?.TaskNum}", deviceCode); |
| | | } |
| | | |
| | | // å¦ææ²¡æåéä»»å¡ï¼è¿å null |
| | | if (candidateTask == null) |
| | | { |
| | | _logger.LogDebug("SelectTaskï¼æ²¡æåéä»»å¡ï¼è®¾å¤: {DeviceCode}", deviceCode); |
| | | QuartzLogger.Debug($"没æåéä»»å¡ï¼è®¾å¤: {deviceCode}", deviceCode); |
| | | return null; |
| | | } |
| | | |
| | | // 妿䏿¯åºåºä»»å¡ï¼ç´æ¥è¿å |
| | | if (candidateTask.TaskType.GetTaskTypeGroup() != TaskTypeGroup.OutbondGroup) |
| | | { |
| | | _logger.LogInformation("SelectTaskï¼éä¸éåºåºä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}ï¼ä»»å¡ç±»å: {TaskType}", deviceCode, candidateTask.TaskNum, candidateTask.TaskType); |
| | | QuartzLogger.Info($"éä¸éåºåºä»»å¡ï¼ä»»å¡å·: {candidateTask.TaskNum}ï¼ä»»å¡ç±»å: {candidateTask.TaskType}", deviceCode); |
| | | return candidateTask; |
| | | } |
| | | |
| | |
| | | Dt_Task? selectedTask = TrySelectOutboundTask(candidateTask); |
| | | if (selectedTask != null) |
| | | { |
| | | _logger.LogInformation("SelectTaskï¼éä¸åºåºä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", deviceCode, selectedTask.TaskNum); |
| | | QuartzLogger.Info($"éä¸åºåºä»»å¡ï¼ä»»å¡å·: {selectedTask.TaskNum}", deviceCode); |
| | | return selectedTask; |
| | | } |
| | | |
| | | // æ¥æ¾å
¶ä»å¯ç¨çåºåºç«å° |
| | | var otherOutStationCodes = _routerService |
| | | .QueryNextRoutes(commonStackerCrane.DeviceCode, candidateTask.NextAddress, candidateTask.TaskType) |
| | | .QueryNextRoutes(deviceCode, candidateTask.NextAddress, candidateTask.TaskType) |
| | | .Select(x => x.ChildPosi) |
| | | .ToList(); |
| | | |
| | | // æ¥è¯¢å
¶ä»ç«å°çåºåºä»»å¡ |
| | | var tasks = _taskService.QueryStackerCraneOutTasks(commonStackerCrane.DeviceCode, otherOutStationCodes); |
| | | var tasks = _taskService.QueryStackerCraneOutTasks(deviceCode, otherOutStationCodes); |
| | | foreach (var alternativeTask in tasks) |
| | | { |
| | | selectedTask = TrySelectOutboundTask(alternativeTask); |
| | | if (selectedTask != null) |
| | | { |
| | | _logger.LogInformation("SelectTaskï¼éä¸å¤éåºåºä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", deviceCode, selectedTask.TaskNum); |
| | | QuartzLogger.Info($"éä¸å¤éåºåºä»»å¡ï¼ä»»å¡å·: {selectedTask.TaskNum}", deviceCode); |
| | | return selectedTask; |
| | | } |
| | | } |
| | | |
| | | // 没æå¯ç¨åºåºä»»å¡ï¼å°è¯è¿åå
¥åºä»»å¡ |
| | | return _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode); |
| | | var inboundTask = _taskService.QueryStackerCraneInTask(deviceCode); |
| | | _logger.LogInformation("SelectTaskï¼è¿åå
¥åºä»»å¡ï¼è®¾å¤: {DeviceCode}ï¼ä»»å¡å·: {TaskNum}", deviceCode, inboundTask?.TaskNum); |
| | | QuartzLogger.Info($"è¿åå
¥åºä»»å¡ï¼ä»»å¡å·: {inboundTask?.TaskNum}", deviceCode); |
| | | return inboundTask; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | if (router == null) |
| | | { |
| | | // æªæ¾å°ç«å°è·¯ç±ä¿¡æ¯ |
| | | _logger.LogWarning("IsOutTaskStationAvailableï¼æªæ¾å°ç«å°è·¯ç±ä¿¡æ¯ï¼ç«å°: {NextAddress}ï¼ä»»å¡å·: {TaskNum}", task.NextAddress, task.TaskNum); |
| | | QuartzLogger.Warn($"IsOutTaskStationAvailableï¼æªæ¾å°ç«å°è·¯ç±ä¿¡æ¯ï¼ç«å°: {task.NextAddress}", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"æªæ¾å°ç«å°ã{task.NextAddress}ãä¿¡æ¯ï¼æ æ³æ ¡éªç«å°"); |
| | | return false; |
| | | } |
| | |
| | | if (device == null) |
| | | { |
| | | // æªæ¾å°è®¾å¤ |
| | | _logger.LogWarning("IsOutTaskStationAvailableï¼æªæ¾å°åºåºç«å°å¯¹åºçé讯对象ï¼ç«å°: {ChildPosiDeviceCode}ï¼ä»»å¡å·: {TaskNum}", router.ChildPosiDeviceCode, task.TaskNum); |
| | | QuartzLogger.Warn($"IsOutTaskStationAvailableï¼æªæ¾å°åºåºç«å°å¯¹åºçé讯对象ï¼ç«å°: {router.ChildPosiDeviceCode}", task.Roadway); |
| | | _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"æªæ¾å°åºåºç«å°ã{router.ChildPosiDeviceCode}ã对åºçéè®¯å¯¹è±¡ï¼æ æ³å¤æåºåºç«å°æ¯å¦è¢«å ç¨"); |
| | | return false; |
| | | } |
| | |
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device; |
| | | |
| | | // æ£æ¥ç«å°æ¯å¦è¢«å ç¨ |
| | | return conveyorLine.IsOccupied(router.ChildPosi); |
| | | bool isOccupied = conveyorLine.IsOccupied(router.ChildPosi); |
| | | _logger.LogInformation("IsOutTaskStationAvailableï¼ç«å° {ChildPosi}ï¼æ¯å¦è¢«å ç¨: {IsOccupied}ï¼ä»»å¡å·: {TaskNum}", router.ChildPosi, isOccupied, task.TaskNum); |
| | | QuartzLogger.Info($"IsOutTaskStationAvailableï¼ç«å° {router.ChildPosi}ï¼æ¯å¦è¢«å ç¨: {isOccupied}", task.Roadway); |
| | | |
| | | return !isOccupied; |
| | | } |
| | | } |
| | | } |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Moq; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | |
| | | taskService.Setup(x => x.AddData(It.IsAny<Dt_Task>())).Returns(WebResponseContent.Instance.OK()); |
| | | |
| | | var transferCheckCalledCount = 0; |
| | | var mockLogger = new Mock<ILogger>(); |
| | | var selector = new StackerCraneTaskSelector( |
| | | taskService.Object, |
| | | routerService.Object, |
| | |
| | | transferCheckCalledCount++; |
| | | Assert.Equal(1001, taskNum); |
| | | return relocationTask; |
| | | }); |
| | | }, |
| | | mockLogger.Object); |
| | | |
| | | var selectedTask = selector.SelectTask(stackerCrane.Object); |
| | | |
| | |
| | | .Setup(x => x.QueryNextRoutes("SC01", "OUT-01", (int)TaskOutboundTypeEnum.Outbound)) |
| | | .Returns(new List<WIDESEAWCS_QuartzJob.Models.Dt_Router>()); |
| | | |
| | | var mockLogger = new Mock<ILogger>(); |
| | | var selector = new StackerCraneTaskSelector( |
| | | taskService.Object, |
| | | routerService.Object, |
| | | _ => newOutboundTask); |
| | | _ => newOutboundTask, |
| | | mockLogger.Object); |
| | | |
| | | _ = selector.SelectTask(stackerCrane.Object); |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # è·¯ç±ç¼åå®ç°è®¡å |
| | | |
| | | > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| | | |
| | | **Goal:** å¨ RouterService ä¸å¼å
¥ HybridCacheService æ··åç¼åï¼ç¬¬ä¸æ¬¡æ¥è¯¢å è½½å
¨éè·¯ç±å°ç¼åï¼åç»æ¥è¯¢ç´æ¥ä»ç¼å读åï¼AddRouters åå
¥ååæ¥æ´æ°ç¼åã |
| | | |
| | | **Architecture:** æ InOutType åå¼ç¼å两份ï¼å
¥å£/åºå£ï¼ï¼GetOrAdd æå è½½ï¼åç©¿æ´æ°ç¼åï¼åå®ä¾é¨ç½²æ 广æéæ±ã |
| | | |
| | | **Tech Stack:** ASP.NET Core 6.0, HybridCacheService, SqlSugar ORM |
| | | |
| | | --- |
| | | |
| | | ## æä»¶åæ´æ¦è§ |
| | | |
| | | **ä¿®æ¹æä»¶ï¼** |
| | | - `WIDESEAWCS_QuartzJob/Service/RouterService.cs` â å
¨é¨ç¼åé»è¾æ¹å¨ |
| | | |
| | | **ä¸åï¼** |
| | | - `FindRoutesInMemory` â åªæ¹è°ç¨æ¹ï¼ç®æ³é»è¾ä¸å |
| | | - `QueryAllPositions` â å·²æç¬ç«ç¼åï¼ä¸ä¾èµæ¬æ¹æ¡ |
| | | |
| | | --- |
| | | |
| | | ## Task 1: æ°å¢ GetAllRoutersFromCache ç§ææ¹æ³ |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` |
| | | |
| | | å¨ç±»æååé声æåºä¹åãç°ææ¹æ³ä¹åï¼æ°å¢ä»¥ä¸ç§ææ¹æ³ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// ä»ç¼åè·åæå®ç±»åçå
¨éè·¯ç±æ°æ®ï¼ç¼åä¸å卿¶èªå¨ä»æ°æ®åºå 载并åå
¥ç¼å |
| | | /// </summary> |
| | | /// <param name="routeType">è·¯ç±ç±»åï¼å
¥å£/åºå£ï¼</param> |
| | | /// <returns>该类åçå
¨é¨è·¯ç±å表</returns> |
| | | private List<Dt_Router> GetAllRoutersFromCache(int routeType) |
| | | { |
| | | string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | return _cacheService.GetOrAdd( |
| | | cacheKey, |
| | | () => BaseDal.QueryData(x => x.InOutType == routeType) |
| | | ); |
| | | } |
| | | |
| | | --- |
| | | |
| | | ## Task 2: æ¹é QueryNextRoutes éè½½ï¼2ä¸ªæ¹æ³ï¼ |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:48-98` |
| | | |
| | | ### QueryNextRoutes(string, string) â 第48-69è¡ |
| | | |
| | | å代ç ï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => true); |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | // å
¥å£+åºå£é½å è½½ï¼FindRoutesInMemory å
鍿 routeType==null ä¸åè¿æ»¤ |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | allRouters.AddRange(outRouters); |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null); |
| | | ``` |
| | | |
| | | ### QueryNextRoutes(string, string, int) â 第78-99è¡ |
| | | |
| | | å代ç ï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); |
| | | routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 3: æ¹é QueryNextRoute éè½½ï¼4ä¸ªæ¹æ³ï¼ |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:189-314` |
| | | |
| | | ### QueryNextRoute(string) â 第189-205è¡ |
| | | |
| | | å代ç ï¼ |
| | | ```csharp |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, ...); |
| | | return routes.FirstOrDefault(); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼ |
| | | ```csharp |
| | | List<Dt_Router> routes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | return routes.FirstOrDefault(); |
| | | ``` |
| | | |
| | | ### QueryNextRoute(string, int) â 第213-229è¡ |
| | | |
| | | å代ç ï¼ |
| | | ```csharp |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, ...); |
| | | return routes.FirstOrDefault(); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼ |
| | | ```csharp |
| | | List<Dt_Router> routes = GetAllRoutersFromCache(routeType) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | return routes.FirstOrDefault(); |
| | | ``` |
| | | |
| | | ### QueryNextRoute(string, string, int) â 第238-272è¡ |
| | | |
| | | å代ç ï¼ç¬¬255è¡ï¼ï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); |
| | | ``` |
| | | |
| | | å
¶ä½ç´æ¥è·¯ç±å¤æå `FindRoutesInMemory` è°ç¨é»è¾ä¸åã |
| | | |
| | | ### QueryNextRoute(string, string) â 第280-314è¡ |
| | | |
| | | å代ç ï¼ç¬¬285è¡ï¼ï¼ |
| | | ```csharp |
| | | List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, ...); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼åå¹¶å
¥å£+åºå£ä¸¤ä»½ç¼åï¼ä¸åæ¹æ³å
¨éæ¥è¯¢è¯ä¹ä¸è´ï¼ï¼ |
| | | ```csharp |
| | | List<Dt_Router> inRoutes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRoutes = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | List<Dt_Router> routes = inRoutes.Concat(outRoutes) |
| | | .Where(x => x.StartPosi == startPosi) |
| | | .ToList(); |
| | | routes = routes.OrderByDescending(x => x.IsEnd).ToList(); |
| | | ``` |
| | | |
| | | ç¶åå¤ç¨å·²æçç´æ¥è·¯ç±å¤æé»è¾ã |
| | | |
| | | --- |
| | | |
| | | ## Task 4: æ¹é QueryRoutePath |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:323-366` |
| | | |
| | | 第355è¡éè¿ï¼å代ç ä¸ `while` 循ç¯éæ¯æ¬¡è°ç¨ `QueryNextRoute` çé»è¾**ä¸éè¦æ¹å¨**ï¼å 为 `QueryNextRoute` å·²ç»å¨ Task3 䏿¹é äºï¼ãæ¬ä»»å¡çæ¹å¨ä»
确认 `QueryRoutePath` æ¹æ³æ¬èº«ä¸åç´æ¥è°ç¨ `BaseDal.QueryData`ï¼å³ä¸éè¦ä»»ä½æ¹å¨ ââ å®è°ç¨çæ¯ `QueryNextRoute`ï¼èåè
已被æ¹é ã |
| | | |
| | | **éªè¯ï¼** 确认 `QueryRoutePath` æ¹æ³ä½å
没æç´æ¥è°ç¨ `BaseDal.QueryData`ï¼åªæå¯¹ `QueryNextRoute` çè°ç¨ã |
| | | |
| | | --- |
| | | |
| | | ## Task 5: æ¹é GetAllWholeRouters |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:412-446` |
| | | |
| | | å代ç ï¼ |
| | | ```csharp |
| | | List<Dt_Router> allRouters = BaseDal.QueryData(x => true); |
| | | ``` |
| | | |
| | | æ¹ä¸ºï¼ |
| | | ```csharp |
| | | List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | List<Dt_Router> allRouters = inRouters.Concat(outRouters).ToList(); |
| | | ``` |
| | | |
| | | åç»éå `dt_Routers`ï¼å `IsEnd == true` çè·¯ç±ï¼çé»è¾ä¸åã |
| | | |
| | | --- |
| | | |
| | | ## Task 6: æ¹é AddRoutersï¼åå
¥ DB åæ´æ°ç¼å |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:511-594` |
| | | |
| | | å¨ç¬¬568è¡éè¿ï¼æ¾å°ï¼ |
| | | ```csharp |
| | | // æ¥è¯¢æ°æ®åºä¸å·²æçè·¯ç±ä¿¡æ¯ |
| | | List<Dt_Router> dt_Routers = BaseDal.QueryData(x => x.InOutType == routerType); |
| | | ``` |
| | | |
| | | è¿ä¸ª `dt_Routers` æ¯**æ·»å ä¹å**çå·²ææ°æ®ï¼ä¸å
嫿¬æ¬¡æ°å¢çè·¯ç±ãå¨ç¬¬586è¡ `BaseDal.AddData(routers)` **ä¹å**ã`content = WebResponseContent.Instance.OK()` **ä¹å**ï¼å¿
须鿰æ¥è¯¢ä¸æ¬¡å
¨éæ°æ®ååå
¥ç¼åï¼ |
| | | |
| | | ```csharp |
| | | // æ·»å æ°çè·¯ç±ä¿¡æ¯ |
| | | BaseDal.AddData(routers); |
| | | |
| | | // éæ°æ¥è¯¢å
¨éè·¯ç±ï¼æ¤æ¶æå
嫿°å¢çè·¯ç±ï¼ï¼ååå
¥ç¼å |
| | | List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); |
| | | string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | _cacheService.Set(cacheKey, updatedRouters); |
| | | |
| | | content = WebResponseContent.Instance.OK(); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 7: ç¼è¯éªè¯ |
| | | |
| | | **éªè¯å½ä»¤ï¼** |
| | | ```bash |
| | | dotnet build WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj |
| | | ``` |
| | | |
| | | é¢æï¼æ ç¼è¯é误ï¼CS0103/CS0019 çç±»å/è¯æ³é误å
¨é¨ä¿®å¤åï¼ |
| | | |
| | | --- |
| | | |
| | | ## 宿½é¡ºåº |
| | | |
| | | 1. Task 1 â æ°å¢ `GetAllRoutersFromCache` ç§ææ¹æ³ |
| | | 2. Task 2 â æ¹é `QueryNextRoutes` 两个éè½½ |
| | | 3. Task 3 â æ¹é `QueryNextRoute` å个éè½½ |
| | | 4. Task 4 â 确认 `QueryRoutePath` æ éæ¹å¨ï¼å®ä¾èµå·²æ¹é ç `QueryNextRoute`ï¼ |
| | | 5. Task 5 â æ¹é `GetAllWholeRouters` |
| | | 6. Task 6 â æ¹é `AddRouters` æ´æ°ç¼å |
| | | 7. Task 7 â ç¼è¯éªè¯ |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # RouterService é»è¾ä¿®å¤ä¸æ°æ¹æ³å®ç°è®¡å |
| | | |
| | | > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| | | |
| | | **Goal:** ä¿®å¤ RouterService ä¸ç 3 个é»è¾é®é¢ï¼æ°å¢ 7 ä¸ªè·¯ç±æ¥è¯¢/ç®¡çæ¹æ³ï¼å¹¶æ´æ°æ¥å£å±ã |
| | | |
| | | **Architecture:** å¨ç°æ RouterService åºç¡ä¸æ°å¢ç¼åç®¡çæ¹æ³åè·¯ç±æ¥è¯¢å¢å¼ºæ¹æ³ï¼ä¿æç°æ HybridCacheService ç¼åæ¶æä¸åã |
| | | |
| | | **Tech Stack:** ASP.NET Core 6.0, HybridCacheService, SqlSugar ORM |
| | | |
| | | --- |
| | | |
| | | ## æä»¶åæ´æ¦è§ |
| | | |
| | | **ä¿®æ¹æä»¶ï¼** |
| | | - `WIDESEAWCS_QuartzJob/Service/RouterService.cs` â é»è¾ä¿®å¤ + æ°å¢æ¹æ³å®ç° |
| | | - `WIDESEAWCS_QuartzJob/Service/IRouterService.cs` â æ¥å£æ°å¢æ¹æ³ç¾å + 廿å¤ä½ `public` 修饰符 |
| | | |
| | | --- |
| | | |
| | | ## Task 1: ä¿®å¤ AddRouters ç¼åä¸è´æ§é®é¢ |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:605-613` |
| | | |
| | | **å代ç ï¼** |
| | | ```csharp |
| | | BaseDal.AddData(routers); |
| | | |
| | | List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); |
| | | string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | _cacheService.AddOrUpdate(cacheKey, updatedRouters); |
| | | |
| | | content = WebResponseContent.Instance.OK(); |
| | | ``` |
| | | |
| | | **æ¹ä¸ºï¼** |
| | | ```csharp |
| | | // æ·»å æ°çè·¯ç±ä¿¡æ¯ |
| | | BaseDal.AddData(routers); |
| | | |
| | | // éæ°æ¥è¯¢å
¨éè·¯ç±ï¼æ¤æ¶æå
嫿°å¢çè·¯ç±ï¼ï¼ååå
¥ç¼å |
| | | List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType); |
| | | string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | |
| | | try |
| | | { |
| | | _cacheService.AddOrUpdate(cacheKey, updatedRouters); |
| | | } |
| | | catch |
| | | { |
| | | // ç¼åæ´æ°å¤±è´¥æ¶éé»å¿½ç¥ï¼ä¸æ¬¡æ¥è¯¢ä¼ä»DBèªå¨é建ç¼å |
| | | } |
| | | |
| | | content = WebResponseContent.Instance.OK(); |
| | | ``` |
| | | |
| | | **说æ**ï¼ç¨ try-catch å
裹ç¼åæ´æ°æä½ï¼é²æ¢ç¼ååå
¥å¤±è´¥æ¶å¼å¸¸éé¸å°å¤å±è¢«å½ä½é误è¿åãDB å·²åå
¥æåï¼ç¼å失败ä¸å½±åä¸å¡æ£ç¡®æ§ã |
| | | |
| | | --- |
| | | |
| | | ## Task 2: ä¿®å¤ QueryAllPositions 空 catch å |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:412-415` |
| | | |
| | | **å代ç ï¼** |
| | | ```csharp |
| | | catch |
| | | { |
| | | |
| | | } |
| | | ``` |
| | | |
| | | **æ¹ä¸ºï¼** |
| | | ```csharp |
| | | catch (Exception ex) |
| | | { |
| | | ConsoleHelper.WriteErrorLine($"RouterService.QueryAllPositions æ¥è¯¢å¤±è´¥: {ex.Message}"); |
| | | } |
| | | ``` |
| | | |
| | | **说æ**ï¼å¢å é误æ¥å¿è®°å½ï¼ä¾¿äºææ¥é®é¢ãè¿åå¼ä»ä¸ºç©ºå表ï¼è°ç¨æ¹è¡ä¸ºä¸åã |
| | | |
| | | --- |
| | | |
| | | ## Task 3: ä¿®å¤ IRouterService æ¥å£ public 修饰符 + æ°å¢æ¹æ³ç¾å |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/IRouterService.cs` |
| | | |
| | | 廿以ä¸è¡ç `public` ä¿®é¥°ç¬¦ï¼ |
| | | - 第40è¡ï¼`public Dt_Router QueryNextRoute(string startPosi);` â `Dt_Router QueryNextRoute(string startPosi);` |
| | | - 第48è¡ |
| | | - 第57è¡ |
| | | - 第65è¡ |
| | | - 第74è¡ |
| | | |
| | | 忶卿¥å£æ«å°¾æ°å¢ä»¥ä¸æ¹æ³ç¾åï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æ¸
é¤è·¯ç±ç¼å |
| | | /// </summary> |
| | | void ClearRouterCache(); |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®è®¾å¤ç¼å·æ¥è¯¢ç»è¿è¯¥è®¾å¤çææè·¯ç± |
| | | /// </summary> |
| | | List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode); |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ï¼å
¨ç±»åï¼ |
| | | /// </summary> |
| | | bool ExistsRouter(string startPosi, string endPosi); |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦å卿å®ç±»åçè·¯ç± |
| | | /// </summary> |
| | | bool ExistsRouter(string startPosi, string endPosi, int routeType); |
| | | |
| | | /// <summary> |
| | | /// è·åå
¨éè·¯ç±æ°éï¼åå¹¶å
¥å£+åºå£ï¼ |
| | | /// </summary> |
| | | int GetRouterCount(); |
| | | |
| | | /// <summary> |
| | | /// è·åæå®ç±»åè·¯ç±æ°é |
| | | /// </summary> |
| | | int GetRouterCount(int routeType); |
| | | |
| | | /// <summary> |
| | | /// æ¹éå é¤è·¯ç± |
| | | /// </summary> |
| | | WebResponseContent DeleteRouters(List<long> routerIds); |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 4: å®ç° ClearRouterCache() |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` |
| | | |
| | | å¨ `GetAllRoutersFromCache` æ¹æ³ä¹åæ°å¢ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æ¸
餿æè·¯ç±ç¼åï¼å
¥å£ååºå£ç±»åï¼ |
| | | /// </summary> |
| | | public void ClearRouterCache() |
| | | { |
| | | _cacheService.Remove("Router:AllRouters:In"); |
| | | _cacheService.Remove("Router:AllRouters:Out"); |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 5: å®ç° QueryRoutersByDeviceCode |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` |
| | | |
| | | å¨ `ClearRouterCache` ä¹åæ°å¢ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æ ¹æ®è®¾å¤ç¼å·æ¥è¯¢ç»è¿è¯¥è®¾å¤çææè·¯ç±ï¼åå¹¶å
¥å£+åºå£ç±»åï¼ |
| | | /// </summary> |
| | | /// <param name="deviceCode">设å¤ç¼å·</param> |
| | | /// <returns>ç»è¿è¯¥è®¾å¤çè·¯ç±å表</returns> |
| | | public List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode) |
| | | { |
| | | List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | return inRouters.Concat(outRouters) |
| | | .Where(x => x.ChildPosiDeviceCode == deviceCode) |
| | | .ToList(); |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 6: å®ç° ExistsRouterï¼ä¸¤ä¸ªéè½½ï¼ |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` |
| | | |
| | | å¨ `QueryRoutersByDeviceCode` ä¹åæ°å¢ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ï¼å
¨ç±»åï¼ |
| | | /// </summary> |
| | | public bool ExistsRouter(string startPosi, string endPosi) |
| | | { |
| | | List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); |
| | | List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); |
| | | var allRouters = inRouters.Concat(outRouters).ToList(); |
| | | var routes = FindRoutesInMemory(startPosi, endPosi, allRouters, null); |
| | | return routes.Count > 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 夿䏤ç¹ä¹é´æ¯å¦å卿å®ç±»åçè·¯ç± |
| | | /// </summary> |
| | | public bool ExistsRouter(string startPosi, string endPosi, int routeType) |
| | | { |
| | | List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); |
| | | var routes = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType); |
| | | return routes.Count > 0; |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 7: å®ç° GetRouterCountï¼ä¸¤ä¸ªéè½½ï¼ |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` |
| | | |
| | | å¨ `ExistsRouter` ä¹åæ°å¢ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// è·åå
¨éè·¯ç±æ°éï¼å
¥å£+åºå£åè®¡ï¼ |
| | | /// </summary> |
| | | public int GetRouterCount() |
| | | { |
| | | int inCount = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()).Count; |
| | | int outCount = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()).Count; |
| | | return inCount + outCount; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæå®ç±»åè·¯ç±æ°é |
| | | /// </summary> |
| | | public int GetRouterCount(int routeType) |
| | | { |
| | | return GetAllRoutersFromCache(routeType).Count; |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 8: å®ç° DeleteRouters |
| | | |
| | | **æä»¶:** |
| | | - Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs` |
| | | |
| | | å¨ `AddRouters` æ¹æ³ä¹åæ°å¢ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æ¹éå 餿å®IDçè·¯ç±ï¼å é¤å忥æ¸
é¤å¯¹åºç±»åçç¼å |
| | | /// </summary> |
| | | /// <param name="routerIds">å¾
å é¤çè·¯ç±IDå表</param> |
| | | /// <returns>è¿åå¤çç»æ</returns> |
| | | public WebResponseContent DeleteRouters(List<long> routerIds) |
| | | { |
| | | WebResponseContent content = new WebResponseContent(); |
| | | try |
| | | { |
| | | if (routerIds == null || routerIds.Count == 0) |
| | | { |
| | | return content = WebResponseContent.Instance.Error("å¾
å é¤çè·¯ç±IDå表ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // æ¥è¯¢å¾
å é¤è·¯ç±çç±»åï¼ç¨äºåç»æ¸
é¤ç¼åï¼ |
| | | var routersToDelete = BaseDal.QueryData(x => routerIds.Contains(x.Id)); |
| | | if (routersToDelete.Count == 0) |
| | | { |
| | | return content = WebResponseContent.Instance.Error("æªæ¾å°å¾
å é¤çè·¯ç±"); |
| | | } |
| | | |
| | | // è®°å½æ¶åçç±»åï¼å»éï¼ |
| | | var affectedTypes = routersToDelete.Select(x => x.InOutType).Distinct().ToList(); |
| | | |
| | | // æ§è¡æ¹éå é¤ |
| | | BaseDal.DeleteData(routersToDelete); |
| | | |
| | | // æ¸
é¤åå½±åç±»åçç¼å |
| | | foreach (var routeType in affectedTypes) |
| | | { |
| | | string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}"; |
| | | _cacheService.Remove(cacheKey); |
| | | } |
| | | |
| | | content = WebResponseContent.Instance.OK(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | content = WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | return content; |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 9: ç¼è¯éªè¯ |
| | | |
| | | **éªè¯å½ä»¤ï¼** |
| | | ```bash |
| | | dotnet build WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj |
| | | ``` |
| | | |
| | | 颿ï¼0 errors |
| | | |
| | | --- |
| | | |
| | | ## 宿½é¡ºåº |
| | | |
| | | 1. Task 1 â ä¿®å¤ AddRouters ç¼åä¸è´æ§ |
| | | 2. Task 2 â ä¿®å¤ QueryAllPositions 空 catch å |
| | | 3. Task 3 â ä¿®å¤ IRouterService æ¥å£ï¼å»æ public + æ°å¢ç¾åï¼ |
| | | 4. Task 4 â å®ç° ClearRouterCache |
| | | 5. Task 5 â å®ç° QueryRoutersByDeviceCode |
| | | 6. Task 6 â å®ç° ExistsRouter 两个éè½½ |
| | | 7. Task 7 â å®ç° GetRouterCount 两个éè½½ |
| | | 8. Task 8 â å®ç° DeleteRouters |
| | | 9. Task 9 â ç¼è¯éªè¯ |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # RouterService é»è¾ä¿®å¤ä¸æ°æ¹æ³è®¾è®¡ |
| | | |
| | | > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:writing-plans to create implementation plan. |
| | | |
| | | **Goal:** ä¿®å¤ `RouterService` ä¸å·²åç°çé»è¾éè¯¯ï¼æ°å¢ 5 ä¸ªè·¯ç±æ¥è¯¢/ç®¡çæ¹æ³ï¼å¹¶æ´æ°æ¥å£å±ã |
| | | |
| | | **Architecture:** å¨ç°æ `RouterService` åºç¡ä¸æ°å¢ç¼åç®¡çæ¹æ³åè·¯ç±æ¥è¯¢å¢å¼ºæ¹æ³ï¼ä¿æç°æç¼åæ¶æä¸åã |
| | | |
| | | **Tech Stack:** ASP.NET Core 6.0, HybridCacheService, SqlSugar ORM |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãç°æé»è¾é®é¢ä¿®å¤ |
| | | |
| | | ### 1.1 AddRouters ç¼åä¸è´æ§ |
| | | |
| | | **é®é¢**ï¼`BaseDal.AddData` å `_cacheService.AddOrUpdate` ä¹é´æ ä¿æ¤ã妿 `AddOrUpdate` æå¼å¸¸ï¼DB å·²åå
¥ä½ç¼åæªæ´æ°ï¼ä¸æ¬¡æ¥è¯¢è¯»å°æ§æ°æ®ã |
| | | |
| | | **ä¿®å¤**ï¼ä½¿ç¨ try-finally é»è¾ï¼ä¿è¯ DB åå
¥ååæ´æ°ç¼åã妿ç¼åæ´æ°å¤±è´¥ï¼ä¸æ¬¡æ¥è¯¢ä¼ä» DB èªå¨é建ç¼åï¼`GetOrAdd` æå è½½ä¿è¯ï¼ã |
| | | |
| | | ### 1.2 QueryAllPositions 空 catch å |
| | | |
| | | **é®é¢**ï¼catch åä»
ææ³¨éï¼æ å®é
æ¥å¿è®°å½ãå¼å¸¸è¢«éé»åæï¼è°ç¨æ¹æ æ³åºå"æ²¡ææ°æ®"å"æ¥è¯¢å¤±è´¥"ã |
| | | |
| | | **ä¿®å¤**ï¼å¢å `ConsoleHelper.WriteErrorLine` è®°å½é误ã |
| | | |
| | | ### 1.3 æ¥å£å± public 修饰符 |
| | | |
| | | **é®é¢**ï¼`IRouterService` ä¸çæ¹æ³ç¾åæå¤ä½ç `public` 修饰符ã |
| | | |
| | | **ä¿®å¤**ï¼ç§»é¤æ¥å£æ¹æ³ä¸ç `public` 修饰符ã |
| | | |
| | | --- |
| | | |
| | | ## äºãæ°å¢æ¹æ³è®¾è®¡ |
| | | |
| | | ### 2.1 ClearRouterCache() |
| | | |
| | | æ¸
é¤ `Router:AllRouters:In` å `Router:AllRouters:Out` 两个ç¼åé®ã |
| | | |
| | | **ç¾å**ï¼`void ClearRouterCache()` |
| | | **å®ç°**ï¼ |
| | | ```csharp |
| | | _cacheService.Remove("Router:AllRouters:In"); |
| | | _cacheService.Remove("Router:AllRouters:Out"); |
| | | ``` |
| | | |
| | | ### 2.2 QueryRoutersByDeviceCode(string deviceCode) |
| | | |
| | | æ¥è¯¢ç»è¿æå®è®¾å¤çææè·¯ç±ï¼åå¹¶å
¥å£/åºå£ç±»åï¼ã |
| | | |
| | | **ç¾å**ï¼`List<Dt_Router> QueryRoutersByDeviceCode(string deviceCode)` |
| | | **é»è¾**ï¼ä»ç¼åå è½½ In + Out è·¯ç±ï¼çé `ChildPosiDeviceCode == deviceCode` çè·¯ç±ã |
| | | **ç¼å**ï¼ä¸ç¬å ç¼åï¼ç´æ¥ä½¿ç¨ç°æ `GetAllRoutersFromCache` è·åæ°æ®ã |
| | | |
| | | ### 2.3 ExistsRouterï¼ä¸¤ä¸ªéè½½ï¼ |
| | | |
| | | 夿䏤ç¹ä¹é´æ¯å¦åå¨è·¯ç±ã |
| | | |
| | | **ç¾å**ï¼ |
| | | - `bool ExistsRouter(string startPosi, string endPosi)` â å
¨ç±»å |
| | | - `bool ExistsRouter(string startPosi, string endPosi, int routeType)` â æå®ç±»å |
| | | |
| | | **é»è¾**ï¼è°ç¨ `FindRoutesInMemory`ï¼è¿å `routers.Count > 0`ã |
| | | |
| | | ### 2.4 GetRouterCountï¼ä¸¤ä¸ªéè½½ï¼ |
| | | |
| | | è¿åè·¯ç±æ°éã |
| | | |
| | | **ç¾å**ï¼ |
| | | - `int GetRouterCount()` â åå¹¶ In + Out æ»æ° |
| | | - `int GetRouterCount(int routeType)` â æå®ç±»åæ°é |
| | | |
| | | **å®ç°**ï¼ä»ç¼åè·åå `.Count`ã |
| | | |
| | | ### 2.5 DeleteRouters(List<long> routerIds) |
| | | |
| | | æ¹éå é¤æå® ID çè·¯ç±ï¼å é¤å忥æ¸
é¤å¯¹åºç±»åç¼åã |
| | | |
| | | **ç¾å**ï¼`WebResponseContent DeleteRouters(List<long> routerIds)` |
| | | **é»è¾**ï¼ |
| | | 1. æ¥åºå¾
å é¤è·¯ç±åèªç `InOutType` |
| | | 2. `BaseDal.DeleteData` æ¹éå é¤ |
| | | 3. æ ¹æ®æ¶åç `InOutType` æ¸
é¤å¯¹åºç¼åé® |
| | | 4. è¿å `WebResponseContent` |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãæ¶åæä»¶ |
| | | |
| | | | æä»¶ | æ¹å¨ | |
| | | |------|------| |
| | | | `WIDESEAWCS_QuartzJob/Service/RouterService.cs` | ä¿®å¤é»è¾ + æ°å¢æ¹æ³å®ç° | |
| | | | `WIDESEAWCS_QuartzJob/Service/IRouterService.cs` | æ¥å£æ°å¢æ¹æ³ç¾åï¼å»æå¤ä½ `public` | |
| | | |
| | | --- |
| | | |
| | | ## åãç¼å鮿±æ» |
| | | |
| | | | é® | ç¨é | |
| | | |----|------| |
| | | | `Router:AllRouters:In` | å
¥å£ç±»åå
¨éè·¯ç± | |
| | | | `Router:AllRouters:Out` | åºå£ç±»åå
¨éè·¯ç± | |
| | | | `System:DevicePositions:{deviceCode}` | `QueryAllPositions` å·²æç¼åï¼ä¸å¨æ¬æ¹æ¡èå´å
| |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 任塿¥å¿å¢å¼ºè®¾è®¡ææ¡£ |
| | | |
| | | ## æ¦è¿° |
| | | |
| | | 为 `RobotJob`ã`ConveyorLineNewJob`ã`StackerCraneJob` ä¸ä¸ªæ¨¡åæ·»å å®åçæ¥å¿è®°å½åè½ã |
| | | |
| | | ## æ¥å¿è§è |
| | | |
| | | ### æ¥å¿çº§å«å®ä¹ï¼ä¸¥æ ¼æè¯ä¹ï¼ |
| | | |
| | | | çº§å« | ç¨é | 示ä¾åºæ¯ | |
| | | |------|------|----------| |
| | | | `Info` | æ£å¸¸æµç¨èç¹ | ä»»å¡å¼å§å¤çãå½ä»¤ä¸åæåãç¶æè½¬æ¢å®æ | |
| | | | `Warn` | éè¦å
³æ³¨ä½éé误 | 客æ·ç«¯æè¿éè¯ãç«å°ä¸å¯ç¨ãçæ¬å²çª | |
| | | | `Error` | å¼å¸¸/失败 | WMS è°ç¨å¤±è´¥ãå½ä»¤åé失败ã任塿¥è¯¢å¤±è´¥ | |
| | | | `Debug` | 详ç»ä¿¡æ¯ | 轮询æä½ãç¼å读åï¼å¯éï¼ | |
| | | |
| | | ### æ¥å¿è¾åºæ¹å¼ |
| | | |
| | | 1. **ILogger<T>** - éè¿ä¾èµæ³¨å
¥æç¶ç±»ä¼ é |
| | | 2. **QuartzLogger** - 弿¥æä»¶æ¥å¿ï¼åæ¶è®°å½ |
| | | |
| | | ```csharp |
| | | // æ 忥å¿åæ³ |
| | | _logger.LogInformation("æ¶æ¯å
容"); |
| | | QuartzLogger.Info("æ¶æ¯å
容", source); |
| | | ``` |
| | | |
| | | ## ä¿®æ¹æ¸
å |
| | | |
| | | ### RobotJob 模å |
| | | |
| | | #### RobotJob.cs |
| | | - ç¶æï¼å·²æ ILoggerï¼æ éä¿®æ¹ |
| | | |
| | | #### RobotClientManager.cs |
| | | - æ·»å `ILogger<RobotClientManager>` |
| | | - ä¿®æ£æè¿æ¥å¿ï¼Warn â Infoï¼å®¢æ·ç«¯æå¼æ¯æ£å¸¸æµç¨ï¼ |
| | | - æ·»å EnsureClientSubscribed ä¸çéè¯/ä¸å¯ç¨æ¥å¿ |
| | | |
| | | #### RobotTaskProcessor.cs |
| | | - æ·»å `ILogger<RobotTaskProcessor>` |
| | | - ä¿®æ£ SendSocketRobotPickAsyncï¼Error â Infoï¼æåä¸ååºè®°å½ Infoï¼ |
| | | - æ·»å HandleInboundTaskAsync ç WMS è°ç¨ç»ææ¥å¿ |
| | | |
| | | #### RobotStateManager.cs |
| | | - æ·»å `ILogger<RobotStateManager>` |
| | | - æé 彿°ç GetOrCreateState æ·»å Info æ¥å¿ |
| | | - TryUpdateStateSafely æ·»å çæ¬å²çª Warn æ¥å¿ |
| | | |
| | | #### RobotMessageHandler.cs |
| | | - å·²æ ILoggerï¼å·²æè¯å¥½æ¥å¿ï¼ä¿æä¸å |
| | | |
| | | #### RobotWorkflowOrchestrator.cs |
| | | - æ·»å `ILogger<RobotWorkflowOrchestrator>` |
| | | - ExecuteAsync æ·»å ç¶ææºå³çæ¥å¿ï¼æ»¡è¶³æ¡ä»¶æ¶è®°å½ Infoï¼ |
| | | - HandlePickFinishedStateAsync æ·»å æ¾è´§æä»¤ä¸åæ¥å¿ |
| | | - HandlePutFinishedStateAsync æ·»å åè´§æä»¤ä¸åæ¥å¿ |
| | | |
| | | ### ConveyorLineNewJob 模å |
| | | |
| | | #### CommonConveyorLineNewJob.cs |
| | | - æ·»å `ILogger<CommonConveyorLineNewJob>` |
| | | - Execute æ¹æ³ï¼ |
| | | - åè®¾å¤æ°é为 0ï¼Info |
| | | - Parallel.For å¼å§ï¼Debug |
| | | - å½ä»¤ä¸ºç©ºè·³è¿ï¼Debug |
| | | - WCS_ACK å¤çï¼Debug |
| | | - æ£æ¥æçä½ç½®ï¼Info |
| | | - PLC_STB æ£æ¥ï¼Debug |
| | | - æ æ¡ç 请æ±åºåºï¼Info |
| | | - æä»»å¡å·å¤çä»»å¡ï¼Info |
| | | - å¼å¸¸æè·ï¼Error |
| | | - ProcessTaskState æ¹æ³ï¼æ·»å åç¶æåæ¯çå
¥å£æ¥å¿ |
| | | |
| | | #### ConveyorLineDispatchHandler.cs |
| | | - æ·»å `ILogger<ConveyorLineDispatchHandler>` |
| | | - HeartBeatï¼Debug |
| | | - RequestInboundï¼Infoï¼å
¥åºè¯·æ±å¼å§ï¼ |
| | | - RequestInNextAddressï¼Infoï¼å
¥åºä¸ä¸å°åï¼ |
| | | - ConveyorLineInFinishï¼Infoï¼å
¥åºå®æï¼ |
| | | - RequestOutboundï¼Infoï¼åºåºè¯·æ±ï¼ |
| | | - RequestOutNextAddressï¼Infoï¼åºåºä¸ä¸å°åï¼ |
| | | - ConveyorLineOutFinishï¼Infoï¼åºåºå®æï¼ |
| | | |
| | | #### ConveyorLineTaskFilter.cs |
| | | - æ·»å `ILogger<ConveyorLineTaskFilter>` |
| | | - QueryPendingTaskï¼Debug |
| | | - QueryExecutingTaskï¼Debug |
| | | - RequestWmsTaskï¼Infoï¼WMS 请æ±ï¼ |
| | | |
| | | #### ConveyorLineTargetAddressSelector.cs |
| | | - æ·»å `ILogger<ConveyorLineTargetAddressSelector>` |
| | | - HandleInboundNextAddressï¼Debug |
| | | - HandleOutboundNextAddressï¼Debug |
| | | - HandleDeviceRequestï¼Debug |
| | | - ProcessDeviceRequestï¼Debug |
| | | |
| | | ### StackerCraneJob 模å |
| | | |
| | | #### CommonStackerCraneJob.cs |
| | | - æ·»å `ILogger<CommonStackerCraneJob>` |
| | | - Execute æ¹æ³ï¼ |
| | | - åæ°æ æï¼Warn |
| | | - äºä»¶è®¢é
ï¼Info |
| | | - ä»»å¡å®ææ£æ¥ï¼Debug |
| | | - ä¸å¯åéä»»å¡ï¼Debug |
| | | - ä»»å¡éæ©ç»æï¼Infoï¼éä¸ä»»å¡å·ææ ä»»å¡ï¼ |
| | | - å½ä»¤æå»ºç»æï¼Info |
| | | - å½ä»¤åéç»æï¼Info |
| | | - å¼å¸¸æè·ï¼Error |
| | | - CommonStackerCrane_StackerCraneTaskCompletedEventHandlerï¼Info |
| | | - LoadConfig 失败ï¼Warn |
| | | |
| | | #### StackerCraneTaskSelector.cs |
| | | - æ·»å `ILogger<StackerCraneTaskSelector>` |
| | | - SelectTaskï¼Infoï¼ä»»å¡éæ©å¼å§ãéæ©ç»æï¼ |
| | | - TrySelectOutboundTaskï¼Debug |
| | | - IsOutTaskStationAvailableï¼Infoï¼ç«å°å¯ç¨/ä¸å¯ç¨ï¼ |
| | | - TryAddTaskFromWmsï¼Info |
| | | |
| | | #### StackerCraneCommandBuilder.cs |
| | | - æ·»å `ILogger<StackerCraneCommandBuilder>` |
| | | - ConvertToStackerCraneTaskCommandï¼Infoï¼å½ä»¤ç±»åãä»»å¡å·ï¼ |
| | | - GetCommandTypeï¼Debug |
| | | - BuildInboundCommandï¼Infoï¼å
¥åºå½ä»¤æå»ºï¼ |
| | | - BuildOutboundCommandï¼Infoï¼åºåºå½ä»¤æå»ºï¼ |
| | | - BuildRelocationCommandï¼Infoï¼ç§»åºå½ä»¤æå»ºï¼ |
| | | - å°åè§£æå¤±è´¥ï¼Error |
| | | |
| | | ## ILogger ä¾èµä¼ éæ¹æ¡ |
| | | |
| | | 对äºéè¿ `new` ç´æ¥å®ä¾åçè¾
å©ç±»ï¼éè¿ç¶ç±»æé 彿°ä¼ å
¥ ILoggerï¼ |
| | | |
| | | ```csharp |
| | | // è¾
å©ç±»æ¥æ¶ ILogger |
| | | public class RobotStateManager |
| | | { |
| | | private readonly ILogger _logger; |
| | | public RobotStateManager(ICacheService cache, ILogger<RobotStateManager> logger) |
| | | { |
| | | _logger = logger; |
| | | } |
| | | } |
| | | |
| | | // Job å¨å建è¾
å©ç±»æ¶ä¼ å
¥èªå·±ç logger |
| | | public RobotJob(..., ILogger<RobotJob> logger) |
| | | { |
| | | _stateManager = new RobotStateManager(cache, logger); |
| | | } |
| | | ``` |
| | | |
| | | ## éä¿®æ£çæ¥å¿è¯ä¹é®é¢ |
| | | |
| | | | ä½ç½® | ååæ³ | ä¿®æ£å | |
| | | |------|--------|--------| |
| | | | RobotTaskProcessor.SendSocketRobotPickAsync | QuartzLogger.Error (æåæ¶) | QuartzLogger.Info | |
| | | | RobotClientManager.EnsureClientSubscribed | QuartzLogger.Info (å¼å¸¸æ¶) | QuartzLogger.Error | |
| | | | RobotClientManager.OnRobotReceived | QuartzLogger.Warn (æè¿) | QuartzLogger.Info | |
| | | |
| | | ## éªæ¶æ å |
| | | |
| | | 1. ææå
³é®ä¸å¡èç¹æ Info æ¥å¿ |
| | | 2. å¼å¸¸æ
嵿 Error æ¥å¿å¹¶å
å«å¼å¸¸ä¿¡æ¯ |
| | | 3. éè¦å
³æ³¨çæ
嵿 Warn æ¥å¿ |
| | | 4. æ¥å¿åæ¶è¾åºå° ILogger å QuartzLogger |
| | | 5. æ¥å¿æ¶æ¯æ¸
æ°ï¼å
å«å
³é®ä¸ä¸æï¼å¦ä»»å¡å·ã设å¤ç¼ç ï¼ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Newtonsoft.Json; |
| | | using System.Collections.Generic; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_DTO.MES; |
| | | |
| | | namespace WIDESEA_BasicService |
| | | { |
| | | /// <summary> |
| | | /// MESæå¡å®ç° - é西顷å»è½æºç§æMESç³»ç»å¯¹æ¥ |
| | | /// </summary> |
| | | public class MesService : IMesService |
| | | { |
| | | private readonly HttpClientHelper _httpClient; |
| | | private readonly string _baseUrl; |
| | | private readonly string _authorization; |
| | | |
| | | private const string BindContainerPath = "/EquipmentService/api/v1/BindContainer"; |
| | | private const string UnBindContainerPath = "/EquipmentService/api/v1/UnBindContainer"; |
| | | private const string ContainerNgReportPath = "/EquipmentService/api/v1/ContainerNgReport"; |
| | | private const string InboundInContainerPath = "/EquipmentService/api/v1/InboundInContainer"; |
| | | private const string OutboundInContainerPath = "/EquipmentService/api/v1/OutboundInContainer"; |
| | | |
| | | public MesService(HttpClientHelper httpClient) |
| | | { |
| | | _httpClient = httpClient; |
| | | _baseUrl = AppSettings.Get("MES:BaseUrl").TrimEnd('/'); |
| | | _authorization = AppSettings.Get("MES:Authorization"); |
| | | } |
| | | |
| | | private HttpRequestConfig BuildConfig() |
| | | { |
| | | return new HttpRequestConfig |
| | | { |
| | | Headers = new Dictionary<string, string> |
| | | { |
| | | { "Authorization", _authorization } |
| | | }, |
| | | TimeoutMs = 30000, |
| | | MaxRetryCount = 0, |
| | | EnableLogging = true |
| | | }; |
| | | } |
| | | |
| | | private HttpResponseResult<MesResponse> Post<T>(string url, T request) |
| | | { |
| | | string json = JsonConvert.SerializeObject(request); |
| | | return _httpClient.Post<MesResponse>(url, json, "application/json", BuildConfig()); |
| | | } |
| | | |
| | | public HttpResponseResult<MesResponse> BindContainer(BindContainerRequest request) |
| | | { |
| | | return Post(_baseUrl + BindContainerPath, request); |
| | | } |
| | | |
| | | public HttpResponseResult<MesResponse> UnBindContainer(UnBindContainerRequest request) |
| | | { |
| | | return Post(_baseUrl + UnBindContainerPath, request); |
| | | } |
| | | |
| | | public HttpResponseResult<MesResponse> ContainerNgReport(ContainerNgReportRequest request) |
| | | { |
| | | return Post(_baseUrl + ContainerNgReportPath, request); |
| | | } |
| | | |
| | | public HttpResponseResult<MesResponse> InboundInContainer(InboundInContainerRequest request) |
| | | { |
| | | return Post(_baseUrl + InboundInContainerPath, request); |
| | | } |
| | | |
| | | public HttpResponseResult<MesResponse> OutboundInContainer(OutboundInContainerRequest request) |
| | | { |
| | | return Post(_baseUrl + OutboundInContainerPath, request); |
| | | } |
| | | } |
| | | } |
| | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\WIDESEA_IBasicService\WIDESEA_IBasicService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_IRecordService\WIDESEA_IRecordService.csproj" /> |
| | | <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | #region æççµè¯ç»å® |
| | | |
| | | /// <summary> |
| | | /// æççµè¯ç»å® - è¯·æ± |
| | | /// </summary> |
| | | public class BindContainerRequest |
| | | { |
| | | /// <summary> |
| | | /// 设å¤ç¼ç |
| | | /// </summary> |
| | | public string EquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èµæºç¼ç |
| | | /// </summary> |
| | | public string ResourceCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨æ¬å°æ¶é´ |
| | | /// </summary> |
| | | public DateTime LocalTime { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æçç |
| | | /// </summary> |
| | | public string ContainerCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ç»å®ççµè¯æ¡ç å表 |
| | | /// </summary> |
| | | public List<ContainerSfcItem> ContainerSfcList { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æä½ç±»åï¼0-é»è®¤ 1-è¿ç« 2-åºç« 3-è¿åºç« |
| | | /// </summary> |
| | | public int OperationType { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æççµè¯é¡¹ |
| | | /// </summary> |
| | | public class ContainerSfcItem |
| | | { |
| | | /// <summary> |
| | | /// çµè¯ç |
| | | /// </summary> |
| | | public string Sfc { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ä½ç½®ä¿¡æ¯ |
| | | /// </summary> |
| | | public string Location { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æççµè¯è§£ç» |
| | | |
| | | /// <summary> |
| | | /// æççµè¯è§£ç» - è¯·æ± |
| | | /// </summary> |
| | | public class UnBindContainerRequest |
| | | { |
| | | /// <summary> |
| | | /// 设å¤ç¼ç |
| | | /// </summary> |
| | | public string EquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èµæºç¼ç |
| | | /// </summary> |
| | | public string ResourceCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨æ¬å°æ¶é´ |
| | | /// </summary> |
| | | public DateTime LocalTime { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æçç |
| | | /// </summary> |
| | | public string ContainCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµè¯æ¡ç ç» |
| | | /// </summary> |
| | | public List<string> SfcList { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æçNGçµè¯ä¸æ¥ |
| | | |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥ - è¯·æ± |
| | | /// </summary> |
| | | public class ContainerNgReportRequest |
| | | { |
| | | /// <summary> |
| | | /// 设å¤ç¼ç |
| | | /// </summary> |
| | | public string EquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èµæºç¼ç |
| | | /// </summary> |
| | | public string ResourceCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨æ¬å°æ¶é´ |
| | | /// </summary> |
| | | public DateTime LocalTime { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æçç |
| | | /// </summary> |
| | | public string ContainerCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯æ¡ç å表 |
| | | /// </summary> |
| | | public List<NgSfcItem> NgSfcList { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// NGçµè¯é¡¹ |
| | | /// </summary> |
| | | public class NgSfcItem |
| | | { |
| | | /// <summary> |
| | | /// äº§åæ¡ç |
| | | /// </summary> |
| | | public string Sfc { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NG代ç |
| | | /// </summary> |
| | | public string NgCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGè®¾å¤ |
| | | /// </summary> |
| | | public string NgEquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// NGèµæº |
| | | /// </summary> |
| | | public string NgResourceCode { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æçè¿ç« |
| | | |
| | | /// <summary> |
| | | /// æçè¿ç« - è¯·æ± |
| | | /// </summary> |
| | | public class InboundInContainerRequest |
| | | { |
| | | /// <summary> |
| | | /// 设å¤ç¼ç |
| | | /// </summary> |
| | | public string EquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èµæºç¼ç |
| | | /// </summary> |
| | | public string ResourceCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨æ¬å°æ¶é´ |
| | | /// </summary> |
| | | public DateTime LocalTime { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æçç |
| | | /// </summary> |
| | | public string ContainerCode { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region æçåºç« |
| | | |
| | | /// <summary> |
| | | /// æçåºç« - è¯·æ± |
| | | /// </summary> |
| | | public class OutboundInContainerRequest |
| | | { |
| | | /// <summary> |
| | | /// 设å¤ç¼ç |
| | | /// </summary> |
| | | public string EquipmentCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èµæºç¼ç |
| | | /// </summary> |
| | | public string ResourceCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è°ç¨æ¬å°æ¶é´ |
| | | /// </summary> |
| | | public DateTime LocalTime { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æçç |
| | | /// </summary> |
| | | public string ContainerCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 产ååæ°å表 |
| | | /// </summary> |
| | | public List<ParamItem> ParamList { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 忰项 |
| | | /// </summary> |
| | | public class ParamItem |
| | | { |
| | | /// <summary> |
| | | /// åæ°ç¼ç |
| | | /// </summary> |
| | | public string ParamCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åæ°å¼ |
| | | /// </summary> |
| | | public string ParamValue { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ééåæ°çæ¶é´ |
| | | /// </summary> |
| | | public DateTime CollectionTime { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace WIDESEA_DTO.MES |
| | | { |
| | | /// <summary> |
| | | /// MESæ¥å£ç»ä¸ååº |
| | | /// </summary> |
| | | public class MesResponse |
| | | { |
| | | /// <summary> |
| | | /// æ§è¡ä»£ç ï¼0-æåï¼å
¶ä»-失败 |
| | | /// </summary> |
| | | public int Code { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è¿åä¿¡æ¯ |
| | | /// </summary> |
| | | public string Msg { get; set; } |
| | | |
| | | /// <summary> |
| | | /// æ¯å¦æå |
| | | /// </summary> |
| | | public bool IsSuccess => Code == 0; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System.Net.Http; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_DTO.MES; |
| | | |
| | | namespace WIDESEA_IBasicService |
| | | { |
| | | /// <summary> |
| | | /// MESæå¡æ¥å£ - é西顷å»è½æºç§æMESç³»ç»å¯¹æ¥ |
| | | /// </summary> |
| | | public interface IMesService : IDependency |
| | | { |
| | | /// <summary> |
| | | /// æççµè¯ç»å® |
| | | /// </summary> |
| | | HttpResponseResult<MesResponse> BindContainer(BindContainerRequest request); |
| | | |
| | | /// <summary> |
| | | /// æççµè¯è§£ç» |
| | | /// </summary> |
| | | HttpResponseResult<MesResponse> UnBindContainer(UnBindContainerRequest request); |
| | | |
| | | /// <summary> |
| | | /// æçNGçµè¯ä¸æ¥ |
| | | /// </summary> |
| | | HttpResponseResult<MesResponse> ContainerNgReport(ContainerNgReportRequest request); |
| | | |
| | | /// <summary> |
| | | /// æçè¿ç« |
| | | /// </summary> |
| | | HttpResponseResult<MesResponse> InboundInContainer(InboundInContainerRequest request); |
| | | |
| | | /// <summary> |
| | | /// æçåºç« |
| | | /// </summary> |
| | | HttpResponseResult<MesResponse> OutboundInContainer(OutboundInContainerRequest request); |
| | | } |
| | | } |
| | |
| | | public async Task<WebResponseContent> GroupPalletAsync(StockDTO stock) |
| | | { |
| | | WebResponseContent content = new WebResponseContent(); |
| | | var now = DateTime.Now; |
| | | var details = stock.Details.Select(item => new Dt_StockInfoDetail |
| | | try |
| | | { |
| | | MaterielCode = "çµè¯", |
| | | MaterielName = "çµè¯", |
| | | StockQuantity = item.Quantity, |
| | | Unit = "PCS", |
| | | Creater = "system", |
| | | OrderNo = "111", |
| | | ProductionDate = now.ToString(), |
| | | EffectiveDate = now.AddYears(1).ToString(), |
| | | SerialNumber = item.CellBarcode, |
| | | InboundOrderRowNo = item.Channel, |
| | | Status = StockStatusEmun.ç»çæå.GetHashCode(), |
| | | }).ToList(); |
| | | |
| | | return await ExecuteWithinTransactionAsync(async () => |
| | | { |
| | | var existingStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo); |
| | | var result = false; |
| | | if (existingStock != null) |
| | | var now = DateTime.Now; |
| | | var details = stock.Details.Select(item => new Dt_StockInfoDetail |
| | | { |
| | | details.ForEach(d => d.StockId = existingStock.Id); |
| | | result = await StockInfoDetailService.Repository.AddDataAsync(details) > 0; |
| | | return result ? content.OK("ç»çæå") : content.Error("ç»ç失败"); |
| | | } |
| | | |
| | | var entity = new Dt_StockInfo |
| | | { |
| | | PalletCode = stock.TargetPalletNo, |
| | | //WarehouseId = stock.WarehouseId > 0 ? stock.WarehouseId : 1, |
| | | WarehouseId = 1, |
| | | StockStatus = StockStatusEmun.ç»çæå.GetHashCode(), |
| | | MaterielCode = "çµè¯", |
| | | MaterielName = "çµè¯", |
| | | StockQuantity = item.Quantity, |
| | | Unit = "PCS", |
| | | Creater = "system", |
| | | Details = details |
| | | }; |
| | | OrderNo = "111", |
| | | ProductionDate = now.ToString(), |
| | | EffectiveDate = now.AddYears(1).ToString(), |
| | | SerialNumber = item.CellBarcode, |
| | | InboundOrderRowNo = item.Channel, |
| | | Status = StockStatusEmun.ç»çæå.GetHashCode(), |
| | | }).ToList(); |
| | | |
| | | result = StockInfoService.Repository.AddData(entity, x => x.Details); |
| | | return result ? content.OK("ç»çæå") : content.Error("ç»ç失败"); |
| | | }); |
| | | return await ExecuteWithinTransactionAsync(async () => |
| | | { |
| | | var existingStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo); |
| | | var result = false; |
| | | if (existingStock != null) |
| | | { |
| | | details.ForEach(d => d.StockId = existingStock.Id); |
| | | result = await StockInfoDetailService.Repository.AddDataAsync(details) > 0; |
| | | return result ? content.OK("ç»çæå") : content.Error("ç»ç失败"); |
| | | } |
| | | |
| | | var entity = new Dt_StockInfo |
| | | { |
| | | PalletCode = stock.TargetPalletNo, |
| | | //WarehouseId = stock.WarehouseId > 0 ? stock.WarehouseId : 1, |
| | | WarehouseId = 1, |
| | | StockStatus = StockStatusEmun.ç»çæå.GetHashCode(), |
| | | Creater = "system", |
| | | Details = details |
| | | }; |
| | | |
| | | result = StockInfoService.Repository.AddData(entity, x => x.Details); |
| | | return result ? content.OK("ç»çæå") : content.Error("ç»ç失败"); |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return content.Error($"ç»ç失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | public async Task<WebResponseContent> ChangePalletAsync(StockDTO stock) |
| | | { |
| | | WebResponseContent content = new WebResponseContent(); |
| | | if (stock == null || |
| | | string.IsNullOrWhiteSpace(stock.TargetPalletNo) || |
| | | string.IsNullOrWhiteSpace(stock.SourcePalletNo) || |
| | | string.Equals(stock.SourcePalletNo, stock.TargetPalletNo, StringComparison.OrdinalIgnoreCase)) |
| | | try |
| | | { |
| | | return content.Error("æºæçå·ä¸ç®æ æçå·ç¸å"); |
| | | } |
| | | |
| | | return await ExecuteWithinTransactionAsync(async () => |
| | | { |
| | | var sourceStock = await StockInfoService.Repository.QueryDataNavFirstAsync(s => s.PalletCode == stock.SourcePalletNo); |
| | | if (sourceStock == null) return content.Error("æºæçä¸åå¨"); |
| | | |
| | | var targetStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo); |
| | | if (targetStock == null) |
| | | if (stock == null || |
| | | string.IsNullOrWhiteSpace(stock.TargetPalletNo) || |
| | | string.IsNullOrWhiteSpace(stock.SourcePalletNo) || |
| | | string.Equals(stock.SourcePalletNo, stock.TargetPalletNo, StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | var newStock = new Dt_StockInfo |
| | | { |
| | | PalletCode = stock.TargetPalletNo, |
| | | WarehouseId = sourceStock.WarehouseId, |
| | | StockStatus = StockStatusEmun.ç»çæå.GetHashCode(), |
| | | Creater = "system", |
| | | }; |
| | | |
| | | var newId = StockInfoService.Repository.AddData(newStock); |
| | | if (newId <= 0) return content.Error("æ¢ç失败"); |
| | | |
| | | targetStock = newStock; |
| | | targetStock.Id = newId; |
| | | return content.Error("æºæçå·ä¸ç®æ æçå·ç¸å"); |
| | | } |
| | | |
| | | var serialNumbers = stock.Details.Select(d => d.Channel).Distinct().ToList(); |
| | | if (!serialNumbers.Any()) return content.Error("æªæ¾å°ææçåºåå·"); |
| | | return await ExecuteWithinTransactionAsync(async () => |
| | | { |
| | | var sourceStock = await StockInfoService.Repository.QueryDataNavFirstAsync(s => s.PalletCode == stock.SourcePalletNo); |
| | | if (sourceStock == null) return content.Error("æºæçä¸åå¨"); |
| | | |
| | | var detailEntities = StockInfoDetailService.Repository.QueryData( |
| | | d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.InboundOrderRowNo)); |
| | | if (!detailEntities.Any()) return content.Error("æªæ¾å°ææçåºåæç»"); |
| | | var targetStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.TargetPalletNo); |
| | | if (targetStock == null) |
| | | { |
| | | var newStock = new Dt_StockInfo |
| | | { |
| | | PalletCode = stock.TargetPalletNo, |
| | | WarehouseId = sourceStock.WarehouseId, |
| | | StockStatus = StockStatusEmun.ç»çæå.GetHashCode(), |
| | | Creater = "system", |
| | | }; |
| | | |
| | | if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "æ¢ç")) <= 0) |
| | | return content.Error("æ¢çåå²è®°å½ä¿å失败"); |
| | | var newId = StockInfoService.Repository.AddData(newStock); |
| | | if (newId <= 0) return content.Error("æ¢ç失败"); |
| | | |
| | | if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock, targetStock }, "æ¢ç")) <= 0) |
| | | return content.Error("æ¢çåå²è®°å½ä¿å失败"); |
| | | targetStock = newStock; |
| | | targetStock.Id = newId; |
| | | } |
| | | |
| | | detailEntities.ForEach(d => d.StockId = targetStock.Id); |
| | | var result = await StockInfoDetailService.Repository.UpdateDataAsync(detailEntities); |
| | | if (!result) return content.Error("æ¢ç失败"); |
| | | return content.OK("æ¢çæå"); |
| | | }); |
| | | var serialNumbers = stock.Details.Select(d => d.Channel).Distinct().ToList(); |
| | | if (!serialNumbers.Any()) return content.Error("æªæ¾å°ææçåºåå·"); |
| | | |
| | | var detailEntities = StockInfoDetailService.Repository.QueryData( |
| | | d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.InboundOrderRowNo)); |
| | | if (!detailEntities.Any()) return content.Error("æªæ¾å°ææçåºåæç»"); |
| | | |
| | | if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "æ¢ç")) <= 0) |
| | | return content.Error("æ¢çåå²è®°å½ä¿å失败"); |
| | | |
| | | if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock, targetStock }, "æ¢ç")) <= 0) |
| | | return content.Error("æ¢çåå²è®°å½ä¿å失败"); |
| | | |
| | | detailEntities.ForEach(d => d.StockId = targetStock.Id); |
| | | var result = await StockInfoDetailService.Repository.UpdateDataAsync(detailEntities); |
| | | if (!result) return content.Error("æ¢ç失败"); |
| | | return content.OK("æ¢çæå"); |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return content.Error($"æ¢ç失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | public async Task<WebResponseContent> SplitPalletAsync(StockDTO stock) |
| | | { |
| | | WebResponseContent content = new WebResponseContent(); |
| | | if (stock == null || string.IsNullOrWhiteSpace(stock.SourcePalletNo)) |
| | | return content.Error("æºæçå·ä¸è½ä¸ºç©º"); |
| | | |
| | | return await ExecuteWithinTransactionAsync(async () => |
| | | try |
| | | { |
| | | var sourceStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo); |
| | | if (sourceStock == null) return content.Error("æºæçä¸åå¨"); |
| | | if (stock == null || string.IsNullOrWhiteSpace(stock.SourcePalletNo)) |
| | | return content.Error("æºæçå·ä¸è½ä¸ºç©º"); |
| | | |
| | | var serialNumbers = stock.Details.Select(d => d.CellBarcode).Distinct().ToList(); |
| | | if (!serialNumbers.Any()) |
| | | return await ExecuteWithinTransactionAsync(async () => |
| | | { |
| | | serialNumbers = sourceStock.Details |
| | | .Where(x => stock.Details.Any(d => d.Channel == x.InboundOrderRowNo)) |
| | | .Select(x => x.SerialNumber) |
| | | .ToList(); |
| | | } |
| | | var sourceStock = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo); |
| | | if (sourceStock == null) return content.Error("æºæçä¸åå¨"); |
| | | |
| | | var detailEntities = StockInfoDetailService.Repository.QueryData( |
| | | d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber)); |
| | | if (!detailEntities.Any()) return content.Error("æªæ¾å°ææçåºåæç»"); |
| | | var serialNumbers = stock.Details.Select(d => d.CellBarcode).Distinct().ToList(); |
| | | if (!serialNumbers.Any()) |
| | | { |
| | | serialNumbers = sourceStock.Details |
| | | .Where(x => stock.Details.Any(d => d.Channel == x.InboundOrderRowNo)) |
| | | .Select(x => x.SerialNumber) |
| | | .ToList(); |
| | | } |
| | | |
| | | if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "æç")) <= 0) |
| | | return content.Error("æçåå²è®°å½ä¿å失败"); |
| | | var detailEntities = StockInfoDetailService.Repository.QueryData( |
| | | d => d.StockId == sourceStock.Id && serialNumbers.Contains(d.SerialNumber)); |
| | | if (!detailEntities.Any()) return content.Error("æªæ¾å°ææçåºåæç»"); |
| | | |
| | | if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock }, "æç")) <= 0) |
| | | return content.Error("æçåå²è®°å½ä¿å失败"); |
| | | if (await StockInfoDetail_HtyService.Repository.AddDataAsync(CreateDetailHistory(detailEntities, "æç")) <= 0) |
| | | return content.Error("æçåå²è®°å½ä¿å失败"); |
| | | |
| | | var result = await StockInfoDetailService.Repository.DeleteDataAsync(detailEntities); |
| | | if (!result) return content.Error("æç失败"); |
| | | return content.OK("æçæå"); |
| | | }); |
| | | if (await StockInfo_HtyService.Repository.AddDataAsync(CreateStockHistory(new[] { sourceStock }, "æç")) <= 0) |
| | | return content.Error("æçåå²è®°å½ä¿å失败"); |
| | | |
| | | var result = await StockInfoDetailService.Repository.DeleteDataAsync(detailEntities); |
| | | if (!result) return content.Error("æç失败"); |
| | | return content.OK("æçæå"); |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return content.Error($"æç失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | }; |
| | | var taskDtos = task.Adapt<WMSTaskDTO>(); |
| | | |
| | | var addResult = await BaseDal.AddDataAsync(task); |
| | | var addResult = await BaseDal.AddDataAsync(task) > 0; |
| | | if (!addResult) |
| | | return WebResponseContent.Instance.Error("ä»»å¡å建失败"); |
| | | return WebResponseContent.Instance.OK("ä»»å¡å建æå", taskDtos); |
| | |
| | | "GW": [ "11001", "11010", "11068" ], |
| | | "CW": [ "10080" ] |
| | | } |
| | | }, |
| | | "MES": { |
| | | "BaseUrl": "http://localhost:5000", |
| | | "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjMwMTcyNzM5Mzk5NzYxOTIwIiwibmFtZSI6IlBBQ0voo4XphY3lt6XkvY0wMSIsIkZhY3RvcnlJZCI6IjEyMzQ1NiIsIlNpdGVJZCI6IjEyMzQ1NiIsIkNvZGUiOiJYWExQQUNLMDRBRTAzMiIsIm5iZiI6MTcwNDE4NzY5MCwiZXhwIjoyMTQ1NjkxNjkwLCJpc3MiOiJodHRwczovL3d3dy5oeW1zb24uY29tIiwiYXVkIjoiaHR0cHM6Ly93d3cuaHltc29uLmNvbSJ9.An1BE7UgfcSP--LtTOmmmWVE2RQFPDahLkDg1xy5KqY" |
| | | } |
| | | } |
| | |
| | | serverId: 'robot-client-1', |
| | | listenIp: '127.0.0.1', |
| | | listenPort: 2000, |
| | | localPort: 2001 |
| | | localPort: 62212 |
| | | }) |
| | | |
| | | const status = ref<RobotClientStatusResponse | null>(null) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 好çï¼æå·²ç»å°æ¨æä¾çäºä¸ªæ¥å£ææ¡£ä¼åä¸ºæ´æ¸
æ°ãç»ææ´ç»ä¸çMarkdownæ ¼å¼ã主è¦ä¼åç¹å
æ¬ï¼ |
| | | |
| | | 1. **ç»ä¸æ ¼å¼**ï¼å°æææ¥å£ç说æã请æ±å段ãååºå段çéç¨ä¸è´çæ é¢å±çº§åè¡¨æ ¼ç»æã |
| | | 2. **ä¿®æ£é误**ï¼ä¿®æ£äºâæçåºç«âæ¥å£åç§°åâéç¨å·¥åºâä¸çææ¾ç¬è¯¯ã |
| | | 3. **å¢å¼ºå¯è¯»æ§**ï¼ä½¿ç¨å ç²ã代ç åçMarkdownå
ç´ ï¼ä½¿å
³é®ä¿¡æ¯åæ¥æç¤ºä¾æ´çªåºã |
| | | 4. **è¡¥å
说æ**ï¼å¨æ¥æç¤ºä¾ä¸ï¼å°`body`é¨åç¨JSON代ç åé«äº®æ¾ç¤ºï¼ä¾¿äºé
读ã |
| | | |
| | | --- |
| | | |
| | | ### **1.1. æççµè¯ç»å®** |
| | | |
| | | #### **1.1.1. è§¦åæ¡ä»¶** |
| | | |
| | | 1. ç¨äºçµè¯ç ç»å®æçç ã |
| | | |
| | | #### **1.1.2. æ¥å£è¯´æ** |
| | | |
| | | | é¡¹ç® | å
容 | |
| | | | :----------- | :--------------------------------------- | |
| | | | **æ¥å£åç§°** | æççµè¯ç»å®ï¼å¨å¶å&容å¨ï¼ | |
| | | | **æ¥å£æ¹å¼** | WebApi | |
| | | | **è¯·æ±æ¹å¼** | POST | |
| | | | **åéæ¹** | EQP | |
| | | | **æ¥æ¶æ¹** | MES | |
| | | | **æ¥å£å°å** | `/EquipmentService/api/v1/BindContainer` | |
| | | | **éç¨å·¥åº** | çµè¯ç ç»å®æçç | |
| | | |
| | | #### **1.1.3. è¯·æ±æ¥æ** |
| | | |
| | | **Header åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :---------- | :------- | :---------- | |
| | | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | |
| | | |
| | | **Body åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :----------------- | :----------------- | :------------------------------------- | :--------------------- | |
| | | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | |
| | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | |
| | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | |
| | | | 4 | `ContainerCode` | æçç | STRING | | |
| | | | 5 | `ContainerSfcList` | ç»å®ççµè¯æ¡ç å表 | ARRAY OBJECT | | |
| | | | 6 | `OperationType` | æä½ç±»å | 0-é»è®¤<br>1-è¿ç«<br>2-åºç«<br>3-è¿åºç« | æ¢æææçä¸ä¼ 3ï¼å
¶ä½0 | |
| | | |
| | | **`ContainerSfcList` æ°æ®éåæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :--------- | :------- | :------- | :--- | |
| | | | 1 | `Sfc` | çµè¯ç | STRING | | |
| | | | 2 | `Location` | ä½ç½®ä¿¡æ¯ | STRING | | |
| | | |
| | | **æ¥æç¤ºä¾** |
| | | |
| | | ```json |
| | | { |
| | | "equipmentCode": "string", |
| | | "resourceCode": "string", |
| | | "localTime": "2024-03-01T03:12:29.265Z", |
| | | "containerCode": "string", |
| | | "containerSfcList": [ |
| | | { |
| | | "sfc": "string", |
| | | "location": "string" |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | #### **1.1.4. ååºå段** |
| | | |
| | | | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :----- | :------- | :------- | :-------------------- | |
| | | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å
¶ä»: 失败 | |
| | | | `msg` | è¿åä¿¡æ¯ | STRING | å
å«å
·ä½çéè¯¯ä¿¡æ¯ | |
| | | |
| | | --- |
| | | |
| | | ### **1.2. æççµè¯è§£ç»** |
| | | |
| | | #### **1.2.1. è§¦åæ¡ä»¶** |
| | | |
| | | 1. ç¨äºæçç è§£ç»çµè¯ç»ã |
| | | |
| | | #### **1.2.2. æ¥å£è¯´æ** |
| | | |
| | | | é¡¹ç® | å
容 | |
| | | | :----------- | :----------------------------------------- | |
| | | | **æ¥å£åç§°** | æççµè¯è§£ç»ï¼å¨å¶å&容å¨ï¼ | |
| | | | **æ¥å£æ¹å¼** | WebApi | |
| | | | **è¯·æ±æ¹å¼** | POST | |
| | | | **åéæ¹** | EQP | |
| | | | **æ¥æ¶æ¹** | MES | |
| | | | **æ¥å£å°å** | `/EquipmentService/api/v1/UnBindContainer` | |
| | | | **éç¨å·¥åº** | æçç è§£ç»çµè¯ç» | |
| | | |
| | | #### **1.2.3. è¯·æ±æ¥æ** |
| | | |
| | | **Header åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :---------- | :------- | :---------- | |
| | | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | |
| | | |
| | | **Body åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :----------- | :----------- | :--- | |
| | | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | |
| | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | |
| | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | |
| | | | 4 | `ContainCode` | æçç | STRING | | |
| | | | 5 | `SfcList` | çµè¯æ¡ç ç» | ARRAY STRING | | |
| | | |
| | | **æ¥æç¤ºä¾** |
| | | |
| | | ```json |
| | | { |
| | | "equipmentCode": "string", |
| | | "resourceCode": "string", |
| | | "localTime": "2024-03-01T03:13:12.482Z", |
| | | "containCode": "string", |
| | | "sfcList": [ |
| | | "string" |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | #### **1.2.4. ååºå段** |
| | | |
| | | | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :----- | :------- | :------- | :-------------------- | |
| | | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å
¶ä»: 失败 | |
| | | | `msg` | è¿åä¿¡æ¯ | STRING | å
å«å
·ä½çéè¯¯ä¿¡æ¯ | |
| | | |
| | | --- |
| | | |
| | | ### **1.3. æçNGçµè¯ä¸æ¥** |
| | | |
| | | #### **1.3.1. è§¦åæ¡ä»¶** |
| | | |
| | | 1. æçåå¨NGæ¡ç ï¼å¨æçæè
OCV2, OCV3æ¶ï¼éè¦ä¸æ¥NGçµè¯ã |
| | | |
| | | #### **1.3.2. æ¥å£è¯´æ** |
| | | |
| | | | é¡¹ç® | å
容 | |
| | | | :----------- | :------------------------------------------- | |
| | | | **æ¥å£åç§°** | æ¡ç ç»å®ï¼å¨å¶å&容å¨ï¼ | |
| | | | **æ¥å£æ¹å¼** | WebApi | |
| | | | **è¯·æ±æ¹å¼** | POST | |
| | | | **åéæ¹** | EQP | |
| | | | **æ¥æ¶æ¹** | MES | |
| | | | **æ¥å£å°å** | `/EquipmentService/api/v1/ContainerNgReport` | |
| | | | **éç¨å·¥åº** | æçNGçµè¯ä¸æ¥ | |
| | | |
| | | #### **1.3.3. è¯·æ±æ¥æ** |
| | | |
| | | **Header åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :---------- | :------- | :---------- | |
| | | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | |
| | | |
| | | **Body åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :------------------- | :----------- | :--- | |
| | | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | |
| | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | |
| | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | |
| | | | 4 | `ContainerCode` | æçç | STRING | | |
| | | | 5 | `NgSfcList` | ç»å®NGççµè¯æ¡ç å表 | ARRAY OBJECT | | |
| | | |
| | | **`NgSfcList` æ°æ®éåæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :---------------- | :------- | :------- | :--- | |
| | | | 1 | `sfc` | äº§åæ¡ç | STRING | | |
| | | | 2 | `ngCode` | NG代ç | STRING | | |
| | | | 3 | `ngEquipmentCode` | NGè®¾å¤ | STRING | | |
| | | | 4 | `ngResourceCode` | NGèµæº | STRING | | |
| | | |
| | | **æ¥æç¤ºä¾** |
| | | |
| | | ```json |
| | | { |
| | | "equipmentCode": "string", |
| | | "resourceCode": "string", |
| | | "localTime": "2024-03-01T03:42:55.528Z", |
| | | "containerCode": "string", |
| | | "ngSfcList": [ |
| | | "string" |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | #### **1.3.4. ååºå段** |
| | | |
| | | | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :----- | :------- | :------- | :-------------------- | |
| | | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å
¶ä»: 失败 | |
| | | | `msg` | è¿åä¿¡æ¯ | STRING | å
å«å
·ä½çéè¯¯ä¿¡æ¯ | |
| | | |
| | | --- |
| | | |
| | | ### **1.4. æçè¿ç«ï¼å®¹å¨è¿ç«ï¼** |
| | | |
| | | #### **1.4.1. è§¦åæ¡ä»¶** |
| | | |
| | | 1. æçè¿ç«ã |
| | | |
| | | #### **1.4.2. æ¥å£è¯´æ** |
| | | |
| | | | é¡¹ç® | å
容 | |
| | | | :----------- | :-------------------------------------------- | |
| | | | **æ¥å£åç§°** | æçè¿ç«ï¼å®¹å¨è¿ç«ï¼ | |
| | | | **æ¥å£æ¹å¼** | WebApi | |
| | | | **è¯·æ±æ¹å¼** | POST | |
| | | | **åéæ¹** | EQP | |
| | | | **æ¥æ¶æ¹** | MES | |
| | | | **æ¥å£å°å** | `/EquipmentService/api/v1/InboundInContainer` | |
| | | | **éç¨å·¥åº** | æçè¿ç« | |
| | | |
| | | #### **1.4.3. è¯·æ±æ¥æ** |
| | | |
| | | **Header åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :---------- | :------- | :---------- | |
| | | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | |
| | | |
| | | **Body åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :----------- | :------- | :--- | |
| | | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | |
| | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | |
| | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | |
| | | | 4 | `ContainerCode` | æçç | STRING | | |
| | | |
| | | **æ¥æç¤ºä¾** |
| | | |
| | | ```json |
| | | { |
| | | "equipmentCode": "string", |
| | | "resourceCode": "string", |
| | | "localTime": "2024-03-01T03:43:42.144Z", |
| | | "containerCode": "string" |
| | | } |
| | | ``` |
| | | |
| | | #### **1.4.4. ååºå段** |
| | | |
| | | | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :----- | :------- | :------- | :-------------------- | |
| | | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å
¶ä»: 失败 | |
| | | | `msg` | è¿åä¿¡æ¯ | STRING | å
å«å
·ä½çéè¯¯ä¿¡æ¯ | |
| | | |
| | | --- |
| | | |
| | | ### **1.5. æçåºç«ï¼å®¹å¨åºç«ï¼** |
| | | |
| | | #### **1.5.1. è§¦åæ¡ä»¶** |
| | | |
| | | 1. æçåºç«ã |
| | | |
| | | #### **1.5.2. æ¥å£è¯´æ** |
| | | |
| | | | é¡¹ç® | å
容 | |
| | | | :----------- | :--------------------------------------------- | |
| | | | **æ¥å£åç§°** | æçåºç«ï¼å®¹å¨åºç«ï¼ | |
| | | | **æ¥å£æ¹å¼** | WebApi | |
| | | | **è¯·æ±æ¹å¼** | POST | |
| | | | **åéæ¹** | EQP | |
| | | | **æ¥æ¶æ¹** | MES | |
| | | | **æ¥å£å°å** | `/EquipmentService/api/v1/OutboundInContainer` | |
| | | | **éç¨å·¥åº** | æçåºç« | |
| | | |
| | | #### **1.5.3. è¯·æ±æ¥æ** |
| | | |
| | | **Header åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :---------- | :------- | :---------- | |
| | | | 1 | `Authorization` | MES认è¯ä¿¡æ¯ | STRING | å¼ç±MESæä¾ | |
| | | |
| | | **Body åæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :-------------- | :----------- | :----------- | :--- | |
| | | | 1 | `EquipmentCode` | 设å¤ç¼ç | STRING | | |
| | | | 2 | `ResourceCode` | èµæºç¼ç | STRING | | |
| | | | 3 | `LocalTime` | è°ç¨æ¬å°æ¶é´ | DATETIME | | |
| | | | 4 | `ContainerCode` | æçç | STRING | | |
| | | | 5 | `ParamList` | 产ååæ°å表 | ARRAY OBJECT | | |
| | | |
| | | **`ParamList` æ°æ®éåæ®µ** |
| | | |
| | | | åºå· | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :--- | :--------------- | :------- | :------- | :------------- | |
| | | | 1 | `ParamCode` | åæ°ç¼ç | STRING | å·¥èºæä¾ | |
| | | | 2 | `ParamValue` | åæ°å¼ | STRING | | |
| | | | 3 | `CollectionTime` | æ¶é´æ³ | DATETIME | ééåæ°çæ¶é´ | |
| | | |
| | | **æ¥æç¤ºä¾** |
| | | |
| | | ```json |
| | | { |
| | | "equipmentCode": "string", |
| | | "resourceCode": "string", |
| | | "localTime": "2024-03-01T03:43:42.144Z", |
| | | "containerCode": "string", |
| | | "paramList": [ |
| | | { |
| | | "paramCode": "string", |
| | | "paramValue": "string", |
| | | "collectionTime": "2024-03-01T03:43:42.144Z" |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | #### **1.5.4. ååºå段** |
| | | |
| | | | åæ®µ | å
容 | æ°æ®ç±»å | 夿³¨ | |
| | | | :----- | :------- | :------- | :-------------------- | |
| | | | `code` | æ§è¡ä»£ç | INT | 0: æå<br>å
¶ä»: 失败 | |
| | | | `msg` | è¿åä¿¡æ¯ | STRING | å
å«å
·ä½çéè¯¯ä¿¡æ¯ | |