212 lines
9.3 KiB
C#
212 lines
9.3 KiB
C#
|
using AlarmMonitorWorkerService.Models;
|
|||
|
using Microsoft.Extensions.Logging;
|
|||
|
using Quartz;
|
|||
|
using Repository.FrontendRepository.Interface;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using Windows.Data.Xml.Dom;
|
|||
|
using Windows.UI.Notifications;
|
|||
|
using System.IO;
|
|||
|
|
|||
|
namespace AlarmMonitorWorkerService.Quartz.Jobs
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 監控緊急應變畫面是否有開啟
|
|||
|
/// </summary>
|
|||
|
[DisallowConcurrentExecution]
|
|||
|
class AlarmMonitorJob : IJob
|
|||
|
{
|
|||
|
private const string APP_ID = "WPF ToastNotificaiton Test";
|
|||
|
private readonly ILogger<AlarmMonitorJob> logger;
|
|||
|
private readonly IFrontendRepository frontendRepository;
|
|||
|
|
|||
|
public AlarmMonitorJob(
|
|||
|
ILogger<AlarmMonitorJob> logger,
|
|||
|
IFrontendRepository frontendRepository)
|
|||
|
{
|
|||
|
this.logger = logger;
|
|||
|
this.frontendRepository = frontendRepository;
|
|||
|
}
|
|||
|
|
|||
|
public async Task Execute(IJobExecutionContext context)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
logger.LogInformation("【AlarmMonitorJob】【任務開始】");
|
|||
|
//找出當前緊急應變的PID
|
|||
|
var sqlWatchDog = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'watchDogCongfig'";
|
|||
|
|
|||
|
var variable = await frontendRepository.GetAllAsync<KeyValue>(sqlWatchDog);
|
|||
|
var alarmPID = variable.Where(x => x.Name == "AlarmPID").Select(x => x.Value).FirstOrDefault();
|
|||
|
|
|||
|
var category = new PerformanceCounterCategory("Process");
|
|||
|
|
|||
|
var instances = category.GetInstanceNames();
|
|||
|
|
|||
|
var hasFound = false;
|
|||
|
foreach (var instance in instances)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
using (var counter = new PerformanceCounter(category.CategoryName,
|
|||
|
"ID Process", instance, true))
|
|||
|
{
|
|||
|
int val = (int)counter.RawValue;
|
|||
|
if (val == Convert.ToInt32(alarmPID))
|
|||
|
{
|
|||
|
hasFound = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception exception)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var header = string.Empty;
|
|||
|
if (!hasFound)
|
|||
|
{
|
|||
|
header = "請開啟監控頁面";
|
|||
|
}
|
|||
|
|
|||
|
//找出異常的設備
|
|||
|
string sql = $@"SELECT
|
|||
|
amc.id,
|
|||
|
sl.source source_path,
|
|||
|
from_unixtime(amc.timestamp/1000,'%Y-%m-%d %H:%i:%s') alarm_timestamp ,
|
|||
|
temp_source.source_name,
|
|||
|
temp_msg.source_msg
|
|||
|
FROM alarmorion_orionalarmrecord amc
|
|||
|
JOIN (
|
|||
|
SELECT
|
|||
|
MAX(amc.alarm) ad,
|
|||
|
m.source
|
|||
|
FROM alarmorion_orionalarmsourceorder amc
|
|||
|
JOIN (
|
|||
|
SELECT * FROM alarmorion_orionalarmsource a
|
|||
|
WHERE substring(a.source,23,5) ='Arena'
|
|||
|
) m ON amc.alarmSource = m.id
|
|||
|
GROUP BY m.source
|
|||
|
) sl ON amc.id = sl.ad
|
|||
|
JOIN(
|
|||
|
SELECT
|
|||
|
val.alarm ,
|
|||
|
val.value AS source_name
|
|||
|
FROM alarmorion_orionalarmfacetvalue val
|
|||
|
JOIN alarmorion_orionalarmfacetname nam ON val.facetName = nam.id AND nam.facetName = 'sourceName'
|
|||
|
) temp_source ON amc.id = temp_source.alarm
|
|||
|
JOIN(
|
|||
|
SELECT
|
|||
|
val.alarm,
|
|||
|
val.value AS source_msg
|
|||
|
FROM alarmorion_orionalarmfacetvalue val
|
|||
|
JOIN alarmorion_orionalarmfacetname nam ON val.facetName = nam.id AND nam.facetName = 'msgText'
|
|||
|
) temp_msg ON amc.id = temp_msg.alarm
|
|||
|
WHERE amc.sourceState = 1";
|
|||
|
|
|||
|
var alarms = await frontendRepository.GetAllAsync<AlarmorionString>(sql);
|
|||
|
|
|||
|
//組出device_number
|
|||
|
List<string> tempDeviceNumbers = new List<string>();
|
|||
|
foreach (var alarm in alarms)
|
|||
|
{
|
|||
|
var alarmSplit = alarm.source_path.Split("|");
|
|||
|
var deviceSplit = alarmSplit[alarmSplit.Length - 1].Split("/");
|
|||
|
var device_number = deviceSplit[deviceSplit.Length - 3];
|
|||
|
var point = deviceSplit[deviceSplit.Length - 2];
|
|||
|
|
|||
|
alarm.device_number = device_number.Replace("$3", "");
|
|||
|
alarm.point = point;
|
|||
|
|
|||
|
tempDeviceNumbers.Add(device_number);
|
|||
|
}
|
|||
|
|
|||
|
//找出所有設備相關資訊
|
|||
|
var sql_device = $@"SELECT
|
|||
|
d.device_number,
|
|||
|
d.full_name AS device_name,
|
|||
|
b.full_name AS building_name,
|
|||
|
f.full_name AS floor_name,
|
|||
|
(SELECT
|
|||
|
v.system_key
|
|||
|
FROM device_disaster dd
|
|||
|
JOIN variable v ON v.deleted = 0 AND v.system_type = 'disaster' AND v.system_value = dd.device_system_value
|
|||
|
WHERE dd.device_guid = d.device_guid
|
|||
|
) AS Device_disaster_type_text
|
|||
|
FROM device d
|
|||
|
JOIN building b ON b.deleted = 0 AND d.building_guid = b.building_guid
|
|||
|
JOIN floor f ON f.deleted = 0 AND d.floor_guid = f.floor_guid
|
|||
|
WHERE d.deleted = 0 AND d.device_number IN @device_numbers";
|
|||
|
|
|||
|
var deviceInfos = await frontendRepository.GetAllAsync<DeviceInfo>(sql_device, new { device_numbers = tempDeviceNumbers.Distinct().ToList() });
|
|||
|
|
|||
|
var alarmFormat = @"{0}:{1} {2} {3} {4} {5}觸發";
|
|||
|
|
|||
|
List<string> alarmMsg = new List<string>();
|
|||
|
foreach (var alarm in alarms)
|
|||
|
{
|
|||
|
var selected_deviceinfo = deviceInfos.Where(x => x.device_number == alarm.device_number).FirstOrDefault();
|
|||
|
|
|||
|
if (selected_deviceinfo != null)
|
|||
|
{
|
|||
|
alarmMsg.Add(string.Format(alarmFormat,
|
|||
|
selected_deviceinfo.device_disaster_type_text,
|
|||
|
alarm.alarm_timestamp,
|
|||
|
selected_deviceinfo.building_name,
|
|||
|
selected_deviceinfo.floor_name,
|
|||
|
selected_deviceinfo.device_name,
|
|||
|
alarm.point));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GenerateToast("IBMS緊急應變通知", null, header, "", string.Join("\n", alarmMsg));
|
|||
|
logger.LogInformation("【AlarmMonitorJob】【任務完成】");
|
|||
|
}
|
|||
|
catch (Exception exception)
|
|||
|
{
|
|||
|
logger.LogError("【AlarmMonitorJob】【任務失敗】");
|
|||
|
logger.LogError("【AlarmMonitorJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void GenerateToast(string appid, string imageFullPath, string h1, string h2, string p1)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
|
|||
|
var template = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
|
|||
|
|
|||
|
var textNodes = template.GetElementsByTagName("text");
|
|||
|
|
|||
|
textNodes[0].AppendChild(template.CreateTextNode(h1));
|
|||
|
textNodes[1].AppendChild(template.CreateTextNode(h2));
|
|||
|
textNodes[2].AppendChild(template.CreateTextNode(p1));
|
|||
|
|
|||
|
//if (File.Exists(imageFullPath))
|
|||
|
//{
|
|||
|
// XmlNodeList toastImageElements = template.GetElementsByTagName("image");
|
|||
|
// ((XmlElement)toastImageElements[0]).SetAttribute("src", imageFullPath);
|
|||
|
//}
|
|||
|
|
|||
|
IXmlNode toastNode = template.SelectSingleNode("/toast");
|
|||
|
((XmlElement)toastNode).SetAttribute("duration", "long");
|
|||
|
|
|||
|
var notifier = ToastNotificationManager.CreateToastNotifier(appid);
|
|||
|
var notification = new ToastNotification(template);
|
|||
|
|
|||
|
notifier.Show(notification);
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{
|
|||
|
// Ignore
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|