[BGService]新增燈控排程背景程式

[Webapi]搭配燈控排程背景程式進行修改
This commit is contained in:
張家睿 2024-04-30 16:40:48 +08:00
parent 29ee81b469
commit 5b43c7ab63
8 changed files with 238 additions and 14 deletions

View File

@ -17,6 +17,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Backend\Backend.csproj" /> <ProjectReference Include="..\Backend\Backend.csproj" />
<ProjectReference Include="..\FrontendWebApi\FrontendWebApi.csproj" />
<ProjectReference Include="..\Repository\Repository.csproj" /> <ProjectReference Include="..\Repository\Repository.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -19,7 +19,7 @@ using Repository.FrontendRepository.Interface;
using Repository.Helper; using Repository.Helper;
using Repository.Models; using Repository.Models;
using System; using System;
using System.Collections.Generic; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -149,11 +149,20 @@ namespace BackendWorkerService
); );
#endregion #endregion
#region ©w®ÉÀˬd¿O±±±Æµ{
services.AddSingleton< LightScheduleJob>();
services.AddSingleton(
new JobSchedule(jobType: typeof(LightScheduleJob), cronExpression: configuration.GetValue<string>("BackgroundServiceCron:LightScheduleJob "))
);
#endregion
}).ConfigureLogging((hostContext, logFactory) => { }).ConfigureLogging((hostContext, logFactory) => {
IConfiguration configuration = hostContext.Configuration; IConfiguration configuration = hostContext.Configuration;
//logFactory.AddFile("Logs/log-{Date}.txt"); //logFactory.AddFile("Logs/log-{Date}.txt");
logFactory.AddFile(configuration.GetValue<string>("LoggerPath") + "/log-{Date}.txt"); string loggerPath = configuration.GetValue<string>("LoggerPath");
logFactory.AddFile($"{loggerPath}/log-{{Date}}.txt");
}); });
} }
} }

View File

@ -134,8 +134,11 @@ namespace BackendWorkerService.Quartz
{ {
logger.LogInformation($"【Task_Detail】【開始{task},{task_item}任務】"); logger.LogInformation($"【Task_Detail】【開始{task},{task_item}任務】");
} }
else
{
logger.LogInformation($"【Task_Detail】【{LoggerWord}】"); logger.LogInformation($"【Task_Detail】【{LoggerWord}】");
} }
}
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError("【Task_Detail】【任務輸入開始時間】[Exception]{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item); logger.LogError("【Task_Detail】【任務輸入開始時間】[Exception]{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item);
@ -162,8 +165,11 @@ namespace BackendWorkerService.Quartz
{ {
logger.LogInformation($"【Task_Detail】【結束{task},{task_item}任務】"); logger.LogInformation($"【Task_Detail】【結束{task},{task_item}任務】");
} }
else
{
logger.LogInformation($"【Task_Detail】【{LoggerWord}】"); logger.LogInformation($"【Task_Detail】【{LoggerWord}】");
} }
}
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError("【Task_Detail】【任務輸入結束時間】[Exception]{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item); logger.LogError("【Task_Detail】【任務輸入結束時間】[Exception]{0},Task:{1},task_item:{2}", exception.ToString(), task, task_item);

View File

@ -0,0 +1,194 @@
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;
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");
#region
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}");
}
}
#endregion
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)
{
var d = deviceNum.Split("_");
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

@ -15,6 +15,7 @@
"ParkingJob": "0/5 * * * * ?", "ParkingJob": "0/5 * * * * ?",
"ArchiveElectricMeterHourJob": "0 0 2 * * ?", "ArchiveElectricMeterHourJob": "0 0 2 * * ?",
"ArchiveElectricMeterDayJob": "0/5 * * * * ?", "ArchiveElectricMeterDayJob": "0/5 * * * * ?",
"LightScheduleJob ": "0/5 * * * * ?",
"WeatherAPIJob": "0/5 * * * * ?" "WeatherAPIJob": "0/5 * * * * ?"
}, },
"DBConfig": { "DBConfig": {

View File

@ -16,6 +16,7 @@
//"ParkingJob": "0 0 2 * * ?", //"ParkingJob": "0 0 2 * * ?",
"ArchiveElectricMeterHourJob": "0 0 2 * * ?", "ArchiveElectricMeterHourJob": "0 0 2 * * ?",
"ArchiveElectricMeterDayJob": "0/5 * * * * ?", "ArchiveElectricMeterDayJob": "0/5 * * * * ?",
"LightScheduleJob ": "0 0/1 * * * ?",
"WeatherAPIJob": "0 0 2 * * ?" "WeatherAPIJob": "0 0 2 * * ?"
}, },
"DBConfig": { "DBConfig": {

View File

@ -147,8 +147,12 @@ namespace FrontendWebApi.ApiControllers
{ {
opeInput.action_name = "修改"; opeInput.action_name = "修改";
Dictionary<string, object> Schedule = new Dictionary<string, object>(); Dictionary<string, object> Schedule = new Dictionary<string, object>();
// 配合燈控排程背景程式更新guid(因排程根據guid執行起始結束各一次若中途修改條件則不會執行故作此修改)
var newguid = Guid.NewGuid();
Schedule = new Dictionary<string, object>() Schedule = new Dictionary<string, object>()
{ {
{ "@light_schedule_guid",newguid},
{ "@status", saveSchedule.status}, { "@status", saveSchedule.status},
{ "@full_name", saveSchedule.full_name}, { "@full_name", saveSchedule.full_name},
{ "@week", saveSchedule.week}, { "@week", saveSchedule.week},
@ -198,7 +202,7 @@ namespace FrontendWebApi.ApiControllers
Dictionary<string, object> ScheduleDevice = new Dictionary<string, object>(); Dictionary<string, object> ScheduleDevice = new Dictionary<string, object>();
ScheduleDevice = new Dictionary<string, object>() ScheduleDevice = new Dictionary<string, object>()
{ {
{ "@light_schedule_guid", saveSchedule.light_schedule_guid}, { "@light_schedule_guid", newguid},
{ "@device_guid", a} { "@device_guid", a}
}; };
ScheduleDevices.Add(ScheduleDevice); ScheduleDevices.Add(ScheduleDevice);

View File

@ -30,6 +30,14 @@ namespace FrontendWebApi.Models
public string end_time { get; set; } public string end_time { get; set; }
public byte status { get; set; } public byte status { get; set; }
} }
public class ScheduleLog
{
public int light_schedule_log_id { get; set; }
public string light_schedule_guid { get; set; }
public string date { get; set; }
public string start_time { get; set; }
public string end_time { get; set; }
}
public class SaveSchedule : Schedule public class SaveSchedule : Schedule
{ {
public List<string> devicelist { get; set; } public List<string> devicelist { get; set; }