using FLY.OBJComponents.Common; using FLY.OBJComponents.IService; using FObjBase; using Misc; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FLY.OBJComponents.Server { public class ErrorConf { #region 延时推送 MARKNO const int MARKNO_DELAY_ISCONNECTED = 4; #endregion /// /// 需要设置 /// PLCProxySystem PLCos; /// /// 报警系统 /// WarningSystem2 mWarning; /// /// 报警码自动排号,再枚举IsError 属性,对应的异常会被设置为ErrCode, 然后ErrCode++ /// public int ErrCode =0; class PlcDisconnectedErrMsg { public int ErrCode; public string Description; } List plcDisconnectedErrMsgs = new List(); public ErrorConf(PLCProxySystem PLCos, WarningSystem2 mWarning, string plcName) : this(PLCos, mWarning, new string[] { plcName }) { } public ErrorConf(PLCProxySystem PLCos, WarningSystem2 mWarning, string[] plcNames) { initialize(PLCos, mWarning, plcNames, PlcErrNos.Instance.ERRNO_PLC_DISCONNECTED.Code - (PLCos.PLCs.Count() - 1)); } public ErrorConf(PLCProxySystem PLCos, WarningSystem2 mWarning, string[] plcNames, int plcErrCodeBegin) { initialize(PLCos, mWarning, plcNames, plcErrCodeBegin); } void initialize(PLCProxySystem PLCos, WarningSystem2 mWarning, string[] plcNames, int plcErrCodeBegin) { this.PLCos = PLCos; this.mWarning = mWarning; //初始化 PLC连接断开的描述列表 int plcCnt = PLCos.PLCs.Count(); int errCode = plcErrCodeBegin; string descrption = PlcErrNos.Instance.ERRNO_PLC_DISCONNECTED.Description; for (int i = 0; i < plcCnt; i++) { plcDisconnectedErrMsgs.Add(new PlcDisconnectedErrMsg() { ErrCode = errCode + i, Description = $"{GetPlcName(plcCnt, i, plcNames)} " + descrption }); } } #region 报警 public class ErrorAction { public List error_property; public object state; public delegate void ErrorHandler(ref string msg, object state); public ErrorHandler action; } public class ErrorInfo { public string property; public int code; public string msg; } Dictionary obj_error = new Dictionary(); public void AddErrorAction(INotifyPropertyChanged sender, ErrorAction.ErrorHandler errorHandler = null, object state = null) { //反射找出全部是报警的property List error_property = new List(); foreach (var propertyInfo in sender.GetType().GetProperties()) { if (propertyInfo.GetCustomAttributes(typeof(IsErrorAttribute), false).Count() > 0) { //肯定有,没有就让它出错!!! string desp = (propertyInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).First() as DescriptionAttribute).Description; //报警如果是反向, 会被设置为放大=-1, 所以 最后属性 肯定是 true 时报警, offIsError没有用 ErrorInfo errorInfo = new ErrorInfo() { property = propertyInfo.Name, msg = desp, code = ErrCode }; error_property.Add(errorInfo); ErrCode++; } } obj_error.Add(sender, new ErrorAction() { error_property = error_property, action = errorHandler, state = state }); } /// /// 执行之前,需要调用 AddErrorAction, 向 obj_error 添加报警寄存器操作 /// public void InitError() { foreach (var obj in obj_error.Keys) { obj.PropertyChanged += Obj_PropertyChanged_ForError; } //-------------------------------------------------------------------------------- //添加任务 foreach (var kv in obj_error) { string objname = PLCos.ObjNames.First(_kv => _kv.Value == kv.Key).Key; PLCos.SetPlan(objname, kv.Value.error_property.Select(ei => ei.property).ToArray(), 0); } //-------------------------------------------------------------------------------- //连接断开事件, 3秒后再查一次,不能有复位的机会 FObjBase.PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD, () => { for (int i = 0; i < PLCos.PLCs.Count(); i++) { int errcode = plcDisconnectedErrMsgs[i].ErrCode; string description = plcDisconnectedErrMsgs[i].Description; if (!PLCos.PLCs[i].Client.IsConnected) { mWarning.Add(errcode, description, canReset: false); } else { mWarning.Remove(errcode); } } }, TimeSpan.FromSeconds(3), true, false, this, MARKNO_DELAY_ISCONNECTED, false); } string GetPlcName(int plcCnt, int index, string[] plcNames) { if (plcCnt == 1) { return plcNames[0]; } //多个PLC if (plcCnt != plcNames.Count()) { //没有定义全部名字 return $"{plcNames[0]} No.{index + 1}"; } return plcNames[index]; } public void ResetError(INotifyPropertyChanged sender) { var type = sender.GetType(); foreach (var ei in obj_error[sender].error_property) { var property = type.GetProperty(ei.property); property.SetValue(sender, false); } } public void ResetError() { foreach (var sender in obj_error.Keys) { ResetError(sender); } } void Obj_PropertyChanged_ForError(object sender, PropertyChangedEventArgs e) { ErrorAction errorAction = obj_error[sender as INotifyPropertyChanged]; var eis = from ei in errorAction.error_property where ei.property == e.PropertyName select ei; if (eis.Count() > 0) { var ei = eis.First(); //获取描述 var type = sender.GetType(); var property = type.GetProperty(ei.property); bool b = (bool)property.GetValue(sender, null); string description = ei.msg; int errcode = ei.code;//每个报警必须不一样!! if (b) { //修改报警文字内容 errorAction.action?.Invoke(ref description, errorAction.state); //报警, 不能被复位的!!! mWarning.Add(errcode, description, canReset: false); } else { mWarning.Remove(errcode); } } } #endregion } }