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