ibms-dome/BackendWorkerService/Quartz/Jobs/ParkingJob.cs

353 lines
21 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 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
{
/// <summary>
/// 停車場管理
/// </summary>
[DisallowConcurrentExecution]
class ParkingJob : IJob
{
private readonly ILogger<ParkingJob> logger;
private readonly IBackgroundServiceRepository backgroundServiceRepository;
private readonly IBackendRepository backendRepository;
private readonly ILogger<Task_Detail> loggers;
public ParkingJob(
ILogger<ParkingJob> logger,
IBackgroundServiceRepository backgroundServiceRepository, ILogger<Task_Detail> 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<KeyValue>(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<SpaceResponse>(spaceResponseContent);
//取得停車場車位對應表
var sqlSapceMapping = $@"SELECT * FROM variable WHERE deleted = 0 AND system_type = 'parkingSapceMapping'";
var parkingSapceMapping = await backgroundServiceRepository.GetAllAsync<VariableInfo>(sqlSapceMapping);
if (spaceResponseResult != null && spaceResponseResult.Code == "20000")
{
List<string> batchRequests = new List<string>(); // 用來存儲批次請求的列表
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<object> { parkingConfig.ApiBase };
parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段
parames.Add(tagName); // 最後一段 完整 tag
string requestUri = string.Format(apiFormat, parames.ToArray());
// 構建要發送的實體資料
var real = $@"<real val='{area.Remain}' />";
batchRequests.Add($"<uri is='obix:Invoke' val='{requestUri}'>" +
$"<real name='in' val='{area.Remain}' />" +
$"</uri>");
// 進行日誌記錄
logger.LogInformation("【ParkingJob】【停車場剩餘車位】準備更新設備{0},剩餘車位數:{1}", name, area.Remain);
}
else
{
logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】[查無該名稱對應表]{0}", area.Name);
}
}
if (batchRequests.Any())
{
// 建立批次請求 XML
var batchRequestXml = $@"<list is='obix:BatchIn'>
{string.Join("", batchRequests)}
</list>";
// 發送批次請求
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("<err"))
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
// 找到所有的 err 節點
XmlNodeList errNodes = xmlDocument.GetElementsByTagName("err");
// 如果有錯誤節點,進行處理
foreach (XmlNode errNode in errNodes)
{
logger.LogWarning($"【ParkingJob】【停車場剩餘車位資訊】[錯誤內容]{errNode}");
}
}
else
{
logger.LogInformation("【ParkingJob】【停車場剩餘車位資訊】[批次請求成功]");
}
}
else
{
logger.LogWarning("【ParkingJob】【停車場剩餘車位資訊】[沒有需要發送的請求]");
}
}
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<EquipmentResponse>(equipmentResponseContent);
//取得設備對應表
var sqlEquipmentMapping = $@"SELECT * FROM variable WHERE deleted = 0 AND system_type = 'parkingEquipmentMapping'";
var parkingEquipmentMapping = await backgroundServiceRepository.GetAllAsync<VariableInfo>(sqlEquipmentMapping);
//List<VariableInfo> parkingEquipmentMapping = new List<VariableInfo>();
//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<string> batchRequests = new List<string>(); // 用來存儲批次請求的列表
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<object> { parkingConfig.ApiBase };
parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段
parames.Add(tagName); // 最後一段 完整 tag
string requestUri = string.Format(apiFormat, parames.ToArray());
// 構建要發送的實體資料
var real = $@"<real val='{equipment.Alive.ToString().ToLower()}' />";
batchRequests.Add($"<uri is='obix:Invoke' val='{requestUri}'>" +
$"<real name='in' val='{equipment.Alive.ToString().ToLower()}' />" +
$"</uri>");
// 進行日誌記錄
logger.LogInformation("【ParkingJob】【設備資訊】準備更新設備{0},設備狀態:{1}", name, equipment.Alive);
}
else
{
logger.LogWarning("【ParkingJob】【設備資訊】[查無該名稱對應表]{0}", equipment.Id);
}
}
if (batchRequests.Any())
{
// 建立批次請求 XML
var batchRequestXml = $@"<list is='obix:BatchIn'>
{string.Join("", batchRequests)}
</list>";
// 發送批次請求
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("<err"))
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseContent);
// 找到所有的 err 節點
XmlNodeList errNodes = xmlDocument.GetElementsByTagName("err");
// 如果有錯誤節點,進行處理
foreach (XmlNode errNode in errNodes)
{
logger.LogWarning($"【ParkingJob】【設備資訊】[錯誤內容]{errNode}");
}
}
else
{
logger.LogInformation("【ParkingJob】【設備資訊】[批次請求成功]");
}
}
else
{
logger.LogWarning("【ParkingJob】【設備資訊】[沒有需要發送的請求]");
}
}
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());
}
}
}
}