Commit a9727359 authored by 潘栩锋's avatar 潘栩锋 🚴

PLC代理.. 报警辅助.. 数据周期保存辅助

parent d8510138
......@@ -112,4 +112,12 @@ namespace FLY.OBJComponents.Common
public string Descrption;
public bool OffIsError;
}
public static class PlcErrNos
{
/// <summary>
/// PLC连接断开
/// </summary>
public static ERRNO ERRNO_PLC_DISCONNECTED = new ERRNO() { Code = 255, Descrption = "收卷 PLC连接断开" };
}
}
......@@ -79,9 +79,11 @@
<Compile Include="Server\BufferSQLite.cs" />
<Compile Include="Server\BufferStorage.cs" />
<Compile Include="Server\BufferError.cs" />
<Compile Include="Server\ErrorConf.cs" />
<Compile Include="Server\History.cs" />
<Compile Include="Server\Model\DB_Error.cs" />
<Compile Include="Server\Model\IErrorDBModel.cs" />
<Compile Include="Server\PeriodicallySaveData.cs" />
<Compile Include="Server\PLCProxySystem.cs" />
<Compile Include="Server\WarningSystem.cs" />
</ItemGroup>
......@@ -116,7 +118,7 @@
<Version>4.6.8</Version>
</PackageReference>
<PackageReference Include="PropertyChanged.Fody">
<Version>2.6.1</Version>
<Version>3.2.5</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
......
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
/// <summary>
/// 需要设置
/// </summary>
IPLCProxySystemService PLCos;
/// <summary>
/// 报警系统
/// </summary>
WarningSystem mWarning;
public ErrorConf(IPLCProxySystemService PLCos, WarningSystem mWarning)
{
this.PLCos = PLCos;
this.mWarning = mWarning;
}
#region 报警
public class ErrorAction
{
public List<ErrorInfo> error_property;
public object state;
public delegate void ErrorHandler(ref string msg, object state);
public ErrorHandler action;
}
public class ErrorInfo
{
public string property;
public byte code;
public string msg;
public bool offIsError;
}
Dictionary<INotifyPropertyChanged, ErrorAction> obj_error = new Dictionary<INotifyPropertyChanged, ErrorAction>();
public void AddErrorAction(INotifyPropertyChanged sender, ref byte code, ErrorAction.ErrorHandler errorHandler = null, object state = null)
{
//反射找出全部是报警的property
List<ErrorInfo> error_property = new List<ErrorInfo>();
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;
bool offIsError = (propertyInfo.GetCustomAttributes(typeof(IsErrorAttribute), false).First() as IsErrorAttribute).OffIsError;
ErrorInfo errorInfo = new ErrorInfo()
{
property = propertyInfo.Name,
msg = desp,
offIsError = offIsError,
code = code
};
error_property.Add(errorInfo);
code++;
}
}
obj_error.Add(sender, new ErrorAction()
{
error_property = error_property,
action = errorHandler,
state = state
});
}
/// <summary>
/// 执行之前,需要调用 AddErrorAction, 向 obj_error 添加报警寄存器操作
/// </summary>
public void InitError()
{
//byte code = 0;
////反射找出全部是报警的property
//AddErrorAction(
// Accessory,
// ref code);
//AddErrorAction(
// Items[0],
// ref code,
// (ref string description, object state) => { description = "内" + description; }
// );
//AddErrorAction(
// Items[1],
// ref code,
// (ref string description, object state) => { description = "外" + description; }
// );
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);
}
//--------------------------------------------------------------------------------
//连接断开事件
FObjBase.PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD,
() =>
{
Misc.BindingOperations.SetBinding(PLCos, "IsConnectedWithPLC", () =>
{
bool b = !PLCos.IsConnectedWithPLC;
ERR_STATE state = b ? ERR_STATE.ON : ERR_STATE.OFF;
ERRNO errno = PlcErrNos.ERRNO_PLC_DISCONNECTED;
byte errcode = errno.Code;
string description = errno.Descrption;
mWarning.Add(errcode, description, state);
});
}, TimeSpan.FromSeconds(3), true, false, this, MARKNO_DELAY_ISCONNECTED, true);
//--------------------------------------------------------------------------------
//把全部报警状态取反,也就是不报警!!!
foreach (var kv in obj_error)
{
object sender = kv.Key;
foreach (var ei in kv.Value.error_property)
{
if (ei.offIsError)
{
Misc.PropertiesManager.SetValue(sender, ei.property, true);
}
//false 不用写,默认值就是
}
}
}
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 desp = ei.msg;
bool offIsError = ei.offIsError;
ERR_STATE state;
if (offIsError)
state = !b ? ERR_STATE.ON : ERR_STATE.OFF;
else
state = b ? ERR_STATE.ON : ERR_STATE.OFF;
byte errcode = ei.code;//每个报警必须不一样!!
string description = desp;
errorAction.action?.Invoke(ref description, errorAction.state);
mWarning.Add(errcode, description, state);
}
}
#endregion
}
}
......@@ -55,7 +55,7 @@ namespace FLY.OBJComponents.Server
{
foreach (var plc in PLCs)
{
plc.NameDataChanged += plc_NameDataChanged;
plc.NameDataChanged += Plc_NameDataChanged;
}
......@@ -142,7 +142,7 @@ namespace FLY.OBJComponents.Server
void plc_NameDataChanged(object sender, DataToRegs dr)// NameDataChangedEventArgs e)
void Plc_NameDataChanged(object sender, DataToRegs dr)// NameDataChangedEventArgs e)
{
//var plc = sender as Modbus.WithThread.ModbusMapper_Client;
//object value = plc.GetNameData(e.Owener, e.PropertyName);
......
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FLY.OBJComponents.Server
{
/// <summary>
/// 周期保存数据,写入到数据库的周期为20s;
/// 但数据的周期最小为1s
/// </summary>
public class PeriodicallySaveData<T>
{
Stopwatch stopwatch_interval = new Stopwatch();
Stopwatch stopwatch_1min = new Stopwatch();
List<T> dbWidths_1min = new List<T>();
/// <summary>
/// 数据保存周期,单位s
/// </summary>
public int IntervalSec = 5;
/// <summary>
/// 把缓存区的数据一次性导出
/// </summary>
public Action<List<T>> SaveList;
/// <summary>
/// 创造一次数据
/// </summary>
public Func<T> CreateData;
public void Init(int intervalSec, Action<List<T>> saveList, Func<T> createData)
{
IntervalSec = intervalSec;
SaveList = saveList;
CreateData = createData;
FObjBase.PollModule.Current.Poll_Config(
FObjBase.PollModule.POLL_CONFIG.ADD, OnPoll, TimeSpan.FromSeconds(1));
}
void OnPoll()
{
if (stopwatch_1min.IsRunning && stopwatch_1min.Elapsed >= TimeSpan.FromSeconds(20))
{
//启动了1min 且到点了
if (dbWidths_1min.Count > 0)
{
SaveList(dbWidths_1min);
dbWidths_1min.Clear();
stopwatch_1min.Restart();
}
else
{
stopwatch_1min.Reset();
}
}
if (!stopwatch_interval.IsRunning)
{
stopwatch_interval.Start();
return;
}
else
{
if (stopwatch_interval.Elapsed < TimeSpan.FromSeconds(IntervalSec))
return;
else
stopwatch_interval.Restart();
}
//记录数据
T db_Width = CreateData();
if (db_Width == null)
{
//没有,退出
return;
}
//写入数据库
if (!stopwatch_1min.IsRunning)
{
//第1次立刻写入
SaveList(new List<T> { db_Width });
stopwatch_1min.Start();
}
else
{
//第2次,1分钟后才能保存
dbWidths_1min.Add(db_Width);
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment