| | |
| | | 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("设备绑定")] |
| | |
| | | } |
| | | #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; |
| | |
| | | [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(); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | ProcessConfig config = scope.Resolve<ProcessConfig>(); |
| | | |
| | | config.RobotConfigCollection.ForEach(plc => |
| | | config.RobotConfigCollection.ForEach(robot => |
| | | { |
| | | _hash[plc.ID] = plc.Name; |
| | | _hash[robot.ID] = robot.Name; |
| | | }); |
| | | } |
| | | } |
| | |
| | | { |
| | | ProcessConfig config = scope.Resolve<ProcessConfig>(); |
| | | |
| | | config.CameraConfigCollection.ForEach(plc => |
| | | config.CameraConfigCollection.ForEach(camera => |
| | | { |
| | | _hash[plc.ID] = plc.Name; |
| | | _hash[camera.ID] = camera.Name; |
| | | }); |
| | | } |
| | | } |
| | |
| | | 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; |
| | | }); |
| | | } |
| | | } |
| | | } |