339 lines
18 KiB
C#
339 lines
18 KiB
C#
|
using FrontendWorkerService.Models;
|
|||
|
using Microsoft.Extensions.Logging;
|
|||
|
using Newtonsoft.Json;
|
|||
|
using Newtonsoft.Json.Linq;
|
|||
|
using Quartz;
|
|||
|
using Repository.FrontendRepository.Interface;
|
|||
|
using Repository.Models;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Net;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using System.Xml;
|
|||
|
|
|||
|
namespace FrontendWorkerService.Quartz.Jobs
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 透過obix API向Niagara 訂閱告警設備
|
|||
|
/// </summary>
|
|||
|
[DisallowConcurrentExecution]
|
|||
|
class OntimeAlarmDeviceSubscriptionJob : IJob
|
|||
|
{
|
|||
|
private readonly ILogger<OntimeAlarmDeviceSubscriptionJob> logger;
|
|||
|
private readonly IFrontendRepository frontendRepository;
|
|||
|
|
|||
|
public OntimeAlarmDeviceSubscriptionJob(
|
|||
|
ILogger<OntimeAlarmDeviceSubscriptionJob> logger,
|
|||
|
IFrontendRepository frontendRepository)
|
|||
|
{
|
|||
|
this.logger = logger;
|
|||
|
this.frontendRepository = frontendRepository;
|
|||
|
}
|
|||
|
|
|||
|
public async Task Execute(IJobExecutionContext context)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string watch_id = string.Empty; //紀錄watch id的編號
|
|||
|
XmlDocument xmlDocument = new XmlDocument();
|
|||
|
|
|||
|
logger.LogInformation("【OntimeAlarmDeviceSubscriptionJob】【任務開始】");
|
|||
|
|
|||
|
EDFunction ed = new EDFunction();
|
|||
|
var obixApiConfig = new ObixApiConfig();
|
|||
|
|
|||
|
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
|
|||
|
|
|||
|
var variable = await frontendRepository.GetAllAsync<KeyValue>(sqlObix);
|
|||
|
obixApiConfig.ApiBase = variable.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
|
|||
|
obixApiConfig.UserName = ed.AESDecrypt(variable.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
|
|||
|
obixApiConfig.Password = ed.AESDecrypt(variable.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
|
|||
|
|
|||
|
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
|
|||
|
|
|||
|
ObixAlarmConfig obixAlarmConfig = new ObixAlarmConfig();
|
|||
|
obixAlarmConfig.Alarm_watch_id = variable.Where(x => x.Name == "alarm_watch_id").Select(x => x.Value).FirstOrDefault();
|
|||
|
|
|||
|
#region step 1 檢查watch id是否存活,未存活則重新建立
|
|||
|
HttpWebRequest watchServiceRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/watchService/");
|
|||
|
watchServiceRequest.Method = "GET";
|
|||
|
watchServiceRequest.Headers.Add("Authorization", "Basic " + encoded);
|
|||
|
watchServiceRequest.PreAuthenticate = true;
|
|||
|
|
|||
|
HttpWebResponse watchServiceResponse = (HttpWebResponse)watchServiceRequest.GetResponse();
|
|||
|
var watchServiceResponseContent = new StreamReader(watchServiceResponse.GetResponseStream()).ReadToEnd();
|
|||
|
|
|||
|
xmlDocument.LoadXml(watchServiceResponseContent);
|
|||
|
string watchServiceJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
|||
|
JObject watchServiceJsonResult = (JObject)JsonConvert.DeserializeObject(watchServiceJson);
|
|||
|
|
|||
|
if (watchServiceJsonResult.ContainsKey("err")) //抓取錯誤
|
|||
|
{
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【檢查watch service失敗】");
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【檢查watch service失敗】[錯誤內容]:{0}", watchServiceJson);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (watchServiceJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
|||
|
{
|
|||
|
if (watchServiceJsonResult["obj"]["ref"] != null && watchServiceJsonResult["obj"]["ref"].HasValues)
|
|||
|
{
|
|||
|
var watchServices = watchServiceJsonResult["obj"]["ref"];
|
|||
|
var temp_name_count = 0; //用來計算總共有幾個name
|
|||
|
foreach (var watchService in watchServices.Children())
|
|||
|
{
|
|||
|
var tempKeyValue = watchService.ToString();
|
|||
|
if (tempKeyValue.Contains("@name"))
|
|||
|
{
|
|||
|
temp_name_count++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (temp_name_count > 1)
|
|||
|
{ //有多個watch
|
|||
|
foreach (var watchService in watchServices.Children())
|
|||
|
{
|
|||
|
var tempKeyValue = watchService.ToString();
|
|||
|
|
|||
|
if (tempKeyValue.Contains("@name"))
|
|||
|
{
|
|||
|
var name = watchService["@name"].ToString();
|
|||
|
watch_id = name.Replace("watch", "");
|
|||
|
|
|||
|
if (watch_id == obixAlarmConfig.Alarm_watch_id)
|
|||
|
{ //表示有找到id
|
|||
|
break;
|
|||
|
}
|
|||
|
watch_id = string.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{ //單一個watch
|
|||
|
var tempKeyValue = watchServices.ToString();
|
|||
|
|
|||
|
if (tempKeyValue.Contains("@name"))
|
|||
|
{
|
|||
|
var name = watchServices["@name"].ToString();
|
|||
|
watch_id = name.Replace("watch", "");
|
|||
|
if (watch_id != obixAlarmConfig.Alarm_watch_id)
|
|||
|
{
|
|||
|
watch_id = string.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (string.IsNullOrEmpty(watch_id))
|
|||
|
{ //建立watch service
|
|||
|
HttpWebRequest makeWatchServiceRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/watchService/make/");
|
|||
|
makeWatchServiceRequest.Method = "POST";
|
|||
|
makeWatchServiceRequest.Headers.Add("Authorization", "Basic " + encoded);
|
|||
|
makeWatchServiceRequest.PreAuthenticate = true;
|
|||
|
|
|||
|
HttpWebResponse makeWatchServiceResponse = (HttpWebResponse)makeWatchServiceRequest.GetResponse();
|
|||
|
var makeWatchServiceResponseContent = new StreamReader(makeWatchServiceResponse.GetResponseStream()).ReadToEnd();
|
|||
|
|
|||
|
xmlDocument.LoadXml(makeWatchServiceResponseContent);
|
|||
|
string makeWatchServiceJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
|||
|
JObject makeWatchServiceJsonResult = (JObject)JsonConvert.DeserializeObject(makeWatchServiceJson);
|
|||
|
|
|||
|
|
|||
|
if (makeWatchServiceJsonResult.ContainsKey("err")) //抓取錯誤
|
|||
|
{
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【重新建立watch service失敗】");
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【重新建立watch service失敗】[錯誤內容]:{0}", makeWatchServiceJson);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (makeWatchServiceJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
|||
|
{
|
|||
|
var makeSplit = makeWatchServiceJsonResult["obj"]["@href"].ToString().Split("/");
|
|||
|
watch_id = makeSplit[makeSplit.Length - 2].Replace("watch", "");
|
|||
|
}
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(watch_id))
|
|||
|
{
|
|||
|
//儲存至variable
|
|||
|
Dictionary<string, object> updateWatchId = new Dictionary<string, object>()
|
|||
|
{
|
|||
|
{ "@system_value", watch_id}
|
|||
|
};
|
|||
|
|
|||
|
await frontendRepository.UpdateOneByCustomTable(updateWatchId, "variable", "system_type = 'obixConfig' AND system_key = 'alarm_watch_id'");
|
|||
|
|
|||
|
//修改watch service 存活時間
|
|||
|
HttpWebRequest changeWatchServiceRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/watchService/watch{watch_id}/lease/");
|
|||
|
changeWatchServiceRequest.Method = "PUT";
|
|||
|
changeWatchServiceRequest.Headers.Add("Authorization", "Basic " + encoded);
|
|||
|
changeWatchServiceRequest.PreAuthenticate = true;
|
|||
|
|
|||
|
var realTime = $@"<reltime val='PT24H0S' />";
|
|||
|
byte[] realTimeByteArray = Encoding.UTF8.GetBytes(realTime);
|
|||
|
using (Stream reqStream = changeWatchServiceRequest.GetRequestStream())
|
|||
|
{
|
|||
|
reqStream.Write(realTimeByteArray, 0, realTimeByteArray.Length);
|
|||
|
}
|
|||
|
|
|||
|
HttpWebResponse changeWatchServiceResponse = (HttpWebResponse)changeWatchServiceRequest.GetResponse();
|
|||
|
var changeWatchServiceResponseContent = new StreamReader(changeWatchServiceResponse.GetResponseStream()).ReadToEnd();
|
|||
|
|
|||
|
xmlDocument.LoadXml(changeWatchServiceResponseContent);
|
|||
|
string changeWatchServiceJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
|||
|
JObject changeWatchServiceJsonResult = (JObject)JsonConvert.DeserializeObject(changeWatchServiceJson);
|
|||
|
|
|||
|
if (changeWatchServiceJsonResult.ContainsKey("err")) //抓取錯誤
|
|||
|
{
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【修改watch service存活時間失敗】");
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【修改watch service存活時間失敗】[錯誤內容]:{0}", changeWatchServiceJsonResult);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
#endregion step 1 檢查watch id是否存活,未存活則重新建立
|
|||
|
|
|||
|
#region step 2 訂閱alarm feed,並將回傳的值新增至資料庫
|
|||
|
HttpWebRequest addWatchServiceRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/watchService/watch{watch_id}/add/");
|
|||
|
addWatchServiceRequest.Method = "POST";
|
|||
|
addWatchServiceRequest.Headers.Add("Authorization", "Basic " + encoded);
|
|||
|
addWatchServiceRequest.PreAuthenticate = true;
|
|||
|
|
|||
|
var subscripFullString = $@"<obj is='obix: WatchIn'>
|
|||
|
<list names = 'hrefs'>
|
|||
|
<uri val = '{obixApiConfig.ApiBase}obix/config/Services/OrionAlarmService/~alarmFeed/'/>
|
|||
|
</list>
|
|||
|
</obj>";
|
|||
|
byte[] byteArray = Encoding.UTF8.GetBytes(subscripFullString);
|
|||
|
using (Stream reqStream = addWatchServiceRequest.GetRequestStream())
|
|||
|
{
|
|||
|
reqStream.Write(byteArray, 0, byteArray.Length);
|
|||
|
}
|
|||
|
|
|||
|
HttpWebResponse addWatchServiceResponse = (HttpWebResponse)addWatchServiceRequest.GetResponse();
|
|||
|
var addWatchServiceResponseContent = new StreamReader(addWatchServiceResponse.GetResponseStream()).ReadToEnd();
|
|||
|
|
|||
|
xmlDocument.LoadXml(addWatchServiceResponseContent);
|
|||
|
string addWatchServiceJson = JsonConvert.SerializeXmlNode(xmlDocument);
|
|||
|
JObject addWatchServiceJsonResult = (JObject)JsonConvert.DeserializeObject(addWatchServiceJson);
|
|||
|
|
|||
|
if (addWatchServiceJsonResult.ContainsKey("err")) //抓取錯誤
|
|||
|
{
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【告警設備訂閱失敗】");
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【告警設備訂閱失敗】[錯誤內容]:{0}", addWatchServiceJsonResult);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (addWatchServiceJsonResult.ContainsKey("obj")) //表示可以讀取到內容
|
|||
|
{
|
|||
|
List<Dictionary<string, object>> ontimeAlarmRawDatas = new List<Dictionary<string, object>>();
|
|||
|
List<string> tempDeviceNumbers = new List<string>(); //用來找出設備的區域、系統大小類GUID
|
|||
|
List<OntimeAlarmRawDataPreprocess> alarmRawDataPreprocesses = new List<OntimeAlarmRawDataPreprocess>();
|
|||
|
|
|||
|
var alarmList = addWatchServiceJsonResult["obj"]["list"]["feed"];
|
|||
|
if (alarmList["obj"] != null && alarmList["obj"].HasValues)
|
|||
|
{
|
|||
|
//讀取資料
|
|||
|
foreach (var obj in alarmList["obj"])
|
|||
|
{
|
|||
|
var sourceState = string.Empty;
|
|||
|
var sourceName = string.Empty;
|
|||
|
//找出
|
|||
|
foreach (var str in obj["str"])
|
|||
|
{
|
|||
|
var tempName = str["@name"].ToString();
|
|||
|
if(tempName == "toState")
|
|||
|
{
|
|||
|
sourceState = str["@val"].ToString();
|
|||
|
}
|
|||
|
|
|||
|
if (tempName == "sourceName")
|
|||
|
{
|
|||
|
sourceName = str["@val"].ToString();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(sourceName))
|
|||
|
{
|
|||
|
var sourceNameSplit = sourceName.Split("_");
|
|||
|
|
|||
|
var device_number = string.Join("_", sourceNameSplit, 0, sourceNameSplit.Length - 1); //找出設備編號
|
|||
|
var name = sourceNameSplit[sourceNameSplit.Length - 1];//找出點位
|
|||
|
|
|||
|
tempDeviceNumbers.Add(device_number);
|
|||
|
|
|||
|
OntimeAlarmRawDataPreprocess alarmRawDataPreprocess = new OntimeAlarmRawDataPreprocess()
|
|||
|
{
|
|||
|
DeviceNumber = device_number,
|
|||
|
Name = name,
|
|||
|
SourceStatus = sourceState
|
|||
|
};
|
|||
|
|
|||
|
alarmRawDataPreprocesses.Add(alarmRawDataPreprocess);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(alarmRawDataPreprocesses.Count() > 0)
|
|||
|
{
|
|||
|
//找出設備的區域、系統大小類GUID
|
|||
|
var sql = $@"SELECT * FROM device d WHERE d.deleted = 0 AND d.device_number IN @DeviceNumbers";
|
|||
|
|
|||
|
var deviceInfos = await frontendRepository.GetAllAsync<DeviceInfo>(sql, new { DeviceNumbers = tempDeviceNumbers });
|
|||
|
|
|||
|
foreach(var alarmRawDataPreprocess in alarmRawDataPreprocesses)
|
|||
|
{
|
|||
|
var selectedDeviceInfo = deviceInfos.Where(x => x.device_number == alarmRawDataPreprocess.DeviceNumber).FirstOrDefault();
|
|||
|
|
|||
|
if(selectedDeviceInfo != null)
|
|||
|
{
|
|||
|
Dictionary<string, object> ontimeAlarmRawData = new Dictionary<string, object>()
|
|||
|
{
|
|||
|
{ "@building_guid", selectedDeviceInfo.building_guid },
|
|||
|
{ "@main_system_guid", selectedDeviceInfo.main_system_guid },
|
|||
|
{ "@sub_system_guid", selectedDeviceInfo.sub_system_guid },
|
|||
|
{ "@floor_guid", selectedDeviceInfo.floor_guid },
|
|||
|
{ "@device_number", alarmRawDataPreprocess.DeviceNumber},
|
|||
|
{ "@name", alarmRawDataPreprocess.Name},
|
|||
|
{ "@source_state", alarmRawDataPreprocess.SourceStatus},
|
|||
|
};
|
|||
|
|
|||
|
ontimeAlarmRawDatas.Add(ontimeAlarmRawData);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ontimeAlarmRawDatas.Count() > 0)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var insert_update_sql = $@"INSERT INTO ontime_alarm_device_rawdata (building_guid, main_system_guid, sub_system_guid, device_number, name, source_state) VALUES(@building_guid, @main_system_guid, @sub_system_guid, @device_number, @name, @source_state)
|
|||
|
ON DUPLICATE KEY UPDATE source_state=@source_state";
|
|||
|
await frontendRepository.ExecuteSql(insert_update_sql, ontimeAlarmRawDatas);
|
|||
|
}
|
|||
|
catch (Exception exception)
|
|||
|
{
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【新增設備點位原始資料失敗】");
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【新增設備點位原始資料失敗】[Exception]:{0}", exception.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion step 2 訂閱alarm feed,並將回傳的值新增至資料庫
|
|||
|
|
|||
|
logger.LogInformation("【OntimeAlarmDeviceSubscriptionJob】【任務完成】");
|
|||
|
}
|
|||
|
catch (Exception exception)
|
|||
|
{
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【任務失敗】");
|
|||
|
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|