using Backend.Models; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.Text; using Dapper; using System.Linq; using Newtonsoft.Json.Linq; using System.Xml; using System.Net; using System.IO; using Newtonsoft.Json; using Repository.Helper; using Repository.BackendRepository.Interface; using Repository.BackendRepository.Implement; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.CodeAnalysis.CSharp.Syntax; using BackendWorkerService.Quartz; using BackendWorkerService.Quartz.Jobs; using Microsoft.Extensions.Logging; using Org.BouncyCastle.Asn1.Pkcs; using NPOI.SS.Formula.Functions; using MySqlX.XDevAPI.Relational; namespace BackendWorkerService.Services.Implement { /// /// 電錶補償歸檔 /// public class ProcEletricMeterService { private readonly ILogger logger; private readonly IBackgroundServiceRepository backgroundServiceRepository; private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository; public ProcEletricMeterService( ILogger logger, IBackgroundServiceRepository backgroundServiceRepository, IBackgroundServiceMsSqlRepository backgroundServiceMySqlRepository) { this.logger = logger; this.backgroundServiceRepository = backgroundServiceRepository; this.backgroundServiceMsSqlRepository = backgroundServiceMySqlRepository; } public async Task ArchiveData() { bool result = false; int repeatTimes = 0; string targetTable = string.Empty; string sql_error_day = string.Empty; EDFunction ed = new EDFunction(); XmlDocument xmlDocument = new XmlDocument(); var obixApiConfig = new ObixApiConfig(); string encoded = string.Empty; //異常清單 Dictionary dicError = new Dictionary(); try { //取得可錯誤次數 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); repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault()); var saveToMSDB = await backgroundServiceRepository.GetOneAsync("select system_value from variable where system_type = 'save_to_ms_db' and deleted = 0"); var buildingStation = await backgroundServiceRepository.GetAllAsync("select SUBSTRING_INDEX(system_value, '/', 1) system_value, system_key from variable where system_type = 'dashboard_total_elec' and deleted = 0 and (SUBSTRING_INDEX(system_value, '/', 1) != '' and SUBSTRING_INDEX(system_value, '/', 1) is not null)"); #region 取得obix 設定 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 = variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault(); obixApiConfig.Password = variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault(); encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); #endregion 取得obix 設定 //取得錯誤的設備sql format var sql_error_format = @"SELECT * FROM {0} WHERE is_complete = 0 AND repeat_times < @RepeatTimes AND (point = 'KWH' or point = 'RCV')"; //MY 新增/修改sql format var MYsql_update_format = @" UPDATE {0} SET count_rawdata = @count_rawdata, min_rawdata = round(@min_rawdata, 2), max_rawdata = round(@max_rawdata, 2), kwh_result = round(@max_rawdata, 2) - round(@min_rawdata, 2), 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 {0} ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, kwh_result, avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) SELECT @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, round(@min_rawdata, 2), round(@max_rawdata, 2), round(@max_rawdata, 2) - round(@min_rawdata, 2), @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason WHERE ROW_COUNT() = 0;"; //新增/修改sql format var sql_update_format = @"BEGIN TRANSACTION; UPDATE {0} SET count_rawdata = @count_rawdata, min_rawdata = round(@min_rawdata, 2), max_rawdata = round(@max_rawdata, 2), kwh_result = round(@max_rawdata, 2) - round(@min_rawdata, 2), 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 {0} ( device_number, point, start_timestamp, end_timestamp, count_rawdata, min_rawdata, max_rawdata, kwh_result avg_rawdata, sum_rawdata, is_complete, repeat_times, fail_reason) VALUES ( @device_number, @point, @start_timestamp, @end_timestamp, @count_rawdata, round(@min_rawdata, 2), round(@max_rawdata, 2), round(@max_rawdata, 2) - round(@min_rawdata, 2), @avg_rawdata, @sum_rawdata, @is_complete, @repeat_times, @fail_reason) END COMMIT TRANSACTION;"; #region 時歸檔補償 //using (IDbConnection conn = new SqlConnection(Connection1)) //{ // //取得所有須補償的設備資訊 // targetTable = "archive_electric_meter_hour"; // var sql_error_hour = string.Format(sql_error_format, targetTable); // var error_hours = conn.Query(sql_error_hour, new { RepeatTimes = repeatTimes }).ToList(); // List> archiveHourRawDatas = new List>(); // if (error_hours.Count() > 0) // { // foreach (var error_hour in error_hours) // { // DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); // deviceNumberPoint.DeviceNumber = error_hour.Device_number; // deviceNumberPoint.Point = error_hour.Point; // deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_hour.Device_number, error_hour.Point); // var startTimestamp = string.Format("{0}+08:00", error_hour.Start_timestamp.Replace(" ", "T")); // var endTimestamp = string.Format("{0}+08:00", error_hour.End_timestamp.Replace(" ", "T")); // var historyQueryFilter = $@" // // // // "; // HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/"); // //HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/{station}/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); // archiveHourRequest.Method = "POST"; // archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded); // archiveHourRequest.PreAuthenticate = true; // byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); // using (Stream reqStream = archiveHourRequest.GetRequestStream()) // { // reqStream.Write(byteArray, 0, byteArray.Length); // } // HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse(); // var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd(); // xmlDocument.LoadXml(archiveHourResponseContent); // string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument); // JObject archiveHourJsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson); // if (archiveHourJsonResult.ContainsKey("err")) //抓取錯誤 // { // Dictionary archiveDayRawData = new Dictionary(); // archiveDayRawData.Add("@device_number", error_hour.Device_number); // archiveDayRawData.Add("@point", error_hour.Point); // archiveDayRawData.Add("@start_timestamp", error_hour.Start_timestamp); // archiveDayRawData.Add("@end_timestamp", error_hour.End_timestamp); // archiveDayRawData.Add("@is_complete", 0); // archiveDayRawData.Add("@repeat_times", ++error_hour.Repeat_times); // archiveDayRawData.Add("@fail_reason", archiveHourJson); // 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")); // archiveHourRawDatas.Add(archiveDayRawData); // } // if (archiveHourJsonResult.ContainsKey("obj")) //表示可以讀取到內容 // { // var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveHourJsonResult); // if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) // { // archiveHourRawDatas.AddRange(ArrangeRawDatas); // } // } // } // if (archiveHourRawDatas.Count() > 0) // { // var sql_error_update = string.Format(sql_update_format, targetTable); // conn.Execute(sql_error_update, archiveHourRawDatas); // } // } // conn.Close(); //} #endregion 時歸檔補償 #region 天歸檔補償 #region 電錶補償 day string schema = await backgroundServiceRepository.GetOneAsync(@" select system_value from variable where system_type = 'project_name' and deleted = 0"); //取得所有須補償的設備資訊 //targetTable = await backgroundServiceRepository.GetOneAsync($@" // select table_name // from information_schema.`TABLES` // where TABLE_NAME like 'archive_electric_meter_day%' and TABLE_SCHEMA = '{schema.Split('/')[0]}' // order by TABLE_NAME desc limit 1 "); var archiveTables = await backgroundServiceRepository.GetAllAsync($@" select archive_yyyymm from ( select CONCAT( 'archive_electric_meter_day_', year(start_timestamp), case when MONTH(start_timestamp) < 10 then CONCAT('0' , MONTH(start_timestamp)) else MONTH(start_timestamp) end ) archive_yyyymm from archive_electric_meter_month where point = 'KWH' and is_complete = 0 )a group by archive_yyyymm"); //if (!string.IsNullOrEmpty(targetTable)) //{ foreach (var tb_yyyymm in archiveTables) { targetTable = tb_yyyymm.archive_yyyymm; sql_error_day = $@"SELECT * FROM {targetTable} WHERE is_complete = 0 AND repeat_times < @RepeatTimes AND (point = 'KWH' or point = 'RCV')"; var electric_error_days = await backgroundServiceRepository.GetAllAsync(sql_error_day, new { RepeatTimes = repeatTimes }); List> electricArchiveDayRawDatas = new List>(); if (electric_error_days.Count() > 0) { foreach (var error_day in electric_error_days) { DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); deviceNumberPoint.DeviceNumber = error_day.Device_number; deviceNumberPoint.Point = error_day.Point; deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_day.Device_number, error_day.Point); //var startTimestamp = string.Format("{0}+08:00", error_day.Start_timestamp.Replace(" ", "T")); //var startTimestamp = string.Format("{0}+08:00", DateTime.Parse(error_day.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); var startTimestamp = string.Format("{0}T00:00:00.000+08:00", DateTime.Parse(error_day.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); var endTimestamp = ""; //var endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T")); if (DateTime.Parse(error_day.Start_timestamp).ToString("yyyy-MM-dd") == DateTime.Parse(error_day.End_timestamp).ToString("yyyy-MM-dd")) { //同一天為 舊有格式 採用 endtime endTimestamp = string.Format("{0}T00:00:10.000+08:00", DateTime.Parse(error_day.End_timestamp).AddDays(1).ToString("yyyy-MM-dd").Replace(" ", "T")); } else { //不同天為新格式 採用 Start_timestamp endTimestamp = string.Format("{0}T00:00:10.000+08:00", DateTime.Parse(error_day.Start_timestamp).AddDays(1).ToString("yyyy-MM-dd").Replace(" ", "T")); } var historyQueryFilter = $@" "; string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); var station = backgroundServiceRepository.GetOneAsync($@"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; HttpWebRequest archiveDayRequest = (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/"); 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); } try { HttpWebResponse archiveDayResponse = (HttpWebResponse)archiveDayRequest.GetResponse(); var archiveDayResponseContent = new StreamReader(archiveDayResponse.GetResponseStream()).ReadToEnd(); xmlDocument.LoadXml(archiveDayResponseContent); string archiveDayJson = JsonConvert.SerializeXmlNode(xmlDocument); // logger.LogInformation( Environment.NewLine + " json = " + archiveDayJson + Environment.NewLine); JObject archiveDayJsonResult = (JObject)JsonConvert.DeserializeObject(archiveDayJson); if (archiveDayJsonResult.ContainsKey("err")) //抓取錯誤 { Dictionary archiveDayRawData = new Dictionary(); archiveDayRawData.Add("@device_number", error_day.Device_number); archiveDayRawData.Add("@point", error_day.Point); archiveDayRawData.Add("@start_timestamp", DateTime.Parse(error_day.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveDayRawData.Add("@end_timestamp", DateTime.Parse(error_day.End_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveDayRawData.Add("@is_complete", 0); archiveDayRawData.Add("@repeat_times", ++error_day.Repeat_times); 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")); electricArchiveDayRawDatas.Add(archiveDayRawData); } if (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult, ref dicError); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { electricArchiveDayRawDatas.AddRange(ArrangeRawDatas); } } } catch (Exception ex) { logger.LogError("【ArchiveElectricMeterDayJob】【補償機制 - 天】【任務失敗】Device_number=" + error_day.Device_number + " point = " + error_day.Point + " date =" + error_day + " startTimestamp" + startTimestamp + " endTimestamp =" + endTimestamp); logger.LogError("【ArchiveElectricMeterDayJob】【補償機制 - 天】【任務失敗】[Exception]:{0}", ex.ToString() + Environment.NewLine); } } if (electricArchiveDayRawDatas.Count() > 0) { var Mysql_error_update = string.Format(MYsql_update_format, targetTable); var sql_error_update = string.Format(sql_update_format, targetTable); await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveDayRawDatas); if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1") { await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveDayRawDatas); } #region 月總計 string yyyymm = targetTable.Split('_')[targetTable.Split('_').Length - 1]; //取出 archive_electric_meter_day_202308 的最後一段 202308 string yyyy = yyyymm.Substring(0, 4); string mm = yyyymm.Remove(0, 4); //先清空 該月份的數據 string sql = @$"update archive_electric_meter_month set count_rawdata = 0, kwh_result = 0, max_rawdata = 0, min_rawdata = 0, repeat_times = 0, is_complete = 0, fail_reason = null, updated_at = null where `point` = 'KWH' and date(start_timestamp) = CONCAT('{yyyy}-{mm}', '-01'); "; try { await backgroundServiceRepository.ExecuteSql(sql); sql = $@"update archive_electric_meter_month a join ( select device_number, `point` , CONCAT('{yyyy}-{mm}', '-01') start_timestamp , LAST_DAY('{yyyy}/{mm}/01') end_timestamp , sum(count_rawdata) count_rawdata , sum(kwh_result) kwh_result , max(max_rawdata) max_rawdata , MIN(min_rawdata) min_rawdata from {targetTable} where point = 'KWH' group by device_number, `point` ) b on a.device_number = b.device_number and a.`point` = b.`point` and date(a.start_timestamp) = date(b.start_timestamp) set a.count_rawdata = b.count_rawdata, a.kwh_result = b.kwh_result, a.max_rawdata = b.max_rawdata, a.min_rawdata = b.min_rawdata, a.is_complete = 1, updated_at = now();"; await backgroundServiceRepository.ExecuteSql(sql); } catch (Exception ex) { //await task_Detail.WorkFail("ArchiveElectricMeterDayJob", "Compensate", ex.ToString()); logger.LogError("【ArchiveElectricMeterDayJob】【補償機制 - 月總計】【任務失敗】"); logger.LogError("【ArchiveElectricMeterDayJob】【補償機制 - 月總計】【任務失敗】[Exception]:{0}", ex.ToString() + Environment.NewLine + sql); } #endregion } } } #endregion 電錶補償 day #region 水錶補償 day targetTable = await backgroundServiceRepository.GetOneAsync($@" select table_name from information_schema.`TABLES` where TABLE_NAME like 'archive_water_meter_day%' and TABLE_SCHEMA = '{schema.Split('/')[0]}' order by TABLE_NAME desc limit 1 "); if (!string.IsNullOrEmpty(targetTable)) { sql_error_day = string.Format(sql_error_format, targetTable); var water_error_days = await backgroundServiceRepository.GetAllAsync(sql_error_day, new { RepeatTimes = repeatTimes }); List> waterArchiveDayRawDatas = new List>(); if (water_error_days.Count() > 0) { foreach (var error_day in water_error_days) { DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); deviceNumberPoint.DeviceNumber = error_day.Device_number; deviceNumberPoint.Point = error_day.Point; deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_day.Device_number, error_day.Point); //var startTimestamp = string.Format("{0}+08:00", error_day.Start_timestamp.Replace(" ", "T")); //var startTimestamp = string.Format("{0}+08:00", DateTime.Parse(error_day.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); var startTimestamp = string.Format("{0}T00:00:00.000+08:00", DateTime.Parse(error_day.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); //var endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T")); var endTimestamp = string.Format("{0}T00:00:01.000+08:00", DateTime.Parse(error_day.End_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); var historyQueryFilter = $@" "; string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); var station = backgroundServiceRepository.GetOneAsync($@"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; HttpWebRequest archiveDayRequest = (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/"); 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")) //抓取錯誤 { Dictionary archiveDayRawData = new Dictionary(); archiveDayRawData.Add("@device_number", error_day.Device_number); archiveDayRawData.Add("@point", error_day.Point); archiveDayRawData.Add("@start_timestamp", DateTime.Parse(error_day.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveDayRawData.Add("@end_timestamp", DateTime.Parse(error_day.End_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveDayRawData.Add("@is_complete", 0); archiveDayRawData.Add("@repeat_times", ++error_day.Repeat_times); 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, ref dicError); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { waterArchiveDayRawDatas.AddRange(ArrangeRawDatas); } } } if (waterArchiveDayRawDatas.Count() > 0) { var Mysql_error_update = string.Format(MYsql_update_format, targetTable); var sql_error_update = string.Format(sql_update_format, targetTable); if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1") { await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveDayRawDatas); } await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveDayRawDatas); } } } #endregion 水錶補償 day #endregion 天歸檔補償 #region 週歸檔補償 //取得所有須補償的設備資訊 targetTable = "archive_electric_meter_week"; var sql_error_week = string.Format(sql_error_format, targetTable); var eletric_error_weeks = await backgroundServiceRepository.GetAllAsync(sql_error_week, new { RepeatTimes = repeatTimes }); List> electricArchiveWeekRawDatas = new List>(); if (eletric_error_weeks.Count() > 0) { foreach (var error_week in eletric_error_weeks) { DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); deviceNumberPoint.DeviceNumber = error_week.Device_number; deviceNumberPoint.Point = error_week.Point; deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_week.Device_number, error_week.Point); //var startTimestamp = string.Format("{0}+08:00", error_week.Start_timestamp.Replace(" ", "T")); var startTimestamp = string.Format("{0}T00:00:00.000+08:00", DateTime.Parse(error_week.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); //var endTimestamp = string.Format("{0}+08:00", error_week.End_timestamp.Replace(" ", "T")); var endTimestamp = string.Format("{0}T00:00:01.000+08:00", DateTime.Parse(error_week.End_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); //var endTimestamp = string.Format("{0}T00:00:01.000+08:00", DateTime.Parse(error_week.End_timestamp).ToString("dd/MM/yyyy").Replace(" ", "T")); var historyQueryFilter = $@" "; string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); var station = backgroundServiceRepository.GetOneAsync($@"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; HttpWebRequest archiveWeekRequest = (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/"); 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")) //抓取錯誤 { Dictionary archiveWeekRawData = new Dictionary(); archiveWeekRawData.Add("@device_number", error_week.Device_number); archiveWeekRawData.Add("@point", error_week.Point); archiveWeekRawData.Add("@start_timestamp", DateTime.Parse(error_week.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveWeekRawData.Add("@end_timestamp", DateTime.Parse(error_week.End_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveWeekRawData.Add("@is_complete", 0); archiveWeekRawData.Add("@repeat_times", ++error_week.Repeat_times); 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, ref dicError); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { electricArchiveWeekRawDatas.AddRange(ArrangeRawDatas); } } } if (electricArchiveWeekRawDatas.Count() > 0) { var Mysql_error_update = string.Format(MYsql_update_format, targetTable); var sql_error_update = string.Format(sql_update_format, targetTable); if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1") { await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveWeekRawDatas); } await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveWeekRawDatas); } } targetTable = "archive_water_meter_week"; sql_error_week = string.Format(sql_error_format, targetTable); var water_error_weeks = await backgroundServiceRepository.GetAllAsync(sql_error_week, new { RepeatTimes = repeatTimes }); List> waterArchiveWeekRawDatas = new List>(); if (water_error_weeks.Count() > 0) { foreach (var error_week in water_error_weeks) { DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); deviceNumberPoint.DeviceNumber = error_week.Device_number; deviceNumberPoint.Point = error_week.Point; deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_week.Device_number, error_week.Point); //var startTimestamp = string.Format("{0}+08:00", error_week.Start_timestamp.Replace(" ", "T")); //var endTimestamp = string.Format("{0}+08:00", error_week.End_timestamp.Replace(" ", "T")); var startTimestamp = string.Format("{0}T00:00:00.000+08:00", DateTime.Parse(error_week.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); var endTimestamp = string.Format("{0}T00:00:01.000+08:00", DateTime.Parse(error_week.End_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); var historyQueryFilter = $@" "; string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); var station = backgroundServiceRepository.GetOneAsync($@"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; HttpWebRequest archiveWeekRequest = (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/"); 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")) //抓取錯誤 { Dictionary archiveWeekRawData = new Dictionary(); archiveWeekRawData.Add("@device_number", error_week.Device_number); archiveWeekRawData.Add("@point", error_week.Point); archiveWeekRawData.Add("@start_timestamp", DateTime.Parse(error_week.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveWeekRawData.Add("@end_timestamp", DateTime.Parse(error_week.End_timestamp, System.Globalization.CultureInfo.CurrentCulture)); archiveWeekRawData.Add("@is_complete", 0); archiveWeekRawData.Add("@repeat_times", ++error_week.Repeat_times); 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, ref dicError); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { waterArchiveWeekRawDatas.AddRange(ArrangeRawDatas); } } } if (waterArchiveWeekRawDatas.Count() > 0) { var Mysql_error_update = string.Format(MYsql_update_format, targetTable); var sql_error_update = string.Format(sql_update_format, targetTable); if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1") { await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveWeekRawDatas); } await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveWeekRawDatas); } } #endregion 週歸檔補償 #region 月歸檔補償 ////取得所有須補償的設備資訊 //targetTable = "archive_electric_meter_month"; //var sql_error_month = string.Format(sql_error_format, targetTable); //var electric_error_months = await backgroundServiceRepository.GetAllAsync(sql_error_month, new { RepeatTimes = repeatTimes }); //List> electricArchiveMonthRawDatas = new List>(); //if (electric_error_months.Count() > 0) //{ // foreach (var error_month in electric_error_months) // { // DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); // deviceNumberPoint.DeviceNumber = error_month.Device_number; // deviceNumberPoint.Point = error_month.Point; // deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_month.Device_number, error_month.Point); // //var startTimestamp = string.Format("{0}+08:00", error_month.Start_timestamp.Replace(" ", "T")); // //var endTimestamp = string.Format("{0}+08:00", error_month.End_timestamp.Replace(" ", "T")); // var startTimestamp = string.Format("{0}T00:00:00.000+08:00", DateTime.Parse(error_month.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); // var endTimestamp = string.Format("{0}T00:00:01.000+08:00", DateTime.Parse(error_month.End_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); // var startDateTime = Convert.ToDateTime(error_month.Start_timestamp); // var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month) + 1; //比原定的多加 1天 // var historyQueryFilter = $@" // // // // "; // string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); // var station = backgroundServiceRepository.GetOneAsync($@"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; // HttpWebRequest archiveMonthRequest = (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/"); // 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")) //抓取錯誤 // { // Dictionary archiveMonthRawData = new Dictionary(); // archiveMonthRawData.Add("@device_number", error_month.Device_number); // archiveMonthRawData.Add("@point", error_month.Point); // archiveMonthRawData.Add("@start_timestamp", DateTime.Parse(error_month.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture)); // archiveMonthRawData.Add("@end_timestamp", DateTime.Parse(error_month.End_timestamp, System.Globalization.CultureInfo.CurrentCulture)); // archiveMonthRawData.Add("@is_complete", 0); // archiveMonthRawData.Add("@repeat_times", ++error_month.Repeat_times); // 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); // } // } // } // if (electricArchiveMonthRawDatas.Count() > 0) // { // var Mysql_error_update = string.Format(MYsql_update_format, targetTable); // var sql_error_update = string.Format(sql_update_format, targetTable); // if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1") // { // await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveMonthRawDatas); // } // await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveMonthRawDatas); // } //} //targetTable = "archive_water_meter_month"; //sql_error_month = string.Format(sql_error_format, targetTable); //var water_error_months = await backgroundServiceRepository.GetAllAsync(sql_error_month, new { RepeatTimes = repeatTimes }); //List> waterArchiveMonthRawDatas = new List>(); //if (water_error_months.Count() > 0) //{ // foreach (var error_month in water_error_months) // { // DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint(); // deviceNumberPoint.DeviceNumber = error_month.Device_number; // deviceNumberPoint.Point = error_month.Point; // deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_month.Device_number, error_month.Point); // //var startTimestamp = string.Format("{0}+08:00", error_month.Start_timestamp.Replace(" ", "T")); // //var endTimestamp = string.Format("{0}+08:00", error_month.End_timestamp.Replace(" ", "T")); // var startTimestamp = string.Format("{0}T00:00:00.000+08:00", DateTime.Parse(error_month.Start_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); // var endTimestamp = string.Format("{0}T00:00:01.000+08:00", DateTime.Parse(error_month.End_timestamp).ToString("yyyy-MM-dd").Replace(" ", "T")); // var startDateTime = Convert.ToDateTime(error_month.Start_timestamp); // var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month) + 1; //比原定的多加 1天 // var historyQueryFilter = $@" // // // // "; // string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); // var station = backgroundServiceRepository.GetOneAsync($@"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; // HttpWebRequest archiveMonthRequest = (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/"); // 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")) //抓取錯誤 // { // Dictionary archiveMonthRawData = new Dictionary(); // archiveMonthRawData.Add("@device_number", error_month.Device_number); // archiveMonthRawData.Add("@point", error_month.Point); // archiveMonthRawData.Add("@start_timestamp", DateTime.Parse(error_month.Start_timestamp, System.Globalization.CultureInfo.CurrentCulture)); // archiveMonthRawData.Add("@end_timestamp", DateTime.Parse(error_month.End_timestamp, System.Globalization.CultureInfo.CurrentCulture)); // archiveMonthRawData.Add("@is_complete", 0); // archiveMonthRawData.Add("@repeat_times", ++error_month.Repeat_times); // 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); // } // } // } // if (waterArchiveMonthRawDatas.Count() > 0) // { // var Mysql_error_update = string.Format(MYsql_update_format, targetTable); // var sql_error_update = string.Format(sql_update_format, targetTable); // if (!string.IsNullOrEmpty(saveToMSDB) && saveToMSDB == "1") // { // await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveMonthRawDatas); // } // await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveMonthRawDatas); // } //} #endregion 月歸檔補償 result = true; } catch (Exception exception) { logger.LogError("【ProcEletricMeterService】【補償機制 - 任務失敗】"); logger.LogError("【ProcEletricMeterService】【補償機制 - 任務失敗】[Exception]:{0} {1}", exception.ToString()); } return result; } /// /// 獲取 Niagara 資料,並儲存於 List 中 /// /// /// /// /// /// /// /// /// /// public void obixData_collect(XmlDocument xmlDocument, List DeviceNumberPoints, ObixApiConfig obixApiConfig, string encoded, List> resultArchiveDayRawDatas, ref Dictionary dicError) { #region 水電錶 save to DB start logger.LogInformation($@"s0 DeviceNumberPoints.Count() = {DeviceNumberPoints.Count().ToString()}"); foreach (var deviceNumberPoint in DeviceNumberPoints) { if (deviceNumberPoint.DeviceNumber == "NTPC_G6_EE_E4_B1F_CB1_WHT_N1") //NTPC_G6_EE_E4_B1F_CB2_WHT_N1 NTPC_G6_EE_E4_B1F_MVCB_WHT_N1 { logger.LogInformation($@"s1 devie_number = NTPC_G6_EE_E4_B1F_CB1_WHT_N1 archive_lastDate={deviceNumberPoint.archive_lastDate}"); } if (deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")) { logger.LogInformation($@" foreach (var deviceNumberPoint in DeviceNumberPoints) 判斷為今天 不用跑 deviceNumberPoint.archive_lastDate = {deviceNumberPoint.archive_lastDate} "); // ----------- log continue; //如果是今天 就不要用歸檔了 } //var startDay = string.Format("{0}T00:00:00.000+08:00", deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd").Replace(" ", "T")); var startDay = deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd"); var endDay = System.DateTime.Now.ToString("yyyy-MM-dd"); //var startDay = string.Format("{0}T00:00:00.000+08:00", deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd").Replace(" ", "T")); //var endDay = System.DateTime.Now.AddDays(-29).ToString(); //logger.LogInformation($@"before startDay = {startDay} endDay={endDay}"); // ----------- log #region foreach (DateTime day in EachDay(startDay, endDay)) { if (day.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")) { //logger.LogInformation($@"s2 foreach (DateTime day in EachDay(startDay, endDay)) 判斷為今天 不用跑 day = {day} "); // ----------- log break; //如果是今天 就不要用歸檔了 } //logger.LogInformation(@$"obix query for {deviceNumberPoint.DeviceNumber} day = {day.ToString("yyyy-MM-dd")}"); var sDay = string.Format("{0}T00:00:00.000+08:00", day.ToString("yyyy-MM-dd").Replace(" ", "T")); var eDay = string.Format("{0}T00:01:00.000+08:00", day.AddDays(1).ToString("yyyy-MM-dd").Replace(" ", "T")); string historyQueryFilter = $@" "; string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); //logger.LogInformation($@" {device_number} after sDay = {sDay} eDay={eDay}"); // ----------- log var station = backgroundServiceRepository.GetOneAsync($@"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; HttpWebRequest 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; // logger.LogInformation($@"url= {$"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/" + Environment.NewLine} {device_number} station = {station} task= {startDay} ~ {endDay} action ={sDay} ~ {eDay}"); // ----------- log byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); using (Stream reqStream = archiveRequest.GetRequestStream()) { reqStream.Write(byteArray, 0, byteArray.Length); } var archiveResponse = (HttpWebResponse)archiveRequest.GetResponse(); var archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd(); archiveResponse.Dispose(); archiveResponse.Close(); xmlDocument.LoadXml(archiveResponseContent); var archiveJson = JsonConvert.SerializeXmlNode(xmlDocument); var archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson); //if (device_number == "NTPC_G6_EE_E4_B1F_CB3_WHT_N1_KWH") //{ // logger.LogError("obixData_collect - NTPC_G6_EE_E4_B1F_CB3_WHT_N1_KWH json = " + archiveJsonResult); //} if (archiveJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】"); //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveDayJsonResult); archiveJsonResult logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveJsonResult); Dictionary archiveDayRawData = new Dictionary(); 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")); //object vv = null; //archiveDayRawData.TryGetValue("@start_timestamp",out vv).ToString(); //var cc = vv.ToString(); resultArchiveDayRawDatas.Add(archiveDayRawData); if (!dicError.ContainsKey(deviceNumberPoint.DeviceNumber)) { dicError.Add(deviceNumberPoint.DeviceNumber, day.ToString("yyyy-MM-dd")); //記錄異常設備與日期 } } if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { //logger.LogInformation("【ArchiveElectricMeterDayJob】【天歸檔】【OK】{0}", archiveJsonResult); var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult, ref dicError); // <-- 解析內容中 也有判斷是否 max == 0 的收集 if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { //logger.LogInformation(@$"obix result {deviceNumberPoint.DeviceNumber} day = {day.ToString("yyyy-MM-dd")} ArrangeRawDatas.count() = {ArrangeRawDatas.Count().ToString()}"); resultArchiveDayRawDatas.AddRange(ArrangeRawDatas); } else { if (!dicError.ContainsKey(deviceNumberPoint.DeviceNumber)) { dicError.Add(deviceNumberPoint.DeviceNumber, day.ToString("yyyy-MM-dd")); //記錄異常設備與日期 } } } } #endregion } #endregion 水電錶作業 save to DB end string funish = string.Empty; } public void obixData_collect_range(XmlDocument xmlDocument, List DeviceNumberPoints, ObixApiConfig obixApiConfig, string encoded, List> resultArchiveDayRawDatas) { //異常清單 Dictionary dicError = new Dictionary(); //僅需要記錄在 day 此處不需要 #region 水電錶 save to DB start // 需要先 group by DeviceNumberPoints 因為已經展開日期 //var DevicePoints = DeviceNumberPoints // .GroupBy(x => new { _FullDeviceNumberPoint = x.FullDeviceNumberPoint }) // .Select(x => new DeviceNumberPoint { FullDeviceNumberPoint = x.Key._FullDeviceNumberPoint }).ToList(); //logger.LogInformation($@"before groupby DeviceNumberPoints.Count() = {DeviceNumberPoints.Count().ToString()} after DevicePoints.Count() = {DevicePoints.Count().ToString()}"); // ----------- log // string last_deviceNumber = string.Empty; foreach (var deviceNumberPoint in DeviceNumberPoints) { //if (string.IsNullOrEmpty(last_deviceNumber)) last_deviceNumber = deviceNumberPoint.DeviceNumber; //if (deviceNumberPoint.DeviceNumber == "NTPC_G6_EE_E4_B1F_CB3_WHT_N1") //{ // logger.LogInformation($@"s1 devie_number = NTPC_G6_EE_E4_B1F_CB3_WHT_N1 archive_lastDate={deviceNumberPoint.archive_lastDate}"); //} //if (deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd")) //{ // logger.LogInformation($@" foreach (var deviceNumberPoint in DeviceNumberPoints) 判斷為今天 不用跑 deviceNumberPoint.archive_lastDate = {deviceNumberPoint.archive_lastDate} "); // ----------- log // continue; //如果是今天 就不要用歸檔了 //} var startDay = deviceNumberPoint.archive_lastDate.ToString("yyyy-MM-dd"); var endDay = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"); DateTime today = DateTime.Now; logger.LogInformation($@"before startDay = {startDay} endDay={endDay}"); // ----------- log #region foreach (DateTime month in EachMonth(startDay, endDay)) { // 需要比原定日期增加 1天:因 Niagara 內部判斷為 < lastData, 並未包含結束當天 add by jiahao @2023-09-16 //var dayInMonth = DateTime.DaysInMonth(day.Year, day.Month) +1; 、、(DateTime.Now - DateTime.Parse(startDay)).Days var startTimestamp = ""; var endTimestamp = ""; var dayInMonth = 0; // 區分當月與其他月份 if (month.ToString("yyyy-MM") == System.DateTime.Now.AddDays(-1).ToString("yyyy-MM")) { var preDay = today.AddDays(-1); //取得前一天 dayInMonth = DateTime.DaysInMonth(preDay.Year, preDay.Month); var FirstDay = new DateTime(preDay.Year, preDay.Month, 1); var LastDay = today; startTimestamp = string.Format("{0}T00:00:00.000+08:00", FirstDay.ToString("yyyy-MM-dd")); endTimestamp = string.Format("{0}T00:01:00.000+08:00", LastDay.ToString("yyyy-MM-dd")); } else { 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).AddDays(1); startTimestamp = string.Format("{0}T00:00:00.000+08:00", FirstDay.ToString("yyyy-MM-dd")); endTimestamp = string.Format("{0}T00:01:00.000+08:00", LastDay.ToString("yyyy-MM-dd")); } //var dayInMonth = (DateTime.Now - DateTime.Parse(today.ToString("yyyy-MM-") + "01")).Days + 1; //var startTimestamp = string.Format("{0}T00:00:00.000+08:00", today.ToString("yyyy-MM-") + "01"); ////var endTimestamp = string.Format("{0}T23:59:59.000+08:00", LastDay.ToString("yyyy-MM-dd")); ////var endTimestamp = string.Format("{0}T00:00:10.000+08:00", day.AddMonths(1).ToString("yyyy-MM-") + "01"); // by jiahao @2023-09-26 //var endTimestamp = string.Format("{0}T00:00:10.000+08:00", DateTime.Now.ToString("yyyy-MM-dd")); // by jiahao @2023-10-03 var historyQueryFilter = $@" "; string device_number = deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", ""); var station = backgroundServiceRepository.GetOneAsync($@"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; HttpWebRequest 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); } var archiveResponse = (HttpWebResponse)archiveRequest.GetResponse(); var archiveResponseContent = new StreamReader(archiveResponse.GetResponseStream()).ReadToEnd(); archiveResponse.Dispose(); archiveResponse.Close(); //logger.LogInformation(@$"【ArchiveElectricMeterMonth】{device_number} startTimestamp={startTimestamp} endTimestamp= {endTimestamp} interval = PT{dayInMonth.ToString()}D url = {$"{obixApiConfig.ApiBase}obix/histories/{station}/{deviceNumberPoint.FullDeviceNumberPoint.Replace("$3", "")}/~historyRollup/"}"); xmlDocument.LoadXml(archiveResponseContent); var archiveJson = JsonConvert.SerializeXmlNode(xmlDocument); var archiveJsonResult = (JObject)JsonConvert.DeserializeObject(archiveJson); //if (device_number == "NTPC_D8_EE_E4_RF_Total_WHT_N1" || device_number == "NTPC_D8_EE_E4_RF_H2_WHT_N1") //{ logger.LogInformation(@$"{device_number} json = {archiveJsonResult}"); //} if (archiveJsonResult.ContainsKey("err")) //抓取錯誤 { //logger.LogError("【ArchiveElectricMeterDayJob】【天歸檔】【取得資料失敗】"); logger.LogError("【ArchiveElectricMeterDayJob】【月歸檔】【取得資料失敗】[錯誤內容]:{0}", archiveJsonResult); 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", 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")); resultArchiveDayRawDatas.Add(archiveDayRawData); } if (archiveJsonResult.ContainsKey("obj")) //表示可以讀取到內容 { var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveJsonResult, ref dicError); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { resultArchiveDayRawDatas.AddRange(ArrangeRawDatas); } } } #endregion } #endregion 水電錶作業 save to DB end } private List> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult, ref Dictionary dicError) { 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 = 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); //add by jiahao 2023-09-26 //if (max == 0) //{ // if (!dicError.ContainsKey(deviceNumberPoint.DeviceNumber)) // { // dicError.Add(deviceNumberPoint.DeviceNumber, arrangeRawData["@start_timestamp"].ToString()); //記錄異常設備與日期 // } //} 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 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 = 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); //add by jiahao 2023-09-26 //if (max == 0) //{ // if (!dicError.ContainsKey(deviceNumberPoint.DeviceNumber)) // { // dicError.Add(deviceNumberPoint.DeviceNumber, arrangeRawData["@start_timestamp"].ToString()); //記錄異常設備與日期 // } //} 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; } /// /// 回傳區間內的每一天 /// /// /// /// public IEnumerable EachDay(string from, string thru) { var strtday = DateTime.Parse(from).AddDays(-15); //每次重做 2天 // 20241106 因明志Niagara最多存14天資料,故考慮資料回補的狀況增多至15天 var endday = DateTime.Parse(thru); for (var day = strtday.Date; day.Date <= endday.Date; day = day.AddDays(1)) yield return day; } public IEnumerable EachMonth(string from, string thru) { var strtday = DateTime.Parse(from).AddMonths(-1); var endday = DateTime.Parse(thru); for (var _month = strtday.Date; _month <= endday; _month = _month.AddMonths(1)) { yield return _month; } } } }