using Backend.Models; using BackendWorkerService.Services.Implement; using Dapper; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; 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 logger; private readonly IBackgroundServiceRepository backgroundServiceRepository; private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository; protected readonly IDatabaseHelper _databaseHelper; private readonly ILogger loggers; public ArchiveElectricMeterDayJob( ILogger logger, IBackgroundServiceRepository backgroundServiceRepository, IBackgroundServiceMsSqlRepository backgroundServiceMySqlRepository, IDatabaseHelper databaseHelper, ILogger 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); try { if(await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "All")) { await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "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(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(); #region 找出所有電錶設備 var sWhere = "deleted = 0 AND device_name_tag = @sub_system_guid"; var electricMeters = await backgroundServiceRepository.GetAllAsync("device", sWhere, new { sub_system_guid = electricMeterGuid }); var waterMeters = await backgroundServiceRepository.GetAllAsync("device", sWhere, new { sub_system_guid = waterMeterGuid }); #endregion 找出所有電錶設備 #region 找出所有電錶系統的點位 var sPointWhere = "deleted = 0 AND device_name_tag = @sub_system_guid"; var electricPoints = await backgroundServiceRepository.GetAllAsync("device_item", sPointWhere, new { sub_system_guid = electricMeterGuid }); var waterPoints = await backgroundServiceRepository.GetAllAsync("device_item", sPointWhere, new { sub_system_guid = waterMeterGuid }); #endregion 找出所有電錶系統的點位 #region 組合出所有電錶設備點位 List electricDeviceNumberPoints = new List(); foreach (var electricMeter in electricMeters) { foreach (var point in electricPoints) { DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); deviceNumberPoint.DeviceNumber = electricMeter.Device_number; deviceNumberPoint.Point = point.points; deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", electricMeter.Device_number, point.points); electricDeviceNumberPoints.Add(deviceNumberPoint); } } #endregion 組合出所有電錶設備點位 #region 組合出所有水錶設備點位 List waterDeviceNumberPoints = new List(); foreach (var waterMeter in waterMeters) { foreach (var point in waterPoints) { DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); deviceNumberPoint.DeviceNumber = waterMeter.Device_number; deviceNumberPoint.Point = point.points; deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", waterMeter.Device_number, point.points); 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(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 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 = $@" "; //Stopwatch stopWatch = new Stopwatch(); //stopWatch.Start(); //抓取每個設備的資料 List> electericArchiveDayRawDatas = new List>(); List> waterArchiveDayRawDatas = new List>(); foreach (var deviceNumberPoint in electricDeviceNumberPoints) { HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); //HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); archiveDayRequest.Method = "POST"; archiveDayRequest.Headers.Add("Authorization", "Basic " + encoded); archiveDayRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveDayRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveDayResponse = (HttpWebResponse)archiveDayRequest.GetResponse(); var archiveDayResponseContent = new StreamReader(archiveDayResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveDayResponseContent); string archiveDayJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject archiveDayJsonResult = (JObject)JsonConvert.DeserializeObject(archiveDayJson); if (archiveDayJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveDayJsonResult); Dictionary archiveDayRawData = new Dictionary(); archiveDayRawData.Add("@device_number", deviceNumberPoint.DeviceNumber); archiveDayRawData.Add("@point", deviceNumberPoint.Point); archiveDayRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19)); archiveDayRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19)); archiveDayRawData.Add("@is_complete", 0); archiveDayRawData.Add("@repeat_times", 0); archiveDayRawData.Add("@fail_reason", archiveDayJson); 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 (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { electericArchiveDayRawDatas.AddRange(ArrangeRawDatas); } } } foreach (var deviceNumberPoint in waterDeviceNumberPoints) { HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); //HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); archiveDayRequest.Method = "POST"; archiveDayRequest.Headers.Add("Authorization", "Basic " + encoded); archiveDayRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveDayRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveDayResponse = (HttpWebResponse)archiveDayRequest.GetResponse(); var archiveDayResponseContent = new StreamReader(archiveDayResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveDayResponseContent); string archiveDayJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject archiveDayJsonResult = (JObject)JsonConvert.DeserializeObject(archiveDayJson); if (archiveDayJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveDayJsonResult); Dictionary archiveDayRawData = new Dictionary(); archiveDayRawData.Add("@device_number", deviceNumberPoint.DeviceNumber); archiveDayRawData.Add("@point", deviceNumberPoint.Point); archiveDayRawData.Add("@start_timestamp", startTimestamp.Replace("T", " ").Substring(0, 19)); archiveDayRawData.Add("@end_timestamp", endTimestamp.Replace("T", " ").Substring(0, 19)); archiveDayRawData.Add("@is_complete", 0); archiveDayRawData.Add("@repeat_times", 0); archiveDayRawData.Add("@fail_reason", archiveDayJson); 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 (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { waterArchiveDayRawDatas.AddRange(ArrangeRawDatas); } } } //stopWatch.Stop(); //logger.LogInformation("【ArchiveElectricMeterDayJob】【天歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds); if (electericArchiveDayRawDatas.Count() > 0) { var sql = $@" UPDATE archive_electric_meter_day SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_meter_day ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0;"; var mySql = $@"BEGIN TRANSACTION; UPDATE archive_electric_meter_day SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_meter_day ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; await backgroundServiceRepository.ExecuteSql(sql, electericArchiveDayRawDatas); await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electericArchiveDayRawDatas); } if (waterArchiveDayRawDatas.Count() > 0) { var sql = $@" UPDATE archive_water_meter_day SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_water_meter_day ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0;"; var mySql = $@"BEGIN TRANSACTION; UPDATE archive_water_meter_day SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_water_meter_day ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; await backgroundServiceRepository.ExecuteSql(sql, waterArchiveDayRawDatas); await backgroundServiceMsSqlRepository.ExecuteSql(mySql, waterArchiveDayRawDatas); } 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}", exception.ToString()); } } #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 = $@" "; //Stopwatch stopWatch = new Stopwatch(); //stopWatch.Start(); //抓取每個設備的資料 List> electricArchiveWeekRawDatas = new List>(); List> waterArchiveWeekRawDatas = new List>(); foreach (var deviceNumberPoint in electricDeviceNumberPoints) { HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); //HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); archiveWeekRequest.Method = "POST"; archiveWeekRequest.Headers.Add("Authorization", "Basic " + encoded); archiveWeekRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveWeekRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveWeekResponse = (HttpWebResponse)archiveWeekRequest.GetResponse(); var archiveWeekResponseContent = new StreamReader(archiveWeekResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveWeekResponseContent); string archiveWeekJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject archiveWeekJsonResult = (JObject)JsonConvert.DeserializeObject(archiveWeekJson); if (archiveWeekJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveWeekJsonResult); Dictionary archiveWeekRawData = new Dictionary(); 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", archiveWeekJson); 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 (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { electricArchiveWeekRawDatas.AddRange(ArrangeRawDatas); } } } foreach (var deviceNumberPoint in waterDeviceNumberPoints) { HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); //HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); archiveWeekRequest.Method = "POST"; archiveWeekRequest.Headers.Add("Authorization", "Basic " + encoded); archiveWeekRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveWeekRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveWeekResponse = (HttpWebResponse)archiveWeekRequest.GetResponse(); var archiveWeekResponseContent = new StreamReader(archiveWeekResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveWeekResponseContent); string archiveWeekJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject archiveWeekJsonResult = (JObject)JsonConvert.DeserializeObject(archiveWeekJson); if (archiveWeekJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【週歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveWeekJsonResult); Dictionary archiveWeekRawData = new Dictionary(); 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", archiveWeekJson); 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 (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult); 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_meter_week SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_meter_week ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0; "; var mySql = $@"BEGIN TRANSACTION; UPDATE archive_electric_meter_week SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_meter_week ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; await backgroundServiceRepository.ExecuteSql(sql, electricArchiveWeekRawDatas); await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveWeekRawDatas); } if (waterArchiveWeekRawDatas.Count() > 0) { var sql = $@" UPDATE archive_water_meter_week SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_water_meter_week ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0; "; var mySql = $@"BEGIN TRANSACTION; UPDATE archive_water_meter_week SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_water_meter_week ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; await backgroundServiceRepository.ExecuteSql(sql, waterArchiveWeekRawDatas); 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()); } } #endregion 週歸檔 #region 月歸檔 if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Month")) { try { await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Month", "任務開始"); var FirstDay = now.AddDays(-now.Day + 1); var LastDay = now.AddMonths(1).AddDays(-now.AddMonths(1).Day); var dayInMonth = DateTime.DaysInMonth(now.Year, now.Month); var 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")); var historyQueryFilter = $@" "; //Stopwatch stopWatch = new Stopwatch(); //stopWatch.Start(); //抓取每個設備的資料 List> electricArchiveMonthRawDatas = new List>(); List> waterArchiveMonthRawDatas = new List>(); foreach (var deviceNumberPoint in electricDeviceNumberPoints) { HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); //HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); archiveMonthRequest.Method = "POST"; archiveMonthRequest.Headers.Add("Authorization", "Basic " + encoded); archiveMonthRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveMonthRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveMonthResponse = (HttpWebResponse)archiveMonthRequest.GetResponse(); var archiveMonthResponseContent = new StreamReader(archiveMonthResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveMonthResponseContent); string archiveMonthJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject archiveMonthJsonResult = (JObject)JsonConvert.DeserializeObject(archiveMonthJson); if (archiveMonthJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveMonthJsonResult); Dictionary archiveMonthRawData = new Dictionary(); 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", archiveMonthJson); 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 (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { electricArchiveMonthRawDatas.AddRange(ArrangeRawDatas); } } } foreach (var deviceNumberPoint in waterDeviceNumberPoints) { HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); //HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); archiveMonthRequest.Method = "POST"; archiveMonthRequest.Headers.Add("Authorization", "Basic " + encoded); archiveMonthRequest.PreAuthenticate = true; byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveMonthRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } HttpWebResponse archiveMonthResponse = (HttpWebResponse)archiveMonthRequest.GetResponse(); var archiveMonthResponseContent = new StreamReader(archiveMonthResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveMonthResponseContent); string archiveMonthJson = JsonConvert.SerializeXmlNode(xmlDocument); JObject archiveMonthJsonResult = (JObject)JsonConvert.DeserializeObject(archiveMonthJson); if (archiveMonthJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveMonthJsonResult); Dictionary archiveMonthRawData = new Dictionary(); 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", archiveMonthJson); 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 (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { waterArchiveMonthRawDatas.AddRange(ArrangeRawDatas); } } } //stopWatch.Stop(); //logger.LogInformation("【ArchiveElectricMeterDayJob】【月歸檔效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds); if (electricArchiveMonthRawDatas.Count() > 0) { var sql = $@" UPDATE archive_electric_meter_month SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_meter_month ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0;"; var mySql = $@"BEGIN TRANSACTION; UPDATE archive_electric_meter_month SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_meter_month ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; await backgroundServiceRepository.ExecuteSql(sql, electricArchiveMonthRawDatas); await backgroundServiceMsSqlRepository.ExecuteSql(mySql, electricArchiveMonthRawDatas); } if (waterArchiveMonthRawDatas.Count() > 0) { var sql = $@" UPDATE archive_water_meter_month SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_water_meter_month ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0;"; var mySql = $@"BEGIN TRANSACTION; UPDATE archive_water_meter_month SET count_rawdata = @count_rawdata, min_rawdata = @min_rawdata, max_rawdata = @max_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_water_meter_month ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, @min_rawdata, @max_rawdata, @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; await backgroundServiceRepository.ExecuteSql(sql, waterArchiveMonthRawDatas); 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}", exception.ToString()); } } #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()); logger.LogError("【ArchiveElectricMeterDayJob】【補償機制】【任務失敗】"); logger.LogError("【ArchiveElectricMeterDayJob】【補償機制】【任務失敗】[Exception]:{0}", 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}", exception.ToString()); } } private List> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult) { List> arrangeRawDatas = new List>(); 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 arrangeRawData = new Dictionary(); 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 = Convert.ToDecimal(real["@val"].ToString()); arrangeRawData.Add("@min_rawdata", min); break; case "max": var max = Convert.ToDecimal(real["@val"].ToString()); arrangeRawData.Add("@max_rawdata", max); break; case "avg": var avg = Convert.ToDecimal(real["@val"].ToString()); arrangeRawData.Add("@avg_rawdata", avg); break; case "sum": var sum = Convert.ToDecimal(real["@val"].ToString()); 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 arrangeRawData = new Dictionary(); 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 = Convert.ToDecimal(real["@val"].ToString()); arrangeRawData.Add("@min_rawdata", min); break; case "max": var max = Convert.ToDecimal(real["@val"].ToString()); arrangeRawData.Add("@max_rawdata", max); break; case "avg": var avg = Convert.ToDecimal(real["@val"].ToString()); arrangeRawData.Add("@avg_rawdata", avg); break; case "sum": var sum = Convert.ToDecimal(real["@val"].ToString()); 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; } } }