Control.cs 6.6 KB
using System;
using System.Diagnostics;
using System.Threading;
using Model;

namespace BLL
{
    public class Control
    {
        private Timer timerCall;

        public delegate void AgvChangedEvent(int agvIndex);
        public event AgvChangedEvent AgvChanged;
        public event AgvChangedEvent AgvOnline;

        public Control()
        {
            ThreadPool.SetMaxThreads(5, 5);  //线程池最大数量
        }

        public void Start()
        {
            timerCall = new Timer(CallProcess, null, 0, 2000);
        }

        public void Stop()
        {
            if (timerCall != null)
                timerCall.Dispose();
        }



        private void CallProcess(object obj)
        {
            for (int i = 0; i < Common.agvInfos.Count; i++)
            {
                AgvInfo info = Common.agvInfos[i];
                if (info.IsCall) continue;

                try
                {
                    info.IsCall = true;
                    CheckAgvOnline(ref info);
                    if (!info.IsOnline) continue;   //脱机
                    GetAgvState(ref info);
                    if (!info.IsAuto) continue;     //手动

                    if (info.StateID == (int)StateID.Pause)
                        Common.mir.State_Ready(info.IP, info.Authorization);

                    if (info.CurrentJob == null)
                        info.CurrentJob = new StandbyJob();
                    else
                        info.CurrentJob = info.CurrentJob.Execute(info);
                }
                catch (Exception ex)
                {
                    Common.log.Error("CallProcess " + info.Name, ex);
                }
                finally
                {
                    info.IsCall = false;
                }
            }
        }

        private void GetAgvState(ref AgvInfo info)
        {
            if (!info.IsOnline) return;
            bool rtn = Common.mir.Get_State(info.IP, info.Authorization, out int stateID, out string stateText, out int battery, out string missionText, out System.Drawing.PointF position);
            //Common.log.Debug(string.Format("{1} GetAgvState[return={0}] stateID={2}, stateText={3}, battery={4}, missionText={5}, position={6}", rtn, info.FullName, stateID, stateText, battery, missionText, position));

            if (rtn)
            {
                info.StateID = stateID;
                info.StateText = stateText;
                info.Battery = battery;
                info.MissionText = missionText;
                //info.Position = position;
                CheckStandTimeOut(info,position);
                UpdateDisplayBoard(info);
                string ip = info.IP;
                int idx = Common.agvInfos.FindIndex(s => s.IP == ip);
                if (idx > -1) AgvChanged?.Invoke(idx);

            }
        }
        /// <summary>
        /// 检查小车是否在原地停留超时
        /// </summary>
        /// <returns></returns>
        private void CheckStandTimeOut(AgvInfo agv,System.Drawing.PointF position)
        {
            if (agv.IsCall && agv.CurrentJob != null && !(agv.CurrentJob is ChargeJob) && !(agv.CurrentJob is StandbyJob))//!CurTaskName.Contains(SettingString.AutoCharge) ||
            {
                if (Math.Abs(position.X - agv.Position.X) < 1 && Math.Abs(position.Y - agv.Position.Y) < 1)
                {
                    //满足条件,计算持续时间
                    if (agv.StandStartTime == DateTime.MaxValue)
                    {
                        agv.StandStartTime = DateTime.Now;
                    }
                    TimeSpan lastTimeSpan = DateTime.Now - agv.StandStartTime;
                    agv.StandTimeOut = (lastTimeSpan.TotalMinutes >= agv.StandLastTimeMinute);
                }
                else
                {
                    //重新计时
                    agv.StandStartTime = DateTime.Now;
                    agv.StandTimeOut = false;

                }
            }
            else if (agv.CurrentJob != null && ((agv.CurrentJob is ChargeJob)|| (agv.CurrentJob is StandbyJob)))
            {
                agv.StandTimeOut = false;
                agv.StandStartTime = DateTime.Now;
            }
            else
            {
                agv.StandTimeOut = false;
                agv.StandStartTime = DateTime.Now;
            }
            agv.Position = position;
        }

        private void UpdateDisplayBoard(AgvInfo agv)
        {
            try
            {
                if (agv.StandTimeOut)
                {
                   // isAlarm = true;
                    agv.DisplayBoard.Add(agv.Name, "lineAgv." + agv.Name + ".StandTimeOut", "在" + agv.Place + "停留超时" + (DateTime.Now - agv.StandStartTime).TotalMinutes.ToString("f2") + "分钟");
                }

                if ((int)StateID.Error == agv.StateID || (int)StateID.EmergencyStop == agv.StateID || (int)StateID.Pause == agv.StateID)
                {
                    //isAlarm = true;
                    agv.DisplayBoard.Add(agv.Name, "lineAgv." + agv.Name + ".Error.EmergencyStop", "agv状态:" + agv.StateText);
                }
                agv.DisplayBoard.UpdateAlarmMsg();
            }
            catch (Exception ex)
            {
                Common.log.Error(agv.Name + "上报小车信息失败",ex);
            }
        }
        private void CheckAgvOnline(ref AgvInfo info)
        {
            bool rtn = Common.mir.CheckIP(info.IP);
            if (rtn)
            {
                if (!info.IsOnline)
                {
                    info.IsOnline = true;
                    string ip = info.IP;
                    int idx = Common.agvInfos.FindIndex(s => s.IP == ip);
                    if (idx > -1) AgvOnline?.Invoke(idx);

                    //rtn = Common.mir.Get_IO_Modules(info.IP, info.Authorization, out string[] guid);
                    //if (rtn) info.IOGuid = guid[0];
                }
            }
            else
            {
                if (info.IsOnline)
                {
                    info.IsOnline = false;
                    string ip = info.IP;
                    int idx = Common.agvInfos.FindIndex(s => s.IP == ip);
                    if (idx > -1) AgvOnline?.Invoke(idx);
                }
                Common.log.Debug(string.Format("{0}[{1}] 脱机", info.Name, info.IP));
            }
        }

        private enum StateID : int
        {
            None,
            Starting,
            ShuttingDown,
            Ready,
            Pause,
            Executing,
            Aborted,
            Completed,
            Docked,
            Docking,
            EmergencyStop,
            ManualControl,
            Error
        }

    }
}