Quellcode durchsuchen

Merge branch 'develop-test' of http://192.168.10.198:3000/Skyunion/SKMC.API-v3 into develop-test

Mihuan vor 5 Tagen
Ursprung
Commit
6f113804d5

+ 61 - 0
SKMC.API/Common/CommonUtil.cs

@@ -112,6 +112,67 @@ namespace SKMC.Api.Common
             }
         }
 
+        /// <summary>
+        /// 自动根据字节长度,返回对应有符号数值类型
+        /// </summary>
+        public static object AutoConvertToValue(byte[] bytes)
+        {
+            if (bytes == null || bytes.Length == 0)
+                return 0;
+
+            switch(bytes.Length)
+            {
+                case 2:
+                    return BitConverter.ToInt16(bytes, 0);
+                case 4:
+                    return BitConverter.ToInt32(bytes, 0);
+                case 8:
+                    return BitConverter.ToInt64(bytes, 0);
+                default:
+                    return BitConverter.ToInt64(bytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// 自动根据字节长度,返回对应无符号数值类型
+        /// </summary>
+        public static object AutoConvertToUnsignedValue(byte[] bytes)
+        {
+            if (bytes == null || bytes.Length == 0)
+                return 0;
+
+            switch (bytes.Length)
+            {
+                case 2:
+                    return BitConverter.ToUInt16(bytes, 0);
+                case 4:
+                    return BitConverter.ToUInt32(bytes, 0);
+                case 8:
+                    return BitConverter.ToUInt64(bytes, 0);
+                default:
+                    return BitConverter.ToUInt64(bytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// 将 long 转为 固定长度的字节数组(小端)
+        /// 支持:1、2、4、8 字节
+        /// 不足自动补0,超长自动截断
+        /// </summary>
+        public static byte[] ToFixedBytes(long value, int fixedLength)
+        {
+            // 支持 1/2/4/8 字节
+            // 先转成标准8字节
+            byte[] bytes = BitConverter.GetBytes(value);
+            byte[] result = new byte[fixedLength];
+
+            // 取前面fixedLength 字节
+            int copyLen = Math.Min(bytes.Length, fixedLength);
+            Array.Copy(bytes, result, copyLen);
+
+            return result;
+        }
+
         /// <summary>
         /// Float类型変換
         /// </summary>

+ 6 - 0
SKMC.API/Common/DB/SqlSugarTool.cs

@@ -33,6 +33,12 @@ namespace SKMC.Api.Common.DB
         /// <returns></returns>
         public static SqlSugarClient GetRuntimeDB() => GetDB("DB_RUNDATA");
 
+        /// <summary>
+        /// 从硬件库文件获取数据库实例
+        /// </summary>
+        /// <returns></returns>
+        public static SqlSugarClient GetDeviceDB() => GetDB("DB_DEVICE");
+
         private static SqlSugarClient GetDB(string dbName)
         {
             SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()

+ 2 - 0
SKMC.API/Common/Logger/ILogger.cs

@@ -24,7 +24,9 @@ namespace SKMC.Api.Common.Logger
         void Warn(string message);
 
         void Error(string message, Exception ex = null);
+        void Error(Exception ex,string message);
 
         void Fatal(string message, Exception ex = null);
+        void Fatal(Exception ex,string message);
     }
 }

+ 8 - 1
SKMC.API/Common/Logger/Log4netLogger.cs

@@ -46,10 +46,17 @@ namespace SKMC.Api.Common.Logger
         {
             log.Error(message, ex);
         }
-
+        public void Error(Exception ex, string message)
+        {
+            log.Error(message, ex);
+        }
         public void Fatal(string message, Exception ex = null)
         {
             log.Fatal(message, ex);
         }
+        public void Fatal(Exception ex, string message)
+        {
+            log.Fatal(message,ex);
+        }
     }
 }

+ 5 - 1
SKMC.API/Common/Logger/LogDataService.cs

@@ -14,6 +14,10 @@ namespace SKMC.Api.Common.Logger
 
         private readonly object lockObject = new object();
         public ObservableCollection<LoggingEventModel> LogEventModels { get; set; } = new ObservableCollection<LoggingEventModel>();
+        public ObservableCollection<LoggingEventModel> LogProductionModels { get; set; } = new ObservableCollection<LoggingEventModel>();
+        public ObservableCollection<LoggingEventModel> LogParameterModels { get; set; } = new ObservableCollection<LoggingEventModel>();
+        public ObservableCollection<LoggingEventModel> LogProcessModels { get; set; } = new ObservableCollection<LoggingEventModel>();
+        public ObservableCollection<LoggingEventModel> LogActionModels { get; set; } = new ObservableCollection<LoggingEventModel>();
 
         public static LogDataService Instance()
         {
@@ -23,7 +27,7 @@ namespace SKMC.Api.Common.Logger
 
         private LogDataService()
         {
-            BindingOperations.EnableCollectionSynchronization(LogEventModels, lockObject);
+            //BindingOperations.EnableCollectionSynchronization(LogEventModels, lockObject);
         }
     }
 }

+ 34 - 1
SKMC.API/Common/Logger/LogFactory.cs

@@ -12,7 +12,7 @@ namespace SKMC.Api.Common.Logger
         /// <summary>
         /// "Log4Net" 或 "NLog"
         /// </summary>
-        private static readonly string LoggerType = "Log4Net";
+        private static readonly string LoggerType = "NLog";
 
         public static ILogger Get(Type type)
         {
@@ -32,6 +32,7 @@ namespace SKMC.Api.Common.Logger
 
         public static ILogger Get([CallerFilePath] string callerFilePath = "")
         {
+
             var callerType = System.IO.Path.GetFileNameWithoutExtension(callerFilePath);
             if (LoggerType == "Log4Net")
             {
@@ -46,5 +47,37 @@ namespace SKMC.Api.Common.Logger
                 throw new NotSupportedException($"Logger type {LoggerType} is not supported.");
             }
         }
+
+        public static ILogger Get(LogCategory logCategory)
+        {
+            if (logCategory == LogCategory.ProductionLogger)
+            {
+                return new NLogLogger("ProductionLogger");
+            }
+            else if(logCategory == LogCategory.ParameterLogger)
+            {
+                return new NLogLogger("ParameterLogger");
+            }
+            else if (logCategory == LogCategory.ProcessLogger)
+            {
+                return new NLogLogger("ProcessLogger");
+            }
+            else if(logCategory == LogCategory.ActionLogger)
+            {
+                return new NLogLogger("ActionLogger");
+            }
+            else
+            {
+                throw new NotSupportedException($"Logger category {logCategory.ToString()} is not supported.");
+            }
+        }
+        public enum LogCategory
+        {
+            ProductionLogger,
+            ParameterLogger,
+            ProcessLogger,
+            ActionLogger
+        }
+
     }
 }

+ 30 - 0
SKMC.API/Common/Logger/LoggingActionTarget.cs

@@ -0,0 +1,30 @@
+using NLog;
+using NLog.Targets;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Common.Logger
+{
+    /// <summary>
+    /// NLog 扩展
+    /// </summary>
+    public class LoggingActionTarget : TargetWithLayout
+    {
+        static readonly int LOGVIEW_MAXLINE = 1000;
+
+        private readonly LogDataService logDataService = LogDataService.Instance();
+
+        protected override void Write(LogEventInfo loggingEvent)
+        {
+            logDataService.LogActionModels.Insert(0, new LoggingEventModel(loggingEvent));
+
+            if (logDataService.LogActionModels.Count == LOGVIEW_MAXLINE)
+            {
+                logDataService.LogActionModels.RemoveAt(LOGVIEW_MAXLINE - 1);
+            }
+        }
+    }
+}

+ 1 - 1
SKMC.API/Common/Logger/LoggingEventModel.cs

@@ -34,7 +34,7 @@ namespace SKMC.Api.Common.Logger
             Level = loggingEvent.Level.Name;
             Thread = Convert.ToString(System.Threading.Thread.CurrentThread.ManagedThreadId);
             Message = loggingEvent.Message;
-            Exception = loggingEvent.Exception.Message;
+            Exception = loggingEvent.Exception?.Message;
         }
     }
 }

+ 30 - 0
SKMC.API/Common/Logger/LoggingParameterTarget.cs

@@ -0,0 +1,30 @@
+using NLog;
+using NLog.Targets;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Common.Logger
+{
+    /// <summary>
+    /// NLog 扩展
+    /// </summary>
+    public class LoggingParameterTarget : TargetWithLayout
+    {
+        static readonly int LOGVIEW_MAXLINE = 1000;
+
+        private readonly LogDataService logDataService = LogDataService.Instance();
+
+        protected override void Write(LogEventInfo loggingEvent)
+        {
+            logDataService.LogParameterModels.Insert(0, new LoggingEventModel(loggingEvent));
+
+            if (logDataService.LogParameterModels.Count == LOGVIEW_MAXLINE)
+            {
+                logDataService.LogParameterModels.RemoveAt(LOGVIEW_MAXLINE - 1);
+            }
+        }
+    }
+}

+ 30 - 0
SKMC.API/Common/Logger/LoggingProcessTarget.cs

@@ -0,0 +1,30 @@
+using NLog;
+using NLog.Targets;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Common.Logger
+{
+    /// <summary>
+    /// NLog 扩展
+    /// </summary>
+    public class LoggingProcessTarget : TargetWithLayout
+    {
+        static readonly int LOGVIEW_MAXLINE = 1000;
+
+        private readonly LogDataService logDataService = LogDataService.Instance();
+
+        protected override void Write(LogEventInfo loggingEvent)
+        {
+            logDataService.LogProcessModels.Insert(0, new LoggingEventModel(loggingEvent));
+
+            if (logDataService.LogProcessModels.Count == LOGVIEW_MAXLINE)
+            {
+                logDataService.LogProcessModels.RemoveAt(LOGVIEW_MAXLINE - 1);
+            }
+        }
+    }
+}

+ 30 - 0
SKMC.API/Common/Logger/LoggingProductionTarget.cs

@@ -0,0 +1,30 @@
+using NLog;
+using NLog.Targets;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Common.Logger
+{
+    /// <summary>
+    /// NLog 扩展
+    /// </summary>
+    public class LoggingProductionTarget: TargetWithLayout
+    {
+        static readonly int LOGVIEW_MAXLINE = 1000;
+
+        private readonly LogDataService logDataService = LogDataService.Instance();
+
+        protected override void Write(LogEventInfo loggingEvent)
+        {
+            logDataService.LogProductionModels.Insert(0, new LoggingEventModel(loggingEvent));
+
+            if (logDataService.LogProductionModels.Count == LOGVIEW_MAXLINE)
+            {
+                logDataService.LogProductionModels.RemoveAt(LOGVIEW_MAXLINE - 1);
+            }
+        }
+    }
+}

+ 9 - 1
SKMC.API/Common/Logger/NLogLogger.cs

@@ -28,7 +28,7 @@ namespace SKMC.Api.Common.Logger
 
         public void Trace(string message)
         {
-            throw new NotImplementedException();
+            log.Trace(message);
         }
 
         public void Warn(string message)
@@ -40,10 +40,18 @@ namespace SKMC.Api.Common.Logger
         {
             log.Error(message, ex);
         }
+        public void Error(Exception ex,string message)
+        {
+            log.Error(ex, message);
+        }
 
         public void Fatal(string message, Exception ex = null)
         {
             log.Fatal(message, ex);
         }
+        public void Fatal(Exception ex,string message)
+        {
+            log.Fatal(ex, message);
+        }
     }
 }

+ 55 - 6
SKMC.API/Common/Tasks/TaskToken.cs

@@ -2,23 +2,72 @@
 
 namespace SKMC.Api.Common.Tasks
 {
+    /// <summary>
+    /// 任务执行控制令牌,用于控制线程/工站任务的执行状态
+    /// 主要包含三种控制能力:
+    /// 1. 暂停 / 恢复(Pause / Resume)
+    /// 2. 取消执行(Cancel / Stop)
+    /// 3. 等待执行许可(SetWaitPoint)
+    /// 注意:
+    /// - Pause / Resume 属于可重复状态控制
+    /// - Cancel / Stop 为一次性终止操作,调用后不可恢复
+    /// </summary>
     public class TaskToken
     {
-        public CancellationTokenSource TokenSource { get; set; } = new CancellationTokenSource();
+        public int Id { get; set; }
 
-        public CancellationToken Token { get; set; }
+        public CancellationTokenSource TokenSource { get; set; } = new CancellationTokenSource();
 
         public ManualResetEvent ResetEvent { get; set; } = new ManualResetEvent(true);
 
-        public TaskToken()
+        /// <summary>
+        /// 添加中断点
+        /// </summary>
+        public void SetWaitPoint()
         {
-            Token = TokenSource.Token;
+            ResetEvent.WaitOne();
         }
 
-        public void SetWaitPoint()
+        /// <summary>
+        /// 取消
+        /// </summary>
+        public void Cancel()
         {
-            ResetEvent.WaitOne();
+            TokenSource.Cancel();
+        }
+
+        /// <summary>
+        /// 是否取消
+        /// </summary>
+        /// <returns></returns>
+        public bool IsCancelled()
+        {
+            return TokenSource.IsCancellationRequested;
         }
 
+        /// <summary>
+        /// 暂停
+        /// </summary>
+        public void Pause()
+        {
+            ResetEvent.Reset();
+        }
+
+        /// <summary>
+        /// 恢复
+        /// </summary>
+        public void Resume()
+        {
+            ResetEvent.Set();
+        }
+
+        /// <summary>
+        /// 停止
+        /// </summary>
+        public void Stop()
+        {
+            Cancel();
+            Resume();
+        }
     }
 }

+ 104 - 31
SKMC.API/Common/Tasks/TaskTokener.cs

@@ -2,21 +2,50 @@
 
 namespace SKMC.Api.Common.Tasks
 {
+    /// <summary>
+    /// TaskToken(任务执行控制令牌)容器
+    /// 用于管理多个TaskToken相关的线程执行暂停、恢复、停止
+    /// </summary>
     public class TaskTokener
     {
 
         private static readonly ConcurrentDictionary<int, TaskToken> taskTokens = new ConcurrentDictionary<int, TaskToken>();
 
-        public static void Add(int id)
+        /// <summary>
+        /// 创建一个TaskToken
+        /// </summary>
+        /// <param name="id">TaskToken的Id</param>
+        public static TaskToken Add(int id)
         {
             if (taskTokens.ContainsKey(id))
             {
-                taskTokens.TryRemove(id, out var taskToken);
-                taskToken?.TokenSource.Cancel();
+                taskTokens.TryRemove(id, out var taskTokenGet);
+                taskTokenGet?.Cancel();
             };
-            taskTokens.TryAdd(id, new TaskToken());
+            TaskToken taskTokenNew = new TaskToken { Id = id };
+            bool result = taskTokens.TryAdd(id, taskTokenNew);
+            if (result) return taskTokenNew;
+            return null;
         }
 
+        /// <summary>
+        /// 重新创建所有的TaskToken
+        /// </summary>
+        public static void AddAll()
+        {
+            foreach (int stationId in taskTokens.Keys)
+            {
+                TaskToken taskToken = GetTaskToken(stationId);
+                if (taskToken == null) continue;
+                Add(stationId);
+            }
+        }
+
+        /// <summary>
+        /// 根据Id获取TaskToken
+        /// </summary>
+        /// <param name="id">TaskToken的Id</param>
+        /// <returns></returns>
         public static TaskToken GetTaskToken(int id)
         {
             if (!taskTokens.ContainsKey(id))
@@ -26,29 +55,59 @@ namespace SKMC.Api.Common.Tasks
             return taskTokens[id];
         }
 
-        public static void SetWaitPoint(int id)
+        /// <summary>
+        /// 设置TaskToken中断点(在Stop之前有效)
+        /// </summary>
+        /// <param name="id"></param>
+        public static void SetWaitPoint(int id) => SetWaitPoint(GetTaskToken(id));
+
+        /// <summary>
+        /// 设置TaskToken中断点(在Stop之前有效)
+        /// </summary>
+        /// <param name="taskToken"></param>
+        public static void SetWaitPoint(TaskToken taskToken)
         {
-            TaskToken taskToken = GetTaskToken(id);
             if (taskToken == null) return;
             taskToken.SetWaitPoint();
         }
 
+        /// <summary>
+        /// TaskToken是否已取消/停止
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public static bool IsCancelled(int id) => IsCancelled(GetTaskToken(id));
 
-        public static bool IsCancelled(int id)
+        /// <summary>
+        /// TaskToken是否已取消/停止
+        /// </summary>
+        /// <param name="taskToken"></param>
+        /// <returns></returns>
+        public static bool IsCancelled(TaskToken taskToken)
         {
-            TaskToken taskToken = GetTaskToken(id);
             if (taskToken == null) return true;
-            bool result = taskToken.TokenSource.IsCancellationRequested;
-            return result;
+            return taskToken.IsCancelled();
         }
 
-        public static void Pause(int id)
+        /// <summary>
+        /// 暂停TaskToken
+        /// </summary>
+        /// <param name="id"></param>
+        public static void Pause(int id) => Pause(GetTaskToken(id));
+
+        /// <summary>
+        /// 暂停TaskToken
+        /// </summary>
+        /// <param name="taskToken"></param>
+        public static void Pause(TaskToken taskToken)
         {
-            TaskToken taskToken = GetTaskToken(id);
             if (taskToken == null) return;
-            taskToken.ResetEvent.Reset();
+            taskToken.Pause();
         }
 
+        /// <summary>
+        /// 暂停所有的TaskToken
+        /// </summary>
         public static void PauseAll()
         {
             foreach (int stationId in taskTokens.Keys)
@@ -57,13 +116,25 @@ namespace SKMC.Api.Common.Tasks
             }
         }
 
-        public static void Resume(int id)
+        /// <summary>
+        /// 恢复TaskToken
+        /// </summary>
+        /// <param name="id"></param>
+        public static void Resume(int id) => Resume(GetTaskToken(id));
+
+        /// <summary>
+        /// 恢复TaskToken
+        /// </summary>
+        /// <param name="taskToken"></param>
+        public static void Resume(TaskToken taskToken)
         {
-            TaskToken taskToken = GetTaskToken(id);
             if (taskToken == null) return;
-            taskToken.ResetEvent.Set();
+            taskToken.Resume();
         }
 
+        /// <summary>
+        /// 恢复所有的TaskToken
+        /// </summary>
         public static void ResumeAll()
         {
             foreach (int station in taskTokens.Keys)
@@ -72,30 +143,32 @@ namespace SKMC.Api.Common.Tasks
             }
         }
 
-        public static void Stop(int id)
+        /// <summary>
+        /// 停止TaskToken
+        /// </summary>
+        /// <param name="id"></param>
+        public static void Stop(int id) => Stop(GetTaskToken(id));
+
+        /// <summary>
+        /// 停止TaskToken
+        /// </summary>
+        /// <param name="taskToken"></param>
+        public static void Stop(TaskToken taskToken)
         {
-            TaskToken taskToken = GetTaskToken(id);
             if (taskToken == null) return;
-            taskToken.TokenSource.Cancel();
-            taskToken.ResetEvent.Set();
+            taskToken.Stop();
+            //taskTokens.TryRemove(taskToken.Id, out _);
         }
 
+        /// <summary>
+        /// 停止所有的TaskToken
+        /// </summary>
         public static void StopAll()
         {
             foreach (int stationId in taskTokens.Keys)
             {
                 Stop(stationId);
             }
-        }
-
-        public static void RestoreAll()
-        {
-            foreach (int stationId in taskTokens.Keys)
-            {
-                TaskToken taskToken = GetTaskToken(stationId);
-                if (taskToken == null) continue;
-                Add(stationId);
-            }
-        }
+        }    
     }
 }

+ 47 - 0
SKMC.API/Machine/Control/IMachineDriverControl.cs

@@ -0,0 +1,47 @@
+using SKMC.Api.Machine.Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Machine.Control
+{
+    public interface IMachineDriverControl
+    {
+        #region SDO
+        /// <summary>
+        /// 获取所有SDO 配置列表
+        /// </summary>
+        List<ConfigSlaveSDO> GetAllDeviceSdo();
+
+        /// <summary>
+        /// 刷新单个 SDO 参数当前值
+        /// </summary>
+        bool ReadSDOUsageValue(ConfigSlaveSDO sdo, out string stateMsg);
+
+        /// <summary>
+        /// 保存 SDO 到数据库 + 驱动器
+        /// </summary>
+        bool WriteSDORecordedValue(ConfigSlaveSDO sdo, out string stateMsg);
+        #endregion
+
+        #region PDO
+        ///// <summary>
+        ///// 获取所有PDO 配置列表
+        ///// </summary>
+        //List<ConfigSlavePDO> GetAllDevicePdo();
+
+        ///// <summary>
+        ///// 刷新单个 PDO 参数当前值
+        ///// </summary>
+        //bool ReadPDOUsageValue(ConfigSlavePDO sdo, out string stateMsg);
+
+
+        ///// <summary>
+        ///// 保存 PDO 到数据库 + 驱动器
+        ///// </summary>
+        //bool WritePDORecordedValue(ConfigSlavePDO sdo, out string stateMsg);
+        #endregion
+    }
+}

+ 12 - 0
SKMC.API/Machine/Model/ConfigSlavePDO.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Machine.Model
+{
+    public class ConfigSlavePDO : ConfigSlaveSDO
+    {
+    }
+}

+ 97 - 0
SKMC.API/Machine/Model/ConfigSlaveSDO.cs

@@ -0,0 +1,97 @@
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Machine.Model
+{
+    public class ConfigSlaveSDO : BindableBase
+    {
+        private short _slaveNo;
+        private string _paramName;
+        private int _recordedValue;
+        private int _usageValue;
+        private string _range;
+        private string _unit;
+        private string _defaultValue;
+        private int _saveMode;
+        private int _isImmediately;
+        private string _remark;
+        private string _stateMsg;
+        private string _textColor = "Green";
+
+        public short SlaveNo
+        {
+            get { return _slaveNo; }
+            set { _slaveNo = value; RaisePropertyChanged(); }
+        }
+
+        public string ParamName
+        {
+            get { return _paramName; }
+            set { _paramName = value; RaisePropertyChanged(); }
+        }
+
+        public int RecordedValue
+        {
+            get { return _recordedValue; }
+            set { _recordedValue = value; RaisePropertyChanged(); }
+        }
+
+        public int UsageValue
+        {
+            get { return _usageValue; }
+            set { _usageValue = value; RaisePropertyChanged(); }
+        }
+
+        public string Range
+        {
+            get { return _range; }
+            set { _range = value; RaisePropertyChanged(); }
+        }
+
+        public string Unit
+        {
+            get { return _unit; }
+            set { _unit = value; RaisePropertyChanged(); }
+        }
+
+        public string DefaultValue
+        {
+            get { return _defaultValue; }
+            set { _defaultValue = value; RaisePropertyChanged(); }
+        }
+
+        public int SaveMode
+        {
+            get { return _saveMode; }
+            set { _saveMode = value; RaisePropertyChanged(); }
+        }
+
+        public int IsImmediately
+        {
+            get { return _isImmediately; }
+            set { _isImmediately = value; RaisePropertyChanged(); }
+        }
+
+        public string Remark
+        {
+            get { return _remark; }
+            set { _remark = value; RaisePropertyChanged(); }
+        }
+
+        public string StateMsg
+        {
+            get { return _stateMsg; }
+            set { _stateMsg = value; RaisePropertyChanged(); }
+        }
+
+        public string TextColor
+        {
+            get => _textColor;
+            set { _textColor = value; RaisePropertyChanged(); }
+        }
+    }
+}

+ 76 - 0
SKMC.API/Machine/Model/MachineSlaveError.cs

@@ -0,0 +1,76 @@
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Machine.Model
+{
+    public class MachineSlaveError : BindableBase
+    {
+        private string _vendorId;
+        private string _errorCode;
+        private int _errorvalue;
+        private int _assist‌Value;
+        private string _faultName;
+        private string _reason;
+        private string _confirmMethod;
+        private string _handlingMeasures;
+        private string _faultRange;
+
+        public string VendorId
+        {
+            get { return _vendorId; }
+            set { _vendorId = value; RaisePropertyChanged(); }
+        }
+
+        public string ErrorCode
+        {
+            get { return _errorCode; }
+            set { _errorCode = value; RaisePropertyChanged(); }
+        }
+
+        public int ErrorValue
+        {
+            get { return _errorvalue; }
+            set { _errorvalue = value; RaisePropertyChanged(); }
+        }
+
+        public int Assist‌Value
+        {
+            get { return _assist‌Value; }
+            set { _assist‌Value = value; RaisePropertyChanged(); }
+        }
+
+        public string FaultName
+        {
+            get { return _faultName; }
+            set { _faultName = value; RaisePropertyChanged(); }
+        }
+
+        public string Reason
+        {
+            get { return _reason; }
+            set { _reason = value; RaisePropertyChanged(); }
+        }
+
+        public string ConfirmMethod
+        {
+            get { return _confirmMethod; }
+            set { _confirmMethod = value; RaisePropertyChanged(); }
+        }
+
+        public string HandlingMeasures
+        {
+            get { return _handlingMeasures; }
+            set { _handlingMeasures = value; RaisePropertyChanged(); }
+        }
+
+        public string FaultRange
+        {
+            get { return _faultRange; }
+            set { _faultRange = value; RaisePropertyChanged(); }
+        }
+    }
+}

+ 45 - 34
SKMC.API/Motion/Control/IMotionControl.cs

@@ -19,7 +19,8 @@ namespace SKMC.Api.Motion.Control
         void Set(string key, int value);
 
         /// <summary>
-        /// 设置流程站点Id,绑定流程站点的中断点
+        /// 设置流程站点Id,绑定流程站点的TaskToken
+        /// 绑定后可实现电机回零、移动完成后自动设置中断点,更及时更方便的完成Station暂停、恢复、停止
         /// </summary>
         /// <param name="stationId"></param>
         void SetStationId(int stationId);
@@ -31,18 +32,6 @@ namespace SKMC.Api.Motion.Control
         /// <returns></returns>
         int Get(string key);
 
-        /// <summary>
-        /// 控制使能, true: motion控制有效,  false: motion控制无效
-        /// 运动过程中如有电机抛出MotionException, 该控制使能自动失效
-        /// </summary>
-        //void Enable(bool enabled = true);
-
-        /// <summary>
-        /// 控制使能是否有效
-        /// </summary>
-        /// <returns></returns>
-        //bool IsEnable();
-
         /// <summary>
         /// 开启所有电机使能
         /// </summary>
@@ -151,9 +140,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="pointCode">点位码</param>
         /// <param name="speedRound">电机每秒旋转圈数</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void MoveRound(string pointCode, double speedRound, bool waiting = true, double inRange = -1, Action onTimeout = null);
+        void MoveRound(string pointCode, double speedRound, bool waiting = true, 
+            bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的(多个)电机以指定速度运动到点位码
@@ -161,9 +152,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="pointCode">点位码</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void MovePoint(string pointCode, string speedCode = null, bool waiting = true, double inRange = -1, Action onTimeout = null);
+        void MovePoint(string pointCode, string speedCode = null, bool waiting = true, 
+            bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的(多个)电机以指定速度运动到点位码
@@ -171,9 +164,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="recipePoint">点位对象</param>
         /// <param name="recipeSpeed">速度对象, null表示使用该点配置的默认速度</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void MovePoint(RecipePoint recipePoint, RecipeSpeed recipeSpeed = null, bool waiting = true, double inRange = -1, Action onTimeout = null);
+        void MovePoint(RecipePoint recipePoint, RecipeSpeed recipeSpeed = null, bool waiting = true, 
+            bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的(多个)电机以指定速度运动到点位码
@@ -181,9 +176,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="recipePoint">点位对象</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void MovePoint(RecipePoint recipePoint, string speedCode = null, bool waiting = true, double inRange = -1, Action onTimeout = null);
+        void MovePoint(RecipePoint recipePoint, string speedCode = null, bool waiting = true, 
+            bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的(多个)电机以指定速度运动到点位码并能叠加指定偏移量
@@ -192,10 +189,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="posOffsets">各个电机的偏移量数组, 需要按电机绑定顺序赋值</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointFix(string pointCode, double[] posOffsets, string speedCode = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的(多个)电机以指定速度运动到点位码,并能叠加指定偏移量
@@ -204,10 +202,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="posOffsets">各个电机的偏移量数组, 需要按电机绑定顺序赋值</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointFix(RecipePoint recipePoint, double[] posOffsets, string speedCode = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的(多个)电机以指定速度运动到点位码,并能叠加指定偏移量
@@ -216,10 +215,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="posOffsets">各个电机的偏移量数组, 需要按电机绑定顺序赋值</param>
         /// <param name="recipeSpeed">速度对象, null表示使用该点配置的默认速度</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointFix(RecipePoint recipePoint, double[] posOffsets, RecipeSpeed recipeSpeed = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的指定单个电机以指定速度运动到点位码
@@ -228,10 +228,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="axisCode">指定电机的电机码</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointOne(string pointCode, string axisCode, string speedCode = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的指定单个电机以指定速度运动到点位码
@@ -240,10 +241,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="axisCode">指定电机的电机码</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointOne(RecipePoint recipePoint, string axisCode, string speedCode = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的指定单个电机以指定速度运动到点位码
@@ -252,10 +254,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="axisCode">指定电机的电机码</param>
         /// <param name="recipeSpeed">速度对象, null表示使用该点配置的默认速度</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointOne(RecipePoint recipePoint, string axisCode, RecipeSpeed recipeSpeed = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的指定单个电机以指定速度运动到点位码,并能叠加指定偏移量
@@ -265,10 +268,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="axisCode">指定电机的电机码</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointOneFix(string pointCode, double fixset, string axisCode, string speedCode = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的指定单个电机以指定速度运动到点位码,并能叠加指定偏移量
@@ -278,10 +282,11 @@ namespace SKMC.Api.Motion.Control
         /// <param name="axisCode">指定电机的电机码</param>
         /// <param name="recipeSpeed">速度对象, null表示使用该点配置的默认速度</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointOneFix(RecipePoint recipePoint, double fixset, string axisCode, RecipeSpeed recipeSpeed = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 让绑定点位码的指定单个电机以指定速度运动到点位码,并能叠加指定偏移量
@@ -291,21 +296,23 @@ namespace SKMC.Api.Motion.Control
         /// <param name="axisCode">指定电机的电机码</param>
         /// <param name="speedCode">速度码, null表示使用该点配置的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePointOneFix(RecipePoint recipePoint, double fixset, string axisCode, string speedCode = null,
-            bool waiting = true, double inRange = -1, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 聚合多个点位码并同时运动
         /// </summary>
         /// <param name="recipePoints">需要聚合运动的点位对象集合</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="sync">是否同步到达,false: 使用recipeSpeed的速度,true:以recipeSpeed为基准,调整各点位速度</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePoints(List<RecipePoint> recipePoints, RecipeSpeed recipeSpeed,
-            bool waiting = true, double inRange = -1, bool sync = false, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, bool sync = false, Action onTimeout = null);
 
         /// <summary>
         /// 聚合多个点位码并同时运动
@@ -313,47 +320,52 @@ namespace SKMC.Api.Motion.Control
         /// <param name="pointCodes">需要聚合运动的点位码集合</param>
         /// <param name="speedCode">速度码, null表示使用各点位的默认速度码</param>
         /// <param name="waiting">是否等待到位, 默认为true</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="sync">是否同步到达,false: 使用各自的点位中的速度,true:以speedCode为基准,调整各点位速度</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
         void MovePoints(string[] pointCodes, string speedCode = null,
-            bool waiting = true, double inRange = -1, bool sync = false, Action onTimeout = null);
+            bool waiting = true, bool pausePoint = true, double inRange = -1, bool sync = false, Action onTimeout = null);
 
         /// <summary>
         /// 等待电机运动到位
         /// </summary>
         /// <param name="axisCode">电机码</param>
         /// <param name="timeout">超时时间</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void WaitAxis(string axisCode, int timeout = 10000, double inRange = -1, Action onTimeout = null);
+        void WaitAxis(string axisCode, int timeout = 10000, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 等待电机运动到位
         /// </summary>
         /// <param name="motionAxis">电机对象</param>
         /// <param name="timeout">超时时间</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void WaitAxis(MotionAxis motionAxis, int timeout = 10000, double inRange = -1, Action onTimeout = null);
+        void WaitAxis(MotionAxis motionAxis, int timeout = 10000, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 等待点位上所有电机到位
         /// </summary>
         /// <param name="pointCode">点位码</param>
         /// <param name="timeout">超时时间</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void WaitPoint(string pointCode, int timeout = 10000, double inRange = -1, Action onTimeout = null);
+        void WaitPoint(string pointCode, int timeout = 10000, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 等待点位上所有电机到位
         /// </summary>
         /// <param name="recipePoint">点位对象</param>
         /// <param name="timeout">超时时间</param>
+        /// <param name="pausePoint">到位是否设置暂停点, 默认为true</param>
         /// <param name="inRange">整定范围, 单位毫米或者步距</param>
         /// <param name="onTimeout">超时未完成的回调动作</param>
-        void WaitPoint(RecipePoint recipePoint, int timeout = 10000, double inRange = -1, Action onTimeout = null);
+        void WaitPoint(RecipePoint recipePoint, int timeout = 10000, bool pausePoint = true, double inRange = -1, Action onTimeout = null);
 
         /// <summary>
         /// 等待电机组所有电机到位
@@ -385,8 +397,7 @@ namespace SKMC.Api.Motion.Control
         /// <param name="speedCode">速度码</param>
         /// <param name="distance">距离</param>
         /// <param name="waiting">是否等待</param>
-        void MoveRel(string axisCode, string speedCode, double distance, bool waiting = true);
-
+        void MoveRel(string axisCode, string speedCode, double distance, bool waiting = false);
 
         /// <summary>
         /// 电机绝对运动,确保回零后调用

+ 4 - 4
SKMC.API/Motion/Driver/IMotionDriver.cs

@@ -351,8 +351,8 @@ namespace SKMC.Api.Motion.Driver
         /// 写入SDO数据
         /// </summary>
         /// <param name="motionSdo">Sdo对象</param>
-        /// <returns>读取的SDO数据长度</returns>
-        int ReadSdoData(MotionSdo motionSdo);
+        /// <returns>是否读取成功</returns>
+        short ReadSdoData(MotionSdo motionSdo);
 
         /// <summary>
         /// 初始化Pdo配置
@@ -371,8 +371,8 @@ namespace SKMC.Api.Motion.Driver
         /// 读取Pdo数据
         /// </summary>
         /// <param name="motionPdo">Pdo对象</param>
-        /// <returns>读取的PDO数据长度</returns>
-        int ReadPdoData(MotionPdo motionPdo);
+        /// <returns>是否读取成功</returns>
+        short ReadPdoData(MotionPdo motionPdo);
 
         /// <summary>
         /// 写入自定义数据码

+ 16 - 0
SKMC.API/Motion/Driver/IMotionDriverError.cs

@@ -0,0 +1,16 @@
+using SKMC.Api.Machine.Model;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Motion.Driver
+{
+    public interface IMotionDriverError
+    {
+        string GetAxisErrorInfo(short axisNo);
+
+        List<MachineSlaveError> GetAllErrorType();
+    }
+}

+ 5 - 8
SKMC.API/Motion/Model/MotionAxis.cs

@@ -102,6 +102,11 @@ namespace SKMC.Api.Motion.Model
         /// </summary>
         public double InRange { get; set; }
 
+        /// <summary>
+        /// 异常时是否可自动恢复(0:不恢复 1:恢复)
+        /// </summary>
+        public short AutoRecovery { get; set; }
+
         /// <summary>
         /// 是否已停止
         /// </summary>
@@ -112,12 +117,6 @@ namespace SKMC.Api.Motion.Model
         /// </summary>
         public bool IsEnabled => _axisSts.IsEnable == 1;
 
-        /// <summary>
-        /// <para>如果该轴出现异常, 是否会中断其他电机与IO控制</para>
-        /// <para>如果需要对该轴出现异常后进行恢复处理, 为不影响到其他电机与IO控制, 这里需要设置为false</para>
-        /// </summary>
-        public bool CanInterruptAll { get; set; } = true;
-
         /// <summary>
         /// 是否已回零
         /// </summary>
@@ -127,7 +126,6 @@ namespace SKMC.Api.Motion.Model
             set => _axisSts.IsHomed = value ? (byte)1 : (byte)0;
         }
 
-
         private string _name;
 
         /// <summary>
@@ -357,7 +355,6 @@ namespace SKMC.Api.Motion.Model
         /// 当前位置是否在偏移量之内
         /// </summary>
         /// <param name="targetVal"></param>
-        /// <param name="offset"></param>
         /// <returns></returns>
         public bool IsEncInRange(double targetVal)
         {

+ 1 - 1
SKMC.API/Motion/Model/MotionSdo.cs

@@ -39,6 +39,6 @@ namespace SKMC.Api.Motion.Model
         /// <summary>
         /// 数值(10进制)
         /// </summary>
-        public int DataVal { get; set; }
+        public long DataVal { get; set; }
     }
 }

+ 85 - 0
SKMC.API/Nlog.config

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+	<!-- 定义日志输出格式模板 -->
+	<variable name="myLayout" value="[${longdate}] ${level:uppercase=true} [${threadid}][${callsite:className=true:methodName=false:includeNamespace=false:skipFrames=1}] - ${message}${newline}${exception:format=toString}" />
+
+	<!-- 全局设置:定义四个不同的异步文件目标 -->
+	<targets>
+		<!-- 1. 生产日志 (运行生产、机台操作、MES通讯) -->
+		<target name="ProductionFile" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard">
+			<target xsi:type="File"
+                    fileName="D:/SkyUnion/SK.RF3.Data/Log/生产/${shortdate}.log"
+                    layout="${myLayout}"
+                    archiveEvery="Day"
+                    archiveAboveSize="104857600"
+                    archiveNumbering="Sequence"
+                    maxArchiveFiles="30"
+                    concurrentWrites="true"
+                    keepFileOpen="false"
+                    encoding="utf-8"/>
+		</target>
+
+		<!-- 2. 参数日志 (参数修改) -->
+		<target name="ParameterFile" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard">
+			<target xsi:type="File"
+                    fileName="D:/SkyUnion/SK.RF3.Data/Log/参数/${shortdate}.log"
+                    layout="${myLayout}"
+                    archiveEvery="Day"
+                    archiveAboveSize="104857600"
+                    archiveNumbering="Sequence"
+                    maxArchiveFiles="30"
+                    concurrentWrites="true"
+                    keepFileOpen="false"
+                    encoding="utf-8"/>
+		</target>
+
+		<!-- 3. 流程日志 (流程步骤及状态) -->
+		<target name="ProcessFile" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard">
+			<target xsi:type="File"
+                    fileName="D:/SkyUnion/SK.RF3.Data/Log/流程/${shortdate}.log"
+                    layout="${myLayout}"
+                    archiveEvery="Day"
+                    archiveAboveSize="104857600"
+                    archiveNumbering="Sequence"
+                    maxArchiveFiles="30"
+                    concurrentWrites="true"
+                    keepFileOpen="false"
+                    encoding="utf-8"/>
+		</target>
+
+		<!-- 4. 动作日志 (动作执行、视觉通讯) -->
+		<target name="ActionFile" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard">
+			<target xsi:type="File"
+                    fileName="D:/SkyUnion/SK.RF3.Data/Log/动作/${shortdate}.log"
+                    layout="${myLayout}"
+                    archiveEvery="Day"
+                    archiveAboveSize="104857600"
+                    archiveNumbering="Sequence"
+                    maxArchiveFiles="30"
+                    concurrentWrites="true"
+                    keepFileOpen="false"
+                    encoding="utf-8"/>
+		</target>
+		<target name="LoggingProductionTarget" xsi:type="LoggingProductionTarget"/>
+		<target name="LoggingParameterTarget" xsi:type="LoggingParameterTarget"/>
+		<target name="LoggingProcessTarget" xsi:type="LoggingProcessTarget"/>
+		<target name="LoggingActionTarget" xsi:type="LoggingActionTarget"/>
+	</targets>
+
+	<!-- 规则设置:将不同名称的 logger 映射到对应的目标文件 -->
+	<rules>
+		<!-- 所有名为 "ProductionLogger" 的日志写入 生产.log -->
+		<logger name="ProductionLogger" minlevel="Trace" writeTo="ProductionFile,LoggingProductionTarget"/>
+
+		<!-- 所有名为 "ParameterLogger" 的日志写入 参数.log -->
+		<logger name="ParameterLogger" minlevel="Trace" writeTo="ParameterFile,LoggingParameterTarget"/>
+
+		<!-- 所有名为 "ProcessLogger" 的日志写入 流程.log -->
+		<logger name="ProcessLogger" minlevel="Trace" writeTo="ProcessFile,LoggingProcessTarget"/>
+
+		<!-- 所有名为 "ActionLogger" 的日志写入 动作.log -->
+		<logger name="ActionLogger" minlevel="Trace" writeTo="ActionFile,LoggingActionTarget"/>
+	</rules>
+</nlog>

+ 24 - 1
SKMC.API/SKMC.API.csproj

@@ -33,6 +33,23 @@
     <WarningLevel>4</WarningLevel>
     <PlatformTarget>x64</PlatformTarget>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <LangVersion>7.3</LangVersion>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <PlatformTarget>x64</PlatformTarget>
+    <LangVersion>7.3</LangVersion>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="DryIoc, Version=4.7.7.0, Culture=neutral, PublicKeyToken=dfbf2bd50fcf7768, processorArchitecture=MSIL">
       <HintPath>..\packages\DryIoc.dll.4.7.7\lib\net45\DryIoc.dll</HintPath>
@@ -44,7 +61,7 @@
       <HintPath>..\packages\Microsoft.Xaml.Behaviors.Wpf.1.1.77\lib\net462\Microsoft.Xaml.Behaviors.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <HintPath>H:\SKMC\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
       <HintPath>..\packages\NLog.5.3.4\lib\net46\NLog.dll</HintPath>
@@ -131,8 +148,13 @@
     <Compile Include="Common\Tasks\Tasks.cs" />
     <Compile Include="Common\Tcp\TCPClient.cs" />
     <Compile Include="Common\Tcp\TcpClientBase.cs" />
+    <Compile Include="Machine\Control\IMachineDriverControl.cs" />
+    <Compile Include="Machine\Model\ConfigSlavePDO.cs" />
+    <Compile Include="Machine\Model\ConfigSlaveSDO.cs" />
+    <Compile Include="Machine\Model\MachineSlaveError.cs" />
     <Compile Include="Machine\Monitor\MachineLatchTask.cs" />
     <Compile Include="Machine\Monitor\MachineStateLatchMonitor.cs" />
+    <Compile Include="Motion\Driver\IMotionDriverError.cs" />
     <Compile Include="Vision\SKV0\SKVisionClient.cs" />
     <Compile Include="Vision\SKV0\SKVisionProtocol.cs" />
     <Compile Include="Vision\SKV0\SKVisionClientBase.cs" />
@@ -219,6 +241,7 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="app.config" />
+    <None Include="NLog.Config" />
     <None Include="packages.config" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />