MainMachine.cs 13.0 KB
using OnlineStore;
using OnlineStore.Common;
using OnlineStore.LoadCSVLibrary;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DeviceLibrary
{
    public partial class MainMachine : DeviceBase, IRobot
    {
        new public string Name { get; set; } = "Cycle Line";
        private volatile bool _canRunning = true;
        public bool canRunning
        {
            get { return _canRunning; }
            set
            {
                if (_canRunning != value) {
                    Msg.setlogones();
                }
                _canRunning = value;
            }
        }
        public bool isBusy { get; set; } = false;
        public bool isAlarm { get; set; } = false;
        public RunStatus runStatus { get; set; } = RunStatus.Stop;
        public Robot_Config Config { get; set; }
        public Dictionary<string, DeviceGroup> DeviceGroup { get=>RobotManage.DeviceGroup; }
        public bool UserPause { get; set; } = false;

        public ServerCommunication ServerCM;

        public ManualResetEvent ResetEvent = new ManualResetEvent(true);

        /// <summary>
        /// 是否在急停中
        /// </summary>
        public bool isInSuddenDown = false;

        public MainMachine(out string msg) {
            GroupName = "root";
            msg = "";
            ServerCM = new ServerCommunication(Setting_Init.Device_CID);
            Config = RobotManage.Config;
            Msg = new MsgService("root");
            crc.LanguageChangeEvent += Crc_LanguageChangeEvent;

            SideMove.Init(Config, DeviceGroup, out string m);
            msg += m;
            TransplantMove.Init(Config, DeviceGroup, out m);
            msg += m;
            TrayStop.Init(Config, DeviceGroup, out m);
            msg += m;
            TrayManager.Init(DeviceGroup);

            MI.Init(Config, DeviceGroup, out m);
            msg += m;
            #region 初始化led
            RunningLed = new Led(Config.DOList["root"][IO_Type.Run_Led].GetIOAddr(), LedColor.green);
            StandbyLed = new Led(Config.DOList["root"][IO_Type.Standby_Led].GetIOAddr(), LedColor.yellow);
            AlarmLed = new Led(Config.DOList["root"][IO_Type.Alarm_Led].GetIOAddr(), LedColor.red);
            #endregion

            AlarmBuzzer.SetOnOffAction(() =>{ IOMove(IO_Type.Alarm_Buzzer, IO_VALUE.HIGH); }, () => { IOMove(IO_Type.Alarm_Buzzer, IO_VALUE.LOW); });

            IOMonitor.RegisterIO(IO_Type.Reset_BTN, "root", IO_VALUE.HIGH, Reset_BTN, 2500,100);
            IOMonitor.RegisterIO(IO_Type.AutoRun_Single, "root", IO_VALUE.HIGH, Run_BTN, 2500,100);
            LedProcessInit();
        }



        private void Crc_LanguageChangeEvent(object sender, EventArgs e)
        {
            //ResetMoveInfo.Name = crc.GetString("Res0173","重置");

        }
        public bool hasAlarm = false;
        /// <summary>
        /// 整机启动变量,设置为false后将退出线程,只在停止时调用
        /// </summary>
        public volatile bool mstart=true;
        public void Run() {
            mstart = true;
            while (mstart) {
                try
                {
                    canRunning = DeviceCheck();                    
                    if (canRunning)
                    {
                        
                        BtnProcess();
                        canRunning = SafeCheck();
                    }
                    Thread.Sleep(150);
                    ResetEvent.Set();
                    Debug.WriteLine($"DeviceRunControl canRunning:{RobotManage.mainMachine.canRunning}, mstart:{RobotManage.mainMachine.mstart}");
                    if (!canRunning || !mstart)
                        continue;
                    if (runStatus == RunStatus.Running)
                    {
                       ioMonitor();
                    }
                    else if (runStatus == RunStatus.HomeReset)
                    {
                        IOMove(IO_Type.Line_Run, IO_VALUE.HIGH);
                        runStatus = RunStatus.Running;
                    }
                }
                catch (Exception ex)
                {
                    Msg.add(ex.ToString(), MsgLevel.warning);
                    Msg.setlogones();
                }
                finally {
                    var m = Msg.get();
                    Msg.Show();
                    ServerCM.ProcessMsg(m);
                    StoreStatus currnetstoreStatus= StoreStatus.None;
                    if (m.Find((aa) => aa.msgLevel == MsgLevel.alarm) == null)
                    {
                        hasAlarm = false;
                        AlarmBuzzer.OFF();
                        if (ServerCM.storeStatus != StoreStatus.InStoreExecute
                            && ServerCM.storeStatus != StoreStatus.OutStoreExecute
                            && ServerCM.storeStatus != StoreStatus.ResetMove && ServerCM.storeStatus != StoreStatus.StoreOnline)
                        {
                            LogUtil.info($"test storeStatus is {ServerCM.storeStatus} change to StoreOnline");
                            currnetstoreStatus = StoreStatus.StoreOnline;
                        }
                    }
                    else {
                        hasAlarm = true;
                        AlarmBuzzer.ON();
                        currnetstoreStatus = isInSuddenDown ? StoreStatus.SuddenStop : StoreStatus.Warning;
                    }
                    //ProcessMoveinfoEvent?.Invoke(MoveInfo.List);
                    if (!UserPause && mstart)
                        Msg.clear();
                    else
                        currnetstoreStatus = StoreStatus.Debugging;

                    if (currnetstoreStatus!=StoreStatus.None)
                        ServerCM.storeStatus = currnetstoreStatus;
                }
            }
            LogUtil.info("主线程已退出.");
        }
        public void Start() {
            MoveInfo.List.ForEach((m) => { m.EndMove(); });
            Run();
        }
        public void Stop() {            
            mstart = false;
            DeviceSnapshot();
            SideMove.DeviceList.Values.ToList().ForEach(s => s.Stop());
            TransplantMove.DeviceList.Values.ToList().ForEach(s => s.Stop());
            TrayStop.DeviceList.Values.ToList().ForEach(s => s.Stop());
            MI.DeviceList.Values.ToList().ForEach(s => s.Stop());
            IOMove(IO_Type.Line_Run, IO_VALUE.LOW);
            ResetEvent.Set();
            Alarm(AlarmType.None);
            StopMove(true);
            LedProcess(null);
            SafetyDevice.PauseAll();
        }
        public void BeginHomeReset(bool firstRun=false) {
            if (!firstRun)
            {
                StopMove();
                Thread.Sleep(500);
            }
            OpenAllServo();
            Alarm(AlarmType.None);
            runStatus = RunStatus.HomeReset;
            SideMove.DeviceList.Values.ToList().ForEach(s => s.Start());
            TransplantMove.DeviceList.Values.ToList().ForEach(s => s.Start());
            TrayStop.DeviceList.Values.ToList().ForEach(s => s.Start());
            MI.DeviceList.Values.ToList().ForEach(s => s.Start());
            
        }       


        bool lastSafeCheckStatus = true;
        bool SafeCheck() {
            bool ok = true;            
            if (!lastSafeCheckStatus && ok)
            {
                IOMove(IO_Type.Line_Run, IO_VALUE.HIGH);
                MoveInfo.List.ForEach(mi => {
                    mi.LastSetpTime = DateTime.Now;
                    mi.IsInWait = true;                    
                    mi.WaitList.Add(WaitResultInfo.WaitTime(8000)); 
                });
                SafetyDevice.ResumeAll();
            }
            lastSafeCheckStatus = ok;
            return ok;
        }

        void DeviceSuddenStop() {
            if (lastSafeCheckStatus)
            {
                LogUtil.info("开始急停");
                ResetEvent.Reset();
                LogUtil.info("复位线程锁,等待其他线程完成");
                ManualResetEvent.WaitAll(DeviceRunControl.manualResets.ToArray(),500);
                LogUtil.info("其他线程已完成");
                AxisBean.StopMultiAxis(AxisBean.List[GroupName]);
                MoveInfo.List.ForEach((m) => { m.CanWhileCount = 5; });
                SafetyDevice.PauseAll();
                Task.Run(() => {
                    Task.Delay(4000).Wait();
                    IOMove(IO_Type.Line_Run, IO_VALUE.LOW);
                });
            }
        }

        /// <summary>
        /// 最后一次气压检测变为0的时间
        /// </summary>
        DateTime lastAirCloseTime = DateTime.MinValue;

        internal DateTime checkAlarmTime = DateTime.Now;
        public bool DeviceCheck() {
            bool ok = true;

            if (UserPause)
            {
                Msg.add(crc.GetString("Res0175", "系统暂停"), MsgLevel.warning);
                DeviceSuddenStop();
                lastSafeCheckStatus = false;
                ok = false;
                return ok;
            }
            if (G.simulate)
                return true;
            isInSuddenDown = IOValue(IO_Type.SuddenStop_BTN).Equals(IO_VALUE.LOW);
            if (IOValue(IO_Type.AutoRun_Single).Equals(IO_VALUE.LOW)) {
                Msg.add(crc.GetString("Res0001","自动运行开关未开"), MsgLevel.warning);
                DeviceSuddenStop();
                lastSafeCheckStatus = false;
                ok = false;
            }             
            else if (isInSuddenDown)
            {
                Msg.add(crc.GetString("Res0176", "急停中"), MsgLevel.alarm);
                ok = false;
            }
            else if (alarmType != AlarmType.None)
            {
                Msg.add(crc.GetString("Res0177", "系统需要重置"), MsgLevel.alarm);
                ok = false;
            }
            if (IOValue(IO_Type.Airpressure_Check).Equals(IO_VALUE.LOW) && !G.simulate)
            {
                if (lastAirCloseTime == DateTime.MinValue)
                    lastAirCloseTime = DateTime.Now;

                TimeSpan span = DateTime.Now - lastAirCloseTime;
                if (span.TotalSeconds > RobotManage.Config.AirCheckSeconds)
                {
                    ok = false;
                    Msg.add(crc.GetString("Res0178","气压不足"), MsgLevel.warning);
                }
            }
            else {
                lastAirCloseTime = DateTime.MinValue;
            }
            foreach (var al in AxisBean.List.Values.ToList())
            {
                if (ok && !AxisBean.RunMultiAxis(true, out string msg, al))
                {
                    ok = false;
                    Msg.add(msg, MsgLevel.warning);
                }
            }
            if (alarmType!=AlarmType.SuddenStop)
            {
                TimeSpan span = DateTime.Now - checkAlarmTime;
                if (span.TotalSeconds > 2)
                {
                    checkAlarmTime = DateTime.Now;
                    AxisBean.List.ToList().ForEach((x) => { x.Value.ForEach(y => {
                        if (y.Disable)
                            return;

                        AxisManager.AlarmClear(y.Config.DeviceName, y.Config.GetAxisValue());
                        if (AxisManager.GetAlarmStatus(y.Config.DeviceName, y.Config.GetAxisValue()) == 1)
                        {
                            Msg.add(crc.GetString(y.Config.ProName, y.Config.Explain) + $"[{y.Config.GetAxisValue()}]:" + crc.GetString("Res0179", "运动报警"), MsgLevel.alarm, ErrInfo.SuddenStop);
                            ok = false;
                            LogUtil.error(string.Join(",",HuichuanLibrary.HCBoardManager.GetAxisErrorDetail(y.Config.GetAxisValue())));
                        }
                    }); });

                }
            }
            return ok;
        }
        public void DeviceSnapshot()
        {
            LogUtil.info("===开始记录系统当前情况.===");
            MoveInfo.List.ForEach(m => {
                LogUtil.info($"\t{m.Name}: {m.MoveStep}\t{m.MoveParam.ToStr()}");
            });
            AxisBean.List.ToList().ForEach(al => {
                al.Value.ForEach(ax => {
                    LogUtil.info($"\t{ax.AxisName}: {ax.GetAclPosition()}");
                });                
            });

            VStoreCollection.VStoreList.Values.ToList().ForEach(vs => {

                LogUtil.info($"\t{vs.TowerName}\t{vs.CID}: {vs.RTStoreStatus}\tCurrentTerminalReelID:{vs.CurrentTerminalReelID}\tInStoreJobInfo:{vs.InStoreJobInfo?.ToStr()}");
            });
            ConfigHelper.Config.Configlist.ToList().ForEach(cc => {
                LogUtil.info($"\t{cc.Key}: {cc.Value}");
            });
            MsgService.MSList.ToList().ForEach(msl =>
            {
                msl.Value.get().ToList().ForEach(cc =>
                {
                    LogUtil.info($"\t{cc.datetime}\t{cc.msgLevel}\t{cc.msgtxt} ");
                });
            });
                
            LogUtil.info("===记录结束.===");
        }
    }
}