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 _alarmValues; public string Name { get; set; } = ""; List _allAlarms { get; set; } //ConcurrentBag //验证,如果还报线程问题,就用ConcurrentBag List _allAlarmContent { get; set; } public IUnityContainer _unityContainer { get; set; } List _arrayAlert = new List(); 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(); _eventAggregator = eventAggregator; Start(); } public void Start() { _allAlarms = _unityContainer.Resolve().GetAllInAlarms(); _allAlarmContent = _unityContainer.Resolve().GetAll(); foreach(var item in _allAlarms) { _eventAggregator.GetEvent().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().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable) { _unityContainer.Resolve().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().Insert(currentAlarm); //增加到DB _eventAggregator.GetEvent().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().CancelAlarm(alarm); _eventAggregator.GetEvent().Publish(alarm); } } public void Stop() { } } }