Control.cs 9.4 KB
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using Model;

namespace BLL
{
    public class Control
    {
        private Timer timerCall;
        private PointF[] position;
        private DateTime[] timeout;

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

        public Control()
        {
            ThreadPool.SetMaxThreads(5, 5);  //线程池最大数量
            position = new PointF[Common.agvInfos.Count];
            for (int i = 0; i < position.Length; i++)
                position[i] = new PointF();
        }

        public void Start()
        {
            timeout = new DateTime[Common.agvInfos.Count];
            for (int i = 0; i < timeout.Length; i++)
                timeout[i] = DateTime.Now;
            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)
                    {
                        //软件刚打开时,防止有任务在运行
                        Common.mir.Del_Mission(info.IP, info.Authorization);
                        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;
                }
            }
            UpdateBoard();

            //for (int i = 0; i < Common.agvInfos.Count; i++)
            //{
            //    AgvInfo agv = Common.agvInfos[i];
            //    if (agv.IsCall) continue;

            //    try
            //    {
            //        agv.LogJson.OutputLog();
            //        string name = "12号车";
            //        agv.IsCall = true;
            //        CheckAgvOnline(agv);
            //        if (!agv.IsOnline && agv.IsAuto)   //脱机
            //        {
            //            DisplayBoard.Add(name, "lineAgv." + name + ".Msg", "离线", 0);
            //            continue;
            //        }
            //        if (!agv.IsOnline && agv.IsAuto)   //脱机
            //        {
            //            DisplayBoard.Add(name, "lineAgv." + name + ".Msg", "停用", 0);
            //            continue;
            //        }
            //        GetAgvState(agv);
            //        if (!agv.IsAuto) continue;     //手动

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

            //        if (agv.CurrentJob == null)
            //        {
            //            //软件刚打开时,防止有任务在运行
            //            Common.mir.Del_Mission(agv.IP, agv.Authorization);
            //            agv.CurrentJob = new StandbyJob();
            //        }
            //        else
            //        {
            //            agv.CurrentJob = agv.CurrentJob.Execute(agv);
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        Common.log.Error("CallProcess " + agv.Name, ex);
            //    }
            //    finally
            //    {
                  
            //        agv.IsCall = false;
            //    }
            //}
            //DisplayBoard.UpdateAlarmMsg();
        }

        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 PointF position);
            //Common.log.Debug(string.Format("{0}[{1}] AgvState[{2}] stateID={3}, stateText={4}, battery={5}, missionText={6}, position={7}", info.Name, info.IP, rtn, stateID, stateText, battery, missionText, position.ToString()));

            if (rtn)
            {
                info.StateID = stateID;
                info.StateText = stateText;
                info.Battery = battery;
                info.MissionExplain = missionText;
                info.Position = position;

                string ip = info.IP;
                int idx = Common.agvInfos.FindIndex(s => s.IP == ip);
                if (idx > -1) AgvChanged?.Invoke(idx);
            }
        }

        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);
                    Common.log.Info(string.Format("{0}[{1}] 上线", info.Name, info.IP));
                }
            }
            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.Warn(string.Format("{0}[{1}] 脱机", info.Name, info.IP));
            }
        }

        private void UpdateBoard()
        {
            for (int i = 0; i < Common.agvInfos.Count; i++)
            {
                AgvInfo agv = Common.agvInfos[i];
                if (agv.CurrentJob == null)
                {
                    timeout[i] = DateTime.Now;
                    continue;
                }

                agv.LogJson.OutputLog();
                string name = "12号车";

                if (!agv.IsOnline && agv.IsAuto)  //自动+离线
                {
                    DisplayBoard.Add(name, "lineAgv." + name + ".Msg", "离线", 0);
                    continue;
                }

                if (!agv.IsOnline && !agv.IsAuto)  //手动+离线
                {
                    DisplayBoard.Add(name, "lineAgv." + name + ".Msg", "停用", 0);
                    continue;
                }

                if (agv.IsOnline && !agv.IsAuto)  //手动+在线
                {
                    DisplayBoard.Add(name, "lineAgv." + name + ".Msg", "正常", 1);
                    continue;
                }

                //自动在线,显示当前状态
                if (Math.Abs(agv.Position.X - position[i].X) < 1 && Math.Abs(agv.Position.Y - position[i].Y) < 1)
                {
                    TimeSpan span = DateTime.Now - timeout[i];
                    int tt = Convert.ToInt32(span.TotalMinutes - Common.BoardTimeout);
                    if (tt > 0)
                    {
                        if (agv.CurrentJob is ChargeJob)
                        {
                            DisplayBoard.Add(name, "lineAgv." + name + ".Place", "AutoCharge", 1);
                        }
                        else if (agv.CurrentJob is StandbyJob)
                        {
                            DisplayBoard.Add(name, "lineAgv." + name + ".Place", "Standby", 1);
                        }
                        else
                        {
                            string value = string.Format("在去{0}途中停留超时{1:F}分钟,{2}", agv.Place, tt, agv.MissionName);
                            DisplayBoard.Add(name, "lineAgv." + name + ".StandTimeOut", value, 0);
                            Common.log.Info(agv.Name + " 上传报告 " + value);
                            agv.LogJson.SetErrorStart(agv.TaskName, value);
                        }
                    }
                    else
                    {
                        DisplayBoard.Add(name, "lineAgv." + name + ".Msg", agv.CurrentJob.Msg, 1);
                    }
                }
                else
                {
                    DisplayBoard.Add(name, "lineAgv." + name + ".Msg", agv.CurrentJob.Msg, 1);
                    timeout[i] = DateTime.Now;
                    position[i] = new PointF(agv.Position.X, agv.Position.Y);
                    agv.LogJson.SetErrorOver();
                }


            }

            DisplayBoard.UpdateAlarmMsg();
        }

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

    }
}