MachineBase.cs 13.6 KB
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceLibrary
{
    public class MachineBase
    {
        public virtual DeviceConfig Config { get; set; }
        public virtual string DeviceName { get; set; }
        public virtual bool UserPause { get; set; }
        public RunStatus runStatus { get; set; } = RunStatus.Stop;
        protected MoveInfo ResetMoveInfo;
        public MoveInfo MoveInfo;
        protected List<Msg> Msg = new List<Msg>();
        //public delegate void Event(List<Msg> msg);
        public event EventHandler<List<Msg>> ProcessMsgEvent;
        
        //public delegate void ProcessMoveinfo(List<MoveInfo> moveinfoList);
        public event EventHandler<List<MoveInfo>> ProcessMoveinfoEvent;

        ReelParam _preReelParam = null;
        public ReelParam preReelParam
        {
            get => _preReelParam;
            set
            {
                if (value == null)
                    _preReelParam = null;
                else
                    _preReelParam = value.clone();
            }
        }

        Thread thread;
        /// <summary>
        /// 整机启动变量,设置为false后将退出线程,只在停止时调用
        /// </summary>
        protected bool mstart = false;
        protected int stepDelaytime =100;
        public virtual void Run()
        {
            if (!mstart)
            {
                thread = new Thread(new ThreadStart(LoopProcess));
                thread.Start();
            }
            LogUtil.info(DeviceName + " 主线程已启动.");
            GC.KeepAlive(thread);
        }
        public virtual void Stop()
        {
            LogUtil.info(DeviceName + " 停止设备.");
            mstart = false;
            StopMove(true);
        }
        protected virtual void LoopProcess() {
            throw new NotImplementedException();
        }
        public bool SafeCheck()
        {
            if (UserPause) {
                Msg.add("用户暂停设备", MsgLevel.warning);
                return false;
            }

            return true;
        }
        protected void ProcessMsgEventFire(List<Msg> msg) {
            ProcessMsgEvent?.Invoke(this,msg);
        }
        protected void ProcessMoveinfoEventFire(List<MoveInfo> moveinfoList)
        {
            ProcessMoveinfoEvent?.Invoke(this, moveinfoList);
        }
        /// <summary>
        /// 是否再报警中
        /// </summary>
        public AlarmType alarmType = AlarmType.None;
        protected DateTime LastAlarmTime = DateTime.Now;
        protected DateTime checkAlarmTime = DateTime.Now;
        protected void Alarm(AlarmType alarmType, string alarmMsg = "")
        {
            if (alarmType.Equals(AlarmType.None).Equals(false))
            {
                LastAlarmTime = DateTime.Now;
            }

            if (this.alarmType.Equals(alarmType))
            {
                return;
            }
            LogUtil.error(DeviceName + " 报警,报警类型:" + alarmType);

            this.alarmType = alarmType;
            if (alarmType.Equals(AlarmType.AxisAlarm) || alarmType.Equals(AlarmType.AxisMoveError))
            {
                LogUtil.error(DeviceName + "轴报警, 停止运动, 打开报警灯");
                StopMove(true);
            }
            else if (alarmType == AlarmType.SuddenStop)
            {
                LogUtil.error(DeviceName + "收到急停信号,停止运动, 打开报警灯 ");
                StopMove(true);
            }
            else if (alarmType.Equals(AlarmType.NoAirCheck))
            {
                LogUtil.error(DeviceName + " 未检测到气压信号 ,停止运动, 打开报警灯 ");
                StopMove(true);
            }
            //LogUtil.info();
        }
        protected bool NoAlarm()
        {
            if (alarmType.Equals(AlarmType.None))
            {
                return true;
            }
            return false;
        }
        int logType = 1000;
        public string WarnMsg = "";
        /// <summary>
        /// 返回true代表需要等待
        /// </summary>
        /// <param name="MoveInfo"></param>
        /// <returns></returns>
        protected bool CheckWait(MoveInfo MoveInfo) {

            if (MoveInfo.IsInWait)
            {
                if (!CheckWait2(MoveInfo)) {
                    if (alarmType == AlarmType.IoSingleTimeOut) {
                        alarmType = AlarmType.None;
                    }
                }
               
            }
            return MoveInfo.IsInWait;

        }
        /// <summary>
        /// 返回true代表需要等待
        /// </summary>
        /// <param name="MoveInfo"></param>
        /// <returns></returns>
        protected bool CheckWait2(MoveInfo MoveInfo)
        {
            //当等待超过一分钟时,需要打印提示 
            TimeSpan span = DateTime.Now - MoveInfo.LastSetpTime;
            string NotOkMsg = "";
            if (MoveInfo.WaitList.Count <= 0)
            {
                MoveInfo.EndStepWait();
                return false;
            }
            bool isOk = true;
            if (MoveInfo.OneWaitCanEndStep)
            {
                isOk = false;
            }
            foreach (WaitResultInfo wait in MoveInfo.WaitList)
            {
                if (wait.IsEnd)
                {
                    if (!wait.WaitType.Equals(WaitEnum.W002_IOValue))
                    {
                        continue;
                    }
                }
                NotOkMsg = wait.ToStr();
                if (wait.WaitType.Equals(WaitEnum.W001_AxisMove))
                {
                    string msg = "";
                    if (wait.IsHomeMove)
                    {
                        wait.IsEnd = AxisBean.HomeMoveIsEnd(MoveInfo, wait.AxisInfo, out msg);
                    }
                    else if(wait.IsRelMove)
                    {
                        wait.IsEnd = AxisBean.ACAxisRELMoveIsEnd(MoveInfo, wait.AxisInfo, wait.TargetPosition, wait.TargetSpeed, out msg);
                    }
                    else
                    {
                        wait.IsEnd = AxisBean.ACAxisMoveIsEnd(MoveInfo, wait.AxisInfo, wait.TargetPosition, wait.TargetSpeed, out msg);
                    }
                    if (!msg.Equals(""))
                    {
                        isOk = false;
                        WarnMsg = msg;
                        Alarm(AlarmType.AxisMoveError, WarnMsg);
                        Msg.add(WarnMsg, MsgLevel.warning);
                        break;
                    }
                }
                else if (wait.WaitType.Equals(WaitEnum.W002_IOValue))
                {
                    ConfigIO io = Config.getWaitIO(wait.IoType);
                    NotOkMsg = " 等待【" + io.DisplayStr + "】=【" + wait.IoValue + "】";
                    wait.IsEnd = IOManager.IOValue(wait.IoType,Config).Equals(wait.IoValue);
                    if (!wait.IsEnd)
                    {
                        int timeOutMs = 15*1000;// Config.IOSingle_TimerOut;
                        if (span.TotalMilliseconds > timeOutMs)// && NoAlarm())
                        {

                            WarnMsg = DeviceName + "[" + MoveInfo.MoveStep + "] 等待(" + io.DisplayStr + "=" + wait.IoValue + ") 超时";
                            Alarm(AlarmType.IoSingleTimeOut, WarnMsg);
                            Msg.add(WarnMsg, MsgLevel.warning);
                            LogUtil.error(WarnMsg, logType + 14);
                            //MoveInfo.errlog(WarnMsg);
                            if (!MoveInfo.OneWaitCanEndStep)
                            {
                                isOk = false;
                                break;
                            }
                        }
                    }
                }
                else if (wait.WaitType.Equals(WaitEnum.W003_Time))
                {
                    wait.IsEnd = (span.TotalMilliseconds >= wait.TimeMSeconds);
                }
                else if (wait.WaitType.Equals(WaitEnum.W013_Action))
                {
                    wait.IsEnd = wait.Action.Invoke(wait);
                    LogUtil.info($"{DeviceName} 自定义等待 IsEnd={wait.IsEnd},Type={wait.Action.GetType()}");
                }
                else if (wait.WaitType.Equals(WaitEnum.W008_BatchAxis))
                {
                    AxisBean axisBean=null;

                    axisBean = RobotManage.t1Machine.T_Batch_Axis;
                    //if (wait.AxisInfo.ProName == "Right_Batch_Axis")
                    //    axisBean = Right_Batch_Axis;
                    //else
                    //    axisBean = Left_Batch_Axis;

                    //等待信号亮或者走到绝对位置才停止
                    if (IOValue(axisBean.TargetIoType).Equals(axisBean.TargetIoValue))
                    {
                        LogUtil.debug(DeviceName + "CheckWaitResult 检测到" + axisBean.TargetIoType + "=" + axisBean.TargetIoValue + ",停止运行");
                        axisBean.StopAxisCheckMove();
                        if (AxisManager.GetBusyStatus(wait.AxisInfo.DeviceName, wait.AxisInfo.GetAxisValue()).Equals(1))
                        {
                            axisBean.SuddenStop();
                        }
                        wait.IsEnd = true;
                    }
                    else
                    {
                        bool _isOk = AxisManager.GetBusyStatus(wait.AxisInfo.DeviceName, wait.AxisInfo.GetAxisValue()).Equals(0);
                        if (_isOk)
                        {
                            //TODO 判断是否达到高度,如果未达到,继续上升
                            axisBean.StopAxisCheckMove();
                            wait.IsEnd = true;
                        }
                    }
                }
                if (wait.IsEnd)
                {
                    if (MoveInfo.OneWaitCanEndStep)
                    {
                        isOk = true;
                        break;
                    }
                }
                else
                {
                    if (!MoveInfo.OneWaitCanEndStep)
                    {
                        isOk = false;
                        break;
                    }
                }
            }
            if (isOk)
            {
                MoveInfo.EndStepWait();
                return false;
            }
            else if (span.TotalSeconds > MoveInfo.TimeOutSeconds)
            {
                WarnMsg = DeviceName + "[" + MoveInfo.MoveStep + "]等待" + NotOkMsg + "超时[" + Math.Round(span.TotalSeconds, 1) + "]秒";

                int second = (int)(MoveInfo.TimeOutSeconds / span.TotalSeconds) * 10;
                if (second > 120)
                {
                    second = 120;
                }
                else if (second < 10)
                {
                    second = 10;
                }
                LogUtil.error(WarnMsg, logType + 100, second);
                //MoveInfo.errlog(WarnMsg);
                Alarm(AlarmType.IoSingleTimeOut, WarnMsg);
                Msg.add(WarnMsg, MsgLevel.warning);
            }
            return true;
        }
        protected void OpenAllServo()
        {
            AxisBean.RunMultiAxis(true, out _, AxisBean.GetList(DeviceName));

        }
        protected virtual void StopMove(bool ServoOff = false)
        {
            runStatus = RunStatus.Stop;
            MoveInfo.EndMove();
            AxisBean.StopMultiAxis(AxisBean.GetList(DeviceName));

            if (ServoOff)
                AxisBean.CloseMultiAxis(AxisBean.GetList(DeviceName));
        }
        public void CylinderMove(MoveInfo moveInfo, string IoLowType, string IoHighType, IO_VALUE iO_VALUE=IO_VALUE.HIGH)
        {
            if (iO_VALUE == IO_VALUE.LOW)
            {
                var t = IoHighType;
                IoHighType = IoLowType;
                IoLowType = t;
            }

            IOMove(IoLowType, IO_VALUE.LOW);
            IOMove(IoHighType, IO_VALUE.HIGH);
            if (moveInfo != null)
            {
                moveInfo.WaitList.Add(WaitResultInfo.WaitIO(IoLowType, IO_VALUE.LOW));
                moveInfo.WaitList.Add(WaitResultInfo.WaitIO(IoHighType, IO_VALUE.HIGH));
            }
        }
        public IO_VALUE IOValue(string ioType)
        {
            return IOManager.IOValue(ioType, Config);
        }
        public void IOMove(string IoType, IO_VALUE value, bool isCheck = false, int msTime = 0)
        {
            if (msTime <= 0)
            {
                if (isCheck && (IOValue(IoType).Equals(value)))
                {
                    return;
                }
                IOManager.IOMove(IoType, value, Config);
            }
            else
            {
                Task.Run(() =>
                {
                    IOManager.IOMove(IoType, value, Config);
                    Thread.Sleep(msTime);
                    IO_VALUE tValue = value.Equals(IO_VALUE.HIGH) ? IO_VALUE.LOW : IO_VALUE.HIGH;

                    LogUtil.info(DeviceName + "定时回写IO:  [" + IoType + "]=[" + value + "],msTime=" + msTime);

                    IOManager.IOMove(IoType, tValue, Config);
                });
            }            
        }

        protected bool WaitIo(string ioType, IO_VALUE value, int timeOut)
        {
            Task w = Task.Delay(timeOut);

            Task p = Task.Run(() =>
            {
                while (!IOValue(ioType).Equals(value))
                {
                    Task.Delay(100).Wait();
                }
            });
            Task.WaitAny(w, p);
            return true;
        }
    }
}