ibms-dome/FrontendWorkerService/Quartz/Jobs/OntimeAlarmDeviceRawDataJob.cs
2022-10-14 16:08:54 +08:00

349 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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());
}
}
}
}