422 lines
20 KiB
C#
422 lines
20 KiB
C#
using Backend.Models;
|
||
using Microsoft.Extensions.Logging;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using Quartz;
|
||
using Repository.BackendRepository.Implement;
|
||
using Repository.BackendRepository.Interface;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Net;
|
||
using System.Net.Http;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Xml;
|
||
using System.Xml.Serialization;
|
||
using System.Linq;
|
||
using NCrontab;
|
||
using BackendWorkerService.Services.Implement;
|
||
using RainApi;
|
||
using System.Globalization;
|
||
using FrontendWebApi.Models;
|
||
using Repository.FrontendRepository.Interface;
|
||
using Microsoft.Extensions.Hosting;
|
||
using Repository.FrontendRepository.Implement;
|
||
using iTextSharp.text;
|
||
using NPOI.SS.Formula.Functions;
|
||
using System.Text.RegularExpressions;
|
||
using Repository.Models;
|
||
|
||
namespace BackendWorkerService.Quartz.Jobs
|
||
{
|
||
[DisallowConcurrentExecution]
|
||
class LightScheduleJob : IJob
|
||
{
|
||
private readonly ILogger<LightScheduleJob> logger;
|
||
private readonly IBackgroundServiceRepository backgroundServiceRepository;
|
||
private readonly IBackendRepository backendRepository;
|
||
private readonly ILogger<Task_Detail> loggers;
|
||
public LightScheduleJob(ILogger<LightScheduleJob> logger,
|
||
IBackgroundServiceRepository backgroundServiceRepository, IBackendRepository backendRepository, ILogger<Task_Detail> loggers)
|
||
{
|
||
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("LightScheduleJob", "light_schedule"))
|
||
{
|
||
try
|
||
{
|
||
await task_Detail.InsertWorkTime("LightScheduleJob", "light_schedule");
|
||
|
||
var TimeNow = DateTime.Now.ToString("dddd HH:mm");
|
||
var schedule = await backendRepository.GetAllAsync<Schedule>("light_schedule", "deleted = 0 and status = 1");
|
||
|
||
string date = DateTime.Now.ToString("yyyy-MM-dd");
|
||
|
||
foreach (var oneSchedule in schedule)
|
||
{
|
||
// 先檢查今日否需執行
|
||
var weeklistN = oneSchedule.week.Split(',');
|
||
List<string> weeklist = new List<string>();
|
||
foreach (var weekN in weeklistN)
|
||
{
|
||
var week = weekN switch
|
||
{
|
||
"0" => "星期日",
|
||
"1" => "星期一",
|
||
"2" => "星期二",
|
||
"3" => "星期三",
|
||
"4" => "星期四",
|
||
"5" => "星期五",
|
||
"6" => "星期六",
|
||
_ => ""
|
||
};
|
||
weeklist.Add(week);
|
||
}
|
||
|
||
var Time = TimeNow.Split(" ");
|
||
if (!weeklist.Contains(Time[0])) { continue; }
|
||
|
||
// 檢查執行log
|
||
string light_schedule_guid = oneSchedule.light_schedule_guid;
|
||
string sWhere = @$"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'";
|
||
var schedule_log = await backendRepository.GetOneAsync<ScheduleLog>("light_schedule_log", sWhere);
|
||
string start_time = null;
|
||
string end_time = null;
|
||
if (schedule_log != null)
|
||
{
|
||
start_time = schedule_log.start_time;
|
||
end_time = schedule_log.end_time;
|
||
}
|
||
|
||
if (schedule_log == null)
|
||
{
|
||
Dictionary<string, object> log = new Dictionary<string, object>()
|
||
{
|
||
{ "@light_schedule_guid", light_schedule_guid },
|
||
{ "@date", date },
|
||
};
|
||
await backendRepository.AddOneByCustomTable(log, "light_schedule_log");
|
||
}
|
||
|
||
|
||
string check = string.Empty;
|
||
|
||
// 檢查起始執行
|
||
if (start_time == null && end_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.start_time))
|
||
{
|
||
check = "true"; // 開啟
|
||
}
|
||
|
||
// 檢查結束執行
|
||
if (end_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.end_time))
|
||
{
|
||
check = "false"; // 關閉
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(check))
|
||
{
|
||
bool requestSuccess = await UpdatedNiagara(oneSchedule, check);
|
||
}
|
||
}
|
||
|
||
await task_Detail.InsertWorkTime_End("LightScheduleJob", "light_schedule");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
logger.LogInformation($"LightScheduleJob fail");
|
||
await task_Detail.WorkFail("LightScheduleJob", "light_schedule", ex.Message.ToString());
|
||
}
|
||
}
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
logger.LogError("【LightScheduleJob】【任務失敗】");
|
||
logger.LogError("【LightScheduleJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||
}
|
||
}
|
||
|
||
public async Task<bool> UpdatedNiagara(Schedule oneSchedule, string check)
|
||
{
|
||
try
|
||
{
|
||
// 取得排程所對應的設備號碼列表
|
||
var deviceNumList = await backendRepository.GetAllAsync<string>(@$"SELECT d.device_number
|
||
FROM schedule_device sd
|
||
JOIN device d ON sd.device_guid = d.device_guid
|
||
WHERE light_schedule_guid = '{oneSchedule.light_schedule_guid}' AND is_link = 1");
|
||
|
||
// 取得obix配置
|
||
var variableObix = await backendRepository.GetAllAsync<Backend.Models.KeyValue>(@$"SELECT system_value as Value, system_key as Name
|
||
FROM variable
|
||
WHERE deleted = 0 AND system_type = 'obixConfig'");
|
||
|
||
// 取得obix相關配置參數
|
||
string url = variableObix.FirstOrDefault(x => x.Name == "ApiBase")?.Value;
|
||
string account = variableObix.FirstOrDefault(x => x.Name == "UserName")?.Value;
|
||
string pass = variableObix.FirstOrDefault(x => x.Name == "Password")?.Value;
|
||
|
||
// 檢查是否有配置缺失
|
||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(account) || string.IsNullOrEmpty(pass))
|
||
{
|
||
logger.LogWarning("【LightScheduleJob】【obix配置缺失】請檢查obix配置");
|
||
return false;
|
||
}
|
||
|
||
// 準備HTTP請求的基本資訊
|
||
string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes($"{account}:{pass}"));
|
||
|
||
// 構建每個設備的請求
|
||
List<string> batchRequests = new List<string>();
|
||
TagChangeFunction tagChange = new TagChangeFunction();
|
||
|
||
foreach (var deviceNum in deviceNumList)
|
||
{
|
||
// 處理設備號碼,分解到URL中
|
||
var d = tagChange.AddStringIfStartsWithDigit(deviceNum, "$3");
|
||
var uri = $"{url}obix/config/Arena/{d[0]}/{d[1]}/{d[2]}/{d[3]}/{deviceNum}/SSC/set";
|
||
|
||
// 構建要發送的實體資料
|
||
string realData = $"<real name='in' val='{check}' />";
|
||
|
||
// 建立批次請求
|
||
batchRequests.Add($"<uri is='obix:Invoke' val='{uri}'>" + realData + "</uri>");
|
||
}
|
||
|
||
// 構建整體批次請求
|
||
var batchRequestData = $@"<list is='obix:BatchIn'>
|
||
{string.Join("", batchRequests)}
|
||
</list>";
|
||
|
||
// 發送批次請求
|
||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "obix/batch");
|
||
request.Method = "POST";
|
||
request.Accept = "application/json; charset=utf-8";
|
||
request.Headers["Authorization"] = "Basic " + authInfo;
|
||
|
||
// 將所有設備的請求內容合併成一個批次請求
|
||
byte[] byteArray = Encoding.UTF8.GetBytes(batchRequestData);
|
||
using (Stream reqStream = request.GetRequestStream())
|
||
{
|
||
reqStream.Write(byteArray, 0, byteArray.Length);
|
||
}
|
||
|
||
// 發送請求並處理回應
|
||
var response = (HttpWebResponse)request.GetResponse();
|
||
string responseContent = string.Empty;
|
||
|
||
using (var sr = new StreamReader(response.GetResponseStream()))
|
||
{
|
||
responseContent = sr.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($"【LightScheduleJob】【Niagara燈控設置失敗】排程名稱 :{oneSchedule.full_name} 顯示錯誤: {errNode}");
|
||
|
||
}
|
||
|
||
return false; // 如果有錯誤,返回 false
|
||
}
|
||
|
||
// 成功後記錄並更新結束時間
|
||
Dictionary<string, object> log = new Dictionary<string, object>();
|
||
|
||
string time = DateTime.Now.ToString("HH:mm");
|
||
if (check == "true")
|
||
{
|
||
log.Add("@start_time", time);
|
||
}
|
||
else
|
||
{
|
||
log.Add("@end_time", time);
|
||
}
|
||
|
||
|
||
await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{oneSchedule.light_schedule_guid}' and date = '{DateTime.Now:yyyy-MM-dd}'");
|
||
|
||
logger.LogInformation($"【LightScheduleJob】【Niagara燈控設置成功】排程名稱 :{oneSchedule.full_name}");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
logger.LogError("【LightScheduleJob】批次請求發送失敗:" + ex.ToString());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//public async Task Execute(IJobExecutionContext context)
|
||
//{
|
||
// Task_Detail task_Detail = new Task_Detail(loggers, backendRepository);
|
||
// try
|
||
// {
|
||
// if (await task_Detail.GetNeedWorkTask("LightScheduleJob", "light_schedule"))
|
||
// {
|
||
// try
|
||
// {
|
||
// await task_Detail.InsertWorkTime("LightScheduleJob", "light_schedule");
|
||
|
||
// var TimeNow = DateTime.Now.ToString("dddd HH:mm");
|
||
// var schedule = await backendRepository.GetAllAsync<Schedule>("light_schedule","deleted = 0 and status = 1");
|
||
// string date = DateTime.Now.ToString("yyyy-MM-dd");
|
||
|
||
// foreach (var oneSchedule in schedule)
|
||
// {
|
||
// // 檢查執行log
|
||
// string light_schedule_guid = oneSchedule.light_schedule_guid;
|
||
// string sWhere = @$"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'";
|
||
// var schedule_log = await backendRepository.GetOneAsync<ScheduleLog>("light_schedule_log", sWhere);
|
||
// string start_time = null;
|
||
// string end_time = null;
|
||
// if (schedule_log != null)
|
||
// {
|
||
// start_time = schedule_log.start_time;
|
||
// end_time = schedule_log.end_time;
|
||
// }
|
||
// if (schedule_log == null)
|
||
// {
|
||
// Dictionary<string, object> log = new Dictionary<string, object>()
|
||
// {
|
||
// { "@light_schedule_guid", light_schedule_guid},
|
||
// { "@date", date},
|
||
// };
|
||
// await backendRepository.AddOneByCustomTable(log, "light_schedule_log");
|
||
// }
|
||
// // 如果log有紀錄
|
||
|
||
// var weeklistN = oneSchedule.week.Split(',');
|
||
// List<string> weeklist = new List<string>();
|
||
// foreach (var weekN in weeklistN)
|
||
// {
|
||
// var week = weekN switch
|
||
// {
|
||
// "0" => "星期日",
|
||
// "1" => "星期一",
|
||
// "2" => "星期二",
|
||
// "3" => "星期三",
|
||
// "4" => "星期四",
|
||
// "5" => "星期五",
|
||
// "6" => "星期六",
|
||
// _ => ""
|
||
// };
|
||
// weeklist.Add(week);
|
||
// }
|
||
// var Time = TimeNow.Split(" ");
|
||
// string check = string.Empty;
|
||
// // 檢查起始執行
|
||
// if (start_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.start_time))
|
||
// {
|
||
// check = "<real val='true' />";
|
||
// UpdatedNiagara(oneSchedule, check);
|
||
// Dictionary<string, object> log = new Dictionary<string, object>()
|
||
// {
|
||
// { "@start_time", Time[1]},
|
||
// };
|
||
// await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'");
|
||
// logger.LogInformation($"【LightScheduleJob】【燈控排程開啟成功】排程名稱 :{oneSchedule.full_name}");
|
||
// }
|
||
// // 檢查結束執行
|
||
// if (end_time == null && DateTime.Parse(Time[1]) >= DateTime.Parse(oneSchedule.end_time))
|
||
// {
|
||
// check = "<real val='false' />";
|
||
// UpdatedNiagara(oneSchedule, check);
|
||
// Dictionary<string, object> log = new Dictionary<string, object>()
|
||
// {
|
||
// { "@end_time", Time[1]},
|
||
// };
|
||
// await backendRepository.UpdateOneByCustomTable(log, "light_schedule_log", $"light_schedule_guid = '{light_schedule_guid}' and date = '{date}'");
|
||
// logger.LogInformation($"【LightScheduleJob】【燈控排程關閉成功】排程名稱 :{oneSchedule.full_name}");
|
||
// }
|
||
// }
|
||
|
||
|
||
// await task_Detail.InsertWorkTime_End("LightScheduleJob", "light_schedule");
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// logger.LogInformation($"LightScheduleJob fail");
|
||
// await task_Detail.WorkFail("LightScheduleJob", "light_schedule", ex.Message.ToString());
|
||
// }
|
||
// }
|
||
// }
|
||
// catch (Exception exception)
|
||
// {
|
||
// logger.LogError("【LightScheduleJob】【任務失敗】");
|
||
// logger.LogError("【LightScheduleJob】【任務失敗】[Exception]:{0}", exception.ToString());
|
||
// }
|
||
//}
|
||
//public async void UpdatedNiagara(Schedule oneSchedule, string check)
|
||
//{
|
||
// try
|
||
// {
|
||
// var deviceNumList = await backendRepository.GetAllAsync<string>(@$"select d.device_number from schedule_device sd join device d on sd.device_guid = d.device_guid
|
||
// where light_schedule_guid = '{oneSchedule.light_schedule_guid}' and is_link = 1");
|
||
|
||
// var variableObix = await backendRepository.GetAllAsync<Backend.Models.KeyValue>("SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'");
|
||
// string url = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
|
||
// string account = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault();
|
||
// string pass = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault();
|
||
// foreach (var deviceNum in deviceNumList)
|
||
// {
|
||
// TagChangeFunction tagChange = new TagChangeFunction();
|
||
// var d = tagChange.AddStringIfStartsWithDigit(deviceNum, "$3");
|
||
// var html = $"{url}obix/config/Arena/" + $"{d[0]}/{d[1]}/{d[2]}/{d[3]}/{deviceNum}/SSC/set";
|
||
// string authInfo = account + ":" + pass;
|
||
// authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
|
||
// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(html);
|
||
// request.Method = "POST";
|
||
// request.Accept = "application/json; charset=utf-8";
|
||
// request.Headers["Authorization"] = "Basic " + authInfo;
|
||
// byte[] byteArray = Encoding.UTF8.GetBytes(check);
|
||
// using (Stream reqStream = request.GetRequestStream())
|
||
// {
|
||
// reqStream.Write(byteArray, 0, byteArray.Length);
|
||
// }
|
||
// var response = (HttpWebResponse)request.GetResponse();
|
||
// string strResponse = "";
|
||
|
||
// using (var sr = new StreamReader(response.GetResponseStream()))
|
||
// {
|
||
// strResponse = sr.ReadToEnd();
|
||
// }
|
||
// // 只取err會取到override
|
||
// if (strResponse.Contains("<err"))
|
||
// {
|
||
// logger.LogWarning($"【LightScheduleJob 】【set niagara light value fail】[排程 名稱]:{oneSchedule.full_name},[設備 名稱]:{deviceNum}");
|
||
// }
|
||
// }
|
||
// }
|
||
// catch (Exception ex)
|
||
// {
|
||
// logger.LogError("【LightScheduleJob】" + "UpdatedNiagaraFail:" + ex.ToString());
|
||
// throw ex;
|
||
// }
|
||
//}
|
||
}
|
||
}
|