ibms-dome/Backend/Quartz/Jobs/ArchiveElectricMeterHourJob.cs

336 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 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 Backend.Quartz.Jobs
{
/// <summary>
/// 電錶歸檔,每小時執行,只執行小時歸檔
/// </summary>
[DisallowConcurrentExecution]
class ArchiveElectricMeterHourJob : IJob
{
private readonly ILogger<ArchiveElectricMeterHourJob> logger;
private readonly IBackgroundServiceRepository backgroundServiceRepository;
private readonly ILogger<Task_Detail> loggers;
public ArchiveElectricMeterHourJob(
ILogger<ArchiveElectricMeterHourJob> logger,
IBackgroundServiceRepository backgroundServiceRepository, ILogger<Task_Detail> loggers)
{
this.logger = logger;
this.backgroundServiceRepository = backgroundServiceRepository;
this.loggers = loggers;
}
public async Task Execute(IJobExecutionContext context)
{
Task_Detail task_Detail = new Task_Detail(loggers, backgroundServiceRepository);
try
{
if(await task_Detail.GetNeedWorkTask("ArchiveElectricMeterHourJob", "All"))
{
await task_Detail.InsertWorkTime("ArchiveElectricMeterHourJob", "All", "任務開始");
EDFunction ed = new EDFunction();
XmlDocument xmlDocument = new XmlDocument();
var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
var electricMeterGuid = variableArchive.Where(x => x.Name == "ElectricMeterGuid").Select(x => x.Value).FirstOrDefault();
#region
var sWhere = "deleted = 0 AND sub_system_guid = @sub_system_guid";
var electricMeters = await backgroundServiceRepository.GetAllAsync<Device>("device", sWhere, new { sub_system_guid = electricMeterGuid });
#endregion
#region
var sPointWhere = "deleted = 0 AND sub_system_guid = @sub_system_guid";
var points = await backgroundServiceRepository.GetAllAsync<Device_item>("device_item", sPointWhere, new { sub_system_guid = electricMeterGuid });
#endregion
#region
List<DeviceNumberPoint> deviceNumberPoints = new List<DeviceNumberPoint>();
foreach (var electricMeter in electricMeters)
{
foreach (var point in points)
{
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
deviceNumberPoint.DeviceNumber = electricMeter.Device_number;
deviceNumberPoint.Point = point.points;
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", electricMeter.Device_number, point.points);
deviceNumberPoints.Add(deviceNumberPoint);
}
}
#endregion
#region obix
var obixApiConfig = new ObixApiConfig();
var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";
var variableObix = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlObix);
obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));
#endregion obix
var now = DateTime.Now;
#region
try
{
var preHour = now.AddHours(-1); //取得前一小時
var tempHour = string.Empty;
if (preHour.Hour < 10)
{
tempHour = "0" + preHour.Hour.ToString();
}
else
{
tempHour = preHour.Hour.ToString();
}
var startTimestamp = string.Format("{0}T{1}:00:00.000+08:00", preHour.ToString("yyyy-MM-dd"), tempHour);
var endTimestamp = string.Format("{0}T{1}:59:59.000+08:00", preHour.ToString("yyyy-MM-dd"), tempHour);
var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val = 'PT1H' />
</obj>";
//Stopwatch stopWatch = new Stopwatch();
//stopWatch.Start();
//抓取每個設備的資料
List<Dictionary<string, object>> archiveHourRawDatas = new List<Dictionary<string, object>>();
foreach (var deviceNumberPoint in deviceNumberPoints)
{
HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
//HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
archiveHourRequest.Method = "POST";
archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveHourRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveHourRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse();
var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd();
xmlDocument.LoadXml(archiveHourResponseContent);
string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument);
JObject archiveHourJsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson);
if (archiveHourJsonResult.ContainsKey("err")) //抓取錯誤
{
//logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【取得資料失敗】");
//logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【取得資料失敗】[錯誤內容]{0}", archiveHourJsonResult);
Dictionary<string, object> archiveHourRawData = new Dictionary<string, object>();
archiveHourRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveHourRawData.Add("@point", deviceNumberPoint.Point);
archiveHourRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
archiveHourRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
archiveHourRawData.Add("@is_complete", 0);
archiveHourRawData.Add("@repeat_times", 0);
archiveHourRawData.Add("@fail_reason", archiveHourJson);
archiveHourRawDatas.Add(archiveHourRawData);
}
if (archiveHourJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var histories = archiveHourJsonResult["obj"]["list"];
var rawdateCount = Convert.ToInt32(archiveHourJsonResult["obj"]["int"]["@val"].ToString());
if (histories != null && histories.HasValues)
{
if (rawdateCount > 1)
{ //多筆資料
foreach (var history in histories)
{
Dictionary<string, object> archiveHourRawData = new Dictionary<string, object>();
archiveHourRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveHourRawData.Add("@point", deviceNumberPoint.Point);
//時間
if (history["abstime"] != null && history["abstime"].HasValues)
{
foreach (var abstime in history["abstime"])
{
var name = abstime["@name"].ToString();
switch (name)
{
case "start":
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
archiveHourRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
archiveHourRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (history["int"] != null && history["int"].HasValues)
{
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
archiveHourRawData.Add("@count_rawdata", count);
}
//整合數值(最大、最小、平均、總和)
if (history["real"] != null && history["real"].HasValues)
{
foreach (var real in history["real"])
{
var name = real["@name"].ToString();
switch (name)
{
case "min":
var min = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@min_rawdata", min);
break;
case "max":
var max = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@sum_rawdata", sum);
break;
}
}
}
archiveHourRawData.Add("@is_complete", 1);
archiveHourRawDatas.Add(archiveHourRawData);
}
}
else
{ //單筆資料
Dictionary<string, object> archiveHourRawData = new Dictionary<string, object>();
archiveHourRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveHourRawData.Add("@point", deviceNumberPoint.Point);
//時間
if (histories["obj"]["abstime"] != null && histories["obj"]["abstime"].HasValues)
{
foreach (var abstime in histories["obj"]["abstime"])
{
var name = abstime["@name"].ToString();
switch (name)
{
case "start":
var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
archiveHourRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
archiveHourRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
{
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
archiveHourRawData.Add("@count_rawdata", count);
}
//整合數值(最大、最小、平均、總和)
if (histories["obj"]["real"] != null && histories["obj"]["real"].HasValues)
{
foreach (var real in histories["obj"]["real"])
{
var name = real["@name"].ToString();
switch (name)
{
case "min":
var min = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@min_rawdata", min);
break;
case "max":
var max = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = Convert.ToDecimal(real["@val"].ToString());
archiveHourRawData.Add("@sum_rawdata", sum);
break;
}
}
}
archiveHourRawData.Add("@is_complete", 1);
archiveHourRawDatas.Add(archiveHourRawData);
}
}
}
}
//stopWatch.Stop();
//logger.LogInformation("【ArchiveElectricMeterHourJob】【小時歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
if (archiveHourRawDatas.Count() > 0)
{
await backgroundServiceRepository.AddMutiByCustomTable(archiveHourRawDatas, "archive_electric_meter_hour");
}
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterHourJob", "All", "任務完成");
}
catch (Exception exception)
{
await task_Detail.WorkFail("ArchiveElectricMeterHourJob", "All", exception.ToString());
logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【任務失敗】");
logger.LogError("【ArchiveElectricMeterHourJob】【小時歸檔】【任務失敗】[Exception]{0}", exception.ToString());
}
#endregion
}
}
catch (Exception exception)
{
await task_Detail.WorkFail("ArchiveElectricMeterHourJob", "All", exception.ToString());
logger.LogError("【ArchiveElectricMeterHourJob】【任務失敗】");
logger.LogError("【ArchiveElectricMeterHourJob】【任務失敗】[Exception]{0}", exception.ToString());
}
}
}
}