| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- using SKMC.Api.Core;
- using SKMC.Api.Common.Logger;
- using SKMC.Api.Common.Tasks;
- using SKMC.Api.Motion.Control;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- namespace SKMC.Api.Process.Model
- {
- /// <summary>
- /// <p>流程站点</p>
- /// <br>每个流程站点由多个ProcessStep组成一个循环流程</br>
- /// </summary>
- public abstract class ProcessStation
- {
- protected static readonly ILogger log = LogFactory.Get();
- /// <summary>
- /// 线性流程引擎
- /// </summary>
- private readonly ProcessFlow processFlow = ObjectFactory.Create<ProcessFlow>();
- /// <summary>
- /// 持久化接口
- /// </summary>
- protected readonly ProcessStorage processStorage = ObjectFactory.Create<ProcessStorage>();
- /// <summary>
- /// 流程站点管理器
- /// </summary>
- public ProcessStationManager ProcessStationManager { get; set; }
- /// <summary>
- /// 物料状态, 使用物料类型、状态值组合
- /// </summary>
- public ConcurrentDictionary<int, int> MatStatuses { get; set; } = new ConcurrentDictionary<int, int>();
- /// <summary>
- /// 流程站点的内置数据集
- /// </summary>
- public ConcurrentDictionary<string, object> DataMapping { get; set; } = new ConcurrentDictionary<string, object>();
- /// <summary>
- /// 流程动作控制接口
- /// </summary>
- protected readonly IMotionControl motionControl = ObjectFactory.Resolve<IMotionControl>();
- private int id;
- public int Id
- {
- get { return id; }
- set { id = value; processFlow.Id = value; }
- }
- public string Name { get; set; }
- /// <summary>
- /// station复位时执行
- /// </summary>
- public Action OnReset { get; set; }
- /// <summary>
- /// station复位结果, 0:复位成功
- /// </summary>
- public int ResetResult { get; set; } = -1;
- /// <summary>
- /// station启动时执行
- /// </summary>
- public Action OnStart { get; set; }
- /// <summary>
- /// station停止后执行
- /// </summary>
- public Action OnStop { get; set; }
- /// <summary>
- /// station暂停后执行
- /// </summary>
- public Action OnPause { get; set; }
- /// <summary>
- /// station暂停恢复后执行
- /// </summary>
- public Action OnResume { get; set; }
- /// <summary>
- /// station恢复状态后执行
- /// </summary>
- public Action OnRestore { get; set; }
- /// <summary>
- /// 每轮循环开始前执行
- /// </summary>
- public Action OnPrepare { set => processFlow.OnPrepare = value; }
- /// <summary>
- /// 触发入料事件时执行
- /// </summary>
- public Action Onload { get; set; }
- /// <summary>
- /// 完全收到物料准备开工时
- /// </summary>
- public Action OnReady { get; set; }
- /// <summary>
- /// 触发出料事件后执行
- /// </summary>
- public Action OnUnload { get; set; }
- /// <summary>
- /// 物料完全离开后执行
- /// </summary>
- public Action OnExit { get; set; }
- /// <summary>
- /// 是否空闲(站内没有物料)
- /// </summary>
- public bool IsIdle { get; set; }
- /// <summary>
- /// 安全运行的判断条件
- /// </summary>
- public Func<bool> SafeChecker { get; set; }
- /// <summary>
- /// 站点运行状态, 同设备状态, 见DeviceStatusEnum
- /// </summary>
- public int RunStatus { get; set; }
- /// <summary>
- /// 多工位序号, 同一类ProcessStation的多个实例, 使用该属性区分
- /// </summary>
- public short StationIndex { get; set; }
- /// <summary>
- /// 获取流程步骤
- /// </summary>
- /// <param name="processStepId"> 流程步骤Id</param>
- /// <returns></returns>
- public virtual ProcessStep Get(int processStepId) => processFlow.Get(processStepId);
- /// <summary>
- /// 注册流程步骤
- /// </summary>
- /// <param name="processStep">流程步骤</param>
- public virtual void Register(ProcessStep processStep) => processFlow.Register(processStep);
- /// <summary>
- /// 设置流程起始的步骤, 后续流程不变
- /// </summary>
- /// <param name="processStep">流程步骤</param>
- public virtual void SetFirst(ProcessStep processStep) => processFlow.SetFirst(processStep);
- /// <summary>
- /// 设置流程起始的步骤, 后续流程不变
- /// </summary>
- /// <param name="processStepId">流程步骤Id</param>
- public virtual void SetFirst(int processStepId) => processFlow.SetFirst(processStepId);
- /// <summary>
- /// 提交下个流程步骤
- /// </summary>
- public virtual void PostAutoNext() => processFlow.PostAutoNext();
- /// <summary>
- /// 提交指定的流程步骤
- /// </summary>
- /// <param name="processStep">流程步骤</param>
- public virtual void PostManual(ProcessStep processStep) => processFlow.PostManual(processStep);
- /// <summary>
- /// 提交指定的流程步骤
- /// </summary>
- /// <param name="processStepId">流程步骤Id</param>
- public virtual void PostManual(int processStepId) => processFlow.PostManual(Get(processStepId));
- /// <summary>
- /// 直接调用一个流程步骤的Actions(自动模式的下一个)
- /// </summary>
- public virtual void CallAutoNext() => processFlow.CallAutoNext();
- /// <summary>
- /// 直接调用一个流程步骤的Actions(手动模式指定)
- /// </summary>
- /// <param name="processStep">流程步骤</param>
- public virtual void CallManual(ProcessStep processStep) => processFlow.CallManual(processStep);
- /// <summary>
- /// 直接调用一个流程步骤的Actions(手动模式指定)
- /// </summary>
- /// <param name="processStepId">流程步骤Id</param>
- public virtual void CallManual(int processStepId) => processFlow.CallManual(Get(processStepId));
- /// <summary>
- /// 获取数据对象
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="key"></param>
- /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
- /// <param name="fromStorage">是否从持久化获取, 如果为true并且从持久化获取成功, 将覆盖掉内存中已有的数据</param>
- /// <returns></returns>
- public virtual T GetData<T>(string key, int stationId = -1, bool fromStorage = false)
- {
- //if (fromStorage) LoadStationData(new[] { key }, true);
- //GetProcessStation(stationId).DataMapping.TryGetValue(key, out object dataVal);
- //return (T) dataVal;
- ProcessStation processStation = GetProcessStation(stationId);
- if (fromStorage) processStorage.LoadStationData(this, new[] { key }, true);
- if (processStation.DataMapping.ContainsKey(key))
- {
- if (processStation.DataMapping[key] != null)
- {
- T t = (T)processStation.DataMapping[key];
- return t;
- }
- }
- return default;
- }
- /// <summary>
- /// 获取数据对象并从数据集中删除
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="key"></param>
- /// <param name="stationId"></param>
- /// <returns></returns>
- public virtual T TakeData<T>(string key, int stationId = -1)
- {
- ProcessStation processStation = GetProcessStation(stationId);
- if (processStation.DataMapping.ContainsKey(key))
- {
- if (processStation.DataMapping[key] != null)
- {
- T t = (T)processStation.DataMapping[key];
- processStation.DataMapping.TryRemove(key, out _);
- return t;
- }
- }
- //return default;
- throw new KeyNotFoundException($"TakeData Failed, can't find key[{key}] from station[{processStation.Id}]");
- }
- /// <summary>
- /// 添加数据对象
- /// </summary>
- /// <param name="key"></param>
- /// <param name="value"></param>
- /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
- /// <param name="toStorage">是否持久化保存, 如果为true将覆盖掉持久化中已有的数据</param>
- public virtual void SetData(string key, object value, int stationId = -1, bool toStorage = false)
- {
- GetProcessStation(stationId).DataMapping.AddOrUpdate(key, value, (k, oldValue) => value);
- if (stationId == -1) stationId = Id;
- log.Debug($"Set Station[{stationId}] Data , key: {key}, value: {value}");
- if (toStorage)
- {
- processStorage.SaveStationData(this, new[] { key }, true);
- }
- }
- /// <summary>
- /// 删除数据对象
- /// </summary>
- /// <param name="key"></param>
- /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
- /// <param name="toStorage">是否持久化同步删除</param>
- public virtual void RemoveData(string key, int stationId = -1, bool toStorage = false)
- {
- bool result = GetProcessStation(stationId).DataMapping.TryRemove(key, out _);
- if (result && toStorage) processStorage.DeleteStationData(this, new[] { key });
- }
- /// <summary>
- /// 清除本站内的数据对象
- /// </summary>
- public void ClearData(int stationId = -1, bool toStorage = false)
- {
- GetProcessStation(stationId).DataMapping.Clear();
- if (toStorage) processStorage.DeleteStationDataAll(this);
- }
- /// <summary>
- /// 检查任务中断点是否触发
- /// </summary>
- /// <param name="onCancel">触发中断后的动作</param>
- /// <returns></returns>
- public virtual bool CheckTaskCancelled(Action onCancel = null)
- {
- TaskTokener.SetWaitPoint(Id);
- if (TaskTokener.IsCancelled(Id))
- {
- onCancel?.Invoke();
- return true;
- }
- return false;
- }
- /// <summary>
- /// 启动流程
- /// </summary>
- public virtual void Start()
- {
- processFlow.Start();
- TaskTokener.Add(Id);
- OnStart?.Invoke();
- processFlow.PostFirst();
- }
- /// <summary>
- /// 停止流程
- /// <param name="hasAction">是否有后续停止动作</param>
- /// </summary>
- public virtual void Stop(bool hasAction = false)
- {
- processFlow.Stop();
- TaskTokener.Stop(Id);
- if (hasAction) OnStop?.Invoke();
- }
- /// <summary>
- /// 复位流程
- /// </summary>
- public virtual void Reset()
- {
- processFlow.Reset();
- TaskTokener.Add(Id);
- OnReset?.Invoke();
- }
- /// <summary>
- /// 暂停流程
- /// </summary>
- public virtual void Pause()
- {
- processFlow.Pause();
- TaskTokener.Pause(Id);
- OnPause?.Invoke();
- }
- /// <summary>
- /// 恢复流程
- /// </summary>
- public virtual void Resume()
- {
- processFlow.Resume();
- OnResume?.Invoke();
- TaskTokener.Resume(Id);
- }
- public virtual void Restore()
- {
- OnRestore?.Invoke();
- TaskTokener.Add(Id);
- }
- /// <summary>
- /// 获取流程站点的物料状态
- /// </summary>
- /// <param name="matType">状态类型, 可以是物料也可以是站点</param>
- /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
- /// <param name="fromStorage">是否从持久化获取, 如果为true并且从持久化获取成功, 将覆盖掉内存中已有的数据</param>
- /// <returns></returns>
- public int GetStationStatus(int matType, int stationId = -1, bool fromStorage = false)
- {
- if (fromStorage) processStorage.LoadStationStatus(this, new[] { matType }, true);
- GetProcessStation(stationId).MatStatuses.TryGetValue(matType, out int statusVal);
- return statusVal;
- }
- /// <summary>
- /// 判断流程站点的物料状态是否在给定的物料状态值内
- /// 只要满足其中一个状态值返回true, 全部不满足返回false
- /// </summary>
- /// <param name="matType">状态类型, 可以是物料也可以是站点</param>
- /// <param name="stationId">流程站点的Id, 如果是本站则为-1</param>
- /// <param name="statusVals">需要比较的物料状态值集合</param>
- /// <returns></returns>
- public bool CheckStationStatus(int matType, int stationId, int[] statusVals)
- {
- int statusVal = GetStationStatus(matType, stationId);
- bool checkResult = false;
- foreach (int val in statusVals)
- {
- if (val == statusVal) return true;
- }
- return checkResult;
- }
- /// <summary>
- /// 设置流程站点的物料状态
- /// </summary>
- /// <param name="matType">状态类型, 可以是物料也可以是站点</param>
- /// <param name="status">状态值</param>
- /// <param name="stationId">站点Id, -1表示本站</param>
- /// <param name="toStorage">是否持久化保存, 如果为true将覆盖掉持久化中已有的数据</param>
- public void SetStationStatus(int matType, int status, int stationId = -1, bool toStorage = false)
- {
- int newStatus = GetProcessStation(stationId).MatStatuses.AddOrUpdate(matType, status, (key, oldValue) => status);
- if (stationId == -1) stationId = Id;
- log.Debug($"Set Station[{stationId}] Status, matType: {matType}, status check: {status == newStatus}, val: (expected:{status}, actual:{newStatus})");
- if (toStorage)
- {
- processStorage.SaveStationStatus(this, new[] { matType }, true);
- }
- }
- /// <summary>
- /// 删除流程站点的物料状态
- /// </summary>
- /// <param name="matType"></param>
- /// <param name="stationId"></param>
- /// <param name="toStorage">是否同步删除持久化中的物料状态</param>
- public void RemoveStationStatus(int matType, int stationId = -1, bool toStorage = false)
- {
- bool result = GetProcessStation(stationId).MatStatuses.TryRemove(matType, out _);
- if (result && toStorage) processStorage.DeleteStationStatus(this, new[] { matType });
- }
- /// <summary>
- /// 清除流程站点的所有状态
- /// </summary>
- /// <param name="stationId"></param>
- public void ClearStationStatus(int stationId = -1, bool toStorage = false)
- {
- GetProcessStation(stationId).MatStatuses.Clear();
- if (toStorage) processStorage.DeleteStationStatusAll(this);
- }
- /// <summary>
- /// 请求其他流程站点物料状态交互:更新物料状态并阻塞,直到目标Station确认收到后(ConfirmStationStatus)退出阻塞
- /// </summary>
- /// <param name="matType"></param>
- /// <param name="statusVals"></param>
- /// <param name="stationId"></param>
- public void RequestStationStatus(int matType, int[] statusVals, int stationId = -1)
- {
- }
- /// <summary>
- /// 阻塞并等待响应其他流程站点的物料状态,如果与期望的物料状态匹配则确认接收
- /// </summary>
- /// <param name="matType"></param>
- /// <param name="statusVals"></param>
- /// <param name="stationId"></param>
- public void ResponsetationStatus(int matType, int[] statusVals, int stationId = -1)
- {
- }
- private ProcessStation GetProcessStation(int stationId = -1)
- {
- ProcessStation processStation = (stationId == -1) ? this : ProcessStationManager.Get(stationId);
- if (processStation == null) throw new ArgumentNullException($"Cannot Find stationId[{stationId}] Object");
- return processStation;
- }
- }
- }
|