191 lines
6.9 KiB
C#
191 lines
6.9 KiB
C#
using Cowain.Bake.BLL;
|
||
using Cowain.Bake.Common.Core;
|
||
using Cowain.Bake.Common.Enums;
|
||
using Cowain.Bake.Common.Interface;
|
||
using Cowain.Bake.Communication.MOM;
|
||
using Cowain.Bake.Model;
|
||
using Cowain.Bake.Model.Models;
|
||
using Opc.Ua;
|
||
using Prism.Ioc;
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Unity;
|
||
using JSON = Newtonsoft.Json.JsonConvert;
|
||
using static Cowain.Bake.Common.Models.MESModel;
|
||
|
||
namespace Cowain.Bake.Main.Station
|
||
{
|
||
public class AlarmStation : IServerManager
|
||
{
|
||
readonly ConcurrentDictionary<string, bool[]> _alarmValues;
|
||
public string Name { get; set; } = "";
|
||
List<TAlarm> _allAlarms { get; set; } //ConcurrentBag //验证,如果还报线程问题,就用ConcurrentBag
|
||
List<TAlarmContent> _allAlarmContent { get; set; }
|
||
public IUnityContainer _unityContainer { get; set; }
|
||
List<AlertInfoModel> _arrayAlert = new List<AlertInfoModel>();
|
||
private readonly Prism.Events.IEventAggregator _eventAggregator;
|
||
readonly static object _objLock = new object();
|
||
|
||
public AlarmStation(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
||
{
|
||
_unityContainer = unityContainer;
|
||
_alarmValues = new ConcurrentDictionary<string, bool[]>();
|
||
_eventAggregator = eventAggregator;
|
||
Start();
|
||
}
|
||
|
||
public void Start()
|
||
{
|
||
_allAlarms = _unityContainer.Resolve<AlarmService>().GetAllInAlarms();
|
||
_allAlarmContent = _unityContainer.Resolve<AlarmContentService>().GetAll();
|
||
|
||
foreach(var item in _allAlarms)
|
||
{
|
||
_eventAggregator.GetEvent<AlarmAddEvent>().Publish(item);//2.界面刷新,发布事件(发送消息)
|
||
}
|
||
}
|
||
|
||
//报警可能是一个数组(TAlarmContent),也可能是一个点(TTagList)。
|
||
public void AlarmInfo(DataValue data, Variable node)
|
||
{
|
||
if (1 == data.WrappedValue.TypeInfo.ValueRank) //数组
|
||
{
|
||
lock (_objLock)
|
||
{
|
||
AlarmArray(data, node); //会导致恢复后,一条报警信息会显示二次
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LogHelper.Instance.Warn("没有单个数据报警!");
|
||
}
|
||
}
|
||
|
||
public TAlarmContent GetAlarmContent(int nodeId, int offset)
|
||
{
|
||
return _allAlarmContent.Where(m => m.Offset == offset
|
||
&& m.TagIds.Split(',').Any(x => x == nodeId.ToString())
|
||
&& !string.IsNullOrEmpty(m.Desc)).FirstOrDefault();
|
||
}
|
||
|
||
AlertInfoModel AssembleAlertModel(int code, string reset, string message)
|
||
{
|
||
return new AlertInfoModel()
|
||
{
|
||
AlertCode = code.ToString(),
|
||
AlertReset = reset,
|
||
AlertMessage = message,
|
||
};
|
||
}
|
||
|
||
//一个数组报警(订阅的是一个数组) --TAlarmContent
|
||
private void AlarmArray(DataValue data, Variable node)
|
||
{
|
||
string key = "";
|
||
_arrayAlert.Clear();
|
||
bool[] value = data.WrappedValue.Value as bool[];
|
||
if (data.WrappedValue.Value is bool[] v)
|
||
{
|
||
value = v;
|
||
}
|
||
else
|
||
{
|
||
LogHelper.Instance.Warn($"数组报警类型异常:{data.WrappedValue.Value.GetType().Name}");
|
||
return;
|
||
}
|
||
|
||
//LogHelper.Instance.Warn($"数组报警:{JSON.SerializeObject(value)}");
|
||
key = $"StationId:{node.StationId},Id:{node.Id}";
|
||
|
||
if (_alarmValues.TryGetValue(key, out bool[] oldValue)) //有
|
||
{
|
||
if (oldValue.Count() != value.Count())
|
||
{
|
||
LogHelper.Instance.Error($"报警老值与新值长度不匹配,key:{key},desc:{node.VarDesc}");
|
||
return;
|
||
}
|
||
|
||
var diffs = value.Zip(oldValue, (a, b) => a != b).Select((b, i) => new { Value = b, Index = i }).Where(x => x.Value);
|
||
foreach (var item in diffs)
|
||
{
|
||
DealAlarmNode(node, item.Index, value[item.Index]);
|
||
}
|
||
}
|
||
else //第一次进入
|
||
{
|
||
|
||
for (int i = 0; i < value.Count(); ++i)
|
||
{
|
||
DealAlarmNode(node, i, value[i]);
|
||
}
|
||
}
|
||
|
||
_alarmValues[key] = value;
|
||
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
||
{
|
||
_unityContainer.Resolve<MESProcess>().MESEqptAlert(_arrayAlert);
|
||
}
|
||
}
|
||
|
||
void DealAlarmNode(Variable node, int offset, bool value)
|
||
{
|
||
TAlarmContent alarmContent = GetAlarmContent(node.Id, offset); //找到报警信息
|
||
|
||
if (alarmContent == null)
|
||
{
|
||
return;
|
||
}
|
||
//报警三种处理,1,入库,2.上传MOM,3.界面显示报警
|
||
if (value)
|
||
{
|
||
AddAlarm(offset, node.StationId, alarmContent.Desc);
|
||
}
|
||
else
|
||
{
|
||
DeleteAlarm(offset, node.StationId, alarmContent.Desc);
|
||
}
|
||
}
|
||
|
||
public void AddAlarm(int errCode, int stationId, string desc)
|
||
{
|
||
var alarm = _allAlarms.Find(x => x.StationId == stationId && x.Desc == desc);
|
||
if (null == alarm)
|
||
{
|
||
TAlarm currentAlarm = new TAlarm()
|
||
{
|
||
StationId = stationId,
|
||
Desc = desc,
|
||
StartTime = DateTime.Now,
|
||
Status = EAlarmStatus.Alert.GetDescription(),
|
||
};
|
||
|
||
_allAlarms.Add(currentAlarm); //增加到内存
|
||
_arrayAlert.Add(AssembleAlertModel(errCode, ((int)EAlarmStatus.Alert).ToString(), desc)); //上传到MES
|
||
_unityContainer.Resolve<AlarmService>().Insert<TAlarm>(currentAlarm); //增加到DB
|
||
_eventAggregator.GetEvent<AlarmAddEvent>().Publish(currentAlarm);//.界面刷新,发布事件(发送消息)
|
||
}
|
||
}
|
||
|
||
public void DeleteAlarm(int errCode, int stationId, string desc)
|
||
{
|
||
TAlarm alarm = _allAlarms.Find(x => x.StationId == stationId
|
||
&& x.Desc == desc);
|
||
|
||
if (null != alarm)
|
||
{
|
||
_allAlarms.Remove(alarm);
|
||
_arrayAlert.Add(AssembleAlertModel(errCode, ((int)EAlarmStatus.Renew).ToString(), desc));
|
||
_unityContainer.Resolve<AlarmService>().CancelAlarm(alarm);
|
||
_eventAggregator.GetEvent<AlarmCancelEvent>().Publish(alarm);
|
||
}
|
||
}
|
||
|
||
public void Stop()
|
||
{
|
||
|
||
}
|
||
}
|
||
}
|