using Backend.Models; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NPOI.OpenXml4Net.OPC; using Quartz; using Repository.BackendRepository.Interface; 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 BackendWorkerService.Quartz.Jobs { /// /// 停車場管理 /// [DisallowConcurrentExecution] class ParkingJob : IJob { private readonly ILogger logger; private readonly IBackgroundServiceRepository backgroundServiceRepository; private readonly IBackendRepository backendRepository; private readonly ILogger loggers; public ParkingJob( ILogger logger, IBackgroundServiceRepository backgroundServiceRepository, ILogger loggers, IBackendRepository backendRepository) { this.logger = logger; this.backgroundServiceRepository = backgroundServiceRepository; this.backendRepository = backendRepository; this.loggers = loggers; } public async Task Execute(IJobExecutionContext context) { Task_Detail task_Detail = new Task_Detail(loggers, backendRepository); try { if(await task_Detail.GetNeedWorkTask("ParkingJob", "All")) { var item = string.Empty; await task_Detail.InsertWorkTime("ParkingJob", "All", "任務開始"); EDFunction ed = new EDFunction(); var parkingConfig = new ParkingConfig(); var sqlParking = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'parkingConfig'"; var variable = await backgroundServiceRepository.GetAllAsync(sqlParking); parkingConfig.Host = variable.Where(x => x.Name == "Host").Select(x => x.Value).FirstOrDefault(); parkingConfig.Prefix = variable.Where(x => x.Name == "Prefix").Select(x => x.Value).FirstOrDefault(); parkingConfig.ApiBase = variable.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault(); parkingConfig.UserName = variable.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault(); parkingConfig.Password = variable.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault(); parkingConfig.VendorId = variable.Where(x => x.Name == "X-VENDOR-ID").Select(x => x.Value).FirstOrDefault(); parkingConfig.VendorToken = variable.Where(x => x.Name == "X-VENDOR-TOKEN").Select(x => x.Value).FirstOrDefault(); String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(parkingConfig.UserName + ":" + parkingConfig.Password)); #region 取得停車場資訊 if (await task_Detail.GetNeedWorkTask("ParkingJob", "Parking")) { try { await task_Detail.InsertWorkTime("ParkingJob", "Parking", "開始執行停車場剩餘車位Job"); HttpWebRequest spaceRequest = (HttpWebRequest)WebRequest.Create($"{parkingConfig.Host}/api/space/details"); spaceRequest.Method = "GET"; //request.Headers.Add("Authorization", "Basic " + encoded); spaceRequest.Headers.Add("X-VENDOR-ID", parkingConfig.VendorId); spaceRequest.Headers.Add("X-VENDOR-TOKEN", parkingConfig.VendorToken); spaceRequest.PreAuthenticate = true; spaceRequest.Timeout = System.Threading.Timeout.Infinite; spaceRequest.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; //Stopwatch stopWatch = new Stopwatch(); //stopWatch.Start(); HttpWebResponse spaceResponse = (HttpWebResponse)spaceRequest.GetResponse(); var spaceResponseContent = new StreamReader(spaceResponse.GetResponseStream()).ReadToEnd(); //logger.LogInformation("【ParkingJob】【取得成功停車場車位資訊】"); //stopWatch.Stop(); //logger.LogInformation("【ParkingJob】【取得停車場車位資訊】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds); var spaceResponseResult = JsonConvert.DeserializeObject(spaceResponseContent); //取得停車場車位對應表 var sqlSapceMapping = $@"SELECT * FROM variable WHERE deleted = 0 AND system_type = 'parkingSapceMapping'"; var parkingSapceMapping = await backgroundServiceRepository.GetAllAsync(sqlSapceMapping); if (spaceResponseResult != null && spaceResponseResult.Code == "20000") { List batchRequests = new List(); // 用來存儲批次請求的列表 foreach (var area in spaceResponseResult.Payload.Areas) { // 找出對應的設備代碼 var selectedMapping = parkingSapceMapping.FirstOrDefault(x => x.System_key == area.Name); if (selectedMapping != null) { var name = area.Name; // 保存設備名稱 var tagName = selectedMapping.system_value; var apiFormat = @"{0}obix/config/Arena/{1}/{2}/{3}/{4}/{5}/CV/set"; var tagNameSplit = tagName.Split("_"); var parames = new List { parkingConfig.ApiBase }; parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段 parames.Add(tagName); // 最後一段 完整 tag string requestUri = string.Format(apiFormat, parames.ToArray()); // 構建要發送的實體資料 var real = $@""; batchRequests.Add($"" + $"" + $""); // 進行日誌記錄 logger.LogInformation("【ParkingJob】【停車場剩餘車位】準備更新設備:{0},剩餘車位數:{1}", name, area.Remain); } else { logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】[查無該名稱對應表]:{0}", area.Name); } } if (batchRequests.Any()) { // 建立批次請求 XML var batchRequestXml = $@" {string.Join("", batchRequests)} "; // 發送批次請求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(parkingConfig.ApiBase + "obix/batch"); request.Method = "POST"; request.Headers.Add("Authorization", "Basic " + encoded); request.PreAuthenticate = true; request.Timeout = System.Threading.Timeout.Infinite; byte[] requestData = Encoding.UTF8.GetBytes(batchRequestXml); using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(requestData, 0, requestData.Length); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd(); // 檢查回應中是否有錯誤 if (responseContent.Contains(" true; HttpWebResponse equipmentResponse = (HttpWebResponse)equipmentRequest.GetResponse(); var equipmentResponseContent = new StreamReader(equipmentResponse.GetResponseStream()).ReadToEnd(); var equipmentResponseResult = JsonConvert.DeserializeObject(equipmentResponseContent); //取得設備對應表 var sqlEquipmentMapping = $@"SELECT * FROM variable WHERE deleted = 0 AND system_type = 'parkingEquipmentMapping'"; var parkingEquipmentMapping = await backgroundServiceRepository.GetAllAsync(sqlEquipmentMapping); //List parkingEquipmentMapping = new List(); //VariableInfo variableInfo_1 = new VariableInfo(); //variableInfo_1.System_key = "APS-000"; //variableInfo_1.system_value = "D3_P_B4F_CAPS_B413"; //parkingEquipmentMapping.Add(variableInfo_1); //VariableInfo variableInfo_2 = new VariableInfo(); //variableInfo_2.System_key = "APS-001"; //variableInfo_2.system_value = "D3_P_B4F_CAPS_B414"; //parkingEquipmentMapping.Add(variableInfo_2); if (equipmentResponseResult != null && equipmentResponseResult.Code == "20000") { List batchRequests = new List(); // 用來存儲批次請求的列表 foreach (var equipment in equipmentResponseResult.Payload) { // 找出對應的設備代碼 var selectedMapping = parkingEquipmentMapping.FirstOrDefault(x => x.System_key == equipment.Id); if (selectedMapping != null) { var name = equipment.Id; // 保存設備ID var tagName = selectedMapping.system_value; var apiFormat = @"{0}obix/config/Arena/{1}/{2}/{3}/{4}/{5}/ST/set"; var tagNameSplit = tagName.Split("_"); var parames = new List { parkingConfig.ApiBase }; parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段 parames.Add(tagName); // 最後一段 完整 tag string requestUri = string.Format(apiFormat, parames.ToArray()); // 構建要發送的實體資料 var real = $@""; batchRequests.Add($"" + $"" + $""); // 進行日誌記錄 logger.LogInformation("【ParkingJob】【設備資訊】準備更新設備:{0},設備狀態:{1}", name, equipment.Alive); } else { logger.LogWarning("【ParkingJob】【設備資訊】[查無該名稱對應表]:{0}", equipment.Id); } } if (batchRequests.Any()) { // 建立批次請求 XML var batchRequestXml = $@" {string.Join("", batchRequests)} "; // 發送批次請求 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(parkingConfig.ApiBase + "obix/batch"); request.Method = "POST"; request.Headers.Add("Authorization", "Basic " + encoded); request.PreAuthenticate = true; byte[] requestData = Encoding.UTF8.GetBytes(batchRequestXml); using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(requestData, 0, requestData.Length); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd(); // 檢查回應中是否有錯誤 if (responseContent.Contains("