| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- using Model;
- using Permission;
- using PlcCom;
- using Sunny.UI;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Drawing;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using System.Xml.Linq;
- namespace PlcUiForm
- {
- [FormDescriptionAttribute("窗体基类")]
- public class PlcBaseForm : UIForm
- {
- List<IPlcBindableComponent> PlcBindableComponents = new List<IPlcBindableComponent>();
- private PlcBindingManager _plcBindingManager;
- private PlcContex plcContex;
- static IPlcComProtocol defaultPlcComProtocol;
- public readonly IPlcComProtocol PlcComProtocol;
- private int refreshInterval=100;
- private ControlConfigManager _configManager;
- [Category("PLC")]
- [Description("窗体内PLC寄存的读取周期,单位:ms")]
- public int RefreshInterval
- {
- get { return refreshInterval; }
- set { if (value < 10) value = 10; refreshInterval = value; }
- }
- public static void SetDefaultProtocol(IPlcComProtocol protocol)
- {
- if(protocol == null)
- throw new NullReferenceException(nameof(protocol));
- defaultPlcComProtocol = protocol;
- }
- public PlcBaseForm(IPlcComProtocol protocol)
- {
- InitializeComponent();
- if (protocol != null)
- {
- PlcComProtocol = protocol;
- plcContex = new PlcContex(protocol);
- }
- else
- {
- throw new Exception("请传入正确的通讯协议");
- }
- OtherInitialize();
- }
- public PlcBaseForm()
- {
- InitializeComponent();
- if (defaultPlcComProtocol != null)
- {
- PlcComProtocol = defaultPlcComProtocol;
- plcContex = new PlcContex(defaultPlcComProtocol);
- }
- else
- {
- // throw new Exception("请使用SetDefaultProtocol方法传入正确的通讯协议");
- }
- OtherInitialize();
- }
- private void InitializeComponent()
- {
- this.SuspendLayout();
- //
- // PlcBaseForm
- //
- this.ClientSize = new System.Drawing.Size(1221, 640);
- this.Name = "PlcBaseForm";
- this.ZoomScaleRect = new System.Drawing.Rectangle(15, 15, 800, 480);
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.PlcComBaseForm_FormClosing);
- this.ResumeLayout(false);
- }
- void OtherInitialize()
- {
- Node.EnableDesignTimeValidation = IsDesignMode;
- }
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- UpdatePermissions();
- // 订阅权限变更事件
- PermissionManager.OnPermissionLevelChanged += OnPermissionChanged;
- //Console.WriteLine(this.GetType().Name);
- //var plcBindableControls = this.Controls.Find("", true).OfType<IPlcUiControl>().ToList();
- var plcBindableControls = FindSpecificControls.FindControlsByInterface<IPlcUiControl>(this);
- PlcBindableComponents.AddRange(plcBindableControls.Select(x => (IPlcBindableComponent)x).ToList());
- PlcBindableComponents.AddRange(GetNonControlComponents());
- foreach (var c in PlcBindableComponents)
- {
- if (c is IPlcInputComponent ic)
- {
- ic.OnWriteRegisterFailed += OnWriteRegisterFailed;
- ic.OnUserSettedValue += OnUserSettedValue;
- }
- if (c is IPlcOutputComponent oc)
- {
- oc.OnReadRegisterFailed += OnReadRegisterFailed;
- oc.OnUpdateComponentStateFailed += OnUpdateComponentStateFailed;
- }
- }
- _plcBindingManager = new PlcBindingManager();
- _plcBindingManager.ReadOK += BindingManager_ReadOK;
- _plcBindingManager.ReadOneNodeFailed += BindingManager_ComponentReadFailed;
- _plcBindingManager.ReadMultiNodesFailed += BindingManager_ReadMultiNodesFailed;
- _plcBindingManager.ReadOverTime += BindingManager_ReadOverTime;
- _plcBindingManager.Bind(PlcBindableComponents, plcBindableControls);
- if (plcContex != null)
- _plcBindingManager.SetPlcContext(plcContex, RefreshInterval); // 或者根据控件动态判断
- //查找带有最大最小值的控件
- _configManager = new ControlConfigManager(this.GetType().Name);
- foreach (IWithMinMaxValue control in FindSpecificControls.FindControlsByInterface<IWithMinMaxValue>(this))
- {
- control.MinMaxValueChanged += OnMinMaxValueChanged;
- var minMaxValue = _configManager.GetMinMax(Name, ((Control)control).Name);
- control.Minimum = minMaxValue.MinValue;
- control.Maximum = minMaxValue.MaxValue;
- }
- ////查找不是PLC地址绑定,但可以让用户操作的控件
- //foreach (IMyOperationalControl control in FindSpecificControls.FindControlsByInterface<IMyOperationalControl>(this))
- //{
- // control.OnUserOperatedControl += Control_OnUserOperatedControl;
- //}
- }
- private void UpdatePermissions()
- {
- SetIPermissionControlRequireLevel();
- PermissionManager.ApplyPermissions(this);
- }
- private void SetIPermissionControlRequireLevel()
- {
- if (IsDesignMode)
- return;
- // 从对应权限文件加载授权列表(建议缓存,不要每次都读文件)
- var authorizedControls = PermissionManager.GetAuthorizedControlsForRole(AppSession.CurrentUser.PermissionLevel);
- // 构建查找集
- var authSet = new HashSet<string>(
- authorizedControls.Select(c => $"{c.Namespace}.{c.FormType}.{c.ControlName}")
- );
- // 遍历所有字段
- var fields = this.GetType().GetFields(
- BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
- var assembly= this.GetType().Assembly;
- var ns = this.GetType().Namespace;
- var formTypeName = this.GetType().Name;
- foreach (var field in fields)
- {
- var fieldValue = field.GetValue(this);
- if (fieldValue is IActionableControl && fieldValue is IPermissionControl control)
- {
- if (control.RequiredPermissionLevel != PermissionLevel.无权限)//为无权限的控件不受权限控制
- {
- var b = authSet.Contains($"{ns}.{formTypeName}.{((Control)control).Name}");
- if (b)
- control.RequiredPermissionLevel = AppSession.CurrentUser.PermissionLevel;
- else
- control.RequiredPermissionLevel = PermissionLevel.开发者;
- }
- }
- }
- }
- //private void Control_OnUserOperatedControl(Control control, object state)
- //{
- // string opMessage;
- // if (control is MyUiButton)
- // {
- // opMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->“{control.Text}”按钮被点击";
- // }
- // else
- // {
- // opMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->“{control.Name}”被修改为:{state}";
- // }
- // AppSession.UserOperations.Add(opMessage);
- //}
- private void OnPermissionChanged(PermissionLevel newPermissionLevel)
- {
- // 在 UI 线程上更新权限(防止跨线程异常)
- if (this.InvokeRequired)
- {
- this.Invoke(new Action(UpdatePermissions));
- }
- else
- {
- UpdatePermissions();
- }
- }
- private IEnumerable<IPlcBindableComponent> GetNonControlComponents()
- {
- var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
- foreach (var field in fields)
- {
- var value = field.GetValue(this);
- if (value is IPlcBindableComponent component && !(value is Control))
- {
- yield return component;
- }
- }
- }
- //public static List<string> ReadWriteErrors = new List<string>();
- //public static List<string> UserOperations = new List<string>();
- public event Action ProtocollReadOK;
- private void BindingManager_ReadOK()
- {
- ProtocollReadOK?.Invoke();
- }
- public event Action ProtocollReadOverTime;
- private void BindingManager_ReadOverTime()
- {
- ProtocollReadOverTime?.Invoke();
- }
- private void BindingManager_ReadMultiNodesFailed(List<string> arg1, uint arg2)
- {
-
- }
- private void BindingManager_ComponentReadFailed(IPlcBindableComponent plcBindableComponent, Node node, uint errorCode)
- {
- string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node},读取失败,错误代码:0X{errorCode:X}";
- AppSession.ReadWriteErrors.Add(err);
- }
- private void OnUpdateComponentStateFailed(IPlcBindableComponent plcBindableComponent,Node node, object state, string errMessage)
- {
- string name = plcBindableComponent is Control control ? control.Name : null;
- string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{name},更新状态:\"{state}\"错误,错误信息:{errMessage}";
- AppSession.ReadWriteErrors.Add(err);
- }
- private void OnUserSettedValue(IPlcBindableComponent plcBindableComponent,OperationType operationType, Node node,object oldValue, object newValue)
- {
- var controlName = GetComponentName(plcBindableComponent);
- OperationRecord operationRecord = new OperationRecord
- {
- Timestamp = DateTime.Now,
- OperationType = operationType,
- ControlName = $"{FormName}->{controlName}",
- OldValue= oldValue,
- NewValue = newValue,
- Detail = $"{node}->{newValue.ToString()}",
- User = AppSession.CurrentUser
- };
- OperationRecordService.Log(operationRecord);
- string opMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node},人工变更为:{newValue.ToString()}";
- AppSession.UserOperations.Add(opMessage);
- }
- private void OnReadRegisterFailed(IPlcBindableComponent plcBindableComponent, Node node, uint errorCode)
- {
- string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node},读取失败,错误代码:0X{errorCode:X}";
- AppSession.ReadWriteErrors.Add(err);
- }
- private void OnWriteRegisterFailed(IPlcBindableComponent plcBindableComponent, Node node, uint errorCode)
- {
- string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node},写入失败,错误代码:0X{errorCode:X}";
- AppSession.ReadWriteErrors.Add(err);
- }
- private void OnMinMaxValueChanged(Control control, double minimum, double maximum)
- {
- _configManager.SetMinMax(this.GetType().Name, control.Name, new MinMaxValue(minimum, maximum));
- _configManager.SaveConfig();
- }
- private void PlcComBaseForm_FormClosing(object sender, FormClosingEventArgs e)
- {
- PermissionManager.OnPermissionLevelChanged -= OnPermissionChanged;
- _plcBindingManager?.Stop();
- FormEx.CloseAllChildForms(this);
- }
- // 窗体关闭时取消订阅,防止内存泄漏
- protected override void OnFormClosed(FormClosedEventArgs e)
- {
- base.OnFormClosed(e);
- }
- public string FormName {
- get
- {
- if (!string.IsNullOrWhiteSpace(this.Text))
- {
- return this.Text;
- }
- else if (!string.IsNullOrWhiteSpace(this.Name))
- {
- return this.Name;
- }
- else
- {
- return this.GetType().Name;
- }
- }
- }
- public string GetTextOrName(Control control)
- {
- // 使用反射获取控件类型上的 Text 属性
- PropertyInfo textProperty = control.GetType().GetProperty("Text", typeof(string));
- if (textProperty != null)
- {
- // 控件有 Text 属性
- string text = (string)textProperty.GetValue(control);
- if (string.IsNullOrWhiteSpace(text))
- {
- return control.Name;
- }
- else
- {
- return text;
- }
- }
- else
- {
- // 控件没有 Text 属性,返回 Name
- return control.Name;
- }
- }
- public string GetComponentName(IPlcBindableComponent plcBindableComponent)
- {
- if (plcBindableComponent is Control control)
- {
- return control.Name;
- }
- else if(plcBindableComponent is IComponent component)
- {
- // 使用反射获取控件类型上的 NodeName 属性
- PropertyInfo NodeNameProperty = component.GetType().GetProperty("NodeName", typeof(string));
- if (NodeNameProperty != null && !string.IsNullOrWhiteSpace((string)NodeNameProperty.GetValue(component))) // 控件有 NodeName 属性,且值不为空
- {
- return (string)NodeNameProperty.GetValue(component);
- }
- else
- {
- return component.Site?.Name;
- }
- }
- else
- return string.Empty;
- }
- public string GetNodeNameOrName(IPlcBindableComponent plcBindableComponent)
- {
- if (plcBindableComponent is Control || plcBindableComponent is Component)
- {
- // 使用反射获取控件类型上的 NodeName 属性
- PropertyInfo nodeNameProperty = plcBindableComponent.GetType().GetProperty("NodeName", typeof(string));
- if (nodeNameProperty != null && !string.IsNullOrWhiteSpace((string)nodeNameProperty.GetValue(plcBindableComponent))) // 控件有 NodeName 属性,且值不为空
- {
- return (string)nodeNameProperty.GetValue(plcBindableComponent);
- }
- else
- {
- // 控件没有 NodeName 属性,返回 Name
- if (plcBindableComponent is Control control)
- return control.Name;
- else if (plcBindableComponent is IComponent component)
- return component.Site?.Name;
- else
- return string.Empty;
- }
- }
- else
- return string.Empty;
- }
- }
- }
|