Control.cs 12.6 KB
using System;
using System.Collections.Generic;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using AGVControl;
using BLL;
using log4net.Util;
using RestSharp;

namespace AGVControl.BLL
{
    public class Control
    {
        //private int areaC_Index;
        private System.Timers.Timer AgvCallTimer;
        private System.Timers.Timer AgvStateTimer;
        private System.Timers.Timer NodeStateTimer;
        //public List<string> Marks;
        private const int REG_STATUS = 20;
        //private List<string> shelfLockedNodeNames;
        public delegate void AgvChangedEvent(int agvIndex);
        public event AgvChangedEvent AgvChanged;
        public event AgvChangedEvent AgvOnline;
        public event AgvChangedEvent NodeChangedEvent;
        public Control()
        {
            AgvCallTimer = new System.Timers.Timer
            {
                Interval = 300,
                AutoReset = true,
                Enabled = false
            };
            AgvCallTimer.Elapsed += AgvCallTimer_Elapsed;

            AgvStateTimer = new System.Timers.Timer
            {
                Interval = 3000,
                AutoReset = true,
                Enabled = false
            };
            AgvStateTimer.Elapsed += AgvStateTimer_Elapsed;
            NodeStateTimer = new System.Timers.Timer
            {
                Interval = 5000,
                AutoReset = true,
                Enabled = false
            };
            NodeStateTimer.Elapsed += NodeStateTimer_Elapsed;
        }


        public void Start()
        {
            AgvCallTimer.Enabled = true;
            AgvStateTimer.Enabled = true;
            NodeStateTimer.Enabled = true;
            AgvCallTimer.Start();
            AgvStateTimer.Start();
            NodeStateTimer.Start();
        }

        public void Stop()
        {
            AgvCallTimer.Enabled = false;
            AgvStateTimer.Enabled = false;
            NodeStateTimer.Enabled = false;
            AgvCallTimer.Stop();
            AgvStateTimer.Stop();
            NodeStateTimer.Stop();
        }
        private bool NodeStateInProcess = false;
        private void NodeStateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (NodeStateInProcess) return;
            NodeStateInProcess = true;
            List<AlarmMsg> msglist = new List<AlarmMsg>();
            try
            {
                String tmp = "";
                for (int j = 0; j < Common.nodeInfo.Count; j++)
                {
                    if (!Common.nodeInfo[j].Online)
                    {
                        msglist.Add(new AlarmMsg(Common.nodeInfo[j].AliceName, "lineAgv." + Common.nodeInfo[j].Name + ".OffLine", "离线"));
                    }
                    if (Common.nodeInfo[j].Name.StartsWith(SettingString.D4_Name_Prefix) || Common.nodeInfo[j].Name.StartsWith(SettingString.C4_Name_Prefix))
                    {
                        if (!Common.nodeInfo[j].Name.Equals(SettingString.C4FeederIn) && !Common.nodeInfo[j].Name.Equals(SettingString.C4FeederOut) &&
                            !Common.nodeInfo[j].Name.Equals(SettingString.D4FeederIn) && !Common.nodeInfo[j].Name.Equals(SettingString.D4FeederOut))
                        {
                            tmp = AGVManager.GetFirstRFID(Common.nodeInfo[j].Name);
                            if (!tmp.Equals(Common.nodeInfo[j].RFID))
                            {
                                Common.nodeInfo[j].RFID = tmp;
                                NodeChangedEvent?.Invoke(j);
                            }

                        }
                        if (Common.nodeInfo[j].Name.Equals(SettingString.C4FeederOut) || Common.nodeInfo[j].Name.Equals(SettingString.D4FeederOut))
                        {
                            if (Common.missionManager.GetUnlockCnt(Common.nodeInfo[j].Name) > 0)
                            {
                                tmp = Common.missionManager.GetUnlockRfids(Common.nodeInfo[j].Name)[0];
                                if (!tmp.Equals(Common.nodeInfo[j].RFID))
                                {
                                    Common.nodeInfo[j].RFID = tmp;
                                    NodeChangedEvent?.Invoke(j);
                                }

                            }

                        }
                    }
                }
                AGVManager.updateDeviceAlarmMsg(msglist);
            }
            catch(Exception ex)
            {
                Common.log.Error("NodeStateTimer " + ex.Message + ex.StackTrace);
            }
            NodeStateInProcess = false;
        }
        private bool AgvStateInProcess = false;
        //private eAGVState preAGVState = eAGVState.None;
        private void AgvStateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            bool rtn;
            if (AgvStateInProcess) return;
            AgvStateInProcess = true;
            List<AlarmMsg> msglist = new List<AlarmMsg>();
            for (int i = 0; i < Common.agvInfo.Count; i++)
            {
                //上报异常
                bool isAlarm = false;
                //if (msglist.Count > 0)
                //    msglist.Clear();
                try
                {
                    if (!CheckOnline(i)) continue;
                    bool change = false;
                    Common.mir.Get_Task_State(Common.agvInfo[i].CurTaskID, out string stateStr);
                    Thread.Sleep(50);
                    //获取AGV状态
                    rtn = Common.mir.Get_State(Common.agvInfo[i], out eAGVState stateID, out string stateText, out int battery, out string mission_text, out Agv_Info.clsPosition position);
                    Thread.Sleep(50);
                    if (rtn) change = Common.agvInfo[i].SetState(stateID, stateStr, battery, mission_text, position);

                   // if (change)
                    {
                        AgvChanged?.Invoke(i);
                    }

                    Thread.Sleep(50);
                    //rtn = Common.mir.Get_IO_Status(Common.agvInfo[i], out bool[] input, out bool[] output);
                   //Common.log.Debug("获取IO状态");

                    //preAGVState = Common.agvInfo[i].StateID;

                    if (Common.agvInfo[i].StandTimeOut)
                    {
                        isAlarm = true;
                        msglist.Add(new AlarmMsg(Common.agvInfo[i].Name, "lineAgv." + Common.agvInfo[i].Name + ".StandTimeOut", "在" + Common.agvInfo[i].PlaceAliceName + "停留超时" + (DateTime.Now - Common.agvInfo[i].StandStartTime).TotalMinutes.ToString("f2") + "分钟"));
                    }

                    if (stateText.Equals("Error") || stateText.Equals("EmergencyStop") || stateText.Equals("Pause"))
                    {
                        isAlarm = true;
                        msglist.Add(new AlarmMsg(Common.agvInfo[i].Name, "lineAgv." + Common.agvInfo[i].Name + ".Error.EmergencyStop", "agv状态:" + stateText + ""));
                    }
                    if (!isAlarm)
                    {
                        try
                        {
                            if (!Common.agvInfo[i].Msg.Equals(""))
                                msglist.Add(new AlarmMsg(Common.agvInfo[i].Name, "lineAgv." + Common.agvInfo[i].Name + ".Msg", Common.agvInfo[i].Msg, 1));
                            else
                            {
                                if ((Common.agvInfo[i].Place.Contains(SettingString.AutoCharge) || Common.agvInfo[i].Place.Contains(SettingString.Standby)))
                                {
                                    msglist.Add(new AlarmMsg(Common.agvInfo[i].Name, "lineAgv." + Common.agvInfo[i].Name + ".Place", Common.agvInfo[i].Place, 1));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Common.log.Error(Common.agvInfo[i].Name + "上报小车运行步骤失败" + ex.Message + ex.StackTrace);
                        }
                    }
                    AGVManager.updateDeviceAlarmMsg(msglist);
                }
                catch (Exception ex)
                {
                    Common.log.Error("AgvStateTimer_" + Common.agvInfo[i].Name + ex.Message + ex.StackTrace);
                }
            }

            AgvStateInProcess = false;
        }

        /// <summary>
        /// 从节点获取任务
        /// </summary>
        /// <param name="agv_Info"></param>
        /// <returns></returns>
        public Job GetJob(Agv_Info agv_Info)
        {
            foreach (Node node in Common.nodeInfo)
            {
                Job job = null;

                if (node.Name.Equals("A5"))
                {
                    if (!SettingString.C4_AGV_IPs.Contains(agv_Info.IP))
                        continue;
                    job = ((DoubleLineNodeFor4C)node).GetNewJob(agv_Info);
                }
                else if (node.Name.Equals("A6"))
                {
                    if (SettingString.C4_AGV_IPs.Contains(agv_Info.IP))
                        continue;
                    job = ((DoubleLineNodeFor4D)node).GetNewJob(agv_Info);
                }
                else
                {
                    job = node.GetNewJob(agv_Info);
                }

                if (job != null)
                {
                    Common.log.Info(node.Name + " GetJob OK " + job.ToString());
                    return job;
                }
            }
            return null;
        }

        private bool AgvCallInProcess = false;
        private void AgvCallTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (AgvCallInProcess) return;
            AgvCallInProcess = true;
            for (int i = 0; i < Common.agvInfo.Count; i++)
            {
                try
                {
                    Agv_Info agv = Common.agvInfo[i];
                    if (!agv.IsCon) continue;   //AGV网络连接
                    if (!Common.agvInfo[i].IsUse) continue;   //AGV是否可用

                    //Ready,Pause,Executing,Error
                    if (!Common.agvInfo[i].StateID.Equals(eAGVState.Ready) && !Common.agvInfo[i].StateID.Equals(eAGVState.Pause)
                        && !Common.agvInfo[i].StateID.Equals(eAGVState.Executing) && !Common.agvInfo[i].StateID.Equals(eAGVState.Error))
                    {
                        Common.LogInfo(string.Format("{0}不能调用 StateID={1}", Common.agvInfo[i].Name, Common.agvInfo[i].StateID.ToString()));
                        continue;
                    }

                    if (agv.CurJob == null)
                    {
                        Job job = GetJob(agv);
                        if (job != null)
                        {
                            agv.CurJob = job;
                        }
                        else
                        {
                            //if (agv.Battery < Common.chargeStatus.chargeMax)
                            agv.CurJob = new ChargeJob(agv.Place);

                        }
                    }

                    if (agv.CurJob != null)
                    {
                        agv.CurJob = agv.CurJob.Execute(agv);
                    }

                }
                catch (Exception ex)
                {
                    Common.log.Error("AgvCall " + ex.Message + ex.StackTrace);
                }
            }

            AgvCallInProcess = false;

        }


        private bool CheckOnline(int idx)
        {
            bool rtn = Common.mir.CheckIP(Common.agvInfo[idx].IP);
            if (rtn)
            {
                if (Common.agvInfo[idx].IsCon)
                {
                    Common.log.Debug(Common.agvInfo[idx].Name + " Online");
                }
                else
                {
                    Common.agvInfo[idx].IsCon = true;
                    Common.LogInfo(Common.agvInfo[idx].Name + " Online");
                    AgvOnline?.Invoke(idx);
                    AgvChanged?.Invoke(idx);
                }
            }
            else
            {
                if (Common.agvInfo[idx].IsCon)
                {
                    Common.agvInfo[idx].IsCon = false;
                    Common.LogInfo(Common.agvInfo[idx].Name + " Offline");
                    AgvOnline?.Invoke(idx);
                    AgvChanged?.Invoke(idx);
                }
                else
                {
                    Common.log.Debug(Common.agvInfo[idx].Name + " Offline");
                }
            }
            return rtn;
        }

    }
}