App.xaml.cs 13.5 KB
using Microsoft.Extensions.Configuration;
using RCS.Communication;
using RCS.Dal;
using RCS.Model.ClientMoel;
using RCS.Model.Entity;
using RCS.Model.ManualModel;
using RCS.Model.PLC;
using RCS.WinClient.Common;
using RCS.WinClient.Views;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace RCS.WinClient
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {

        #region 变量属性
        /// <summary>
        /// 点上下间隔像素
        /// </summary>
        public static int GsHeight = 36;
        /// <summary>
        /// 点左右间隔像素
        /// </summary>
        public static int GsWidth = 36;
        /// <summary>
        /// 地图最小值Y
        /// </summary>
        public static int HeightMin = 0;
        /// <summary>
        /// 地图最大值Y
        /// </summary>
        public static int HeightMax = 0;
        /// <summary>
        /// 地图最小值X
        /// </summary>
        public static int WidthMin = 0;
        /// <summary>
        /// 地图最大值X
        /// </summary>
        public static int WidthMax = 0;
        /// <summary>
        /// 地图显示方向
        /// </summary>
        public static int Rotote = 2;
        /// <summary>
        /// 点位的坐标范围(在这个坐标范围内就认为在点位上)
        /// </summary>
        public static int PointRange = 400;//30;
        /// <summary>
        /// 地图货架显示集合
        /// </summary>
        public static List<Rectangle> ShelfSharp = new List<Rectangle>();
        /// <summary>
        /// 地图小车显示集合
        /// </summary>
        public static List<Ellipse> AgvSharp = new List<Ellipse>();
        /// <summary>
        /// 地图点显示集
        /// </summary>
        public static List<Ellipse> PointSharp = new List<Ellipse>();
        /// <summary>
        /// 控制界面显示
        /// </summary>
        public static Canvas Canvas_Monit = null;
        /// <summary>
        /// 主窗体
        /// </summary>
        public static MainWindow WinMain = null;
        /// <summary>
        /// 线程
        /// </summary>
        public static Dispatcher AppDispatcher;
        /// <summary>
        /// 监听数量
        /// </summary>
        public static int ServerConactNum = 50;
        /// <summary>
        /// 区域个数
        /// </summary>
        public static int KeyAreaNum = 1;
        /// <summary>
        /// 满电量
        /// </summary>
        public static float FullCharge;
        /// <summary>
        /// 安全电量
        /// </summary>
        public static float SafeCharge;
        /// <summary>
        /// 危险电量
        /// </summary>
        public static float DangerCharge;
        /// <summary>
        /// 最低充电量
        /// </summary>
        public static float MinCharges;
        /// <summary>
        /// AGV车身长度
        /// </summary>
        public static int AgvLength = 113;
        /// <summary>
        /// 带货避让的子任务号
        /// </summary>
        public static uint AvoidSubTaskNo = 9999999;
      

        /// <summary>
        /// 连接的AGV客户端
        /// </summary>
        public static BlockingCollection<ClientControl> ClientWork = new BlockingCollection<ClientControl>();
        /// <summary>
        /// 存入日志
        /// </summary>
        public static Log ExFile = new Log();
        /// <summary>
        /// 界面显示集合
        /// </summary>
        public static Sharp Sharp = new Sharp();
        /// <summary>
        /// 参数配置集合
        /// </summary>
        public static Dictionary<string, Config_KeyValue> Config_KeyValueDic = new Dictionary<string, Config_KeyValue>();
        /// <summary>
        /// AGV集合
        /// </summary>
        public static List<Base_Agv> AgvList = new List<Base_Agv>();
        /// <summary>
        /// 站台集合
        /// </summary>
        public static List<Base_Station> StationList = new List<Base_Station>();
        /// <summary>
        /// Point集合
        /// </summary>
        public static List<Base_Point> PointList = new List<Base_Point>();

        /// <summary>
        /// 主任务集合
        /// </summary>
        public static ObservableCollection<Base_Task> TaskList = new ObservableCollection<Base_Task>();
        /// <summary>
        /// 任务分解设置集合
        /// </summary>
        public static List<Config_TaskSplit> Config_TaskSplitList = new List<Config_TaskSplit>();

        /// <summary>
        /// 任务AGV群组匹配关系
        /// </summary>
        public static List<Config_TaskAgvGroup> TaskAgvGroupList = new List<Config_TaskAgvGroup>();
        /// <summary>
        /// 单步控制集合
        /// </summary>
        public static List<SingleControl> SingleControlList = new List<SingleControl>();
        /// <summary>
        /// 旋转锁定点配置集合
        /// </summary>
        public static List<Config_Point> Config_PointList = new List<Config_Point>();
        /// <summary>
        /// 库位地标
        /// </summary>
        public static List<Base_Loction> LoctionList = new List<Base_Loction>();
        /// <summary>
        /// 地标集合
        /// </summary>
        public static List<Base_Point> DemoPointList = new List<Base_Point>();
        /// <summary>
        /// 所有设备集合
        /// </summary>
        public static List<Base_Equipment> EquipmentList = new List<Base_Equipment>();
        /// <summary>
        /// 华恒站台监控
        /// </summary>
        public static List<HuahengStaion> HuahengStaionList = new List<HuahengStaion>();
        /// <summary>
        /// 剪床监控
        /// </summary>
        public static List<Shears> ShearsList = new List<Shears>();
        /// <summary>
        /// 快卷门监控
        /// </summary>
        public static List<Door> DoorList = new List<Door>();


        public static List<Line> MapLines = [];
        /// <summary>
        /// AGV信息监控
        /// </summary>
        public static Dictionary<string, AgvMonitor> AgvMonitorDic = new Dictionary<string, AgvMonitor>();
        /// <summary>
        /// 错误说明列表
        /// </summary>
        public static string[] Config_ErrMsgList { set; get; }

        /// <summary>
        /// agv错误信息
        /// </summary>
        //public static BlockingCollection<Log_AgvErrMsg> AgvErrMsgs { set; get; } = [];
        public static List<Log_AgvErrMsg> AgvErrMsgs { set; get; } = [];
        /// <summary>
        /// 配置文件
        /// </summary>
        public static AppConfig AppConfig { get; set; }


        public static Dictionary<string, Dictionary<string, (string desc, Func<object, object> func)>?> LogObjectInfoCache { get; set; } = new();
        public static Dictionary<string, PropCache> AgvPropCache { get; set; } = [];

        public static Dictionary<int, Protocol> Protocols { get; set; } = [];
        //是否测试模式
        public static bool IsTestMode;
        //是否允许站台中旋转
        public static bool IsAllowStationRotate;
        #endregion

        void Application_Startup(object sender, StartupEventArgs e)
        {
            DispatcherUnhandledException += App_DispatcherUnhandledException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            // 设置文本渲染选项
            //RenderOptions.SetTextRenderingMode(Application.Current.MainWindow, TextRenderingMode.ClearType);
            //RenderOptions.SetClearTypeHint(Application.Current.MainWindow, ClearTypeHint.Enabled);

            Mutex mutex = new Mutex(true, "ElectronicNeedleTherapySystem1", out bool ret);
            //if (!ret)
            //{
            //    ComnMethod.Message("已有一个RCS程序实例运行,请勿重新运行!");
            //    Environment.Exit(0);
            //    return;
            //}

            System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName("RCS.WinClient");
            if (p.Length > 1)
            {
                ComnMethod.Message("RCS程序已启动,请勿重新运行!");
                Environment.Exit(0);
                return;
            }

            //加载配置
            var appConfig = new ConfigurationBuilder().AddJsonFile("AppSettings.json").Build().Get<AppConfig>();
            if (appConfig == null)
            {
                ComnMethod.Message("无启动配置文件请检查程序即将推出!");
                Environment.Exit(0);
                return;
            }
            AppConfig = appConfig;
            DbContext.Log = ExFile.MessageSql;
            DbContext.Init(AppConfig.DalOptions);
            PLCHelper.PLCHelperLog = ExFile.MessageLog;

            //缓存agv属性
            AgvPropCache = ComnMethod.GetPropsCacheInfo(typeof(Base_Agv));

            WinMain = new MainWindow();
            WinMain.Show();
        }

        /// <summary>
        /// 获取参数配置的double值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static double GetKeyValue(string key)
        {
            if (!Config_KeyValueDic.TryGetValue(key, out Config_KeyValue? value))
            {
                throw new Exception($"发生异常:字典中不存在充电需要的参数【{key}】");
            }
            return value.DoubleValue;
        }

        #region 异常捕获
        /// <summary>
        /// Task线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
        {
            Exception ex = e.Exception;
            string msg = string.Format($"Task线程异常,原因:{ex.Message},\n 堆栈:{ex.StackTrace}");
            ExFile.MessageError("App", msg);
        }

        /// <summary>
        /// 非UI线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception ex)
            {
                //异常信息 和 调用堆栈信息
                string msg = String.Format($"发生非UI线程异常,程序即将停止,原因:{ex.Message},\n 堆栈:{ex.StackTrace}");
                ExFile.MessageError("App_DispatcherUnhandledException", msg);

                ComnMethod.Message(msg);
            }
        }

        /// <summary>
        /// UI线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            Exception ex = e.Exception;
            //异常信息 和 调用堆栈信息
            string msg = string.Format($"UI线程异常,原因:{ex.Message},\n 堆栈:{ex.StackTrace}");
            ComnMethod.Message(msg);
            ExFile.MessageError("App", msg);
            e.Handled = true;
        }

        #endregion

        #region 关机AGV设置

        /// <summary>
        /// AGV是否要关机,0=不要关机、1=要关机
        /// </summary>
        public static int offAgv = 0;
        /// <summary>
        /// 关机时间
        /// </summary>
        public static DateTime offTime;
        /// <summary>
        /// 关机AGV编码
        /// </summary>
        public static List<string> OffAgvNos = new List<string>();

        #endregion

        #region 测试全局变量

        public static int StartCycle = 0;
        /// <summary>
        /// 测试行走循环任务
        /// </summary>
        public static List<ManualCycle> ManualCycleList = new List<ManualCycle>();
        /// <summary>
        /// 循环任务
        /// </summary>
        public static List<(Base_Agv agv, string taskType)> RecurrentTasks = new();
        /// <summary>
        /// 随机任务配置
        /// </summary>
        public static (bool IsStartRadom, int Concurrency, List<string> TaskTypes) RadomTaskConfig;


        /// <summary>
        /// 测试耦合旋转循环任务变量
        /// </summary>
        public static int RotateTask = 0;
        public static List<string> RotateAgvNo = new List<string>();
        public static List<string> RotateStartPoint = new List<string>();

        /// <summary>
        /// 测试升降循环任务变量 
        /// </summary>
        public static int LiftTask = 0;
        public static List<string> LiftAgvNo = new List<string>();
        public static List<string> LiftStartPoint = new List<string>();

        /// <summary>
        /// 测试托盘旋转循环任务变量 
        /// </summary>
        public static int PalletTask = 0;
        public static List<string> PalletAgvNo = new List<string>();
        public static List<string> PalletStartPoint = new List<string>();

        /// <summary>
        /// 测试充电电量监测
        /// </summary>
        public static int ChargeTask = 0;

        /// <summary>
        /// 异常小车集合
        /// </summary>
        public static List<string> errAgv = new List<string>();
        #endregion
    }

}