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") { foreach (var area in spaceResponseResult.Payload.Areas) { //找出對定的設備代碼 var selectedMapping = parkingSapceMapping.Where(x => x.System_key == area.Name).FirstOrDefault(); if (selectedMapping != null) { item = 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(); parames.Add(parkingConfig.ApiBase); for (var i = 0; i < tagNameSplit.Length; i++) { if (i != tagNameSplit.Length - 1) { parames.Add(tagNameSplit[i]); // tag 前 4段 } else { parames.Add(tagName); // 第五段 完整 tag } } //logger.LogError(@$"【ParkingJob】【停車場剩餘車位】{apiFormat}"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray())); request.Method = "POST"; request.Headers.Add("Authorization", "Basic " + encoded); request.PreAuthenticate = true; request.Timeout = System.Threading.Timeout.Infinite; var real = $@""; byte[] realByteArray = Encoding.UTF8.GetBytes(real); using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(realByteArray, 0, realByteArray.Length); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(responseContent); string json = JsonConvert.SerializeXmlNode(xmlDocument); JObject jsonResult = (JObject)JsonConvert.DeserializeObject(json); if (jsonResult.ContainsKey("err")) //抓取錯誤 { logger.LogError("【ParkingJob】【停車場剩餘車位資訊】"); logger.LogError("【ParkingJob】【停車場剩餘車位資訊】[錯誤內容]:{0}", json); } else { if (jsonResult.ContainsKey("real")) //表示可以讀取到內容 { List> ontimeRawDatas = new List>(); var realList = jsonResult["real"]; var display = realList["@display"]; if (display != null) { var tempStrSplit = display.ToString().Split(" "); if (tempStrSplit[0] != area.Remain.ToString()) { logger.LogError("【ParkingJob】【停車場剩餘車位資訊】[修改失敗]:{0}", display.ToString()); } } } } } else { logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】[查無該名稱對應表]:{0}", area.Name); } } } else { logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】 - [查無資料]"); } await task_Detail.InsertWorkTime_End("ParkingJob", "Parking", "執行成功停車場剩餘車位Job"); //logger.LogInformation("【ParkingJob】【執行成功停車場剩餘車位Job】"); } catch (Exception exception) { await task_Detail.WorkFail("ParkingJob", "Parking", exception.ToString()); logger.LogInformation("【ParkingJob】【執行失敗停車場剩餘車位Job】"); logger.LogInformation("【ParkingJob】【執行失敗停車場剩餘車位Job】[Exception]:{0}", exception.ToString()); logger.LogInformation("【ParkingJob】【執行失敗停車場剩餘車位Job】[Item]: {0}", item); logger.LogInformation("【ParkingJob】【執行失敗停車場剩餘車位Job】[encoded]: {0}", encoded); } } #endregion #region 取得設備資訊 if (await task_Detail.GetNeedWorkTask("ParkingJob", "Device")) { try { await task_Detail.InsertWorkTime("ParkingJob", "Device", "開始執行設備資訊Job"); //logger.LogInformation("【ParkingJob】【開始執行設備資訊Job】"); HttpWebRequest equipmentRequest = (HttpWebRequest)WebRequest.Create($"{parkingConfig.Host}/api/equipment/state"); equipmentRequest.Method = "GET"; //request.Headers.Add("Authorization", "Basic " + encoded); equipmentRequest.Headers.Add("X-VENDOR-ID", parkingConfig.VendorId); equipmentRequest.Headers.Add("X-VENDOR-TOKEN", parkingConfig.VendorToken); equipmentRequest.PreAuthenticate = true; equipmentRequest.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => 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") { foreach (var equipment in equipmentResponseResult.Payload) { //找出對定的設備代碼 var selectedMapping = parkingEquipmentMapping.Where(x => x.System_key == equipment.Id).FirstOrDefault(); if (selectedMapping != null) { item = equipment.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(); parames.Add(parkingConfig.ApiBase); for (var i = 0; i < tagNameSplit.Length; i++) { if (i != tagNameSplit.Length - 1) { parames.Add(tagNameSplit[i]); } else { parames.Add(tagName); } } HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray())); request.Method = "POST"; request.Headers.Add("Authorization", "Basic " + encoded); request.PreAuthenticate = true; var real = $@""; byte[] realByteArray = Encoding.UTF8.GetBytes(real); using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(realByteArray, 0, realByteArray.Length); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(responseContent); string json = JsonConvert.SerializeXmlNode(xmlDocument); JObject jsonResult = (JObject)JsonConvert.DeserializeObject(json); if (jsonResult.ContainsKey("err")) //抓取錯誤 { logger.LogError("【ParkingJob】【設備資訊】"); logger.LogError("【ParkingJob】【設備資訊】[錯誤內容]:{0}", json); } else { if (jsonResult.ContainsKey("bool")) //表示可以讀取到內容 { List> ontimeRawDatas = new List>(); var realList = jsonResult["bool"]; var val = realList["@val"]; if (val != null) { var tempStrSplit = val.ToString(); if (tempStrSplit != equipment.Alive.ToString().ToLower()) { logger.LogError("【ParkingJob】【設備資訊】[修改失敗]:{0}", val.ToString()); } } } } } else { logger.LogWarning("【ParkingJob】【設備資訊】[查無該名稱對應表]:{0}", equipment.Id); } } } else { logger.LogWarning("【ParkingJob】【設備資訊】 - [查無資料]"); } await task_Detail.InsertWorkTime_End("ParkingJob", "Device", "執行成功設備資訊Job"); //logger.LogInformation("【ParkingJob】【執行成功設備資訊Job】"); } catch (Exception exception) { await task_Detail.WorkFail("ParkingJob", "Device", exception.ToString()); logger.LogInformation("【ParkingJob】【執行失敗設備資訊Job】"); logger.LogInformation("【ParkingJob】【執行失敗設備資訊Job】[Exception]:{0}", exception.ToString()); logger.LogInformation("【ParkingJob】【執行失敗設備資訊Job】[item]:{0}", item); logger.LogInformation("【ParkingJob】【執行失敗設備資訊Job】[encoded]:{0}", encoded); } } #endregion await task_Detail.InsertWorkTime_End("ParkingJob", "All", "任務完成"); } } catch (Exception exception) { await task_Detail.WorkFail("ParkingJob", "All", exception.ToString()); logger.LogError("【ParkingJob】【任務失敗】"); logger.LogError("【ParkingJob】【任務失敗】[Exception]:{0}", exception.ToString()); } } } }