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
}
}