using ConnectionUtil;
|
using HMI.AlarmInfoManage.Entity;
|
using HMI.Base;
|
using HMI.Core.Api;
|
using HMI.Core.Setting;
|
using HMI.Core.Util;
|
using HMI.UI.Util;
|
using HMI.Util;
|
using Microsoft.Win32;
|
using OPCConnection;
|
using Sharp7;
|
using SimensDriver;
|
using System;
|
using System.Collections.Generic;
|
using System.Collections.ObjectModel;
|
using System.Data;
|
using System.IO;
|
using System.Linq;
|
using System.Timers;
|
using System.Windows;
|
using System.Windows.Controls;
|
|
namespace HMI.AlarmInfoManage
|
{
|
/// <summary>
|
/// UserControl1.xaml 的交互逻辑
|
/// </summary>
|
public partial class AlarmInfoManage : PluginControl
|
{
|
private string blockPath;
|
private string markPath;
|
private string alarmTextPath;
|
|
private string opcIP = "127.0.0.1";
|
private int opcPort = 6543;
|
private int localPort = 18888;
|
private volatile bool isClosing = false;
|
|
|
private string dbPath;
|
private Simens plc = new Simens();
|
|
private bool isHaveAlarm;
|
private bool isNewAlarm;
|
|
private SqliteHelper sqliteHelper;
|
|
private Timer MonitorTimer;
|
private Timer PcTimer;
|
|
/// <summary>
|
/// pc警告数字信号
|
/// </summary>
|
private int isPcAlarmnumber = 0;
|
|
/// <summary>
|
/// 当前报警信息
|
/// </summary>
|
private string currentInfo = null;
|
|
/// <summary>
|
/// 接收报警的队列
|
/// </summary>
|
private MSMQHelper alarmQueue = new MSMQHelper("HMI_Alarm");
|
/// <summary>
|
/// 日志生成器
|
/// </summary>
|
private MSMQHelper loggeralarm = new MSMQHelper("LTHMI_Logger");
|
/// <summary>
|
/// 刷新报警的队列
|
/// </summary>
|
private MSMQHelper alarmRefershToMain = new MSMQHelper("LTHMI_Alarm_Rrfresh");
|
|
private SCADAApi lTSCADAApi = new OPCClient();
|
|
/// <summary>
|
/// 报警
|
/// </summary>
|
private byte[] alarmCodeBytes;
|
/// <summary>
|
/// 报警信息缓存
|
/// </summary>
|
private List<AlarmText> currentAlarmCachePlc = new List<AlarmText>();
|
/// <summary>
|
/// PLC报警信息缓存
|
/// </summary>
|
private List<AlarmText> preAlarmCachePlc = new List<AlarmText>();
|
/// <summary>
|
/// 报警信息缓存
|
/// </summary>
|
private List<AlarmText> currentAlarmCachePc = new List<AlarmText>();
|
|
/// <summary>
|
/// 代码管理
|
/// </summary>
|
private ObservableCollection<AlarmSetting> alarmSettings = new ObservableCollection<AlarmSetting>();
|
// <summary>
|
/// 标志位报警管理
|
/// </summary>
|
private ObservableCollection<AlarmSetting> markAlarmSetting = new ObservableCollection<AlarmSetting>();
|
|
/// <summary>
|
/// 传至主窗体的报警信息
|
/// </summary>
|
private List<AlarmText> currentAlarmCachePlcToMain = new List<AlarmText>();
|
|
private AlarmText alarm;
|
private SystemSetting systemSetting;
|
|
private ObservableCollection<AlarmText> datasource = new ObservableCollection<AlarmText>();
|
|
public ObservableCollection<AlarmText> Datasource
|
{
|
get { return datasource; }
|
set { Set(ref datasource, value); }
|
}
|
|
/// <summary>
|
/// 报警文本列表
|
/// </summary>
|
private ObservableCollection<AlarmText> alarmTexts = new ObservableCollection<AlarmText>();
|
public ObservableCollection<AlarmText> AlarmTexts
|
{
|
get { return alarmTexts; }
|
set { Set(ref alarmTexts, value); }
|
}
|
|
public Dictionary<string, AlarmText> textMap = new Dictionary<string, AlarmText>();
|
|
private double size = 30;
|
|
private int currentPage = 0;
|
public int CurrentPage
|
{
|
get => currentPage;
|
set
|
{
|
Set(ref currentPage, value);
|
RefreshData();
|
}
|
}
|
|
private int maxPage = 0;
|
public int MaxPage
|
{
|
get => maxPage;
|
set
|
{
|
Set(ref maxPage, value);
|
}
|
}
|
|
public AlarmInfoManage()
|
{
|
DataContext = this;
|
systemSetting = SystemSetting.Instance;
|
InitializeComponent();
|
}
|
|
public override void SetBaseFolder(string folder)
|
{
|
base.SetBaseFolder(folder);
|
dbPath = Path.Combine(BaseFolder, "alarm.db");
|
alarmTextPath = Path.Combine(BaseFolder, "AlarmText.data");
|
|
blockPath = Path.Combine(BaseFolder, "BlockSetting.xml");
|
markPath = Path.Combine(BaseFolder, "MarkSetting.xml");
|
}
|
|
public override void InitFinish()
|
{
|
if (!File.Exists(dbPath))
|
{
|
SqliteHelper.CreateDatabase(dbPath);
|
}
|
sqliteHelper = new SqliteHelper(dbPath);
|
sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS Alarm (
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
source TEXT NOT NULL,
|
alarmcode TEXT,
|
alarminfo TEXT,
|
time DATETIME);");
|
|
LoadAlarmSetting();
|
LoadAlarmText();
|
|
MonitorTimer = new Timer
|
{
|
Interval = 100,
|
};
|
MonitorTimer.Elapsed += MonitorTimer_Elapsed;
|
if (!lTSCADAApi.Connect2(opcIP, opcPort, localPort, out string errMsg))
|
{
|
//MsgBoxHelper.Error(this, errMsg);
|
}
|
else
|
{
|
this.MonitorTimer.Start();
|
}
|
|
PcTimer = new Timer
|
{
|
Interval = 100,
|
AutoReset = false
|
};
|
PcTimer.Elapsed += PcTimer_Elapsed;
|
PcTimer.Enabled = true;
|
}
|
|
public override void DoClose(object sender, EventArgs e)
|
{
|
isClosing = true;
|
PcTimer.Enabled = false;
|
PcTimer?.Dispose();
|
|
MonitorTimer.Enabled = false;
|
MonitorTimer?.Dispose();
|
}
|
|
private void Button_Click(object sender, RoutedEventArgs e)
|
{
|
Button btn = sender as Button;
|
switch (btn.Name)
|
{
|
case "settingBtn":
|
OpenSettingWindow();
|
break;
|
case "refreshBtn":
|
LoadAlarmText();
|
RefreshPage(CurrentPage);
|
break;
|
case "importBtn":
|
ImportText();
|
break;
|
default:
|
break;
|
}
|
}
|
|
private void OpenSettingWindow()
|
{
|
AlarmSettingList listModal = new AlarmSettingList(blockPath, markPath,alarmSettings,markAlarmSetting, log)
|
{
|
Owner = Window.GetWindow(this)
|
};
|
listModal.ShowDialog();
|
alarmSettings = listModal.Datasource;
|
markAlarmSetting = listModal.MarkDatasource;
|
}
|
|
private void RefreshPage(int? page = null)
|
{
|
var sql = "SELECT COUNT (*) as num FROM Alarm;";
|
var dt = sqliteHelper.GetDataTable(sql);
|
if (dt.Rows.Count <= 0)
|
{
|
CurrentPage = 1;
|
MaxPage = 1;
|
return;
|
}
|
int count = int.Parse(dt.Rows[0]["num"].ToString());
|
MaxPage = (int)Math.Ceiling(count / size);
|
|
if (page != null)
|
{
|
CurrentPage = page.Value;
|
}
|
else if (CurrentPage > MaxPage)
|
{
|
CurrentPage = MaxPage;
|
}
|
}
|
|
private void RefreshData()
|
{
|
var list = new ObservableCollection<AlarmText>();
|
var sql = $"SELECT source, alarmcode, alarminfo, time FROM Alarm ORDER BY time DESC LIMIT ({CurrentPage - 1} * {size}), {size};";
|
var dt = sqliteHelper.GetDataTable(sql);
|
if (dt.Rows.Count > 0)
|
{
|
foreach (DataRow dr in dt.Rows)
|
{
|
var at = new AlarmText
|
{
|
Source = dr["source"].ToString(),
|
AlarmCode = dr["alarmcode"].ToString(),
|
AlarmInfo = dr["alarminfo"].ToString(),
|
Time = dr["time"].ToString(),
|
};
|
list.Add(at);
|
}
|
}
|
Datasource = list;
|
}
|
|
private void ImportText()
|
{
|
try
|
{
|
OpenFileDialog openDialog = new OpenFileDialog();
|
openDialog.Filter = "Files (*.xlsm)|*.xlsm";
|
if (openDialog.ShowDialog() == true)
|
{
|
this.ImportExcelAlarmText(openDialog.FileName);
|
}
|
}
|
catch (Exception ex)
|
{
|
log.Error("AlarmText Import Failed.", ex);
|
ToastHelper.Error(Window.GetWindow(this), $"{this.lang("App.ImportFailed")}: {ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 导入报警代码文本
|
/// </summary>
|
/// <param name="excelFile">电子设计表格文件</param>
|
//private void ImportExcelAlarmText(string excelFile)
|
//{
|
// int index = 0;
|
|
// try
|
// {
|
// if (excelFile.IndexOf(".xlsm") < 0)
|
// {
|
// this.Warning(this.lang("Alm.OnlySupportXlsm"));
|
// return;
|
// }
|
|
// this.alarmTexts.Clear();
|
// XSSFWorkbook workbook = new XSSFWorkbook(excelFile);
|
// XSSFSheet sheet = (XSSFSheet)workbook.GetSheet("sheet1");
|
// XSSFRow row = null;
|
|
// for (int i = 2; i < (sheet.LastRowNum + 1); i++)
|
// {
|
// index = i;
|
// row = (XSSFRow)sheet.GetRow(i);
|
// if (row != null)
|
// {
|
// AlarmText alarm = new AlarmText();
|
// alarm.AlarmCode = row.Cells[0].StringCellValue;
|
// alarm.OpNo = row.Cells[1].StringCellValue;
|
// alarm.ModuleNo = row.Cells[2].StringCellValue;
|
// alarm.ModuleName_CN = row.Cells[3].StringCellValue;
|
// alarm.ModuleName_EN = row.Cells[4].StringCellValue;
|
// alarm.MAlarmCode = row.Cells[5].StringCellValue;
|
// alarm.MAlarmText_CN = row.Cells[6].StringCellValue;
|
// alarm.MAlarmText_EN = row.Cells[7].StringCellValue;
|
// this.alarmTexts.Add(alarm);
|
// }
|
// }
|
|
// if (sheet.LastRowNum > 0)
|
// {
|
// XmlHelper.SerializeToXml(textSettingPath, this.alarmTexts);
|
// }
|
|
// this.Success(this.lang("App.ImportSuccess"));
|
// }
|
// catch (Exception ex)
|
// {
|
// log.Error($"Row {index} AlarmText Import Failed.", ex);
|
// this.Error($"{this.lang("Alm.RowImportFailed", index)}: {ex.Message}");
|
// }
|
//}
|
|
/// <summary>
|
/// 导入报警代码文本
|
/// </summary>
|
/// <param name="excelFile">电子设计表格文件</param>
|
private void ImportExcelAlarmText(string excelFile)
|
{
|
int index = 0;
|
|
try
|
{
|
if (excelFile.IndexOf(".xlsm") < 0)
|
{
|
this.Warning(this.lang("Alm.OnlySupportXlsm"));
|
return;
|
}
|
|
this.alarmTexts = new ObservableCollection<AlarmText>
|
(ExcelHelper.ReadFromExcel<AlarmText>(excelFile));
|
|
if (alarmTexts.Count > 0)
|
{
|
XmlHelper.SerializeToXml(alarmTextPath, this.alarmTexts);
|
}
|
LoadAlarmText();
|
this.Success(this.lang("App.ImportSuccess"));
|
}
|
catch (Exception ex)
|
{
|
log.Error($"Row {index} AlarmText Import Failed.", ex);
|
this.Error($"{this.lang("Alm.RowImportFailed", index)}: {ex.Message}");
|
}
|
}
|
|
private void LoadAlarmText()
|
{
|
try
|
{
|
textMap.Clear();
|
AlarmTexts = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmText>>(alarmTextPath);
|
foreach (var text in AlarmTexts)
|
{
|
textMap[text.AlarmCode] = text;
|
}
|
}
|
catch (Exception ex)
|
{
|
log.Error("LoadAlarmText Error.", ex);
|
AlarmTexts = new ObservableCollection<AlarmText>();
|
}
|
}
|
|
private void LoadAlarmSetting()
|
{
|
try
|
{
|
alarmSettings = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(blockPath);
|
}
|
catch (Exception ex)
|
{
|
log.Error("LoadAlarmSetting Error.", ex);
|
alarmSettings = new ObservableCollection<AlarmSetting>();
|
}
|
|
try
|
{
|
markAlarmSetting = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(markPath);
|
}
|
catch (Exception ex)
|
{
|
log.Error("LoadAlarmText Error.", ex);
|
markAlarmSetting = new ObservableCollection<AlarmSetting>();
|
}
|
}
|
|
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
{
|
//if (!string.IsNullOrEmpty(systemSetting.PlcIp))
|
//{
|
// if (this.plc.isConnection)
|
// {
|
// this.plc.Simens_S7_ConnectPLC(systemSetting.PlcIp, 102, 0, 1, string.Empty);
|
// }
|
//}
|
RefreshPage(1);
|
Loaded -= UserControl_Loaded;
|
}
|
|
private void PcTimer_Elapsed(object sender, ElapsedEventArgs e)
|
{
|
try
|
{
|
PcTimer.Enabled = false;
|
this.alarmQueue.Receive(100, out string MessageID, out string MsgStr);
|
if (MessageID != string.Empty)
|
{
|
switch (MessageID)
|
{
|
case "Clear":
|
this.currentAlarmCachePc.Clear();
|
this.RefershAlarm();
|
break;
|
case "AlarmCode":
|
AlarmText aalarm = AlarmTexts.FirstOrDefault(alarm => alarm.AlarmCode == MsgStr);
|
if (aalarm == null) break;
|
var data = new AlarmText {
|
Source = "PC",
|
AlarmCode = aalarm.AlarmCode,
|
AlarmInfo = aalarm.MAlarmText_CN,
|
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
};
|
//aalarm.Source = "PC";
|
//aalarm.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
if (this.currentAlarmCachePc.Find(alarm => alarm.AlarmCode == aalarm.AlarmCode) == null)
|
{
|
this.currentAlarmCachePc.Add(data);
|
this.RefershAlarm();
|
this.isPcAlarmnumber = this.currentAlarmCachePc.Count;
|
}
|
break;
|
default:
|
string[] arr = MsgStr.Split(',');
|
string source = "PC";
|
string info = string.Empty;
|
if (arr.Length > 1)
|
{
|
source = arr[0];
|
info = arr[1];
|
}
|
else
|
{
|
info = MsgStr;
|
}
|
AlarmText newAlarm = new AlarmText
|
{
|
Source = source,
|
AlarmInfo = info,
|
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
|
};
|
if (this.currentAlarmCachePc
|
.Find(alarm => alarm.Source == newAlarm.Source && alarm.AlarmInfo == newAlarm.AlarmInfo) == null)
|
{
|
this.currentAlarmCachePc.Add(newAlarm);
|
this.RefershAlarm();
|
this.isPcAlarmnumber = this.currentAlarmCachePc.Count;
|
}
|
break;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
log.Error("PcTimer Execute Failed", ex);
|
}
|
finally
|
{
|
if (!isClosing) PcTimer.Enabled = true;
|
}
|
}
|
|
//private void MonitorTimer_Elapsed_bak(object sender, ElapsedEventArgs e)
|
//{
|
// try
|
// {
|
// this.MonitorTimer.Enabled = false;
|
// isHaveAlarm = false;
|
// foreach (var item in signAlarmSetting)
|
// {
|
// //isHaveAlarm = isHaveAlarm ||
|
// // this.plc.Simens_S7_ReadBool_DB(item.DBAddress, item.StartAddress, item.Length);
|
// }
|
|
// ////有报警
|
// if (isHaveAlarm)
|
// {
|
// this.isNewAlarm = false;
|
// this.currentAlarmCachePlc.Clear();
|
// RefreshDBSetting();
|
// for (int i = 0; i < ((int)alarmCodeBytes.Length / 4); i++)
|
// {
|
// int code = S7.GetDIntAt(alarmCodeBytes, 4 * i);
|
// ////有报警
|
// if (code != 0)
|
// {
|
// string acode = string.Format("{0:d10}", code);
|
// alarm = AlarmTexts.FirstOrDefault(item => item.AlarmCode == acode);
|
// if (alarm != null)
|
// {
|
// alarm.Source = "PLC";
|
// alarm.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
// this.currentAlarmCachePlc.Add(alarm);
|
// ////有新报警
|
// if (this.preAlarmCachePlc.Find(alarm => alarm.AlarmCode == acode) == null)
|
// {
|
// this.isNewAlarm = true;
|
// this.SendLogMsg(alarm.ModuleName_CN + alarm.MAlarmText_CN);
|
// }
|
// }
|
// }
|
// }
|
|
// ////有新报警和报警减少时刷新报警表
|
// if (this.isNewAlarm || (this.currentAlarmCachePlc.Count != this.preAlarmCachePlc.Count))
|
// {
|
// this.currentAlarmCachePlcToMain = XmlHelper.DeepClone(this.currentAlarmCachePlc);
|
// this.RefershAlarm();
|
// }
|
|
// this.preAlarmCachePlc.Clear();
|
// this.preAlarmCachePlc = XmlHelper.DeepClone(this.currentAlarmCachePlc);
|
// }
|
// else
|
// {
|
// if (this.preAlarmCachePlc.Count != 0 || this.currentAlarmCachePlcToMain.Count != 0 || this.currentAlarmCachePlc.Count != 0)
|
// {
|
// this.preAlarmCachePlc.Clear();
|
// this.currentAlarmCachePlcToMain.Clear();
|
// this.currentAlarmCachePlc.Clear();
|
// this.RefershAlarm();
|
// }
|
// }
|
// }
|
// catch (Exception ex)
|
// {
|
// log.Error("sdadsa", ex);
|
// }
|
// finally
|
// {
|
// this.MonitorTimer.Enabled = true;
|
// }
|
//}
|
|
private void MonitorTimer_Elapsed(object sender, ElapsedEventArgs e)
|
{
|
try
|
{
|
this.MonitorTimer.Enabled = false;
|
|
if (!lTSCADAApi.IsConnected(out string errMsg))
|
{
|
log.Warn($"OPCServer Connection Error. {errMsg}");
|
if (!lTSCADAApi.Connect2(opcIP, opcPort, localPort, out errMsg))
|
{
|
log.Warn($"OPCServer Try ReConnection Error. {errMsg}");
|
return;
|
}
|
}
|
|
isHaveAlarm = false;
|
List<AlarmText> cache = new List<AlarmText>();
|
foreach (var item in alarmSettings)
|
{
|
var name = $"{item.DBAddress}.{item.StartAddress}";
|
if (lTSCADAApi.DoFctReadSingle(name, out string alarmCode, out errMsg) && alarmCode != "0")
|
{
|
isHaveAlarm = true;
|
if (!textMap.TryGetValue(alarmCode, out alarm)) {
|
continue;
|
}
|
var newAlarm = new AlarmText
|
{
|
Source = "PLC",
|
AlarmCode = alarm.AlarmCode,
|
ModuleName_CN = alarm.ModuleName_CN,
|
MAlarmText_CN = alarm.MAlarmText_CN,
|
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
AlarmInfo = $"{alarm.ModuleName_CN} {alarm.MAlarmText_CN}"
|
};
|
if (this.currentAlarmCachePlc
|
.Find(alarm => alarm.AlarmCode == newAlarm.AlarmCode) == null)
|
{
|
this.currentAlarmCachePlc.Add(newAlarm);
|
}
|
}
|
}
|
|
foreach (var item in markAlarmSetting)
|
{
|
var name = $"{item.DBAddress}.{item.StartAddress}";
|
if (lTSCADAApi.DoFctReadSingle(name, out string alarmCode, out errMsg) && alarmCode != "0")
|
{
|
isHaveAlarm = true;
|
var newAlarm = new AlarmText
|
{
|
Source = "PLC",
|
AlarmCode = alarmCode,
|
Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
AlarmInfo = item.Description
|
};
|
if (this.currentAlarmCachePlc
|
.Find(d => d.AlarmInfo == newAlarm.AlarmInfo) == null)
|
{
|
this.currentAlarmCachePlc.Add(newAlarm);
|
}
|
}
|
}
|
this.RefershAlarm();
|
this.isPcAlarmnumber = this.currentAlarmCachePc.Count;
|
|
if (!isHaveAlarm) currentAlarmCachePlc.Clear();
|
}
|
catch (Exception ex)
|
{
|
log.Error("Read OPCServer Data Error.", ex);
|
}
|
finally
|
{
|
if(!isClosing) this.MonitorTimer.Enabled = true;
|
}
|
}
|
|
/// <summary>
|
/// 刷新报警块信息
|
/// </summary>
|
private void RefreshDBSetting()
|
{
|
List<byte> bytes = new List<byte>();
|
foreach (var item in alarmSettings)
|
{
|
//byte[] itemalarmCodeBytes = this.plc.Simens_S7_ReadBytes_DB("DB", item.DBAddress, item.StartAddress, item.Length);
|
//bytes.AddRange(itemalarmCodeBytes.ToList());
|
}
|
alarmCodeBytes = bytes.ToArray();
|
}
|
|
|
|
/// <summary>
|
/// 刷新报警信息
|
/// </summary>
|
private void RefershAlarm()
|
{
|
this.alarmRefershToMain.Send("AlarmRefersh", string.Empty);
|
|
foreach (AlarmText alarm in this.currentAlarmCachePlc)
|
{
|
var currentInfo = alarm.AlarmInfo;
|
string sqladd = string.Format("INSERT INTO Alarm (source, alarmcode, alarminfo, time) VALUES('{0}','{1}','{2}','{3}');",
|
alarm.Source, alarm.AlarmCode, currentInfo, alarm.Time);
|
if (AlarmShowHelper.ShowAlarm(currentInfo))
|
{
|
sqliteHelper.ExecuteSql(sqladd);
|
}
|
}
|
//this.currentAlarmCachePlc.Clear();
|
|
foreach (AlarmText alarm in this.currentAlarmCachePc)
|
{
|
string sqladd2 = string.Format("INSERT INTO Alarm (source, alarmcode, alarminfo, time) VALUES('{0}','{1}','{2}','{3}');", alarm.Source, alarm.AlarmCode, alarm.AlarmInfo, alarm.Time);
|
if (AlarmShowHelper.ShowAlarm(alarm.AlarmInfo))
|
{
|
sqliteHelper.ExecuteSql(sqladd2);
|
}
|
}
|
this.currentAlarmCachePc.Clear();
|
}
|
|
/// <summary>
|
/// 发送日志消息
|
/// </summary>
|
/// <param name="Msg">日志消息</param>
|
private void SendLogMsg(string Msg)
|
{
|
string LogMsg = "{\"Type\":\"Alarm\",\"Source\":\"" + alarm.Source + "\",\"Msg\":\"" + Msg + "\",\"Time\":\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}";
|
this.loggeralarm.Send("Log", LogMsg);
|
}
|
}
|
}
|