[BGService]將部分obix定時任務改成批次撈取

This commit is contained in:
張家睿 2024-11-26 17:27:46 +08:00
parent e2f3992b9c
commit b60530974f
3 changed files with 595 additions and 224 deletions

View File

@ -38,14 +38,13 @@ namespace BackendWorkerService.Quartz.Jobs
private readonly IBackendRepository backendRepository;
private readonly ILogger<Task_Detail> loggers;
public LightScheduleJob(ILogger<LightScheduleJob> logger,
IBackgroundServiceRepository backgroundServiceRepository, IBackendRepository backendRepository, ILogger<Task_Detail> loggers)
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);
@ -58,33 +57,13 @@ namespace BackendWorkerService.Quartz.Jobs
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");
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)
@ -102,35 +81,53 @@ namespace BackendWorkerService.Quartz.Jobs
};
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 (!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 = "<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}");
check = "false"; // 關閉
}
if (!string.IsNullOrEmpty(check))
{
bool requestSuccess = await UpdatedNiagara(oneSchedule, check);
}
}
await task_Detail.InsertWorkTime_End("LightScheduleJob", "light_schedule");
}
catch (Exception ex)
@ -146,52 +143,279 @@ namespace BackendWorkerService.Quartz.Jobs
logger.LogError("【LightScheduleJob】【任務失敗】[Exception]{0}", exception.ToString());
}
}
public async void UpdatedNiagara(Schedule oneSchedule, string check)
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");
// 取得排程所對應的設備號碼列表
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();
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();
// 處理設備號碼分解到URL中
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 = "";
var uri = $"{url}obix/config/Arena/{d[0]}/{d[1]}/{d[2]}/{d[3]}/{deviceNum}/SSC/set";
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}");
}
// 構建要發送的實體資料
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】" + "UpdatedNiagaraFail:" + ex.ToString());
throw 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;
// }
//}
}
}

View File

@ -95,79 +95,33 @@ namespace BackendWorkerService.Quartz.Jobs
if (spaceResponseResult != null && spaceResponseResult.Code == "20000")
{
List<string> batchRequests = new List<string>(); // 用來存儲批次請求的列表
foreach (var area in spaceResponseResult.Payload.Areas)
{
//找出對定的設備代碼
var selectedMapping = parkingSapceMapping.Where(x => x.System_key == area.Name).FirstOrDefault();
// 找出對應的設備代碼
var selectedMapping = parkingSapceMapping.FirstOrDefault(x => x.System_key == area.Name);
if (selectedMapping != null)
{
item = area.Name;
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>();
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 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}' />";
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();
batchRequests.Add($"<uri is='obix:Invoke' val='{requestUri}'>" +
$"<real name='in' val='{area.Remain}' />" +
$"</uri>");
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);
}
}
}
}
// 進行日誌記錄
logger.LogInformation("【ParkingJob】【停車場剩餘車位】準備更新設備{0},剩餘車位數:{1}", name, area.Remain);
}
else
{
@ -175,11 +129,59 @@ namespace BackendWorkerService.Quartz.Jobs
}
}
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】");
}
@ -233,91 +235,92 @@ namespace BackendWorkerService.Quartz.Jobs
if (equipmentResponseResult != null && equipmentResponseResult.Code == "20000")
{
List<string> batchRequests = new List<string>(); // 用來存儲批次請求的列表
foreach (var equipment in equipmentResponseResult.Payload)
{
//找出對定的設備代碼
var selectedMapping = parkingEquipmentMapping.Where(x => x.System_key == equipment.Id).FirstOrDefault();
// 找出對應的設備代碼
var selectedMapping = parkingEquipmentMapping.FirstOrDefault(x => x.System_key == equipment.Id);
if (selectedMapping != null)
{
item = equipment.Id;
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>();
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);
}
}
var parames = new List<object> { parkingConfig.ApiBase };
parames.AddRange(tagNameSplit.Take(tagNameSplit.Length - 1)); // tag 前 4段
parames.Add(tagName); // 最後一段 完整 tag
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(apiFormat, parames.ToArray()));
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
string requestUri = string.Format(apiFormat, parames.ToArray());
// 構建要發送的實體資料
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);
}
batchRequests.Add($"<uri is='obix:Invoke' val='{requestUri}'>" +
$"<real name='in' val='{equipment.Alive.ToString().ToLower()}' />" +
$"</uri>");
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);
}
}
}
}
// 進行日誌記錄
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】");
}

View File

@ -20,6 +20,7 @@ using BackendWorkerService.Services.Implement;
using RainApi;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace BackendWorkerService.Quartz.Jobs
{
@ -660,44 +661,142 @@ namespace BackendWorkerService.Quartz.Jobs
await task_Detail.WorkFail("WeatherAPI", "api_earthquake", ex.Message.ToString());
}
}
// Niagara批次寫法
if (await task_Detail.GetNeedWorkTask("WeatherAPI", "set_weather"))
{
try
{
await task_Detail.InsertWorkTime("WeatherAPI", "set_weather");
var sql = @$"SELECT
id,
weather_type,
get_value
FROM api_weateher
where id in (select MAX(id) from api_weateher where start_time < NOW() group by weather_type)
order by start_time desc";
id,
weather_type,
get_value
FROM api_weateher
WHERE id IN (
SELECT MAX(id)
FROM api_weateher
WHERE start_time < NOW()
GROUP BY weather_type
)
ORDER BY start_time DESC";
var types = await backendRepository.GetAllAsync<ShowWeather>(sql);
var T = types.Where(a => a.weather_type == "T").FirstOrDefault();
var RbT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value);
UpdatedNiagara("api_weateher", RbT, T.id);
var urlMapping = new Dictionary<string, string>
{
{ "T", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set" },
{ "RH", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set" },
{ "PoP12h", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set" },
{ "Wx", "obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set" }
};
var RH = types.Where(a => a.weather_type == "RH").FirstOrDefault();
var RHT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value);
UpdatedNiagara("api_weateher", RHT, RH.id);
// 建立批次請求
var batchRequests = types
.Where(t => urlMapping.ContainsKey(t.weather_type))
.Select(t => (
url: obixApiConfig.ApiBase + urlMapping[t.weather_type],
value: t.get_value
))
.ToList();
// 呼叫批次請求
var batchResponse = await ProcessBatchRequestAsync(obixApiConfig, batchRequests);
// 解析回應 XML
var batchResponseXml = XDocument.Parse(batchResponse);
var listElement = batchResponseXml.Descendants().FirstOrDefault(e => e.Name.LocalName == "list");
if (listElement == null)
{
throw new Exception("Batch response XML does not contain a 'list' element.");
}
var childElements = listElement.Elements().ToList();
// 使用 urlMapping 的值反向找對應的 weather_type
for (int i = 0; i < childElements.Count; i++)
{
var tag = childElements[i].Name.LocalName;
var responseStr = childElements[i].ToString();
var currentRequest = batchRequests[i];
// 找到當前 URL 在 urlMapping 中的 key (weather_type)
var weatherTypeKey = urlMapping.FirstOrDefault(x => currentRequest.url.Contains(x.Value)).Key;
if (weatherTypeKey != null)
{
var weatherType = types.FirstOrDefault(t => t.weather_type == weatherTypeKey);
if (weatherType != null)
{
if (tag == "err")
{
UpdatedNiagara("api_weateher", responseStr, weatherType.id);
}
else
{
UpdatedNiagara("api_weateher", "success", weatherType.id);
}
}
else
{
logger.LogWarning($"No matching weather type found for key: {weatherTypeKey}");
}
}
else
{
logger.LogWarning($"No matching URL found for request: {currentRequest.url}");
}
}
var PoP12h = types.Where(a => a.weather_type == "PoP12h").FirstOrDefault();
var PoP12hT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value);
UpdatedNiagara("api_weateher", PoP12hT, PoP12h.id);
var Wx = types.Where(a => a.weather_type == "Wx").FirstOrDefault();
var WxT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value);
UpdatedNiagara("api_weateher", WxT, Wx.id);
await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather");
logger.LogInformation($"set niagara weather value success");
logger.LogInformation($"Set Niagara weather value success");
}
catch (Exception ex)
{
logger.LogInformation($"set niagara weather value fail");
await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message.ToString());
logger.LogError($"Set Niagara weather value fail: {ex.Message}");
await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message);
}
}
// Niagara單次寫法
//if (await task_Detail.GetNeedWorkTask("WeatherAPI", "set_weather"))
//{
// try
// {
// await task_Detail.InsertWorkTime("WeatherAPI", "set_weather");
// var sql = @$"SELECT
// id,
// weather_type,
// get_value
// FROM api_weateher
// where id in (select MAX(id) from api_weateher where start_time < NOW() group by weather_type)
// order by start_time desc";
// var types = await backendRepository.GetAllAsync<ShowWeather>(sql);
// var T = types.Where(a => a.weather_type == "T").FirstOrDefault();
// var RbT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value);
// UpdatedNiagara("api_weateher", RbT, T.id);
// var RH = types.Where(a => a.weather_type == "RH").FirstOrDefault();
// var RHT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value);
// UpdatedNiagara("api_weateher", RHT, RH.id);
// var PoP12h = types.Where(a => a.weather_type == "PoP12h").FirstOrDefault();
// var PoP12hT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value);
// UpdatedNiagara("api_weateher", PoP12hT, PoP12h.id);
// var Wx = types.Where(a => a.weather_type == "Wx").FirstOrDefault();
// var WxT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value);
// UpdatedNiagara("api_weateher", WxT, Wx.id);
// await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather");
// logger.LogInformation($"set niagara weather value success");
// }
// catch (Exception ex)
// {
// logger.LogInformation($"set niagara weather value fail");
// await task_Detail.WorkFail("WeatherAPI", "set_weather", ex.Message.ToString());
// }
//}
}
catch (Exception exception)
{
@ -737,6 +836,51 @@ namespace BackendWorkerService.Quartz.Jobs
return rint;
}
public async Task<string> ProcessBatchRequestAsync(ObixApiConfig obixApiConfig, List<(string url, string value)> batchRequests)
{
try
{
var batchRequestData = new StringBuilder();
string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes($"{obixApiConfig.UserName}:{obixApiConfig.Password}"));
// 組合批次請求的資料
foreach (var request in batchRequests)
{
var jsonData = $"<real name='in' val=\"{request.value}\" />";
batchRequestData.AppendLine($"<uri is='obix:Invoke' val='{request.url}'>" + jsonData + "</uri>");
}
// 最終的批次請求資料
var batchRequestXml = $@"<list is='obix:BatchIn'>{batchRequestData}</list>";
// 建立 HTTP 請求
var requestBacth = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/batch");
requestBacth.Method = "POST";
requestBacth.Headers.Add("Authorization", "Basic " + authInfo);
// 寫入請求資料
using (var streamWriter = new StreamWriter(requestBacth.GetRequestStream()))
{
streamWriter.Write(batchRequestXml);
}
// 獲取回應
using (var response = (HttpWebResponse)await requestBacth.GetResponseAsync())
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
return await streamReader.ReadToEndAsync();
}
}
catch (Exception)
{
return "BatchRequestg失敗";
}
}
public async void UpdatedNiagara(string DBTableName, string ResponseStr, int CheckNumId)
{
try