WinMain.xaml.cs 11.7 KB
using HHECS.Bll;
using HHECS.Common;
using HHECS.Controls;
using HHECS.Model;
using HHECS.OPC;
using HHECS.View.Win;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace HHECS.View
{
    /// <summary>
    /// Main.xaml 的交互逻辑
    /// </summary>
    public partial class WinMain : BaseWindow
    {
        #region 属性

        /// <summary>
        /// 时钟同步锁
        /// </summary>
        private object locker = new object();

        /// <summary>
        /// 子窗体
        /// </summary>
        public Dictionary<string, Window> ChildrenWin { get; set; } = new Dictionary<string, Window>();

        /// <summary>
        /// 主控时钟
        /// </summary>
        private System.Timers.Timer timer = new System.Timers.Timer();

        /// <summary>
        /// 结束时钟标志
        /// </summary>
        private bool stop = false;

        /// <summary>
        /// 用于创建设备PLC
        /// </summary>
        public List<Plc> PLCs { get; set; } = new List<Plc>();

        /// <summary>
        /// 设备
        /// </summary>
        public List<Equipment> Equipments { get; set; }

        /// <summary>
        /// 设备属性
        /// </summary>
        public List<EquipmentProp> EquipmentProps { get; set; }

        /// <summary>
        /// 设备类型
        /// </summary>
        public List<EquipmentType> EquipmentTypes { get; set; }

        /// <summary>
        /// 设备属性模板
        /// </summary>
        public List<EquipmentTypePropTemplate> EquipmentTypePropTemplates { get; set; }

        /// <summary>
        /// 堆垛机处理类
        /// </summary>
        public List<IStockerExcute> StockerExcutes { get; set; } = new List<IStockerExcute>();

        /// <summary>
        /// 站台处理类
        /// </summary>
        public List<IStationExcute> StationExcutes { get; set; } = new List<IStationExcute>();

        #endregion

        public WinMain()
        {
            InitializeComponent();
        }

        private void Init()
        {
            //时钟初始化
            InitTimer();
            //日志初始化
            Logger.LogWrite += Logger_LogWrite;
            this.WindowState = WindowState.Maximized;
            this.Lab1.Content = $"欢迎:{AppSession.User.UserName}   {DateTime.Now.ToLocalTime()}";
            //堆垛机监控
            this.StockerView.Content = new StockerMonitor(16, 4, false, 900, 150);

            #region 基础数据
            var result1 = AppSession.Bll.GetCommonModelByCondition<Equipment>("");
            var result2 = AppSession.Bll.GetCommonModelByCondition<EquipmentProp>("");
            var result3 = AppSession.Bll.GetCommonModelByCondition<EquipmentType>("");
            var result4 = AppSession.Bll.GetCommonModelByCondition<EquipmentTypePropTemplate>("");
            if (!result1.Success || !result2.Success || !result3.Success || !result4.Success)
            {
                MessageBox.Show("初始化设备信息异常");
                Btn_BeginExcute.IsEnabled = false;
                Btn_EndExcute.IsEnabled = false;
                return;
            }
            Equipments = result1.Data;
            EquipmentProps = result2.Data;
            EquipmentTypes = result3.Data;
            EquipmentTypePropTemplates = result4.Data;

            //组合逻辑外键
            Equipments.ForEach(t =>
            {
                t.EquipmentType = EquipmentTypes.FirstOrDefault(i => i.Id == t.EquipmentTypeId);
                t.EquipmentProps.AddRange(EquipmentProps.Where(i => i.EquipmentId == t.Id).ToList());
            });
            EquipmentProps.ForEach(t =>
            {
                t.Equipment = Equipments.FirstOrDefault(i => i.Id == t.EquipmentId);
                t.EquipmentTypePropTemplate = EquipmentTypePropTemplates.FirstOrDefault(i => i.Id == t.EquipmentTypePropTemplateId);
            });
            //判断逻辑外键是否组合完毕
            if (Equipments.Count(t => t.EquipmentType == null || t.EquipmentProps.Count == 0) > 0)
            {
                MessageBox.Show("初始化设备信息失败,请检查基础数据");
                Btn_BeginExcute.IsEnabled = false;
                Btn_EndExcute.IsEnabled = false;
                return;
            }
            if (EquipmentProps.Count(t => t.Equipment == null || t.EquipmentTypePropTemplate == null) > 0)
            {
                MessageBox.Show("初始化设备属性失败,请检查基础数据");
                Btn_BeginExcute.IsEnabled = false;
                Btn_EndExcute.IsEnabled = false;
                return;
            }
            //组合Dataitem和Plc
            try
            {
                Equipments.ForEach(t =>
                {
                    if (PLCs.Count(i => i.IP != t.IP) > 0)
                    {
                        PLCs.Add(new Plc(CpuType.S71500, t.IP, 0, 1));
                    }
                });
                EquipmentProps.Where(t => t.EquipmentTypePropTemplate.DataType == "PLC").ToList().ForEach(t =>
                {
                    t.DataItem = S7Helper.FromAddress(t.Address);
                });
                //打开PLC
                PLCs.ForEach(t => t.Open());
            }
            catch (PlcException plcex)
            {
                string error = $"打开通讯连接出现异常:{plcex.Message};请检查网络配置,然后重启本程序!";
                MessageBox.Show(error);
                Logger.Log(error, LogLevel.Error);
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show("组合数据地址时发生错误,请检查数据地址是否配置正确。");
                Btn_BeginExcute.IsEnabled = false;
                Btn_EndExcute.IsEnabled = false;
                return;
            }
            //组合处理类
            EquipmentTypes.ForEach(t =>
            {
                if (t.Code == "stocker")
                {
                    StockerExcutes.Add(new XiangdianStockerExcute() { EquipmentType = t });
                }
                if (t.Code == "StationOut")
                {
                    StationExcutes.Add(new XiangdianOutStationExcute() { EquipmentType = t });
                }
                if (t.Code == "StationInOrOut")
                {
                    StationExcutes.Add(new XiangdianInOrOutStationExcute() { EquipmentType = t });
                }
            });

            #endregion

        }

        #region 组件

        /// <summary>
        /// todo:日志记录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void Logger_LogWrite(object sender, LogEventArgs args)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region 时钟逻辑

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            lock (locker)
            {
                try
                {
                    #region 是否结束处理

                    if (stop)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            Btn_BeginExcute.IsEnabled = true;
                            Btn_EndExcute.IsEnabled = false;
                            timer.Enabled = false;
                        });
                        return;
                    }

                    if (PLCs.Count(t => t.IsAvailable == false || t.IsConnected == false) > 0)
                    {
                        stop = true;
                        return;
                    }

                    #endregion

                    //读取所有地址值
                    PLCs.ForEach(t => S7Helper.PlcSplitRead(t, Equipments.Where(i => t.IP == t.IP).SelectMany(i => i.EquipmentProps).Where(a => a.EquipmentTypePropTemplate.DataType == "PLC").ToList(), 20));

                    #region 堆垛机处理

                    StockerExcutes.ForEach(t =>
                    {
                        //一般根据堆垛机现在的位置来决定优先执行入库还是出库
                        t.Excute(Equipments.Where(a => a.EquipmentType.Id == t.EquipmentType.Id).ToList(), PLCs);
                    });

                    #endregion

                    #region 站台处理

                    StationExcutes.ForEach(t =>
                    {
                        t.Excute(Equipments.Where(a => a.EquipmentType.Id == t.EquipmentType.Id).ToList(), PLCs);
                    });

                    #endregion

                }
                catch (Exception ex)
                {
                    //发生异常,结束处理
                    stop = true;
                    Logger.Log($"程序处理出现异常:{ex.Message};程序处理已停止;", LogLevel.Error);
                }

            }
        }

        #endregion

        #region 窗体事件

        private void InitTimer()
        {
            timer.Interval = AppSession.Interval; //1秒触发一次
            timer.Elapsed += Timer_Elapsed; ;
            timer.AutoReset = true;//每到指定时间Elapsed事件是到时间就触发
            timer.Enabled = false; //指示 Timer 是否应引发 Elapsed 事件。
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            AppSession.Bll.Combine(AppSession.MenuOperations.Where(t => t.ParentId == null).ToList(), AppSession.Bll.GetAllMenuOperation().Data.Where(t => t.MenuType == "catalog" || t.MenuType == "menu").ToList());
            MenuMain.ItemsSource = AppSession.MenuOperations.Where(t => t.ParentId == null).OrderBy(t => t.OrderNum).ToList();

            //初始化
            Init();

        }

        private void Window_Closed(object sender, EventArgs e)
        {
            stop = true;
            timer.Enabled = false;
            Thread.Sleep(1000);
            Application.Current.Shutdown();
        }

        private void MenuMain_Checked(object sender, RoutedEventArgs e)
        {
            try
            {
                MenuOperation menu = (MenuOperation)((MenuItem)e.OriginalSource).Header;
                var win = ChildrenWin.FirstOrDefault(t => t.Key == menu.Url).Value;
                if (String.IsNullOrWhiteSpace(menu?.Url) || menu.Url == "#")
                {
                    return;
                }
                if (win == null)
                {
                    win = (Window)Activator.CreateInstance(null, menu.Url).Unwrap();
                    ChildrenWin.Add(menu.Url, win);
                }
                win.Show();
                if (win.WindowState == WindowState.Minimized)
                    win.WindowState = WindowState.Normal;
                win.Activate();
            }
            catch (Exception ex)
            {
                LogExecute.WriteExceptionLog("打开菜单", ex);
                MessageBox.Show("打开菜单出现异常!");
            }
        }

        private void Btn_BeginExcute_Click(object sender, RoutedEventArgs e)
        {
            stop = false;
            timer.Enabled = true;
            Btn_BeginExcute.IsEnabled = false;
            Btn_EndExcute.IsEnabled = true;
        }

        private void Btn_EndExcute_Click(object sender, RoutedEventArgs e)
        {
            stop = true;
            Btn_BeginExcute.IsEnabled = true;
            Btn_EndExcute.IsEnabled = false;
        }

        #endregion


    }
}