patrick
2019-12-10 1c4426810c71eead57084be8a18ade8d314dd8c4
src/A032.Process/AGVBindUnit.cs
@@ -8,56 +8,96 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading;
namespace A032.Process
{
    public enum TaskStatus
    public enum TaskState
    {
        Available = 1,
        /// <summary>
        /// 新任务
        /// </summary>
        New = 0,
        /// <summary>
        /// 任务完成
        /// </summary>
        Done = 1,
        /// <summary>
        /// 任务失败
        /// </summary>
        Failed = 2,
        /// <summary>
        /// 任务已添加队列,等待执行
        /// </summary>
        Queueing = 3,
        /// <summary>
        /// 任务已指派
        /// </summary>
        Assigned = 4,
        /// <summary>
        /// 任务未指派,已取消
        /// </summary>
        Cancelled = 5,
    }
    public enum AGVState
    {
        /// <summary>
        /// AGV状态不可知
        /// </summary>
        Unknown = 0,
        /// <summary>
        /// 空闲状态,可接收任务
        /// </summary>
        Idle = 1,
        /// <summary>
        /// 任务执行中
        /// </summary>
        Running = 2,
        /// <summary>
        /// 报警中,不可执行任务
        /// </summary>
        Warning = 3,
        /// <summary>
        /// 充电中,不可执行任务
        /// </summary>
        InCharge = 4,
        /// <summary>
        /// 空闲充电状态,可接收任务
        /// </summary>
        IdleCharge = 5,
    }
    public enum TaskAvailableLevel
    {
        Robot = 1,
        AGV = 2,
        Both = 3,
    }
    //public class AGVTaskModel
    //{
    //    public TaskAvailableLevel Level { get; set; } = TaskAvailableLevel.Robot;
    public class AGVTaskModel
    {
        public TaskAvailableLevel Level { get; set; } = TaskAvailableLevel.Robot;
    //    public string MethodName { get; set; }
        public Func<IOperationConfig, IDevice, ProcessResponse> MethodFunc { get; set; }
    //    public IOperationConfig OpConfig { get; set; }
        public IOperationConfig OpConfig { get; set; }
    //    public IDevice Device { get; set; }
        public IDevice Device { get; set; }
    //    //public int Priority { get; set; } = 10;
        //public int Priority { get; set; } = 10;
    //    public AGVTaskModel() { }
        public AGVTaskModel() { }
        public AGVTaskModel(TaskAvailableLevel level, Func<IOperationConfig, IDevice, ProcessResponse> methodFunc, IOperationConfig opConfig = null, IDevice device = null)
        {
            Level = level;
            MethodFunc = methodFunc;
            OpConfig = opConfig ?? new OperationConfigBase();
            Device = device;
        }
    }
    //    public AGVTaskModel(TaskAvailableLevel level, string methodName, IOperationConfig opConfig = null, IDevice device = null)
    //    {
    //        Level = level;
    //        MethodName = methodName;
    //        OpConfig = opConfig ?? new OperationConfigBase();
    //        Device = device;
    //    }
    //}
    public class AGVBindUnit : IComplexDisplay
    {
        #region 可编辑项目
        [Category("设备绑定")]
        [Description("绑定Id")]
        [ReadOnly(true)]
        [Browsable(false)]
        public string Id { get; set; } = Guid.NewGuid().ToString();
        [Category("设备绑定")]
@@ -90,60 +130,32 @@
        }
        #endregion
        #region 后台属性
        #region 状态
        private AGVState unitState = AGVState.Idle;
        [Browsable(false)]
        [JsonIgnore]
        public Action<AGVBindUnit> OnMethodInvoke { get; set; }
        public string AGVDest { get; set; } = "";
        private TaskStatus agvStatus = TaskStatus.Available;
        [Browsable(false)]
        [JsonIgnore]
        public TaskStatus AGVStatus
        public AGVState UnitState
        {
            get => agvStatus;
            get => unitState;
            set
            {
                agvStatus = value;
                InvokeTaskCheck();
            }
        }
                if (value != unitState)
                {
                    var preState = unitState;
                    unitState = value;
        private TaskStatus robotStatus = TaskStatus.Available;
        [Browsable(false)]
        [JsonIgnore]
        public TaskStatus RobotStatus
        {
            get => robotStatus;
            set
            {
                robotStatus = value;
                InvokeTaskCheck();
                    OnUnitStateChanged?.Invoke(this.Id, preState, unitState);
                }
            }
        }
        [Browsable(false)]
        [JsonIgnore]
        public TaskStatus UnitStatus
        {
            get
            {
                if (AGVStatus == TaskStatus.Warning || RobotStatus == TaskStatus.Warning)
                {
                    return TaskStatus.Warning;
                }
                else
                {
                    if (AGVStatus == TaskStatus.Available && RobotStatus == TaskStatus.Available)
                    {
                        return TaskStatus.Available;
                    }
                }
        public List<string> WarningMsg { get; set; } = new List<string>();
        #endregion
                return TaskStatus.Running;
            }
        }
        #region 设备
        [Browsable(false)]
        [JsonIgnore]
        public SeerAGVDriver AGV { get; set; } = null;
@@ -153,77 +165,50 @@
        [Browsable(false)]
        [JsonIgnore]
        public CameraBase Camera { get; set; } = null;
        [Browsable(false)]
        [JsonIgnore]
        public ObservableCollection<AGVTaskModel> TaskList { get; set; } = new ObservableCollection<AGVTaskModel>();
        #endregion
        [Browsable(false)]
        #region 任务信息
        [JsonIgnore]
        public int CurrentEmptyTray { get; set; }
        [Browsable(false)]
        [JsonIgnore]
        public int CurrentFullTray { get; set; }
        [Browsable(false)]
        [JsonIgnore]
        public bool IsFullTrayFull { get; set; }
        [Browsable(false)]
        [JsonIgnore]
        public bool IsFullTrayEmpty { get; set; }
        [Browsable(false)]
        [JsonIgnore]
        public bool IsEmptyTrayEmpty { get; set; }
        public string CurrentTaskId { get; set; }
        [Browsable(false)]
        [JsonIgnore]
        public ManualResetEvent RobotIOHandle { get; set; } = new ManualResetEvent(false);
        [Browsable(false)]
        public bool IsTaskCancelled { get; set; } = false;
        [JsonIgnore]
        [Browsable(false)]
        public bool IsTaskCancelling { get; set; } = false;
        #endregion
        #region 事件
        [JsonIgnore]
        [Browsable(false)]
        public Action<string, AGVState, AGVState> OnUnitStateChanged { get; set; }
        #endregion
        #region 托盘信息
        [JsonIgnore]
        [Browsable(false)]
        public int FullTrayNum { get; set; }
        [JsonIgnore]
        [Browsable(false)]
        public int EmptyTrayNum { get; set; }
        #endregion
        #endregion
        public AGVBindUnit()
        {
            TaskList.CollectionChanged += TaskList_CollectionChanged;
        }
        private void TaskList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        public void Reset()
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                InvokeTaskCheck();
            }
        }
            WarningMsg.Clear();
            UnitState = AGVState.Idle;
        private void InvokeTaskCheck()
        {
            for (int i = 0; i < TaskList.Count; i++)
            {
                var task = TaskList[i];
                bool isAgvOK = false;
                bool isRobotOK = false;
                if ((task.Level & TaskAvailableLevel.AGV) == TaskAvailableLevel.AGV)
                {
                    isAgvOK = AGVStatus == TaskStatus.Available;
                }
                else
                {
                    isAgvOK = true;
                }
                if ((task.Level & TaskAvailableLevel.Robot) == TaskAvailableLevel.Robot)
                {
                    isRobotOK = RobotStatus == TaskStatus.Available;
                }
                else
                {
                    isRobotOK = true;
                }
                if (isRobotOK && isAgvOK)
                {
                    OnMethodInvoke?.Invoke(this);
                    TaskList.RemoveAt(i);
                    break;
                }
            }
            AGV.ResetAlarm();
            Robot.ResetAlarm();
        }
    }
@@ -251,9 +236,9 @@
            {
                ProcessConfig config = scope.Resolve<ProcessConfig>();
                config.RobotConfigCollection.ForEach(plc =>
                config.RobotConfigCollection.ForEach(robot =>
                {
                    _hash[plc.ID] = plc.Name;
                    _hash[robot.ID] = robot.Name;
                });
            }
        }
@@ -267,9 +252,9 @@
            {
                ProcessConfig config = scope.Resolve<ProcessConfig>();
                config.CameraConfigCollection.ForEach(plc =>
                config.CameraConfigCollection.ForEach(camera =>
                {
                    _hash[plc.ID] = plc.Name;
                    _hash[camera.ID] = camera.Name;
                });
            }
        }
@@ -288,7 +273,43 @@
                config.PLCConfigCollection.ForEach(plc =>
                {
                    _hash[plc.ID] = plc.Name;
                });
                });
            }
        }
    }
    public class AllDeviceIdConverter : ComboBoxItemTypeConvert
    {
        public override void GetConvertHash()
        {
            using (var scope = GlobalVar.Container.BeginLifetimeScope())
            {
                _hash[""] = "未指定";
                List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
                deviceList.ForEach(d =>
                {
                    _hash[d.Id] = d.Name;
                });
            }
        }
    }
    public class AllDeviceNameConverter : ComboBoxItemTypeConvert
    {
        public override void GetConvertHash()
        {
            using (var scope = GlobalVar.Container.BeginLifetimeScope())
            {
                _hash[""] = "未指定";
                List<IDevice> deviceList = scope.Resolve<List<IDevice>>();
                deviceList.ForEach(d =>
                {
                    _hash[d.Name] = d.Name;
                });
            }
        }
    }