ibms-dome/FrontendWorkerService/Quartz/Jobs/OntimeAlarmDeviceRawDataJob.cs

349 lines
20 KiB
C#
Raw Normal View History

2022-10-14 16:08:54 +08:00
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.Diagnostics;
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 OntimeAlarmDeviceRawDataJob : IJob
{
private readonly ILogger<OntimeAlarmDeviceRawDataJob> logger;
private readonly IFrontendRepository frontendRepository;
public OntimeAlarmDeviceRawDataJob(
ILogger<OntimeAlarmDeviceRawDataJob> logger,
IFrontendRepository frontendRepository)
{
this.logger = logger;
this.frontendRepository = frontendRepository;
}
public async Task Execute(IJobExecutionContext context)
{
try
{
logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【任務開始】");
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();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/watchService/watch{obixAlarmConfig.Alarm_watch_id}/pollChanges/");
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
//Stopwatch stopWatch = new Stopwatch();
//stopWatch.Start();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();
//stopWatch.Stop();
//logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
//stopWatch.Reset();
//stopWatch.Start();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
string json = JsonConvert.SerializeXmlNode(xmlDocument);
JObject jsonResult = (JObject)JsonConvert.DeserializeObject(json);
if (jsonResult.ContainsKey("err")) //抓取錯誤
{
logger.LogError("【OntimeAlarmDeviceRawDataJob】【API回傳錯誤資訊】");
logger.LogError("【OntimeAlarmDeviceRawDataJob】【API回傳錯誤資訊】[錯誤內容]{0}", json);
#region watch service
logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【開始刪除該watch service】[編號:{0}]", obixAlarmConfig.Alarm_watch_id);
HttpWebRequest deleteWatchServiceRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/watchService/watch{obixAlarmConfig.Alarm_watch_id}/delete/");
deleteWatchServiceRequest.Method = "POST";
deleteWatchServiceRequest.Headers.Add("Authorization", "Basic " + encoded);
deleteWatchServiceRequest.PreAuthenticate = true;
HttpWebResponse deleteWatchServiceResponse = (HttpWebResponse)deleteWatchServiceRequest.GetResponse();
var deleteWatchServiceResponseContent = new StreamReader(deleteWatchServiceResponse.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(deleteWatchServiceResponseContent);
string deleteWatchServiceJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject deleteWatchServiceJsonResult = (JObject)JsonConvert.DeserializeObject(deleteWatchServiceJson);
if (deleteWatchServiceJsonResult.ContainsKey("err")) //抓取錯誤
{
logger.LogError("【OnTimeDeviceSubscriptionJob】【刪除舊有watch service失敗】[編號:{0}]");
logger.LogError("【OnTimeDeviceSubscriptionJob】【刪除舊有watch service失敗】[錯誤內容]{0}", deleteWatchServiceJson);
}
else if (deleteWatchServiceJsonResult.ContainsKey("obj"))
{
var deleteResult = deleteWatchServiceJsonResult["obj"]["@null"].ToString();
if (deleteResult == "true")
{
logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【刪除舊有watch service成功】[編號:{0}]", obixAlarmConfig.Alarm_watch_id);
}
else
{
logger.LogError("【OntimeAlarmDeviceRawDataJob】【刪除舊有watch service失敗】[編號:{0}]", obixAlarmConfig.Alarm_watch_id);
logger.LogError("【OntimeAlarmDeviceRawDataJob】【刪除舊有watch service失敗】[錯誤內容]{0}", deleteWatchServiceJson);
}
}
else //未知錯誤
{
logger.LogError("【OntimeAlarmDeviceRawDataJob】【刪除舊有watch service未知錯誤】[編號:{0}]", obixAlarmConfig.Alarm_watch_id);
logger.LogError("【OntimeAlarmDeviceRawDataJob】【刪除舊有watch service未知錯誤】[錯誤內容]{0}", deleteWatchServiceJson);
}
#endregion
#region watch service
logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【開始重新建立watch service】");
string watch_id = string.Empty; //紀錄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("【OnTimeDeviceSubscriptionJob】【重新建立watch service失敗】");
logger.LogError("【OnTimeDeviceSubscriptionJob】【重新建立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))
{
logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【重新建立watch service的編號】[編號:{0}]", 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("【OnTimeDeviceSubscriptionJob】【修改watch service存活時間失敗】");
logger.LogError("【OnTimeDeviceSubscriptionJob】【修改watch service存活時間失敗】[錯誤內容]{0}", changeWatchServiceJsonResult);
return;
}
}
#endregion
#region 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;
}
#endregion
}
else
{
if (jsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
//logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【取得資料內容】{0}", System.Text.Json.JsonSerializer.Serialize(json));
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 = jsonResult["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);
}
}
}
//stopWatch.Stop();
//logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【效能檢驗】[解析資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
if (ontimeAlarmRawDatas.Count() > 0)
{
try
{
//stopWatch.Reset();
//stopWatch.Start();
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);
//stopWatch.Stop();
//logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【效能檢驗】[資料存入資料庫花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
//logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【存入資料內容】{0}", System.Text.Json.JsonSerializer.Serialize(ontimeAlarmRawDatas));
}
catch (Exception exception)
{
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【新增設備點位原始資料失敗】");
logger.LogError("【OntimeAlarmDeviceSubscriptionJob】【新增設備點位原始資料失敗】[Exception]{0}", exception.ToString());
}
}
}
}
logger.LogInformation("【OntimeAlarmDeviceRawDataJob】【任務完成】");
}
catch (Exception exception)
{
logger.LogError("【OntimeAlarmDeviceRawDataJob】【任務失敗】");
logger.LogError("【OntimeAlarmDeviceRawDataJob】【任務失敗】[Exception]{0}", exception.ToString());
}
}
}
}