350 lines
22 KiB
C#
350 lines
22 KiB
C#
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")
|
||
{
|
||
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<object>();
|
||
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 = $@"<real val='{area.Remain}' />";
|
||
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<Dictionary<string, object>> ontimeRawDatas = new List<Dictionary<string, object>>();
|
||
|
||
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.LogInformation("【ParkingJob】【停車場剩餘車位資訊】[修改成功]:{0}", display.ToString());
|
||
logger.LogInformation("【ParkingJob】【停車場剩餘車位資訊】[停車場資訊]:{0}", item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
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<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")
|
||
{
|
||
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<object>();
|
||
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 = $@"<real val='{equipment.Alive.ToString().ToLower()}' />";
|
||
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<Dictionary<string, object>> ontimeRawDatas = new List<Dictionary<string, object>>();
|
||
|
||
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.LogInformation("【ParkingJob】【設備資訊】[修改成功]:{0}", val.ToString());
|
||
logger.LogInformation("【ParkingJob】【設備資訊】[設備資訊]:{0}", item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
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());
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|