ibms-dome/BackendWorkerService/Quartz/Jobs/ArchiveElectricMeterDayJob.cs

1918 lines
139 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 BackendWorkerService.Services.Implement;
using Dapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.SS.Formula.Functions;
using Quartz;
using Repository.BackendRepository.Interface;
using Repository.Helper;
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
{
[DisallowConcurrentExecution]
class ArchiveElectricMeterDayJob : IJob
{
private readonly ILogger<ArchiveElectricMeterDayJob> logger;
private readonly IBackgroundServiceRepository backgroundServiceRepository;
private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository;
protected readonly IDatabaseHelper _databaseHelper;
private readonly ILogger<Task_Detail> loggers;
public ArchiveElectricMeterDayJob(
ILogger<ArchiveElectricMeterDayJob> logger,
IBackgroundServiceRepository backgroundServiceRepository,
IBackgroundServiceMsSqlRepository backgroundServiceMySqlRepository,
IDatabaseHelper databaseHelper, ILogger<Task_Detail> loggers, IBackendRepository backendRepository)
{
this.logger = logger;
this.backgroundServiceRepository = backgroundServiceRepository;
this.backgroundServiceMsSqlRepository = backgroundServiceMySqlRepository;
this._databaseHelper = databaseHelper;
this.loggers = loggers;
}
public async Task Execute(IJobExecutionContext context)
{
Task_Detail task_Detail = new Task_Detail(loggers, backgroundServiceRepository);
string device_number = string.Empty;
try
{
if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "All"))
{
await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "All", "任務開始");
EDFunction ed = new EDFunction();
XmlDocument xmlDocument = new XmlDocument();
ServicePointManager.DefaultConnectionLimit = 10;
var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";
var saveToMSDB = await backgroundServiceRepository.GetOneAsync<string>("select system_value from variable where system_type = 'save_to_ms_db' and deleted = 0");
var variableArchive = await backgroundServiceRepository.GetAllAsync<KeyValue>(sqlArchive);
var electricMeterGuid = variableArchive.Where(x => x.Name == "ElectricMeterGuid").Select(x => x.Value).FirstOrDefault();
var waterMeterGuid = variableArchive.Where(x => x.Name == "WaterMeterGuid").Select(x => x.Value).FirstOrDefault();
string station = string.Empty;
string tagQuantity = await backgroundServiceRepository.GetOneAsync<string>("select system_value from variable where system_type = 'obixConfig' and system_key = 'tag_quantity' and deleted = 0;");
#region http variable
HttpWebRequest archiveRequest = null;
HttpWebResponse archiveResponse = null;
string archiveResponseContent = null;
string archiveJson = null;
JObject archiveJsonResult = new JObject();
#endregion
#region
var sWhere = "deleted = 0 AND device_name_tag = @sub_system_guid";
var electricMeters = await backgroundServiceRepository.GetAllAsync<Device>("device", sWhere, new { sub_system_guid = electricMeterGuid });
var waterMeters = await backgroundServiceRepository.GetAllAsync<Device>("device", sWhere, new { sub_system_guid = waterMeterGuid });
#endregion
#region
var sPointWhere = "is_needArchive = 1 and deleted = 0 AND device_name_tag = @sub_system_guid";
var electricPoints = await backgroundServiceRepository.GetAllAsync<Device_item>("device_item", sPointWhere, new { sub_system_guid = electricMeterGuid });
var waterPoints = await backgroundServiceRepository.GetAllAsync<Device_item>("device_item", sPointWhere, new { sub_system_guid = waterMeterGuid });
#endregion
#region
List<DeviceNumberPoint> electricDeviceNumberPoints = new List<DeviceNumberPoint>();
foreach (var electricMeter in electricMeters)
{
foreach (var point in electricPoints)
{
if (electricMeter.device_building_tag == point.device_building_tag)
{
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
deviceNumberPoint.DeviceNumber = electricMeter.Device_number;
deviceNumberPoint.Point = point.points;
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", electricMeter.Device_number, point.points);
deviceNumberPoint.archive_lastDate = electricMeter.archive_lastDate;
deviceNumberPoint.created_at = Convert.ToDateTime(electricMeter.Created_at);
electricDeviceNumberPoints.Add(deviceNumberPoint);
}
}
}
#endregion
#region
List<DeviceNumberPoint> waterDeviceNumberPoints = new List<DeviceNumberPoint>();
foreach (var waterMeter in waterMeters)
{
foreach (var point in waterPoints)
{
if (waterMeter.device_building_tag == point.device_building_tag)
{
DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
deviceNumberPoint.DeviceNumber = waterMeter.Device_number;
deviceNumberPoint.Point = point.points;
deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", waterMeter.Device_number, point.points);
deviceNumberPoint.archive_lastDate = waterMeter.archive_lastDate;
deviceNumberPoint.created_at = Convert.ToDateTime(waterMeter.Created_at);
waterDeviceNumberPoints.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
if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Day"))
{
try
{
await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Day", "水電表天任務開始");
var preDay = now.AddDays(-1); //取得前一天
var dbDateName = preDay.Year.ToString().PadLeft(4, '0') + preDay.Month.ToString().PadLeft(2, '0');
//var startTimestamp = string.Format("{0}T00:00:00.000+08:00", preDay.ToString("yyyy-MM-dd"));
//var endTimestamp = string.Format("{0}T23:59:59.000+08:00", preDay.ToString("yyyy-MM-dd"));
//var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
// <abstime name='start' val='{startTimestamp}' />
// <abstime name='end' val='{endTimestamp}' />
// <reltime name='interval' val = 'PT1D' />
// </obj>";
//Stopwatch stopWatch = new Stopwatch();
//stopWatch.Start();
#region
//抓取每個設備的資料
List<Dictionary<string, object>> electericArchiveDayRawDatas = new List<Dictionary<string, object>>();
List<Dictionary<string, object>> waterArchiveDayRawDatas = new List<Dictionary<string, object>>();
foreach (var deviceNumberPoint in electricDeviceNumberPoints)
{
var startDay = deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd");
var endDay = System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
if (startDay == "0001-01-01") // 假設archive_lastDate為null
{
startDay = deviceNumberPoint.created_at.ToString("yyyy-MM-dd");
}
foreach (DateTime day in EachDay(startDay, endDay))
{
var sDay = string.Format("{0}T00:00:00.000+08:00", day.ToString("yyyy-MM-dd").Replace(" ", "T")); // 巨蛋用此時間抓到的實際是T00:15:00的資料
//var sDay = string.Format("{0}T23:59:59.000+08:00", day.AddDays(-1).ToString("yyyy-MM-dd").Replace(" ", "T")); // 巨蛋用此時間抓到的實際是T00:00:00的資料
var eDay = string.Format("{0}T00:15:00.000+08:00", day.AddDays(1).ToString("yyyy-MM-dd").Replace(" ", "T"));
string historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{sDay}' />
<abstime name='end' val='{eDay}' />
<reltime name='interval' val = 'PT2D' />
</obj>";
device_number = deviceNumberPoint.FullDeviceNumberPoint;
if (tagQuantity.Equals("5"))
station = await backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[0]}' and device_floor_tag = '{device_number.Split("_")[2]}'
and device_name_tag = '{device_number.Split("_")[1]}' and device_point_name = '{device_number.Split("_")[5]}'");
else
station = backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{device_number.Split("_")[2]}' and device_name_tag = '{device_number.Split("_")[3]}'
and device_floor_tag = '{device_number.Split("_")[4]}' and device_master_tag = '{device_number.Split("_")[5]}'
and device_last_name_tag = '{device_number.Split("_")[6]}' and device_serial_tag = '{device_number.Split("_")[7]}'
and device_point_name = '{device_number.Split("_")[8]}'").Result;
archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
//HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
archiveRequest.Method = "POST";
archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
archiveResponse.Dispose();
archiveResponse.Close();
xmlDocument.LoadXml(archiveResponseContent);
archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
if (archiveJsonResult.ContainsKey("err")) //抓取錯誤
{
//logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】");
//logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】[錯誤內容]{0}", archiveDayJsonResult);
Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
archiveDayRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveDayRawData.Add("@point", deviceNumberPoint.Point);
archiveDayRawData.Add("@start_timestamp", sDay.Replace("T", " ").Substring(0, 19));
archiveDayRawData.Add("@end_timestamp", eDay.Replace("T", " ").Substring(0, 19));
archiveDayRawData.Add("@is_complete", 0);
archiveDayRawData.Add("@repeat_times", 0);
archiveDayRawData.Add("@fail_reason", archiveJson);
archiveDayRawData.Add("@count_rawdata", 0);
archiveDayRawData.Add("@min_rawdata", 0);
archiveDayRawData.Add("@max_rawdata", 0);
archiveDayRawData.Add("@avg_rawdata", 0);
archiveDayRawData.Add("@sum_rawdata", 0);
archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
electericArchiveDayRawDatas.Add(archiveDayRawData);
}
if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult);
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
{
electericArchiveDayRawDatas.AddRange(ArrangeRawDatas);
}
}
}
}
foreach (var deviceNumberPoint in waterDeviceNumberPoints)
{
var startDay = deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd");
var endDay = System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
if (startDay == "0001-01-01") // 假設archive_lastDate為null
{
startDay = deviceNumberPoint.created_at.ToString("yyyy-MM-dd");
}
foreach (DateTime day in EachDay(startDay, endDay))
{
var sDay = string.Format("{0}T00:00:00.000+08:00", day.ToString("yyyy-MM-dd").Replace(" ", "T")); // 巨蛋用此時間抓到的實際是T00:15:00的資料
//var sDay = string.Format("{0}T23:59:59.000+08:00", day.AddDays(-1).ToString("yyyy-MM-dd").Replace(" ", "T")); // 巨蛋用此時間抓到的實際是T00:00:00的資料
var eDay = string.Format("{0}T00:15:00.000+08:00", day.AddDays(1).ToString("yyyy-MM-dd").Replace(" ", "T"));
string historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{sDay}' />
<abstime name='end' val='{eDay}' />
<reltime name='interval' val = 'PT2D' />
</obj>";
device_number = deviceNumberPoint.FullDeviceNumberPoint;
if (tagQuantity.Equals("5"))
station = await backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[0]}' and device_floor_tag = '{device_number.Split("_")[2]}'
and device_name_tag = '{device_number.Split("_")[1]}' and device_point_name = '{device_number.Split("_")[5]}'");
else
station = backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{device_number.Split("_")[2]}' and device_name_tag = '{device_number.Split("_")[3]}'
and device_floor_tag = '{device_number.Split("_")[4]}' and device_master_tag = '{device_number.Split("_")[5]}'
and device_last_name_tag = '{device_number.Split("_")[6]}' and device_serial_tag = '{device_number.Split("_")[7]}'
and device_point_name = '{device_number.Split("_")[8]}'").Result;
archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
//HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
archiveRequest.Method = "POST";
archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
archiveResponse.Dispose();
archiveResponse.Close();
xmlDocument.LoadXml(archiveResponseContent);
archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
if (archiveJsonResult.ContainsKey("err")) //抓取錯誤
{
//logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】");
//logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】[錯誤內容]{0}", archiveDayJsonResult);
Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
archiveDayRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveDayRawData.Add("@point", deviceNumberPoint.Point);
archiveDayRawData.Add("@start_timestamp", sDay.Replace("T", " ").Substring(0, 19));
archiveDayRawData.Add("@end_timestamp", eDay.Replace("T", " ").Substring(0, 19));
archiveDayRawData.Add("@is_complete", 0);
archiveDayRawData.Add("@repeat_times", 0);
archiveDayRawData.Add("@fail_reason", archiveJson);
archiveDayRawData.Add("@count_rawdata", 0);
archiveDayRawData.Add("@min_rawdata", 0);
archiveDayRawData.Add("@max_rawdata", 0);
archiveDayRawData.Add("@avg_rawdata", 0);
archiveDayRawData.Add("@sum_rawdata", 0);
archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
waterArchiveDayRawDatas.Add(archiveDayRawData);
}
if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult);
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
{
waterArchiveDayRawDatas.AddRange(ArrangeRawDatas);
}
}
}
}
#endregion
//stopWatch.Stop();
//logger.LogInformation("【ArchiveElectricMeterDayJob】【天歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
if (electericArchiveDayRawDatas.Count() > 0)
{
foreach (var row in electericArchiveDayRawDatas)
{
row.TryGetValue("@start_timestamp", out var yyyymmData);
dbDateName = System.DateTime.Parse(yyyymmData.ToString()).ToString("yyyyMM");
var sql = $@"CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_day_{dbDateName}` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
`min_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`max_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sub_result` decimal(15, 3) NULL DEFAULT NULL,
`avg_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '是否完成0:未完成 1:完成',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '重複次數',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '失敗原因',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
UPDATE archive_electric_water_meter_day_{dbDateName} SET
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
INSERT INTO archive_electric_water_meter_day_{dbDateName} (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
SELECT
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason
WHERE ROW_COUNT() = 0;
update device set archive_lastDate = @start_timestamp, archive_lastActionDate = @updated_at
where device_number = @device_number;"; //archive_lastDate 前次完成時間 archive_lastActionDate 本次作業時間
var mySql = $@"BEGIN TRANSACTION;
IF OBJECT_ID(N'dbo.archive_electric_water_meter_day_{dbDateName}', N'U') is null
BEGIN
CREATE TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}](
[device_number] [varchar](50) NOT NULL,
[point] [varchar](20) NOT NULL,
[start_timestamp] [datetime] NOT NULL,
[end_timestamp] [datetime] NULL,
[count_rawdata] [int] NULL,
[min_rawdata] [decimal](15, 3) NULL,
[max_rawdata] [decimal](15, 3) NULL,
[sub_result] [decimal](15, 3) NULL,
[avg_rawdata] [decimal](15, 3) NULL,
[sum_rawdata] [decimal](15, 3) NULL,
[is_complete] [tinyint] NULL,
[repeat_times] [int] NULL,
[fail_reason] [nvarchar](max) NULL,
[created_at] [datetime] NULL,
[updated_at] [datetime] NULL,
CONSTRAINT [PK_archive_electric_water_meter_day_{dbDateName}] PRIMARY KEY CLUSTERED
(
[device_number] ASC,
[point] ASC,
[start_timestamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_water_meter_day_{dbDateName}_repeat_times] DEFAULT ((0)) FOR [repeat_times]
ALTER TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_water_meter_day_{dbDateName}_created_at] DEFAULT (getdate()) FOR [created_at]
ALTER TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_water_meter_day_{dbDateName}_updated_at] DEFAULT (NULL) FOR [updated_at]
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否完成0:未完成 1:完成' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'is_complete'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重複次數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'repeat_times'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'失敗原因' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'fail_reason'
END
UPDATE archive_electric_water_meter_day_{dbDateName} SET
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO archive_electric_water_meter_day_{dbDateName} (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
VALUES (
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason)
END
COMMIT TRANSACTION;";
await backgroundServiceRepository.ExecuteSql(sql, row);
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
{
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, row);
}
}
}
if (waterArchiveDayRawDatas.Count() > 0)
{
foreach (var row in waterArchiveDayRawDatas)
{
row.TryGetValue("@start_timestamp", out var yyyymmData);
dbDateName = System.DateTime.Parse(yyyymmData.ToString()).ToString("yyyyMM");
var sql = $@"
CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_day_{dbDateName}` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
`min_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`max_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sub_result` decimal(15, 3) NULL DEFAULT NULL,
`avg_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '是否完成0:未完成 1:完成',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '重複次數',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '失敗原因',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
UPDATE archive_electric_water_meter_day_{dbDateName} SET
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
INSERT INTO archive_electric_water_meter_day_{dbDateName} (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
SELECT
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason
WHERE ROW_COUNT() = 0;
update device set archive_lastDate = @start_timestamp, archive_lastActionDate = @updated_at
where device_number = @device_number;"; //archive_lastDate 前次完成時間 archive_lastActionDate 本次作業時間
var mySql = $@"BEGIN TRANSACTION;
IF OBJECT_ID(N'dbo.archive_electric_water_meter_day_{dbDateName}', N'U') is null
BEGIN
CREATE TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}](
[device_number] [varchar](50) NOT NULL,
[point] [varchar](20) NOT NULL,
[start_timestamp] [datetime] NOT NULL,
[end_timestamp] [datetime] NULL,
[count_rawdata] [int] NULL,
[min_rawdata] [decimal](15, 3) NULL,
[max_rawdata] [decimal](15, 3) NULL,
[sub_result] [decimal](15, 3) NULL,
[avg_rawdata] [decimal](15, 3) NULL,
[sum_rawdata] [decimal](15, 3) NULL,
[is_complete] [tinyint] NULL,
[repeat_times] [int] NULL,
[fail_reason] [nvarchar](max) NULL,
[created_at] [datetime] NULL,
[updated_at] [datetime] NULL,
CONSTRAINT [PK_archive_electric_water_meter_day_{dbDateName}] PRIMARY KEY CLUSTERED
(
[device_number] ASC,
[point] ASC,
[start_timestamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_water_meter_day_{dbDateName}_repeat_times] DEFAULT ((0)) FOR [repeat_times]
ALTER TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_water_meter_day_{dbDateName}_created_at] DEFAULT (getdate()) FOR [created_at]
ALTER TABLE [dbo].[archive_electric_water_meter_day_{dbDateName}] ADD CONSTRAINT [DF_archive_electric_water_meter_day_{dbDateName}_updated_at] DEFAULT (NULL) FOR [updated_at]
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否完成0:未完成 1:完成' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'is_complete'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重複次數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'repeat_times'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'失敗原因' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_day_{dbDateName}', @level2type=N'COLUMN',@level2name=N'fail_reason'
END
UPDATE archive_electric_water_meter_day_{dbDateName} SET
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO archive_electric_water_meter_day_{dbDateName} (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
VALUES (
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason)
END
COMMIT TRANSACTION;";
await backgroundServiceRepository.ExecuteSql(sql, row);
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
{
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, row);
}
}
}
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Day", "水電表天任務完成");
}
catch (Exception exception)
{
await task_Detail.WorkFail("ArchiveElectricMeterDayJob", "Day", exception.ToString());
logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【任務失敗】");
logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【任務失敗】[Exception]{0}, {1}", exception.ToString(), "device_number = " + device_number);
logger.LogError(await backgroundServiceMsSqlRepository.GetDbAllString());
}
finally
{
if (archiveResponse != null)
{
archiveResponse.Dispose();
archiveResponse.Close();
}
}
}
#endregion
#region
//if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Week"))
//{
// try
// {
// await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Week", "水電表周任務開始");
// int week = Convert.ToInt32(now.DayOfWeek);
// week = week == 0 ? 7 : week;
// var startTimestamp = string.Format("{0}T00:00:00.000+08:00", now.AddDays(1 - week).ToString("yyyy-MM-dd"));
// var endTimestamp = string.Format("{0}T23:59:59.000+08:00", now.AddDays(7 - week).ToString("yyyy-MM-dd"));
// var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
// <abstime name='start' val='{startTimestamp}' />
// <abstime name='end' val='{endTimestamp}' />
// <reltime name='interval' val = 'PT7D' />
// </obj>";
// //Stopwatch stopWatch = new Stopwatch();
// //stopWatch.Start();
// //抓取每個設備的資料
// List<Dictionary<string, object>> electricArchiveWeekRawDatas = new List<Dictionary<string, object>>();
// List<Dictionary<string, object>> waterArchiveWeekRawDatas = new List<Dictionary<string, object>>();
// foreach (var deviceNumberPoint in electricDeviceNumberPoints)
// {
// if (tagQuantity.Equals("5"))
// station = await backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
// where device_building_tag = '{device_number.Split("_")[0]}' and device_floor_tag = '{device_number.Split("_")[2]}'
// and device_name_tag = '{device_number.Split("_")[1]}' and device_point_name = '{device_number.Split("_")[5]}'");
// else
// station = backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
// where device_building_tag = '{device_number.Split("_")[1].Replace("$3", "")}' and
// device_system_tag = '{device_number.Split("_")[2]}' and device_name_tag = '{device_number.Split("_")[3]}'
// and device_floor_tag = '{device_number.Split("_")[4]}' and device_master_tag = '{device_number.Split("_")[5]}'
// and device_last_name_tag = '{device_number.Split("_")[6]}' and device_serial_tag = '{device_number.Split("_")[7]}'
// and device_point_name = '{device_number.Split("_")[8]}'").Result;
// device_number = deviceNumberPoint.FullDeviceNumberPoint;
// archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
// //HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
// archiveRequest.Method = "POST";
// archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
// archiveRequest.PreAuthenticate = true;
// byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
// using (Stream reqStream = archiveRequest.GetRequestStream())
// {
// reqStream.Write(byteArray, 0, byteArray.Length);
// }
// archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
// archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
// archiveResponse.Dispose();
// archiveResponse.Close();
// xmlDocument.LoadXml(archiveResponseContent);
// archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
// archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
// if (archiveJsonResult.ContainsKey("err")) //抓取錯誤
// {
// //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】");
// //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】[錯誤內容]{0}", archiveWeekJsonResult);
// Dictionary<string, object> archiveWeekRawData = new Dictionary<string, object>();
// archiveWeekRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
// archiveWeekRawData.Add("@point", deviceNumberPoint.Point);
// archiveWeekRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
// archiveWeekRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
// archiveWeekRawData.Add("@is_complete", 0);
// archiveWeekRawData.Add("@repeat_times", 0);
// archiveWeekRawData.Add("@fail_reason", archiveJson);
// archiveWeekRawData.Add("@count_rawdata", 0);
// archiveWeekRawData.Add("@min_rawdata", 0);
// archiveWeekRawData.Add("@max_rawdata", 0);
// archiveWeekRawData.Add("@avg_rawdata", 0);
// archiveWeekRawData.Add("@sum_rawdata", 0);
// archiveWeekRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
// electricArchiveWeekRawDatas.Add(archiveWeekRawData);
// }
// if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容
// {
// var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult);
// if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
// {
// electricArchiveWeekRawDatas.AddRange(ArrangeRawDatas);
// }
// }
// }
// foreach (var deviceNumberPoint in waterDeviceNumberPoints)
// {
// device_number = deviceNumberPoint.FullDeviceNumberPoint;
// if (tagQuantity.Equals("5"))
// station = await backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
// where device_building_tag = '{device_number.Split("_")[0]}' and device_floor_tag = '{device_number.Split("_")[2]}'
// and device_name_tag = '{device_number.Split("_")[1]}' and device_point_name = '{device_number.Split("_")[5]}'");
// else
// station = backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
// where device_building_tag = '{device_number.Split("_")[1].Replace("$3", "")}' and
// device_system_tag = '{device_number.Split("_")[2]}' and device_name_tag = '{device_number.Split("_")[3]}'
// and device_floor_tag = '{device_number.Split("_")[4]}' and device_master_tag = '{device_number.Split("_")[5]}'
// and device_last_name_tag = '{device_number.Split("_")[6]}' and device_serial_tag = '{device_number.Split("_")[7]}'
// and device_point_name = '{device_number.Split("_")[8]}'").Result;
// archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
// //HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
// archiveRequest.Method = "POST";
// archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
// archiveRequest.PreAuthenticate = true;
// byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
// using (Stream reqStream = archiveRequest.GetRequestStream())
// {
// reqStream.Write(byteArray, 0, byteArray.Length);
// }
// archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
// archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
// archiveResponse.Dispose();
// archiveResponse.Close();
// xmlDocument.LoadXml(archiveResponseContent);
// archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
// archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
// if (archiveJsonResult.ContainsKey("err")) //抓取錯誤
// {
// //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】");
// //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】[錯誤內容]{0}", archiveWeekJsonResult);
// Dictionary<string, object> archiveWeekRawData = new Dictionary<string, object>();
// archiveWeekRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
// archiveWeekRawData.Add("@point", deviceNumberPoint.Point);
// archiveWeekRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
// archiveWeekRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
// archiveWeekRawData.Add("@is_complete", 0);
// archiveWeekRawData.Add("@repeat_times", 0);
// archiveWeekRawData.Add("@fail_reason", archiveJson);
// archiveWeekRawData.Add("@count_rawdata", 0);
// archiveWeekRawData.Add("@min_rawdata", 0);
// archiveWeekRawData.Add("@max_rawdata", 0);
// archiveWeekRawData.Add("@avg_rawdata", 0);
// archiveWeekRawData.Add("@sum_rawdata", 0);
// archiveWeekRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
// waterArchiveWeekRawDatas.Add(archiveWeekRawData);
// }
// if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容
// {
// var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult);
// if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
// {
// waterArchiveWeekRawDatas.AddRange(ArrangeRawDatas);
// }
// }
// }
// //stopWatch.Stop();
// //logger.LogInformation("【ArchiveElectricMeterDayJob】【週歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
// if (electricArchiveWeekRawDatas.Count() > 0)
// {
// var sql = $@"
// UPDATE archive_electric_water_meter_week SET
// count_rawdata = @count_rawdata,
// min_rawdata = @min_rawdata,
// max_rawdata = @max_rawdata,
// sub_result = @max_rawdata - @min_rawdata,
// avg_rawdata = @avg_rawdata,
// sum_rawdata = @sum_rawdata,
// is_complete = @is_complete,
// repeat_times = @repeat_times,
// fail_reason = @fail_reason,
// updated_at = @updated_at
// WHERE device_number = @device_number
// AND point = @point
// AND start_timestamp = @start_timestamp;
// INSERT INTO archive_electric_water_meter_week (
// device_number,
// point,
// start_timestamp,
// end_timestamp,
// count_rawdata,
// min_rawdata,
// max_rawdata,
// sub_result,
// avg_rawdata,
// sum_rawdata,
// is_complete,
// repeat_times,
// fail_reason)
// SELECT
// @device_number,
// @point,
// @start_timestamp,
// @end_timestamp,
// @count_rawdata,
// @min_rawdata,
// @max_rawdata,
// @max_rawdata - @min_rawdata,
// @avg_rawdata,
// @sum_rawdata,
// @is_complete,
// @repeat_times,
// @fail_reason
// WHERE ROW_COUNT() = 0;
// ";
// var mySql = $@"BEGIN TRANSACTION;
// UPDATE archive_electric_water_meter_week SET
// count_rawdata = @count_rawdata,
// min_rawdata = @min_rawdata,
// max_rawdata = @max_rawdata,
// sub_result = @max_rawdata - @min_rawdata,
// avg_rawdata = @avg_rawdata,
// sum_rawdata = @sum_rawdata,
// is_complete = @is_complete,
// repeat_times = @repeat_times,
// fail_reason = @fail_reason,
// updated_at = @updated_at
// WHERE device_number = @device_number
// AND point = @point
// AND start_timestamp = @start_timestamp;
// IF @@ROWCOUNT = 0
// BEGIN
// INSERT INTO archive_electric_water_meter_week (
// device_number,
// point,
// start_timestamp,
// end_timestamp,
// count_rawdata,
// min_rawdata,
// max_rawdata,
// sub_result,
// avg_rawdata,
// sum_rawdata,
// is_complete,
// repeat_times,
// fail_reason)
// VALUES (
// @device_number,
// @point,
// @start_timestamp,
// @end_timestamp,
// @count_rawdata,
// @min_rawdata,
// @max_rawdata,
// @max_rawdata - @min_rawdata,
// @avg_rawdata,
// @sum_rawdata,
// @is_complete,
// @repeat_times,
// @fail_reason)
// END
// COMMIT TRANSACTION;";
// await backgroundServiceRepository.ExecuteSql(sql, electricArchiveWeekRawDatas);
// if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
// {
// await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveWeekRawDatas);
// }
// }
// if (waterArchiveWeekRawDatas.Count() > 0)
// {
// var sql = $@"
// UPDATE archive_electric_water_meter_week SET
// count_rawdata = @count_rawdata,
// min_rawdata = @min_rawdata,
// max_rawdata = @max_rawdata,
// sub_result = @max_rawdata - @min_rawdata,
// avg_rawdata = @avg_rawdata,
// sum_rawdata = @sum_rawdata,
// is_complete = @is_complete,
// repeat_times = @repeat_times,
// fail_reason = @fail_reason,
// updated_at = @updated_at
// WHERE device_number = @device_number
// AND point = @point
// AND start_timestamp = @start_timestamp;
// INSERT INTO archive_electric_water_meter_week (
// device_number,
// point,
// start_timestamp,
// end_timestamp,
// count_rawdata,
// min_rawdata,
// max_rawdata,
// sub_result,
// avg_rawdata,
// sum_rawdata,
// is_complete,
// repeat_times,
// fail_reason)
// SELECT
// @device_number,
// @point,
// @start_timestamp,
// @end_timestamp,
// @count_rawdata,
// @min_rawdata,
// @max_rawdata,
// @max_rawdata - @min_rawdata,
// @avg_rawdata,
// @sum_rawdata,
// @is_complete,
// @repeat_times,
// @fail_reason
// WHERE ROW_COUNT() = 0;
// ";
// var mySql = $@"BEGIN TRANSACTION;
// UPDATE archive_electric_water_meter_week SET
// count_rawdata = @count_rawdata,
// min_rawdata = @min_rawdata,
// max_rawdata = @max_rawdata,
// sub_result = @max_rawdata - @min_rawdata,
// avg_rawdata = @avg_rawdata,
// sum_rawdata = @sum_rawdata,
// is_complete = @is_complete,
// repeat_times = @repeat_times,
// fail_reason = @fail_reason,
// updated_at = @updated_at
// WHERE device_number = @device_number
// AND point = @point
// AND start_timestamp = @start_timestamp;
// IF @@ROWCOUNT = 0
// BEGIN
// INSERT INTO archive_electric_water_meter_week (
// device_number,
// point,
// start_timestamp,
// end_timestamp,
// count_rawdata,
// min_rawdata,
// max_rawdata,
// sub_result,
// avg_rawdata,
// sum_rawdata,
// is_complete,
// repeat_times,
// fail_reason)
// VALUES (
// @device_number,
// @point,
// @start_timestamp,
// @end_timestamp,
// @count_rawdata,
// @min_rawdata,
// @max_rawdata,
// @max_rawdata - @min_rawdata,
// @avg_rawdata,
// @sum_rawdata,
// @is_complete,
// @repeat_times,
// @fail_reason)
// END
// COMMIT TRANSACTION;";
// await backgroundServiceRepository.ExecuteSql(sql, waterArchiveWeekRawDatas);
// if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
// {
// await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveWeekRawDatas);
// }
// }
// await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Week", "任務完成");
// }
// catch (Exception exception)
// {
// await task_Detail.WorkFail("ArchiveElectricMeterDayJob", "Week", exception.ToString());
// logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【任務失敗】");
// logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【任務失敗】[Exception]{0}", exception.ToString());
// }
// finally
// {
// if (archiveResponse != null)
// {
// archiveResponse.Dispose();
// archiveResponse.Close();
// }
// }
//}
#endregion
#region
if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Month"))
{
try
{
await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Month", "水電表月任務開始");
string startTimestamp = "";
string endTimestamp = "";
string historyQueryFilter = "";
//Stopwatch stopWatch = new Stopwatch();
//stopWatch.Start();
//抓取每個設備的資料
List<Dictionary<string, object>> electricArchiveMonthRawDatas = new List<Dictionary<string, object>>();
List<Dictionary<string, object>> waterArchiveMonthRawDatas = new List<Dictionary<string, object>>();
foreach (var deviceNumberPoint in electricDeviceNumberPoints)
{
var startDay = deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd");
var endDay = System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
foreach (DateTime month in EachMonth(startDay, endDay))
{
if (month.ToString("yyyy-MM") == System.DateTime.Now.AddDays(-1).ToString("yyyy-MM"))
{
var preDay = now.AddDays(-1); //取得前一天
var dayInMonth = DateTime.DaysInMonth(preDay.Year, preDay.Month);
var FirstDay = new DateTime(preDay.Year, preDay.Month, 1);
//var LastDay = now.AddMonths(1).AddDays(-now.AddMonths(1).Day); // 這是抓到該月最後一天
var LastDay = now;
//var startTimestamp = string.Format("{0}T23:59:59.000+08:00", FirstDay.AddDays(-1).ToString("yyyy-MM-dd")); // 巨蛋要這樣抓數據才是對的
startTimestamp = string.Format("{0}T00:00:00.000+08:00", FirstDay.ToString("yyyy-MM-dd"));
//var endTimestamp = string.Format("{0}T23:59:59.000+08:00", LastDay.ToString("yyyy-MM-dd"));
endTimestamp = string.Format("{0}T00:15:00.000+08:00", LastDay.ToString("yyyy-MM-dd")); // 240131 jay for dome
historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val = 'PT{dayInMonth + 1}D' />
</obj>";
}
else
{
var dayInMonth = DateTime.DaysInMonth(month.Year, month.Month);
var FirstDay = new DateTime(month.Year, month.Month, 1);
var LastDay = new DateTime(month.Year, month.Month, dayInMonth);
startTimestamp = string.Format("{0}T00:00:00.000+08:00", FirstDay.ToString("yyyy-MM-dd"));
endTimestamp = string.Format("{0}T00:15:00.000+08:00", LastDay.ToString("yyyy-MM-dd"));
historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val = 'PT{dayInMonth + 1}D' />
</obj>";
}
device_number = deviceNumberPoint.FullDeviceNumberPoint;
if (tagQuantity.Equals("5"))
station = await backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[0]}' and device_floor_tag = '{device_number.Split("_")[2]}'
and device_name_tag = '{device_number.Split("_")[1]}' and device_point_name = '{device_number.Split("_")[5]}'");
else
station = backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{device_number.Split("_")[2]}' and device_name_tag = '{device_number.Split("_")[3]}'
and device_floor_tag = '{device_number.Split("_")[4]}' and device_master_tag = '{device_number.Split("_")[5]}'
and device_last_name_tag = '{device_number.Split("_")[6]}' and device_serial_tag = '{device_number.Split("_")[7]}'
and device_point_name = '{device_number.Split("_")[8]}'").Result;
archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
//HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
archiveRequest.Method = "POST";
archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
archiveResponse.Dispose();
archiveResponse.Close();
xmlDocument.LoadXml(archiveResponseContent);
archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
if (archiveJsonResult.ContainsKey("err")) //抓取錯誤
{
//logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】");
//logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】[錯誤內容]{0}", archiveMonthJsonResult);
Dictionary<string, object> archiveMonthRawData = new Dictionary<string, object>();
archiveMonthRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveMonthRawData.Add("@point", deviceNumberPoint.Point);
archiveMonthRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
archiveMonthRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
archiveMonthRawData.Add("@is_complete", 0);
archiveMonthRawData.Add("@repeat_times", 0);
archiveMonthRawData.Add("@fail_reason", archiveJson);
archiveMonthRawData.Add("@count_rawdata", 0);
archiveMonthRawData.Add("@min_rawdata", 0);
archiveMonthRawData.Add("@max_rawdata", 0);
archiveMonthRawData.Add("@avg_rawdata", 0);
archiveMonthRawData.Add("@sum_rawdata", 0);
archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
electricArchiveMonthRawDatas.Add(archiveMonthRawData);
}
if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult);
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
{
electricArchiveMonthRawDatas.AddRange(ArrangeRawDatas);
}
}
}
}
foreach (var deviceNumberPoint in waterDeviceNumberPoints)
{
var startDay = deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd");
var endDay = System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd");
foreach (DateTime day in EachMonth(startDay, endDay))
{
if (day.ToString("yyyy-MM") == System.DateTime.Now.AddDays(-1).ToString("yyyy-MM"))
{
var preDay = now.AddDays(-1); //取得前一天
var dayInMonth = DateTime.DaysInMonth(preDay.Year, preDay.Month);
var FirstDay = new DateTime(preDay.Year, preDay.Month, 1);
//var LastDay = now.AddMonths(1).AddDays(-now.AddMonths(1).Day); // 這是抓到該月最後一天
var LastDay = now;
//var startTimestamp = string.Format("{0}T23:59:59.000+08:00", FirstDay.AddDays(-1).ToString("yyyy-MM-dd")); // 巨蛋要這樣抓數據才是對的
startTimestamp = string.Format("{0}T00:00:00.000+08:00", FirstDay.ToString("yyyy-MM-dd"));
//var endTimestamp = string.Format("{0}T23:59:59.000+08:00", LastDay.ToString("yyyy-MM-dd"));
endTimestamp = string.Format("{0}T00:15:00.000+08:00", LastDay.ToString("yyyy-MM-dd")); // 240131 jay for dome
historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val = 'PT{dayInMonth + 1}D' />
</obj>";
}
else
{
var dayInMonth = DateTime.DaysInMonth(day.Year, day.Month);
var FirstDay = new DateTime(day.Year, day.Month, 1);
var LastDay = new DateTime(day.Year, day.Month, dayInMonth).AddDays(1);
startTimestamp = string.Format("{0}T00:00:00.000+08:00", FirstDay.ToString("yyyy-MM-dd"));
endTimestamp = string.Format("{0}T00:15:00.000+08:00", LastDay.ToString("yyyy-MM-dd"));
historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
<abstime name='start' val='{startTimestamp}' />
<abstime name='end' val='{endTimestamp}' />
<reltime name='interval' val = 'PT{dayInMonth + 1}D' />
</obj>";
}
device_number = deviceNumberPoint.FullDeviceNumberPoint;
if (tagQuantity.Equals("5"))
station = await backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[0]}' and device_floor_tag = '{device_number.Split("_")[2]}'
and device_name_tag = '{device_number.Split("_")[1]}' and device_point_name = '{device_number.Split("_")[5]}'");
else
station = backgroundServiceRepository.GetOneAsync<string>($@"select parent_path from import_niagara_item_history
where device_building_tag = '{device_number.Split("_")[1].Replace("$3", "")}' and
device_system_tag = '{device_number.Split("_")[2]}' and device_name_tag = '{device_number.Split("_")[3]}'
and device_floor_tag = '{device_number.Split("_")[4]}' and device_master_tag = '{device_number.Split("_")[5]}'
and device_last_name_tag = '{device_number.Split("_")[6]}' and device_serial_tag = '{device_number.Split("_")[7]}'
and device_point_name = '{device_number.Split("_")[8]}'").Result;
archiveRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/");
//HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
archiveRequest.Method = "POST";
archiveRequest.Headers.Add("Authorization", "Basic " + encoded);
archiveRequest.PreAuthenticate = true;
byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
using (Stream reqStream = archiveRequest.GetRequestStream())
{
reqStream.Write(byteArray, 0, byteArray.Length);
}
archiveResponse = (HttpWebResponse)archiveRequest.GetResponse();
archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd();
archiveResponse.Dispose();
archiveResponse.Close();
xmlDocument.LoadXml(archiveResponseContent);
archiveJson = JsonConvert.SerializeXmlNode(xmlDocument);
archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson);
if (archiveJsonResult.ContainsKey("err")) //抓取錯誤
{
//logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】");
//logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】[錯誤內容]{0}", archiveMonthJsonResult);
Dictionary<string, object> archiveMonthRawData = new Dictionary<string, object>();
archiveMonthRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
archiveMonthRawData.Add("@point", deviceNumberPoint.Point);
archiveMonthRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19));
archiveMonthRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19));
archiveMonthRawData.Add("@is_complete", 0);
archiveMonthRawData.Add("@repeat_times", 0);
archiveMonthRawData.Add("@fail_reason", archiveJson);
archiveMonthRawData.Add("@count_rawdata", 0);
archiveMonthRawData.Add("@min_rawdata", 0);
archiveMonthRawData.Add("@max_rawdata", 0);
archiveMonthRawData.Add("@avg_rawdata", 0);
archiveMonthRawData.Add("@sum_rawdata", 0);
archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
waterArchiveMonthRawDatas.Add(archiveMonthRawData);
}
if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容
{
var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult);
if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
{
waterArchiveMonthRawDatas.AddRange(ArrangeRawDatas);
}
}
}
}
//stopWatch.Stop();
//logger.LogInformation("【ArchiveElectricMeterDayJob】【月歸檔效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds);
if (electricArchiveMonthRawDatas.Count() > 0)
{
var sql = $@"
CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_month` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
`min_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`max_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sub_result` decimal(15, 3) NULL DEFAULT NULL,
`avg_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '是否完成0:未完成 1:完成',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '重複次數',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '失敗原因',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
UPDATE archive_electric_water_meter_month SET
start_timestamp = @start_timestamp,
end_timestamp = @end_timestamp,
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
INSERT INTO archive_electric_water_meter_month (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
SELECT
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason
WHERE ROW_COUNT() = 0;";
var mySql = $@"BEGIN TRANSACTION;
IF OBJECT_ID(N'dbo.archive_electric_water_meter_month', N'U') is null
BEGIN
CREATE TABLE [dbo].[archive_electric_water_meter_month](
[device_number] [varchar](50) NOT NULL,
[point] [varchar](20) NOT NULL,
[start_timestamp] [datetime] NOT NULL,
[end_timestamp] [datetime] NULL,
[count_rawdata] [int] NULL,
[min_rawdata] [decimal](15, 3) NULL,
[max_rawdata] [decimal](15, 3) NULL,
[sub_result] [decimal](15, 3) NULL,
[avg_rawdata] [decimal](15, 3) NULL,
[sum_rawdata] [decimal](15, 3) NULL,
[is_complete] [tinyint] NULL,
[repeat_times] [int] NULL,
[fail_reason] [nvarchar](max) NULL,
[created_at] [datetime] NULL,
[updated_at] [datetime] NULL,
CONSTRAINT [PK_archive_electric_water_meter_month] PRIMARY KEY CLUSTERED
(
[device_number] ASC,
[point] ASC,
[start_timestamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[archive_electric_water_meter_month] ADD CONSTRAINT [DF_archive_electric_water_meter_month_repeat_times] DEFAULT ((0)) FOR [repeat_times]
ALTER TABLE [dbo].[archive_electric_water_meter_month] ADD CONSTRAINT [DF_archive_electric_water_meter_month_created_at] DEFAULT (getdate()) FOR [created_at]
ALTER TABLE [dbo].[archive_electric_water_meter_month] ADD CONSTRAINT [DF_archive_electric_water_meter_month_updated_at] DEFAULT (NULL) FOR [updated_at]
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否完成0:未完成 1:完成' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_month', @level2type=N'COLUMN',@level2name=N'is_complete'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重複次數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_month', @level2type=N'COLUMN',@level2name=N'repeat_times'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'失敗原因' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_month', @level2type=N'COLUMN',@level2name=N'fail_reason'
END
UPDATE archive_electric_water_meter_month SET
start_timestamp = @start_timestamp,
end_timestamp = @end_timestamp,
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO archive_electric_water_meter_month (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
VALUES (
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason)
END
COMMIT TRANSACTION;";
await backgroundServiceRepository.ExecuteSql(sql, electricArchiveMonthRawDatas);
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
{
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveMonthRawDatas);
}
}
if (waterArchiveMonthRawDatas.Count() > 0)
{
var sql = $@"
CREATE TABLE IF NOT EXISTS `archive_electric_water_meter_month` (
`device_number` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`point` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`start_timestamp` datetime(6) NOT NULL,
`end_timestamp` datetime(6) NULL DEFAULT NULL,
`count_rawdata` int(11) NULL DEFAULT NULL,
`min_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`max_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sub_result` decimal(15, 3) NULL DEFAULT NULL,
`avg_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`sum_rawdata` decimal(15, 3) NULL DEFAULT NULL,
`is_complete` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '是否完成0:未完成 1:完成',
`repeat_times` int(11) NULL DEFAULT 0 COMMENT '重複次數',
`fail_reason` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '失敗原因',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime(6) NULL DEFAULT NULL,
PRIMARY KEY (`device_number`, `point`, `start_timestamp`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
UPDATE archive_electric_water_meter_month SET
start_timestamp = @start_timestamp,
end_timestamp = @end_timestamp,
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
INSERT INTO archive_electric_water_meter_month (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
SELECT
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason
WHERE ROW_COUNT() = 0;";
var mySql = $@"BEGIN TRANSACTION;
IF OBJECT_ID(N'dbo.archive_electric_water_meter_month', N'U') is null
BEGIN
CREATE TABLE [dbo].[archive_electric_water_meter_month](
[device_number] [varchar](50) NOT NULL,
[point] [varchar](20) NOT NULL,
[start_timestamp] [datetime] NOT NULL,
[end_timestamp] [datetime] NULL,
[count_rawdata] [int] NULL,
[min_rawdata] [decimal](15, 3) NULL,
[max_rawdata] [decimal](15, 3) NULL,
[sub_result] [decimal](15, 3) NULL,
[avg_rawdata] [decimal](15, 3) NULL,
[sum_rawdata] [decimal](15, 3) NULL,
[is_complete] [tinyint] NULL,
[repeat_times] [int] NULL,
[fail_reason] [nvarchar](max) NULL,
[created_at] [datetime] NULL,
[updated_at] [datetime] NULL,
CONSTRAINT [PK_archive_electric_water_meter_month] PRIMARY KEY CLUSTERED
(
[device_number] ASC,
[point] ASC,
[start_timestamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[archive_electric_water_meter_month] ADD CONSTRAINT [DF_archive_electric_water_meter_month_repeat_times] DEFAULT ((0)) FOR [repeat_times]
ALTER TABLE [dbo].[archive_electric_water_meter_month] ADD CONSTRAINT [DF_archive_electric_water_meter_month_created_at] DEFAULT (getdate()) FOR [created_at]
ALTER TABLE [dbo].[archive_electric_water_meter_month] ADD CONSTRAINT [DF_archive_electric_water_meter_month_updated_at] DEFAULT (NULL) FOR [updated_at]
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否完成0:未完成 1:完成' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_month', @level2type=N'COLUMN',@level2name=N'is_complete'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重複次數' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_month', @level2type=N'COLUMN',@level2name=N'repeat_times'
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'失敗原因' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'archive_electric_water_meter_month', @level2type=N'COLUMN',@level2name=N'fail_reason'
END
UPDATE archive_electric_water_meter_month SET
start_timestamp = @start_timestamp,
end_timestamp = @end_timestamp,
count_rawdata = @count_rawdata,
min_rawdata = @min_rawdata,
max_rawdata = @max_rawdata,
sub_result = @max_rawdata - @min_rawdata,
avg_rawdata = @avg_rawdata,
sum_rawdata = @sum_rawdata,
is_complete = @is_complete,
repeat_times = @repeat_times,
fail_reason = @fail_reason,
updated_at = @updated_at
WHERE device_number = @device_number
AND point = @point
AND start_timestamp = @start_timestamp;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO archive_electric_water_meter_month (
device_number,
point,
start_timestamp,
end_timestamp,
count_rawdata,
min_rawdata,
max_rawdata,
sub_result,
avg_rawdata,
sum_rawdata,
is_complete,
repeat_times,
fail_reason)
VALUES (
@device_number,
@point,
@start_timestamp,
@end_timestamp,
@count_rawdata,
@min_rawdata,
@max_rawdata,
@max_rawdata - @min_rawdata,
@avg_rawdata,
@sum_rawdata,
@is_complete,
@repeat_times,
@fail_reason)
END
COMMIT TRANSACTION;";
await backgroundServiceRepository.ExecuteSql(sql, waterArchiveMonthRawDatas);
if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1")
{
await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveMonthRawDatas);
}
}
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Month", "水電表月任務完成");
}
catch (Exception exception)
{
await task_Detail.WorkFail("ArchiveElectricMeterDayJob", "Month", exception.ToString());
logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【任務失敗】");
logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【任務失敗】[Exception]{0}, {1}", exception.ToString(), "device_number = " + device_number);
}
finally
{
if (archiveResponse != null)
{
archiveResponse.Dispose();
archiveResponse.Close();
}
}
}
#endregion
#region
////取得連線字串
//if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Compensate"))
//{
// try
// {
// await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Compensate", "補償機制任務開始");
// ProcEletricMeterService procEletricMeterService = new ProcEletricMeterService(backgroundServiceRepository, backgroundServiceMsSqlRepository);
// await procEletricMeterService.ArchiveData();
// await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Compensate", "任務完成");
// }
// catch (Exception ex)
// {
// await task_Detail.WorkFail("ArchiveElectricMeterDayJob", "Compensate", ex.ToString());
// }
//}
#endregion
await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "All", "任務完成");
}
}
catch (Exception exception)
{
await task_Detail.WorkFail("ArchiveElectricMeterDayJob", "All", exception.ToString());
logger.LogError("【ArchiveElectricMeterDayJob】【任務失敗】");
logger.LogError("【ArchiveElectricMeterDayJob】【任務失敗】[Exception]{0}, {1}", exception.ToString(), "device_number = " + device_number);
}
}
public IEnumerable<DateTime> EachDay(string from, string thru)
{
var strtday = DateTime.Parse(from).AddDays(-1); //每次重做 2天
var endday = DateTime.Parse(thru);
for (var day = strtday.Date; day.Date <= endday.Date; day = day.AddDays(1))
yield return day;
}
public IEnumerable<DateTime> EachMonth(string from, string thru)
{
var strtday = DateTime.Parse(from);
var endday = DateTime.Parse(thru);
for (var _month = strtday.Date; _month <= endday; _month = _month.AddMonths(1))
{
yield return _month;
}
}
private List<Dictionary<string, object>> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult)
{
List<Dictionary<string, object>> arrangeRawDatas = new List<Dictionary<string, object>>();
try
{
var histories = jsonResult["obj"]["list"];
var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString());
if (rawdateCount == 0)
{
return null;
}
if (histories != null && histories.HasValues)
{
if (rawdateCount > 1)
{ //多筆資料
foreach (var history in histories)
{
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
arrangeRawData.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");
arrangeRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (history["int"] != null && history["int"].HasValues)
{
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
arrangeRawData.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 = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@min_rawdata", min);
break;
case "max":
var max = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@sum_rawdata", sum);
break;
}
}
}
arrangeRawData.Add("@is_complete", 1);
arrangeRawData.Add("@repeat_times", 0);
arrangeRawData.Add("@fail_reason", null);
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
arrangeRawDatas.Add(arrangeRawData);
}
}
else
{ //單筆資料
Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
arrangeRawData.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");
arrangeRawData.Add("@start_timestamp", startTimstamp);
break;
case "end":
var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
arrangeRawData.Add("@end_timestamp", endTimstamp);
break;
}
}
}
//區間內資料筆數
if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
{
var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
arrangeRawData.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 = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@min_rawdata", min);
break;
case "max":
var max = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@max_rawdata", max);
break;
case "avg":
var avg = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@avg_rawdata", avg);
break;
case "sum":
var sum = Decimal.Parse(real["@val"].ToString(), System.Globalization.NumberStyles.Float);
arrangeRawData.Add("@sum_rawdata", sum);
break;
}
}
}
arrangeRawData.Add("@is_complete", 1);
arrangeRawData.Add("@repeat_times", 0);
arrangeRawData.Add("@fail_reason", null);
arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
arrangeRawDatas.Add(arrangeRawData);
}
}
return arrangeRawDatas;
}
catch (Exception ex)
{
return arrangeRawDatas;
}
}
}
}