| | |
| | | using HMI.Base; |
| | | using ConnectionUtil; |
| | | using HMI.Base; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.UI; |
| | | using HMI.UI.Util; |
| | | using log4net; |
| | | using OPCConnection; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.DOControl.Entity; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Collections.ObjectModel; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Media; |
| | | |
| | | namespace HMI.DOControl |
| | | namespace Plugin.DOControl |
| | | { |
| | | /// <summary> |
| | | /// UserControl1.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class DOControl : PluginControl |
| | | { |
| | | /// <summary> |
| | | /// 实例化服务器接口函数 |
| | | /// </summary> |
| | | private SCADAApi lTSCADAApi = new OPCClient(); |
| | | //private PipeClient pipeClient = new PipeClient("DAService"); |
| | | |
| | | private ObservableCollection<string> groups; |
| | | public ObservableCollection<string> Groups |
| | | { |
| | | get => groups; |
| | | set |
| | | { |
| | | Set(ref groups, value); |
| | | } |
| | | } |
| | | |
| | | private string selectedGroup; |
| | | public string SelectedGroup |
| | | { |
| | | get => selectedGroup; |
| | | set |
| | | { |
| | | Set(ref selectedGroup, value); |
| | | if (string.IsNullOrEmpty(value)) |
| | | { |
| | | selectedControls.Clear(); |
| | | } |
| | | else if (GroupMap.ContainsKey(value)) |
| | | { |
| | | selectedControls = GroupMap[value]; |
| | | } |
| | | RefreshControl(); |
| | | } |
| | | } |
| | | |
| | | private ObservableCollection<DOControlData> datasource; |
| | | public ObservableCollection<DOControlData> Datasource |
| | | { |
| | | get => datasource; |
| | | set |
| | | { |
| | | Set(ref datasource, value); |
| | | } |
| | | } |
| | | |
| | | private Dictionary<string, List<DOControlData>> GroupMap = new Dictionary<string, List<DOControlData>>(); |
| | | |
| | | private List<FrameworkElement> visiableControls = new List<FrameworkElement>(); |
| | | private List<DOControlData> selectedControls = new List<DOControlData>(); |
| | | |
| | | private System.Timers.Timer motorMonitorTimer; |
| | | |
| | | public DOControl() |
| | | { |
| | | DataContext = this; |
| | | motorMonitorTimer = new System.Timers.Timer(); |
| | | motorMonitorTimer.Interval = 200; |
| | | motorMonitorTimer.AutoReset = false; |
| | | motorMonitorTimer.Elapsed += MotorMonitorTimer_Elapsed; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | public override void Active() |
| | | { |
| | | motorMonitorTimer.Enabled = true; |
| | | base.Active(); |
| | | } |
| | | |
| | | public override void DeActive() |
| | | { |
| | | motorMonitorTimer.Enabled = false; |
| | | base.DeActive(); |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | | { |
| | | try |
| | | { |
| | | |
| | | motorMonitorTimer.Enabled = false; |
| | | base.DoClose(sender, e); |
| | | } |
| | | catch { |
| | | } |
| | | } |
| | | |
| | | public static string FilePath { get; private set; } |
| | | public static ILog Logger { get; private set; } |
| | | |
| | | public override void SetBaseFolder(string folder) |
| | | { |
| | | FilePath = Path.Combine(folder, "DOControlData.data"); |
| | | base.SetBaseFolder(folder); |
| | | } |
| | | |
| | | public override void SetLogger(ILog logger) |
| | | { |
| | | Logger = logger; |
| | | base.SetLogger(logger); |
| | | } |
| | | |
| | | public override void InitFinish() |
| | | { |
| | | base.InitFinish(); |
| | | |
| | | } |
| | | |
| | | private void LoadData() |
| | | { |
| | | ObservableCollection<DOControlData> datas = new ObservableCollection<DOControlData>(); |
| | | try |
| | | { |
| | | motorMonitorTimer.Enabled = false; |
| | | if (File.Exists(FilePath)) |
| | | { |
| | | datas = XmlHelper.DeserializeFromXml<ObservableCollection<DOControlData>>(FilePath); |
| | | } |
| | | GroupMap = datas.GroupBy(x => x.Group) |
| | | .ToDictionary( |
| | | group => group.Key, |
| | | group => group.ToList() |
| | | ); |
| | | Groups = new ObservableCollection<string>(GroupMap.Keys); |
| | | if (string.IsNullOrEmpty(SelectedGroup) && Groups.Count > 0) |
| | | { |
| | | SelectedGroup = Groups[0]; |
| | | } |
| | | else |
| | | { |
| | | RefreshControl(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Load Data Failed.", ex); |
| | | ToastHelper.Error(this, ex.Message); |
| | | } |
| | | finally |
| | | { |
| | | motorMonitorTimer.Enabled = true; |
| | | } |
| | | Datasource = datas; |
| | | } |
| | | |
| | | private void MotorMonitorTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) |
| | | { |
| | | try |
| | | { |
| | | motorMonitorTimer.Enabled = false; |
| | | for (int i = visiableControls.Count - 1; i >= 0; i--) |
| | | { |
| | | var ui = visiableControls[i]; |
| | | ui.Dispatcher.Invoke(() => |
| | | { |
| | | DOControlData data = ui.Tag as DOControlData; |
| | | if (data == null) return; |
| | | string value = GetPlcValue(data.Address); |
| | | switch (data.ControlType) |
| | | { |
| | | case ControlType.BOOL: |
| | | var color = Application.Current.FindResource("VerBar") as Brush; |
| | | if (value == data.PressDownValue) |
| | | { |
| | | color = Application.Current.FindResource("GreenVerBar") as Brush; |
| | | } |
| | | ((Button)ui).Background = color; |
| | | ((Button)ui).Content = value; |
| | | break; |
| | | case ControlType.INT: |
| | | case ControlType.WORD: |
| | | case ControlType.REAL: |
| | | case ControlType.LREAL: |
| | | case ControlType.STRING: |
| | | case ControlType.WSTRING: |
| | | ((Button)ui).Content = value; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | motorMonitorTimer.Enabled = true; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private void RefreshControl() |
| | | { |
| | | try |
| | | { |
| | | motorMonitorTimer.Enabled = false; |
| | | panel0.Children.Clear(); |
| | | panel1.Children.Clear(); |
| | | visiableControls.Clear(); |
| | | int index = 0; |
| | | foreach (string group in GroupMap.Keys) |
| | | { |
| | | int num = index % 2; |
| | | |
| | | WrapPanel panel = new WrapPanel |
| | | { |
| | | Orientation = Orientation.Horizontal |
| | | }; |
| | | GroupBox gb = new GroupBox |
| | | { |
| | | Header = group, |
| | | Content = panel, |
| | | Margin = new Thickness(0, 0, 0, 10) |
| | | }; |
| | | var datas = GroupMap[group]; |
| | | |
| | | foreach (var data in datas) |
| | | { |
| | | FrameworkElement ui = null; |
| | | switch (data.ControlType) |
| | | { |
| | | case ControlType.BOOL: |
| | | case ControlType.PULSE: |
| | | ui = CreateButton(data); |
| | | break; |
| | | case ControlType.TIME: |
| | | break; |
| | | default: |
| | | ui = CreateInput(data); |
| | | break; |
| | | } |
| | | if (ui != null) |
| | | { |
| | | FormGroup fg = new FormGroup |
| | | { |
| | | Header = data.Name, |
| | | Content = ui, |
| | | Orientation = Orientation.Vertical, |
| | | Margin = new Thickness(10, 0, 0, 10) |
| | | }; |
| | | panel.Children.Add(fg); |
| | | visiableControls.Add(ui); |
| | | |
| | | } |
| | | } |
| | | if (num == 0) |
| | | { |
| | | panel0.Children.Add(gb); |
| | | } |
| | | else |
| | | { |
| | | panel1.Children.Add(gb); |
| | | } |
| | | index++; |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | } |
| | | finally |
| | | { |
| | | motorMonitorTimer.Enabled = true; |
| | | } |
| | | } |
| | | |
| | | private Button CreateButton(DOControlData data) |
| | | { |
| | | Style btnStyle = Application.Current.FindResource("PrimaryButton") as Style; |
| | | var btn = new Button |
| | | { |
| | | Tag = data, |
| | | Style = btnStyle, |
| | | MinWidth = 180, |
| | | MinHeight = 40 |
| | | }; |
| | | if (data.ControlType == ControlType.BOOL) |
| | | { |
| | | btn.Click += ControlButton_Click; |
| | | } |
| | | else if (data.ControlType == ControlType.PULSE) |
| | | { |
| | | btn.Content = data.Address; |
| | | btn.PreviewMouseLeftButtonDown += Btn_MouseLeftButtonDown; |
| | | btn.PreviewMouseLeftButtonUp += Btn_MouseLeftButtonUp; |
| | | } |
| | | return btn; |
| | | } |
| | | |
| | | private void Btn_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | Button btn = sender as Button; |
| | | DOControlData data = btn.Tag as DOControlData; |
| | | try |
| | | { |
| | | var color = Application.Current.FindResource("GreenVerBar") as Brush; |
| | | btn.Background = color; |
| | | SetPlcValue(data.Address, data.PressDownValue); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("PressDownClick", ex); |
| | | ToastHelper.Error($"{data.Name}: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private void Btn_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | Button btn = sender as Button; |
| | | DOControlData data = btn.Tag as DOControlData; |
| | | try |
| | | { |
| | | var color = Application.Current.FindResource("VerBar") as Brush; |
| | | btn.Background = color; |
| | | SetPlcValue(data.Address, data.PressUpValue); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("PressUpClick", ex); |
| | | ToastHelper.Error($"{data.Name}: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private Button CreateInput(DOControlData data) |
| | | { |
| | | Style btnStyle = Application.Current.FindResource("PrimaryButton") as Style; |
| | | var tb = new Button |
| | | { |
| | | Tag = data, |
| | | Style = btnStyle, |
| | | MinWidth = 180, |
| | | MinHeight = 40, |
| | | BorderBrush = Brushes.Black, |
| | | BorderThickness = new Thickness(1), |
| | | Background = Brushes.White, |
| | | Foreground = Brushes.Black |
| | | }; |
| | | if (data.ReadOnly) |
| | | { |
| | | tb.Background = Brushes.LightGray; |
| | | return tb; |
| | | } |
| | | |
| | | if (data.ControlType == ControlType.STRING || data.ControlType == ControlType.WSTRING) |
| | | { |
| | | tb.Click += StringInput_Click; |
| | | } |
| | | else |
| | | { |
| | | tb.Click += NumberInput_Click; |
| | | } |
| | | return tb; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 设置plc值 |
| | | /// </summary> |
| | | /// <param name="address">地址</param> |
| | | /// <param name="valueType">类型</param> |
| | | /// <param name="value">值</param> |
| | | private void SetPlcValue(string key, string value) |
| | | { |
| | | if (!lTSCADAApi.DoFctWriteSingle(key, value, out string errMsg)) |
| | | { |
| | | ToastHelper.Error(this, errMsg); |
| | | } |
| | | |
| | | //lTSCADAApi.SendMessage("asdsadasda", out _); |
| | | } |
| | | |
| | | private string GetPlcValue(string key) |
| | | { |
| | | if (lTSCADAApi.DoFctReadSingle(key, out string Val, out string errMsg)) |
| | | { |
| | | return Val; |
| | | } |
| | | else |
| | | { |
| | | return null; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private void ControlButton_Click(object sender, RoutedEventArgs args) |
| | | { |
| | | Button btn = sender as Button; |
| | | DOControlData data = btn.Tag as DOControlData; |
| | | try |
| | | { |
| | | string value = btn.Content?.ToString() == data.PressDownValue ? data.PressUpValue : data.PressDownValue; |
| | | SetPlcValue(data.Address, value); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("ControlButton_Click", ex); |
| | | ToastHelper.Error($"{data.Name}: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private void StringInput_Click(object sender, RoutedEventArgs args) |
| | | { |
| | | Button tb = sender as Button; |
| | | DOControlData data = tb.Tag as DOControlData; |
| | | |
| | | KeyboardWindow kw = new KeyboardWindow |
| | | { |
| | | Title = data.Name, |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (kw.Open(tb.Content?.ToString()) == true) |
| | | { |
| | | SetPlcValue(data.Address, kw.Data?.ToString()); |
| | | } |
| | | } |
| | | |
| | | private void NumberInput_Click(object sender, RoutedEventArgs args) |
| | | { |
| | | Button tb = sender as Button; |
| | | DOControlData data = tb.Tag as DOControlData; |
| | | NumberPanel np = new NumberPanel |
| | | { |
| | | Title = data.Name, |
| | | Owner = Window.GetWindow(this), |
| | | DotEnabled = data.ControlType == ControlType.REAL || data.ControlType == ControlType.LREAL |
| | | }; |
| | | if (np.Open(tb.Content?.ToString()) == true) |
| | | { |
| | | SetPlcValue(data.Address, np.Data?.ToString()); |
| | | } |
| | | } |
| | | |
| | | private void UserControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | |
| | | LoadData(); |
| | | if (SystemSetting.Instance.PlcEnabled) |
| | | { |
| | | if (lTSCADAApi.Connect2("127.0.0.1", 6543, 28888, out string errMsg)) |
| | | { |
| | | motorMonitorTimer.Enabled = true; |
| | | RefreshControl(); |
| | | } |
| | | else |
| | | { |
| | | MsgBoxHelper2.Error(errMsg); |
| | | } |
| | | //try |
| | | //{ |
| | | // pipeClient.OnConnected += PipeClient_OnConnected; |
| | | |
| | | // pipeClient.Connect(); |
| | | //} |
| | | //catch (Exception ex) |
| | | //{ |
| | | // MsgBoxHelper.Error(this, ex.Message); |
| | | //} |
| | | } |
| | | Loaded -= UserControl_Loaded; |
| | | } |
| | | |
| | | private void PipeClient_OnConnected(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | |
| | | Button btn = sender as Button; |
| | | switch (btn.Name) |
| | | { |
| | | case "queryBtn": |
| | | case "addBtn": |
| | | OpenDataModal(null); |
| | | break; |
| | | case "settingBtn": |
| | | OpenDataList(); |
| | | break; |
| | | case "resetBtn": |
| | | LoadData(); |
| | | break; |
| | | case "exportBtn": |
| | | break; |
| | |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void OpenDataModal(DOControlData data) |
| | | { |
| | | DataModal modal = new DataModal |
| | | { |
| | | Title = data == null ? this.lang("App.Add") : this.lang("App.Edit"), |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (modal.Open(data ?? new DOControlData(), Datasource) == true) |
| | | { |
| | | LoadData(); |
| | | } |
| | | } |
| | | |
| | | private void OpenDataList() |
| | | { |
| | | ControlList list = new ControlList |
| | | { |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (list.Open(Datasource) == true) |
| | | { |
| | | LoadData(); |
| | | } |
| | | } |
| | | } |
| | | } |