diff --git a/Backend/Controllers/DeviceManageController.cs b/Backend/Controllers/DeviceManageController.cs index 64e9bed..c810839 100644 --- a/Backend/Controllers/DeviceManageController.cs +++ b/Backend/Controllers/DeviceManageController.cs @@ -1653,18 +1653,18 @@ namespace Backend.Controllers /// /// 取得子系統的device item /// - /// + /// /// [HttpPost] - public async Task>> GetDeviceItem(string sub_system_tag) + public async Task>> GetDeviceItem(DeviceItemInput input) { ApiResult> apiResult = new ApiResult>(); try { - string sWhere = "deleted = 0 AND device_name_tag = @Sub_system_tag"; + string sWhere = "deleted = 0 AND device_name_tag = @Sub_system_tag and device_building_tag = @device_building_tag"; - object param = new { Sub_system_tag = sub_system_tag }; + object param = new { Sub_system_tag = input.sub_system_tag, device_building_tag = input.building_tag }; var deviceItems = await backendRepository.GetAllAsync("device_item", sWhere, param); diff --git a/Backend/Controllers/NiagaraDataSynchronizeController.cs b/Backend/Controllers/NiagaraDataSynchronizeController.cs index a8d1c0b..957dfcb 100644 --- a/Backend/Controllers/NiagaraDataSynchronizeController.cs +++ b/Backend/Controllers/NiagaraDataSynchronizeController.cs @@ -51,19 +51,23 @@ namespace Backend.Controllers var obixApiConfig = new Backend.Models.ObixApiConfig(); EDFunction ed = new EDFunction(); obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault() + "obix/config/Program/ObixQuery/query/"; - obixApiConfig.UrlSlot =variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); + //obixApiConfig.UrlSlot =variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); obixApiConfig.TagQuantity = variableObix.Where(x => x.Name == "tag_quantity").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(); - List ds; + var ds = new List(); string top100 = "";//" top 100 "; webRequestService svc = new webRequestService(); - string bql = obixApiConfig.UrlSlot + "bql:select " + top100 + " * from baja:Folder "; - //ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Arena/Program/ObixQuery/query/", bql); - //ds = svc.obixQuery("http://localhost:8080/obix/config/Program/ObixQuery/query/", bql); - ds = svc.obixQuery(obixApiConfig.ApiBase, bql, obixApiConfig.TagQuantity, obixApiConfig.UserName, obixApiConfig.Password);//三菱 + var urlSlots = backendRepository.GetAllAsync("select obixSlot from building where deleted = 0").Result; + foreach(var us in urlSlots) + { + string bql = us + "bql:select " + top100 + " * from baja:Folder "; + //ds = svc.obixQuery("http://192.168.0.136:8080/obix/config/Arena/Program/ObixQuery/query/", bql); + //ds = svc.obixQuery("http://localhost:8080/obix/config/Program/ObixQuery/query/", bql); + ds.AddRange(svc.obixQuery(obixApiConfig.ApiBase, bql, obixApiConfig.TagQuantity, obixApiConfig.UserName, obixApiConfig.Password));//三菱 + } apiResult.Code = "0000"; apiResult.Data = ds; @@ -93,14 +97,17 @@ namespace Backend.Controllers try { string ss = ds.Where(x => x.tag_name != "").FirstOrDefault().tag_name; - var building = ""; + var data = ds.Where(x => x.tag_name != ""); + List building = null; if (tag_quantity == "5") { - building = ss.Split("_")[0]; + //building.Add(ss.Split("_")[0]); + building = data.GroupBy(x => x.tag_name.Split("_")[0]).Select(x => x.Key).ToList(); } else { - building = ss.Split("_")[1]; + //building.Add(ss.Split("_")[1]); + building = data.GroupBy(x => x.tag_name.Split("_")[1]).Select(x => x.Key).ToList(); } string LightSwitchLevel = await niagaraDataSynchronizeRepository.getLightSwitchLevel(); //獲取照明開關 是否在 device or device_node @@ -135,7 +142,7 @@ namespace Backend.Controllers try { - List ds; + var ds = new List(); webRequestService svc = new webRequestService(); @@ -146,12 +153,19 @@ namespace Backend.Controllers 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(); - obixApiConfig.UrlSlot = variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); - ds = svc.obixHisQuery(obixApiConfig.ApiBase + "obix/config/Program/ObixQuery/query/", obixApiConfig.ApiBase + "obix/histories",obixApiConfig.UrlSlot, obixApiConfig.UserName, - obixApiConfig.Password); + //obixApiConfig.UrlSlot = variableObix.Where(x => x.Name == "url_slot").Select(x => x.Value).FirstOrDefault(); + + var urlSlots = backendRepository.GetAllAsync("select obixSlot from building where deleted = 0").Result; + foreach(var us in urlSlots) + { + var data = svc.obixHisQuery(obixApiConfig.ApiBase + "obix/config/Program/ObixQuery/query/", obixApiConfig.ApiBase + "obix/histories", us, + obixApiConfig.UserName, obixApiConfig.Password); + ds.AddRange(data); + } + var buildings = backendRepository.GetAllAsync("select building_tag from building where deleted = 0").Result; apiResult.Code = "0000"; - apiResult.Data = ds.Where(x => x.device_building_tag == building.building).ToList(); ; + apiResult.Data = ds.Where(x => buildings.Contains(x.device_building_tag)).ToList(); } catch (Exception exception) { @@ -180,7 +194,7 @@ namespace Backend.Controllers //string ss = ds.Where(x => x.tag_name != "").FirstOrDefault().tag_name; //var building = ss.Split("_")[0]; - var building = ds.FirstOrDefault().device_building_tag; + var building = ds.GroupBy(x => x.device_building_tag).Select(x => x.Key).ToList(); await niagaraDataSynchronizeRepository.InsertItemFromNiagara(ds, building); // insert 暫存table import_niagara_item await niagaraDataSynchronizeRepository.DeviceItemComparison(); //insert device_item await niagaraDataSynchronizeRepository.CheckItemDiffFullNameAndCover(); // update device_item.fullname diff --git a/Backend/Controllers/SystemCategoryController.cs b/Backend/Controllers/SystemCategoryController.cs index 2509b47..641391b 100644 --- a/Backend/Controllers/SystemCategoryController.cs +++ b/Backend/Controllers/SystemCategoryController.cs @@ -581,14 +581,14 @@ namespace Backend.Controllers ApiResult> apiResult = new ApiResult>(); try { - + var building_tag = await backendRepository.GetOneAsync($@"select system_value from variable where system_type = 'project_name' and deleted = 0"); var sql = @"SELECT di.* FROM device_item di JOIN variable sv ON di.device_name_tag = sv.system_value JOIN variable mv ON sv.system_parent_id = mv.id AND di.device_system_tag = mv.system_value - WHERE sv.id = @id AND di.deleted = @Deleted"; + WHERE sv.id = @id AND di.deleted = @Deleted and di.device_building_tag = @building_tag"; - object param = new { Deleted = 0, id = id }; + object param = new { Deleted = 0, id = id, building_tag = building_tag.Split("/")[1] }; var systemSubs = await backendRepository.GetAllAsync(sql, param); diff --git a/Backend/Controllers/VariableController.cs b/Backend/Controllers/VariableController.cs index a79ecbf..7943488 100644 --- a/Backend/Controllers/VariableController.cs +++ b/Backend/Controllers/VariableController.cs @@ -242,6 +242,10 @@ namespace Backend.Controllers return apiResult; } + /// + /// 獲取專案名稱(東別) + /// + /// [HttpPost] public async Task> ProjectName() { diff --git a/Backend/Models/SystemCategory.cs b/Backend/Models/SystemCategory.cs index d661db9..ba54301 100644 --- a/Backend/Models/SystemCategory.cs +++ b/Backend/Models/SystemCategory.cs @@ -78,4 +78,10 @@ namespace Backend.Models public string guid { get; set; } public string subguid { get; set; } } + + public class DeviceItemInput + { + public string sub_system_tag { get; set; } + public string building_tag { get; set; } + } } diff --git a/Backend/Views/BuildInfo/Index.cshtml b/Backend/Views/BuildInfo/Index.cshtml index e6ed47c..a498f85 100644 --- a/Backend/Views/BuildInfo/Index.cshtml +++ b/Backend/Views/BuildInfo/Index.cshtml @@ -262,11 +262,11 @@ maxlength: 50, filterspace: true }, - build_file_3d_modal: { - required: true, extension: "nwc|nwd" - } + //build_file_3d_modal: { + // required: true, extension: "nwc|nwd" + //} }, - messages: { build_file_3d_modal: "File must be nwc, nwd" } + //messages: { build_file_3d_modal: "File must be nwc, nwd" } }); //#region 儲存區域基本資料 diff --git a/Backend/Views/DeviceManage/Index.cshtml b/Backend/Views/DeviceManage/Index.cshtml index cb23ecf..f066639 100644 --- a/Backend/Views/DeviceManage/Index.cshtml +++ b/Backend/Views/DeviceManage/Index.cshtml @@ -1551,7 +1551,8 @@ var selectedSub_system_tag = selected_building_menu.main_system ? selected_building_menu.main_system.sub_system ? selected_building_menu.main_system.sub_system.sub_system_tag : "" : ""; var url = "/DeviceManage/GetDeviceItem"; var send_data = { - sub_system_tag: selectedSub_system_tag + sub_system_tag: selectedSub_system_tag, + building_tag: selected_device_building_tag } $.post(url, send_data, function (rel) { diff --git a/BackendWorkerService/Program.cs b/BackendWorkerService/Program.cs index d773820..af122ff 100644 --- a/BackendWorkerService/Program.cs +++ b/BackendWorkerService/Program.cs @@ -83,6 +83,7 @@ namespace BackendWorkerService #region Repository `J services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); #endregion Repository `J diff --git a/BackendWorkerService/Quartz/Jobs/ArchiveElectricMeterDayJob.cs b/BackendWorkerService/Quartz/Jobs/ArchiveElectricMeterDayJob.cs index 68920e0..3e45e0b 100644 --- a/BackendWorkerService/Quartz/Jobs/ArchiveElectricMeterDayJob.cs +++ b/BackendWorkerService/Quartz/Jobs/ArchiveElectricMeterDayJob.cs @@ -1,5 +1,6 @@ using Backend.Models; using BackendWorkerService.Services.Implement; +using Dapper; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -25,6 +26,7 @@ namespace BackendWorkerService.Quartz.Jobs { private readonly ILogger logger; private readonly IBackgroundServiceRepository backgroundServiceRepository; + private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository; protected readonly IDatabaseHelper _databaseHelper; private readonly ILogger loggers; @@ -32,10 +34,12 @@ namespace BackendWorkerService.Quartz.Jobs 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; } @@ -55,29 +59,47 @@ namespace BackendWorkerService.Quartz.Jobs 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 sub_system_guid = @sub_system_guid"; + 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 sub_system_guid = @sub_system_guid"; - var points = await backgroundServiceRepository.GetAllAsync("device_item", sPointWhere, new { sub_system_guid = electricMeterGuid }); + 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 deviceNumberPoints = new List(); + List electricDeviceNumberPoints = new List(); foreach (var electricMeter in electricMeters) { - foreach (var point in points) + 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); - deviceNumberPoints.Add(deviceNumberPoint); + 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 組合出所有電錶設備點位 @@ -118,8 +140,9 @@ namespace BackendWorkerService.Quartz.Jobs //stopWatch.Start(); //抓取每個設備的資料 - List> archiveDayRawDatas = new List>(); - foreach (var deviceNumberPoint in deviceNumberPoints) + 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/"); @@ -162,7 +185,7 @@ namespace BackendWorkerService.Quartz.Jobs archiveDayRawData.Add("@sum_rawdata", 0); archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); - archiveDayRawDatas.Add(archiveDayRawData); + electericArchiveDayRawDatas.Add(archiveDayRawData); } if (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容 @@ -170,7 +193,62 @@ namespace BackendWorkerService.Quartz.Jobs var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { - archiveDayRawDatas.AddRange(ArrangeRawDatas); + 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); } } } @@ -178,9 +256,53 @@ namespace BackendWorkerService.Quartz.Jobs //stopWatch.Stop(); //logger.LogInformation("【ArchiveElectricMeterDayJob】【天歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds); - if (archiveDayRawDatas.Count() > 0) + if (electericArchiveDayRawDatas.Count() > 0) { - var sql = $@"BEGIN TRANSACTION; + 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, @@ -227,8 +349,104 @@ namespace BackendWorkerService.Quartz.Jobs END COMMIT TRANSACTION;"; - await backgroundServiceRepository.ExecuteSql(sql, archiveDayRawDatas); - + 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", "任務完成"); } @@ -263,8 +481,9 @@ namespace BackendWorkerService.Quartz.Jobs //stopWatch.Start(); //抓取每個設備的資料 - List> archiveWeekRawDatas = new List>(); - foreach (var deviceNumberPoint in deviceNumberPoints) + 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/"); @@ -306,7 +525,7 @@ namespace BackendWorkerService.Quartz.Jobs archiveWeekRawData.Add("@sum_rawdata", 0); archiveWeekRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); - archiveWeekRawDatas.Add(archiveWeekRawData); + electricArchiveWeekRawDatas.Add(archiveWeekRawData); } if (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容 @@ -314,7 +533,61 @@ namespace BackendWorkerService.Quartz.Jobs var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { - archiveWeekRawDatas.AddRange(ArrangeRawDatas); + 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); } } } @@ -322,9 +595,55 @@ namespace BackendWorkerService.Quartz.Jobs //stopWatch.Stop(); //logger.LogInformation("【ArchiveElectricMeterDayJob】【週歸檔】【效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds); - if (archiveWeekRawDatas.Count() > 0) + if (electricArchiveWeekRawDatas.Count() > 0) { - var sql = $@"BEGIN TRANSACTION; + 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, @@ -371,8 +690,108 @@ namespace BackendWorkerService.Quartz.Jobs END COMMIT TRANSACTION;"; - await backgroundServiceRepository.ExecuteSql(sql, archiveWeekRawDatas); - + 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", "任務完成"); } @@ -409,8 +828,9 @@ namespace BackendWorkerService.Quartz.Jobs //stopWatch.Start(); //抓取每個設備的資料 - List> archiveMonthRawDatas = new List>(); - foreach (var deviceNumberPoint in deviceNumberPoints) + 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/"); @@ -452,7 +872,7 @@ namespace BackendWorkerService.Quartz.Jobs archiveMonthRawData.Add("@sum_rawdata", 0); archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); - archiveMonthRawDatas.Add(archiveMonthRawData); + electricArchiveMonthRawDatas.Add(archiveMonthRawData); } if (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容 @@ -460,7 +880,61 @@ namespace BackendWorkerService.Quartz.Jobs var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult); if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) { - archiveMonthRawDatas.AddRange(ArrangeRawDatas); + 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); } } } @@ -468,9 +942,52 @@ namespace BackendWorkerService.Quartz.Jobs //stopWatch.Stop(); //logger.LogInformation("【ArchiveElectricMeterDayJob】【月歸檔效能檢驗】[取得資料花費時間]{0} 毫秒", stopWatch.ElapsedMilliseconds); - if (archiveMonthRawDatas.Count() > 0) + if (electricArchiveMonthRawDatas.Count() > 0) { - var sql = $@"BEGIN TRANSACTION; + 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, @@ -517,7 +1034,103 @@ namespace BackendWorkerService.Quartz.Jobs END COMMIT TRANSACTION;"; - await backgroundServiceRepository.ExecuteSql(sql, archiveMonthRawDatas); + 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", "任務完成"); } @@ -532,13 +1145,13 @@ namespace BackendWorkerService.Quartz.Jobs #region 補償機制 //取得連線字串 - if(await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Compensate")) + if (await task_Detail.GetNeedWorkTask("ArchiveElectricMeterDayJob", "Compensate")) { try { await task_Detail.InsertWorkTime("ArchiveElectricMeterDayJob", "Compensate", "任務開始"); - ProcEletricMeterService procEletricMeterService = new ProcEletricMeterService(_databaseHelper.GetMSSqlConnectionString()); - procEletricMeterService.ArchiveData(); + ProcEletricMeterService procEletricMeterService = new ProcEletricMeterService(backgroundServiceRepository, backgroundServiceMsSqlRepository); + await procEletricMeterService.ArchiveData(); await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "Compensate", "任務完成"); } catch(Exception ex) @@ -547,13 +1160,7 @@ namespace BackendWorkerService.Quartz.Jobs logger.LogError("【ArchiveElectricMeterDayJob】【補償機制】【任務失敗】"); logger.LogError("【ArchiveElectricMeterDayJob】【補償機制】【任務失敗】[Exception]:{0}", ex.ToString()); } - - - } - - - #endregion 補償機制 await task_Detail.InsertWorkTime_End("ArchiveElectricMeterDayJob", "All","任務完成"); diff --git a/BackendWorkerService/Quartz/Jobs/WeatherAPIJob.cs b/BackendWorkerService/Quartz/Jobs/WeatherAPIJob.cs index b6f1716..8cf37f2 100644 --- a/BackendWorkerService/Quartz/Jobs/WeatherAPIJob.cs +++ b/BackendWorkerService/Quartz/Jobs/WeatherAPIJob.cs @@ -16,6 +16,7 @@ using System.Xml; using System.Xml.Serialization; using System.Linq; using NCrontab; +using BackendWorkerService.Services.Implement; namespace BackendWorkerService.Quartz.Jobs { @@ -82,7 +83,18 @@ namespace BackendWorkerService.Quartz.Jobs Task_Detail task_Detail = new Task_Detail(loggers, backendRepository); try { + var obixApiConfig = new ObixApiConfig(); + string encoded = string.Empty; + #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 設定 //取得氣象預報 if (await task_Detail.GetNeedWorkTask("WeatherAPI", "api_weateher")) { @@ -211,7 +223,7 @@ namespace BackendWorkerService.Quartz.Jobs var val = RainValue(observation.Alert.MsgType, observation.Alert.Info[0].Headline); if (val < 5) { - var ReStr = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString()); + var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString()); UpdatedNiagara("api_rain", ReStr, id); } } @@ -232,8 +244,8 @@ namespace BackendWorkerService.Quartz.Jobs { "@msgType", observation.Alert.MsgType}, { "@headline", observation.Alert.Info.Headline}, { "@areaDesc", area}, - { "@onset", observation.Alert.Info.Onset}, - { "@expires", observation.Alert.Info.Expires}, + { "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, + { "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; @@ -243,7 +255,7 @@ namespace BackendWorkerService.Quartz.Jobs var val = RainValue(observation.Alert.MsgType, observation.Alert.Info.Headline); if (val < 5) { - var ReStr = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString()); + var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET1/SeverityLEVL_RAIN/set", val.ToString()); UpdatedNiagara("api_rain", ReStr, id); } } @@ -296,7 +308,7 @@ namespace BackendWorkerService.Quartz.Jobs if (observation.Alert.Info[0].Urgency != null && observation.Alert.Info[0].Urgency != "Expected") { - var ReStr = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info[0].Urgency); + var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info[0].Urgency); UpdatedNiagara("api_typhoon", ReStr, id); } } @@ -317,8 +329,8 @@ namespace BackendWorkerService.Quartz.Jobs { "@areaDesc", area}, { "@urgency",observation.Alert.Info.Urgency}, { "@severity",observation.Alert.Info.Severity}, - { "@onset", observation.Alert.Info.Onset}, - { "@expires", observation.Alert.Info.Expires}, + { "@onset", observation.Alert.Info.Onset.ToString("yyyy-MM-dd HH:mm:ss")}, + { "@expires", observation.Alert.Info.Expires.ToString("yyyy-MM-dd HH:mm:ss")}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; @@ -328,7 +340,7 @@ namespace BackendWorkerService.Quartz.Jobs if (observation.Alert.Info.Urgency != null && observation.Alert.Info.Urgency != "Expected") { - var ReStr = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency); + var ReStr = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_MET2/SeverityLEVL_Typhoon/set", observation.Alert.Info.Urgency); UpdatedNiagara("api_typhoon", ReStr, id); } } @@ -353,8 +365,8 @@ namespace BackendWorkerService.Quartz.Jobs var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/E-A0015-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&format=JSON&areaName=%E8%87%BA%E5%8C%97%E5%B8%82"; HttpResponseMessage response = client.GetAsync(UVUri).Result; String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString(); - var observation = JsonConvert.DeserializeObject(jsonUVs); - if (observation.Success != "true") + var observation = QuickType.Welcome.FromJson(jsonUVs); + if (!observation.Success) { logger.LogInformation("【WeatherAPIJob】【取得地震觀測資料不正確】"); } @@ -362,7 +374,7 @@ namespace BackendWorkerService.Quartz.Jobs { logger.LogInformation("【WeatherAPIJob】【開始存入地震觀測到資料庫】"); List> EarthquakeAPIdbS = new List>(); - var nowNo = await backendRepository.GetOneAsync("select iif( Max(earthquakeNo) is null ,0,Max(earthquakeNo)) earthquakeNo from api_earthquake where newEarthquake = 1"); + var nowNo = await backendRepository.GetOneAsync("select if( Max(earthquakeNo) is null ,0,Max(earthquakeNo)) earthquakeNo from api_earthquake where newEarthquake = 1"); foreach (var a in observation.Records.Earthquake) { if (a.EarthquakeNo <= nowNo) @@ -371,8 +383,8 @@ namespace BackendWorkerService.Quartz.Jobs { { "@earthquakeNo", a.EarthquakeNo}, { "@newEarthquake", 0}, - { "@originTime", a.EarthquakeInfo.OriginTime}, - { "@magnitudeValue", a.EarthquakeInfo.Magnitude.MagnitudeValue}, + { "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, + { "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, { "@areaName", null}, { "@areaIntensity", null}, { "@created_by", "system"}, @@ -383,22 +395,22 @@ namespace BackendWorkerService.Quartz.Jobs } else { - if (a.Intensity.ShakingArea.Count > 0) + if (a.Intensity.ShakingArea.Length > 0) { Dictionary EarthquakeAPIdb = new Dictionary() { { "@earthquakeNo", a.EarthquakeNo}, { "@newEarthquake", 1}, - { "@originTime", a.EarthquakeInfo.OriginTime}, - { "@magnitudeValue", a.EarthquakeInfo.Magnitude.MagnitudeValue}, - { "@areaName", a.Intensity.ShakingArea[0].AreaName}, - { "@areaIntensity", a.Intensity.ShakingArea[0].AreaIntensity.Value}, + { "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, + { "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, + { "@areaName", a.Intensity.ShakingArea[0].CountyName}, + { "@areaIntensity", a.Intensity.ShakingArea[0].AreaIntensity}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; - var Nag = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/SeverityLEVL_LMI/set", a.Intensity.ShakingArea[0].AreaIntensity.Value.ToString()); + var Nag = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/SeverityLEVL_LMI/set", a.Intensity.ShakingArea[0].AreaIntensity.ToString()); if (Nag.Contains("err")) { @@ -418,15 +430,15 @@ namespace BackendWorkerService.Quartz.Jobs { { "@earthquakeNo", a.EarthquakeNo}, { "@newEarthquake", 1}, - { "@originTime", a.EarthquakeInfo.OriginTime}, - { "@magnitudeValue", a.EarthquakeInfo.Magnitude.MagnitudeValue}, + { "@originTime", DateTime.Parse(a.EarthquakeInfo.OriginTime.ToString(), System.Globalization.CultureInfo.CurrentCulture)}, + { "@magnitudeValue", a.EarthquakeInfo.EarthquakeMagnitude.MagnitudeValue}, { "@areaName", null}, { "@areaIntensity", null}, { "@created_by", "system"}, { "@created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, }; - var Nag = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/SeverityLEVL_LMI/set", "NULL"); + var Nag = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/CAP/D2_CWB_L110_CAP_GEO/SeverityLEVL_LMI/set", "NULL"); if (Nag.Contains("err")) { EarthquakeAPIdb.Add("@niagara", Nag); @@ -458,23 +470,23 @@ namespace BackendWorkerService.Quartz.Jobs weather_type, get_value FROM api_weateher - where id in (select MAX(id) from api_weateher where start_time < GETDATE() group by weather_type) + where id in (select MAX(id) from api_weateher where start_time < NOW() group by weather_type) order by start_time desc"; var types = await backendRepository.GetAllAsync(sql); var T = types.Where(a => a.weather_type == "T").FirstOrDefault(); - var RbT = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value); + var RbT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/T/set", T.get_value); UpdatedNiagara("api_weateher", RbT, T.id); var RH = types.Where(a => a.weather_type == "RH").FirstOrDefault(); - var RHT = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value); + var RHT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/RH/set", RH.get_value); UpdatedNiagara("api_weateher", RHT, RH.id); var PoP12h = types.Where(a => a.weather_type == "PoP12h").FirstOrDefault(); - var PoP12hT = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value); + var PoP12hT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/PoP6h/set", PoP12h.get_value); UpdatedNiagara("api_weateher", PoP12hT, PoP12h.id); var Wx = types.Where(a => a.weather_type == "Wx").FirstOrDefault(); - var WxT = Fetch_PostWithJSONFormat("http://60.251.164.125:8080/obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value); + var WxT = Fetch_PostWithJSONFormat($@"{obixApiConfig.ApiBase}obix/config/Arena/D2/CWB/L110/OPD/D2_CWB_L110_OPD_element/Wx/set", Wx.get_value); UpdatedNiagara("api_weateher", WxT, Wx.id); await task_Detail.InsertWorkTime_End("WeatherAPI", "set_weather"); } diff --git a/BackendWorkerService/Services/Implement/ProcEletricMeterService.cs b/BackendWorkerService/Services/Implement/ProcEletricMeterService.cs index 320be3a..4b54c1d 100644 --- a/BackendWorkerService/Services/Implement/ProcEletricMeterService.cs +++ b/BackendWorkerService/Services/Implement/ProcEletricMeterService.cs @@ -12,6 +12,10 @@ 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; namespace BackendWorkerService.Services.Implement { @@ -20,23 +24,17 @@ namespace BackendWorkerService.Services.Implement /// public class ProcEletricMeterService { - string Connection1 = string.Empty; - IDbConnection conn; + private readonly IBackgroundServiceRepository backgroundServiceRepository; + private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository; - public ProcEletricMeterService(string Connection_parame = null) + public ProcEletricMeterService(IBackgroundServiceRepository backgroundServiceRepository, + IBackgroundServiceMsSqlRepository backgroundServiceMySqlRepository) { - if (!string.IsNullOrEmpty(Connection_parame)) - { - Connection1 = Connection_parame; - conn = new SqlConnection(Connection_parame); - } - else - { - //Connection1 = ConfigurationManager.ConnectionStrings["mySql"].ConnectionString; - } + this.backgroundServiceRepository = backgroundServiceRepository; + this.backgroundServiceMsSqlRepository = backgroundServiceMySqlRepository; } - public bool ArchiveData() + public async Task ArchiveData() { bool result = false; int repeatTimes = 0; @@ -50,36 +48,68 @@ namespace BackendWorkerService.Services.Implement try { //取得可錯誤次數 - using (IDbConnection conn = new SqlConnection(Connection1)) - { - var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'"; + var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'"; - var variableArchive = conn.Query(sqlArchive); - repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault()); - - conn.Close(); - } + var variableArchive = await backgroundServiceRepository.GetAllAsync(sqlArchive); + repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault()); #region 取得obix 設定 - using (IDbConnection conn = new SqlConnection(Connection1)) - { + var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'"; - 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(); - var variableObix = conn.Query(sqlObix).ToList(); - 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()); - - encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password)); - - conn.Close(); - } + 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"; + //MY 新增/修改sql format + var MYsql_update_format = @" + UPDATE {0} 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 {0} ( + 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;"; //新增/修改sql format var sql_update_format = @"BEGIN TRANSACTION; @@ -130,356 +160,590 @@ namespace BackendWorkerService.Services.Implement 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(); + //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); + // 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 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 = $@" - - - - "; + // var historyQueryFilter = $@" + // + // + // + // "; - HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); - //HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); - archiveHourRequest.Method = "POST"; - archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded); - archiveHourRequest.PreAuthenticate = true; + // HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/"); + // //HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/"); + // archiveHourRequest.Method = "POST"; + // archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded); + // archiveHourRequest.PreAuthenticate = true; - byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter); - using (Stream reqStream = archiveHourRequest.GetRequestStream()) - { - reqStream.Write(byteArray, 0, byteArray.Length); - } + // 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(); + // 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); + // 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); + // 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")); + // 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); - } + // archiveHourRawDatas.Add(archiveDayRawData); + // } - if (archiveHourJsonResult.ContainsKey("obj")) //表示可以讀取到內容 - { - var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveHourJsonResult); - if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) - { - archiveHourRawDatas.AddRange(ArrangeRawDatas); - } - } - } + // 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(); - } + // if (archiveHourRawDatas.Count() > 0) + // { + // var sql_error_update = string.Format(sql_update_format, targetTable); + // conn.Execute(sql_error_update, archiveHourRawDatas); + // } + // } + // conn.Close(); + //} #endregion 時歸檔補償 #region 天歸檔補償 - using (IDbConnection conn = new SqlConnection(Connection1)) + //取得所有須補償的設備資訊 + targetTable = "archive_electric_meter_day"; + var sql_error_day = string.Format(sql_error_format, targetTable); + var electric_error_days = await backgroundServiceRepository.GetAllAsync(sql_error_day, new { RepeatTimes = repeatTimes }); + List> electricArchiveDayRawDatas = new List>(); + if (electric_error_days.Count() > 0) { - //取得所有須補償的設備資訊 - targetTable = "archive_electric_meter_day"; - var sql_error_day = string.Format(sql_error_format, targetTable); - var error_days = conn.Query(sql_error_day, new { RepeatTimes = repeatTimes }).ToList(); - - List> archiveDayRawDatas = new List>(); - if (error_days.Count() > 0) + foreach (var error_day in electric_error_days) { - foreach (var error_day in 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 endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T")); + + var historyQueryFilter = $@" + + + + "; + + 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()) { - 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 endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T")); - - var historyQueryFilter = $@" - - - - "; - - 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")) //抓取錯誤 - { - Dictionary archiveDayRawData = new Dictionary(); - archiveDayRawData.Add("@device_number", error_day.Device_number); - archiveDayRawData.Add("@point", error_day.Point); - archiveDayRawData.Add("@start_timestamp", error_day.Start_timestamp); - archiveDayRawData.Add("@end_timestamp", error_day.End_timestamp); - 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")); - - archiveDayRawDatas.Add(archiveDayRawData); - } - - if (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容 - { - var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult); - if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) - { - archiveDayRawDatas.AddRange(ArrangeRawDatas); - } - } + reqStream.Write(byteArray, 0, byteArray.Length); } - if (archiveDayRawDatas.Count() > 0) + 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")) //抓取錯誤 { - var sql_error_update = string.Format(sql_update_format, targetTable); - conn.Execute(sql_error_update, archiveDayRawDatas); + 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); + if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) + { + electricArchiveDayRawDatas.AddRange(ArrangeRawDatas); + } } } - conn.Close(); + 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 backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveDayRawDatas); + await backgroundServiceRepository.ExecuteSql(Mysql_error_update, electricArchiveDayRawDatas); + } + } + + targetTable = "archive_water_meter_day"; + 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 endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T")); + + var historyQueryFilter = $@" + + + + "; + + 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")) //抓取錯誤 + { + 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); + 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); + await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveDayRawDatas); + await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveDayRawDatas); + } } #endregion 天歸檔補償 #region 週歸檔補償 - using (IDbConnection conn = new SqlConnection(Connection1)) + //取得所有須補償的設備資訊 + 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) { - //取得所有須補償的設備資訊 - targetTable = "archive_electric_meter_week"; - var sql_error_week = string.Format(sql_error_format, targetTable); - var error_weeks = conn.Query(sql_error_week, new { RepeatTimes = repeatTimes }).ToList(); - - List> archiveWeekRawDatas = new List>(); - if (error_weeks.Count() > 0) + foreach (var error_week in eletric_error_weeks) { - foreach (var error_week in 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 historyQueryFilter = $@" + + + + "; + + 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()) { - 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 historyQueryFilter = $@" - - - - "; - - 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")) //抓取錯誤 - { - Dictionary archiveWeekRawData = new Dictionary(); - archiveWeekRawData.Add("@device_number", error_week.Device_number); - archiveWeekRawData.Add("@point", error_week.Point); - archiveWeekRawData.Add("@start_timestamp", error_week.Start_timestamp); - archiveWeekRawData.Add("@end_timestamp", error_week.End_timestamp); - 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")); - - archiveWeekRawDatas.Add(archiveWeekRawData); - } - - if (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容 - { - var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult); - if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) - { - archiveWeekRawDatas.AddRange(ArrangeRawDatas); - } - } + reqStream.Write(byteArray, 0, byteArray.Length); } - if (archiveWeekRawDatas.Count() > 0) + 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")) //抓取錯誤 { - var sql_error_update = string.Format(sql_update_format, targetTable); - conn.Execute(sql_error_update, archiveWeekRawDatas); + 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); + if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) + { + electricArchiveWeekRawDatas.AddRange(ArrangeRawDatas); + } } } - conn.Close(); + if (electricArchiveWeekRawDatas.Count() > 0) + { + var Mysql_error_update = string.Format(MYsql_update_format, targetTable); + var sql_error_update = string.Format(sql_update_format, targetTable); + 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 historyQueryFilter = $@" + + + + "; + + 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")) //抓取錯誤 + { + 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); + 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); + await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveWeekRawDatas); + await backgroundServiceRepository.ExecuteSql(Mysql_error_update, waterArchiveWeekRawDatas); + } } #endregion 週歸檔補償 #region 月歸檔補償 - using (IDbConnection conn = new SqlConnection(Connection1)) + //取得所有須補償的設備資訊 + 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) { - //取得所有須補償的設備資訊 - targetTable = "archive_electric_meter_month"; - var sql_error_month = string.Format(sql_error_format, targetTable); - var error_months = conn.Query(sql_error_month, new { RepeatTimes = repeatTimes }).ToList(); - - List> archiveMonthRawDatas = new List>(); - if (error_months.Count() > 0) + foreach (var error_month in electric_error_months) { - foreach (var error_month in 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 startDateTime = Convert.ToDateTime(error_month.Start_timestamp); + var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month); + + var historyQueryFilter = $@" + + + + "; + + 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()) { - 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 startDateTime = Convert.ToDateTime(error_month.Start_timestamp); - var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month); - - var historyQueryFilter = $@" - - - - "; - - 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")) //抓取錯誤 - { - Dictionary archiveMonthRawData = new Dictionary(); - archiveMonthRawData.Add("@device_number", error_month.Device_number); - archiveMonthRawData.Add("@point", error_month.Point); - archiveMonthRawData.Add("@start_timestamp", error_month.Start_timestamp); - archiveMonthRawData.Add("@end_timestamp", error_month.End_timestamp); - 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")); - - archiveMonthRawDatas.Add(archiveMonthRawData); - } - - if (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容 - { - var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult); - if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0) - { - archiveMonthRawDatas.AddRange(ArrangeRawDatas); - } - } + reqStream.Write(byteArray, 0, byteArray.Length); } - if (archiveMonthRawDatas.Count() > 0) + 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")) //抓取錯誤 { - var sql_error_update = string.Format(sql_update_format, targetTable); - conn.Execute(sql_error_update, archiveMonthRawDatas); + 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); + } } } - conn.Close(); + if (electricArchiveMonthRawDatas.Count() > 0) + { + var Mysql_error_update = string.Format(MYsql_update_format, targetTable); + var sql_error_update = string.Format(sql_update_format, targetTable); + await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, electricArchiveMonthRawDatas); + await backgroundServiceRepository.ExecuteSql(MYsql_update_format, electricArchiveMonthRawDatas); + } + } + + targetTable = "archive_electric_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 startDateTime = Convert.ToDateTime(error_month.Start_timestamp); + var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month); + + var historyQueryFilter = $@" + + + + "; + + 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")) //抓取錯誤 + { + 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); + await backgroundServiceMsSqlRepository.ExecuteSql(sql_error_update, waterArchiveMonthRawDatas); + await backgroundServiceRepository.ExecuteSql(MYsql_update_format, waterArchiveMonthRawDatas); + } } #endregion 月歸檔補償 diff --git a/BackendWorkerService/Services/Implement/Quicktype.cs b/BackendWorkerService/Services/Implement/Quicktype.cs new file mode 100644 index 0000000..35dab94 --- /dev/null +++ b/BackendWorkerService/Services/Implement/Quicktype.cs @@ -0,0 +1,640 @@ +using System; +using System.Collections.Generic; +using System.Text; + +// +// +// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do: +// +// using QuickType; +// +// var welcome = Welcome.FromJson(jsonString); + +namespace QuickType +{ + using System; + using System.Collections.Generic; + + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + public partial class Welcome + { + [JsonProperty("success")] + [JsonConverter(typeof(ParseStringConverter))] + public bool Success { get; set; } + + [JsonProperty("result")] + public Result Result { get; set; } + + [JsonProperty("records")] + public Records Records { get; set; } + } + + public partial class Records + { + [JsonProperty("datasetDescription")] + public DatasetDescription DatasetDescription { get; set; } + + [JsonProperty("Earthquake")] + public Earthquake[] Earthquake { get; set; } + } + + public partial class Earthquake + { + [JsonProperty("EarthquakeNo")] + public long EarthquakeNo { get; set; } + + [JsonProperty("ReportType")] + public DatasetDescription ReportType { get; set; } + + [JsonProperty("ReportColor")] + public ReportColor ReportColor { get; set; } + + [JsonProperty("ReportContent")] + public string ReportContent { get; set; } + + [JsonProperty("ReportImageURI")] + public Uri ReportImageUri { get; set; } + + [JsonProperty("ReportRemark")] + public ReportRemark ReportRemark { get; set; } + + [JsonProperty("Web")] + public Uri Web { get; set; } + + [JsonProperty("ShakemapImageURI")] + public Uri ShakemapImageUri { get; set; } + + [JsonProperty("EarthquakeInfo")] + public EarthquakeInfo EarthquakeInfo { get; set; } + + [JsonProperty("Intensity")] + public Intensity Intensity { get; set; } + } + + public partial class EarthquakeInfo + { + [JsonProperty("OriginTime")] + public DateTimeOffset OriginTime { get; set; } + + [JsonProperty("Source")] + public Source Source { get; set; } + + [JsonProperty("FocalDepth")] + public double FocalDepth { get; set; } + + [JsonProperty("Epicenter")] + public Epicenter Epicenter { get; set; } + + [JsonProperty("EarthquakeMagnitude")] + public EarthquakeMagnitude EarthquakeMagnitude { get; set; } + } + + public partial class EarthquakeMagnitude + { + [JsonProperty("MagnitudeType")] + public MagnitudeType MagnitudeType { get; set; } + + [JsonProperty("MagnitudeValue")] + public double MagnitudeValue { get; set; } + } + + public partial class Epicenter + { + [JsonProperty("Location")] + public string Location { get; set; } + + [JsonProperty("EpicenterLatitude")] + public double EpicenterLatitude { get; set; } + + [JsonProperty("EpicenterLongitude")] + public double EpicenterLongitude { get; set; } + } + + public partial class Intensity + { + [JsonProperty("ShakingArea")] + public ShakingArea[] ShakingArea { get; set; } + } + + public partial class ShakingArea + { + [JsonProperty("AreaDesc")] + public string AreaDesc { get; set; } + + [JsonProperty("CountyName")] + public string CountyName { get; set; } + + [JsonProperty("InfoStatus", NullValueHandling = NullValueHandling.Ignore)] + public InfoStatus? InfoStatus { get; set; } + + [JsonProperty("AreaIntensity")] + public AreaIntensityEnum AreaIntensity { get; set; } + + [JsonProperty("EqStation")] + public EqStation[] EqStation { get; set; } + } + + public partial class EqStation + { + [JsonProperty("pga", NullValueHandling = NullValueHandling.Ignore)] + public Pga Pga { get; set; } + + [JsonProperty("pgv", NullValueHandling = NullValueHandling.Ignore)] + public Pga Pgv { get; set; } + + [JsonProperty("StationName")] + public string StationName { get; set; } + + [JsonProperty("StationID")] + public string StationId { get; set; } + + [JsonProperty("InfoStatus", NullValueHandling = NullValueHandling.Ignore)] + public InfoStatus? InfoStatus { get; set; } + + [JsonProperty("BackAzimuth")] + public double BackAzimuth { get; set; } + + [JsonProperty("EpicenterDistance")] + public double EpicenterDistance { get; set; } + + [JsonProperty("SeismicIntensity")] + public AreaIntensityEnum SeismicIntensity { get; set; } + + [JsonProperty("StationLatitude")] + public double StationLatitude { get; set; } + + [JsonProperty("StationLongitude")] + public double StationLongitude { get; set; } + + [JsonProperty("WaveImageURI", NullValueHandling = NullValueHandling.Ignore)] + public Uri WaveImageUri { get; set; } + } + + public partial class Pga + { + [JsonProperty("unit")] + public Unit Unit { get; set; } + + [JsonProperty("EWComponent")] + public double EwComponent { get; set; } + + [JsonProperty("NSComponent")] + public double NsComponent { get; set; } + + [JsonProperty("VComponent")] + public double VComponent { get; set; } + + [JsonProperty("IntScaleValue")] + public double IntScaleValue { get; set; } + } + + public partial class Result + { + [JsonProperty("resource_id")] + public string ResourceId { get; set; } + + [JsonProperty("fields")] + public Field[] Fields { get; set; } + } + + public partial class Field + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("type")] + public TypeEnum Type { get; set; } + } + + public enum DatasetDescription { 地震報告 }; + + public enum MagnitudeType { 芮氏規模 }; + + public enum Source { 中央氣象局 }; + + public enum AreaIntensityEnum { The1級, The2級, The3級, The4級 }; + + public enum InfoStatus { Observe }; + + public enum Unit { Gal, Kine }; + + public enum ReportColor { 綠色 }; + + public enum ReportRemark { 本報告係中央氣象局地震觀測網即時地震資料地震速報之結果 }; + + public enum TypeEnum { Float, Integer, String, Timestamp }; + + public partial class Welcome + { + public static Welcome FromJson(string json) => JsonConvert.DeserializeObject(json, QuickType.Converter.Settings); + } + + public static class Serialize + { + public static string ToJson(this Welcome self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings); + } + + internal static class Converter + { + public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings + { + MetadataPropertyHandling = MetadataPropertyHandling.Ignore, + DateParseHandling = DateParseHandling.None, + Converters = + { + MagnitudeTypeConverter.Singleton, + SourceConverter.Singleton, + AreaIntensityEnumConverter.Singleton, + InfoStatusConverter.Singleton, + UnitConverter.Singleton, + ReportColorConverter.Singleton, + ReportRemarkConverter.Singleton, + DatasetDescriptionConverter.Singleton, + TypeEnumConverter.Singleton, + new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal } + }, + }; + } + + internal class MagnitudeTypeConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(MagnitudeType) || t == typeof(MagnitudeType?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "芮氏規模") + { + return MagnitudeType.芮氏規模; + } + throw new Exception("Cannot unmarshal type MagnitudeType"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (MagnitudeType)untypedValue; + if (value == MagnitudeType.芮氏規模) + { + serializer.Serialize(writer, "芮氏規模"); + return; + } + throw new Exception("Cannot marshal type MagnitudeType"); + } + + public static readonly MagnitudeTypeConverter Singleton = new MagnitudeTypeConverter(); + } + + internal class SourceConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(Source) || t == typeof(Source?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "中央氣象局") + { + return Source.中央氣象局; + } + throw new Exception("Cannot unmarshal type Source"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (Source)untypedValue; + if (value == Source.中央氣象局) + { + serializer.Serialize(writer, "中央氣象局"); + return; + } + throw new Exception("Cannot marshal type Source"); + } + + public static readonly SourceConverter Singleton = new SourceConverter(); + } + + internal class AreaIntensityEnumConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(AreaIntensityEnum) || t == typeof(AreaIntensityEnum?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + switch (value) + { + case "1級": + return AreaIntensityEnum.The1級; + case "2級": + return AreaIntensityEnum.The2級; + case "3級": + return AreaIntensityEnum.The3級; + case "4級": + return AreaIntensityEnum.The4級; + } + throw new Exception("Cannot unmarshal type AreaIntensityEnum"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (AreaIntensityEnum)untypedValue; + switch (value) + { + case AreaIntensityEnum.The1級: + serializer.Serialize(writer, "1級"); + return; + case AreaIntensityEnum.The2級: + serializer.Serialize(writer, "2級"); + return; + case AreaIntensityEnum.The3級: + serializer.Serialize(writer, "3級"); + return; + case AreaIntensityEnum.The4級: + serializer.Serialize(writer, "4級"); + return; + } + throw new Exception("Cannot marshal type AreaIntensityEnum"); + } + + public static readonly AreaIntensityEnumConverter Singleton = new AreaIntensityEnumConverter(); + } + + internal class InfoStatusConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(InfoStatus) || t == typeof(InfoStatus?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "observe") + { + return InfoStatus.Observe; + } + throw new Exception("Cannot unmarshal type InfoStatus"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (InfoStatus)untypedValue; + if (value == InfoStatus.Observe) + { + serializer.Serialize(writer, "observe"); + return; + } + throw new Exception("Cannot marshal type InfoStatus"); + } + + public static readonly InfoStatusConverter Singleton = new InfoStatusConverter(); + } + + internal class UnitConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(Unit) || t == typeof(Unit?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + switch (value) + { + case "gal": + return Unit.Gal; + case "kine": + return Unit.Kine; + } + throw new Exception("Cannot unmarshal type Unit"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (Unit)untypedValue; + switch (value) + { + case Unit.Gal: + serializer.Serialize(writer, "gal"); + return; + case Unit.Kine: + serializer.Serialize(writer, "kine"); + return; + } + throw new Exception("Cannot marshal type Unit"); + } + + public static readonly UnitConverter Singleton = new UnitConverter(); + } + + internal class ReportColorConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(ReportColor) || t == typeof(ReportColor?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "綠色") + { + return ReportColor.綠色; + } + throw new Exception("Cannot unmarshal type ReportColor"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (ReportColor)untypedValue; + if (value == ReportColor.綠色) + { + serializer.Serialize(writer, "綠色"); + return; + } + throw new Exception("Cannot marshal type ReportColor"); + } + + public static readonly ReportColorConverter Singleton = new ReportColorConverter(); + } + + internal class ReportRemarkConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(ReportRemark) || t == typeof(ReportRemark?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "本報告係中央氣象局地震觀測網即時地震資料地震速報之結果。") + { + return ReportRemark.本報告係中央氣象局地震觀測網即時地震資料地震速報之結果; + } + throw new Exception("Cannot unmarshal type ReportRemark"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (ReportRemark)untypedValue; + if (value == ReportRemark.本報告係中央氣象局地震觀測網即時地震資料地震速報之結果) + { + serializer.Serialize(writer, "本報告係中央氣象局地震觀測網即時地震資料地震速報之結果。"); + return; + } + throw new Exception("Cannot marshal type ReportRemark"); + } + + public static readonly ReportRemarkConverter Singleton = new ReportRemarkConverter(); + } + + internal class DatasetDescriptionConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(DatasetDescription) || t == typeof(DatasetDescription?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + if (value == "地震報告") + { + return DatasetDescription.地震報告; + } + throw new Exception("Cannot unmarshal type DatasetDescription"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (DatasetDescription)untypedValue; + if (value == DatasetDescription.地震報告) + { + serializer.Serialize(writer, "地震報告"); + return; + } + throw new Exception("Cannot marshal type DatasetDescription"); + } + + public static readonly DatasetDescriptionConverter Singleton = new DatasetDescriptionConverter(); + } + + internal class TypeEnumConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(TypeEnum) || t == typeof(TypeEnum?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + switch (value) + { + case "Float": + return TypeEnum.Float; + case "Integer": + return TypeEnum.Integer; + case "String": + return TypeEnum.String; + case "Timestamp": + return TypeEnum.Timestamp; + } + throw new Exception("Cannot unmarshal type TypeEnum"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (TypeEnum)untypedValue; + switch (value) + { + case TypeEnum.Float: + serializer.Serialize(writer, "Float"); + return; + case TypeEnum.Integer: + serializer.Serialize(writer, "Integer"); + return; + case TypeEnum.String: + serializer.Serialize(writer, "String"); + return; + case TypeEnum.Timestamp: + serializer.Serialize(writer, "Timestamp"); + return; + } + throw new Exception("Cannot marshal type TypeEnum"); + } + + public static readonly TypeEnumConverter Singleton = new TypeEnumConverter(); + } + + internal class ParseStringConverter : JsonConverter + { + public override bool CanConvert(Type t) => t == typeof(bool) || t == typeof(bool?); + + public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) return null; + var value = serializer.Deserialize(reader); + bool b; + if (Boolean.TryParse(value, out b)) + { + return b; + } + throw new Exception("Cannot unmarshal type bool"); + } + + public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer) + { + if (untypedValue == null) + { + serializer.Serialize(writer, null); + return; + } + var value = (bool)untypedValue; + var boolString = value ? "true" : "false"; + serializer.Serialize(writer, boolString); + return; + } + + public static readonly ParseStringConverter Singleton = new ParseStringConverter(); + } +} diff --git a/BackendWorkerService/appsettings.Development.json b/BackendWorkerService/appsettings.Development.json index 0b7f905..c92b558 100644 --- a/BackendWorkerService/appsettings.Development.json +++ b/BackendWorkerService/appsettings.Development.json @@ -7,23 +7,40 @@ } }, "BackgroundServiceCron": { - "ExecutionBackgroundServicePlanJob": "0 0 2 * * ?", - "MessageNotificationJob": "0 0 2 * * ?", - "DataDeliveryJob": "0 0 2 * * ?", - "RegularUpdateDBTableJob": "0 0 2 * * ?", - "ParkingJob": "0 0 2 * * ?", - "ArchiveElectricMeterHourJob": "0 0 2 * * ?", - "ArchiveElectricMeterDayJob": "0 0 2 * * ?", + "ExecutionBackgroundServicePlanJob": "0 0 1 * * ?", + "MessageNotificationJob": "0 0 1 * * ?", + "DataDeliveryJob": "0 0 1 * * ?", + "RegularUpdateDBTableJob": "0 0 1 * * ?", + "ParkingJob": "0 0 1 * * ?", + "ArchiveElectricMeterHourJob": "0 0 1 * * ?", + "ArchiveElectricMeterDayJob": "0 0 1 * * ?", "WeatherAPIJob": "0/5 * * * * ?" }, "DBConfig": { + //"MySqlDBConfig": { + // "Server": "TNi6aupYHPZT8ZU177KTKw==", //172.16.220.251 + // "Port": "mkF51jVbg40V5K5eTh2Ckw==", + // "Database": "VvfWH/59gQguY2eA2xBCug==", + // "Root": "IV8Ec1Ng2AWAnkBafXy2kg==", + // "Password": "Jue6jMFRi11meN6xbdKwDA==" + //}, "MySqlDBConfig": { - "Server": "TNi6aupYHPZT8ZU177KTKw==", //172.16.220.251 - "Port": "mkF51jVbg40V5K5eTh2Ckw==", - "Database": "VvfWH/59gQguY2eA2xBCug==", - "Root": "IV8Ec1Ng2AWAnkBafXy2kg==", - "Password": "Jue6jMFRi11meN6xbdKwDA==" + "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201 + "Port": "js2LutKe+rdjzdxMPQUrvQ==", + //"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 + //"Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp + "Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome + //"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel + "Root": "SzdxEgaJJ7tcTCrUl2zKsA==", + "Password": "FVAPxztxpY4gJJKQ/se4bQ==" }, + "MSSqlDBConfig": { + "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130 + "Port": "S5cUXKnKOacFtFy9+0dtpw==", + "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome + "Root": "sD8GZ9UPiIQGU6dU011/4A==", + "Password": "0O24es2ZRF5uoJ4aU+YCdg==" + } //"MSSqlDBConfig": { //greencloud.fic.com.tw,1433 // "Server": "ueFp+VFb200lhh1Uctc97WH0/tX6tfXYU2v1oxCWuuM=", // "Port": "S5cUXKnKOacFtFy9+0dtpw==", @@ -31,13 +48,13 @@ // "Root": "+plVKQ+enAqt7BYV2uMQng==", // "Password": "0O24es2ZRF5uoJ4aU+YCdg==" //} - "MSSqlDBConfig": { - "Server": "zp3Nilx0PISEEC4caZWqCg==", //172.16.220.250 - "Port": "7puf4kd9qJ/q0fq2QASWeQ==", - "Database": "VvfWH/59gQguY2eA2xBCug==", - "Root": "sD8GZ9UPiIQGU6dU011/4A==", - "Password": "Jue6jMFRi11meN6xbdKwDA==" - } + //"MSSqlDBConfig": { + // "Server": "zp3Nilx0PISEEC4caZWqCg==", //172.16.220.250 + // "Port": "7puf4kd9qJ/q0fq2QASWeQ==", + // "Database": "VvfWH/59gQguY2eA2xBCug==", + // "Root": "sD8GZ9UPiIQGU6dU011/4A==", + // "Password": "Jue6jMFRi11meN6xbdKwDA==" + //} }, "SMTPConfig": { diff --git a/BackendWorkerService/appsettings.json b/BackendWorkerService/appsettings.json index 619afd3..7271896 100644 --- a/BackendWorkerService/appsettings.json +++ b/BackendWorkerService/appsettings.json @@ -14,13 +14,30 @@ "RegularUpdateDBTableJob": "0 0 2 * * ?" }, "DBConfig": { + //"MySqlDBConfig": { + // "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201 + // "Port": "js2LutKe+rdjzdxMPQUrvQ==", + // "Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 + // "Root": "SzdxEgaJJ7tcTCrUl2zKsA==", + // "Password": "FVAPxztxpY4gJJKQ/se4bQ==" + //}, "MySqlDBConfig": { "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201 "Port": "js2LutKe+rdjzdxMPQUrvQ==", - "Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 + //"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 + //"Database": "IgYBsgG2VLKKxFb64j7LOA==", //wsp + "Database": "7gWfmZ28HGIJZbxEbK+0yg==", //tpe_dome_dome + //"Database": "siTUcDaC/g2yGTMFWD72Kg==", //tpe_dome_hotel "Root": "SzdxEgaJJ7tcTCrUl2zKsA==", "Password": "FVAPxztxpY4gJJKQ/se4bQ==" }, + "MSSqlDBConfig": { + "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130 + "Port": "S5cUXKnKOacFtFy9+0dtpw==", + "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome + "Root": "sD8GZ9UPiIQGU6dU011/4A==", + "Password": "0O24es2ZRF5uoJ4aU+YCdg==" + } //"MSSqlDBConfig": { // "Server": "avZg8PA8C9GVgYZBgEKzCg==", // "Port": "lJA0KPkG6RvFfTgWiXFyUw==", diff --git a/BackendWorkerService/root/PowerfulRain.xml b/BackendWorkerService/root/PowerfulRain.xml new file mode 100644 index 0000000..fdfa044 --- /dev/null +++ b/BackendWorkerService/root/PowerfulRain.xml @@ -0,0 +1,192 @@ + + + + CWB-Weather_extremely-rain_202305081515001 + weather@cwb.gov.tw + 2023-05-08T15:21:31+08:00 + Actual + Cancel + Public + weather@cwb.gov.tw,CWB-Weather_extremely-rain_202305081030001,2023-05-08T10:37:48+08:00 weather@cwb.gov.tw,CWB-Weather_extremely-rain_202305080840001,2023-05-08T08:51:11+08:00 + + zh-TW + Met + 降雨 + Past + Minor + Observed + + profile:CAP-TWP:Event:1.0 + rainfall + + 2023-05-08T15:15:00+08:00 + 2023-05-08T15:17:00+08:00 + 2023-05-08T15:31:31+08:00 + 中央氣象局 + 解除大雨特報 + +由於降雨趨於緩和,發生大雨的機率降低,故解除大雨特報;今(8)日屏東及臺東山區仍有局部較大雨勢發生,請注意。 + + + https://www.cwb.gov.tw/V8/C/P/Warning/FIFOWS.html + + alert_title + 大雨特報 + + + + 基隆市 + + Taiwan_Geocode_103 + 10017 + + + + 臺北市 + + Taiwan_Geocode_103 + 63 + + + + 新北市 + + Taiwan_Geocode_103 + 65 + + + + 桃園市 + + Taiwan_Geocode_103 + 68 + + + + 新竹市 + + Taiwan_Geocode_103 + 10018 + + + + 新竹縣 + + Taiwan_Geocode_103 + 10004 + + + + 苗栗縣 + + Taiwan_Geocode_103 + 10005 + + + + 臺中市 + + Taiwan_Geocode_103 + 66 + + + + 彰化縣 + + Taiwan_Geocode_103 + 10007 + + + + 雲林縣 + + Taiwan_Geocode_103 + 10009 + + + + 南投縣 + + Taiwan_Geocode_103 + 10008 + + + + 嘉義縣 + + Taiwan_Geocode_103 + 10010 + + + + 嘉義市 + + Taiwan_Geocode_103 + 10020 + + + + 臺南市 + + Taiwan_Geocode_103 + 67 + + + + 高雄市 + + Taiwan_Geocode_103 + 64 + + + + 屏東縣 + + Taiwan_Geocode_103 + 10013 + + + + 宜蘭縣 + + Taiwan_Geocode_103 + 10002 + + + + 花蓮縣 + + Taiwan_Geocode_103 + 10015 + + + + 臺東縣 + + Taiwan_Geocode_103 + 10014 + + + + 澎湖縣 + + Taiwan_Geocode_103 + 10016 + + + + 金門縣 + + Taiwan_Geocode_103 + 09020 + + + + 連江縣 + + Taiwan_Geocode_103 + 09007 + + + + \ No newline at end of file diff --git a/BackendWorkerService/root/Typhoon.xml b/BackendWorkerService/root/Typhoon.xml new file mode 100644 index 0000000..6098d81 --- /dev/null +++ b/BackendWorkerService/root/Typhoon.xml @@ -0,0 +1,197 @@ + + + + CWB-Weather_typhoon-warning_202210162030001 + weather@cwb.gov.tw + 2022-10-16T20:20:41+08:00 + Actual + Cancel + Public + weather@cwb.gov.tw,CWB-Weather_typhoon-warning_202210161730001,2022-10-16T17:20:00+08:00 + + zh-TW + Met + 颱風 + Past + Minor + Observed + + profile:CAP-TWP:Event:1.0 + typhoon + + 2022-10-16T20:30:00+08:00 + 2022-10-16T20:30:00+08:00 + 2022-10-16T20:40:00+08:00 + 中央氣象局 + 解除颱風警報 + +[颱風動態] +根據最新資料顯示,第20號颱風已增強為中度颱風,中心目前在鵝鑾鼻西南方海面,向西南西移動,對巴士海峽近海的威脅已解除。 + +[注意事項] +*今(16日)晚至明(17)日巴士海峽及臺灣附近各海面風浪仍偏大,各沿海地區(含蘭嶼、綠島)及澎湖、金門、馬祖有長浪發生的機率,請避免前往海邊活動。*今(16日)晚雲林以北、恆春半島沿海空曠地區及澎湖、馬祖易有9至10級強陣風,東半部、嘉義、臺南沿海空曠地區及蘭嶼、綠島、金門亦有較強陣風;明(17)日臺南以北沿海空曠地區、蘭嶼、綠島、澎湖、金門、馬祖易有9至12級強陣風,東半部沿海地區及西半部地區有8至9級強陣風,路樹、懸掛物、招牌等物品宜加強固定,外出活動、機車騎士行車或行經高架橋車輛,請特別注意安全。*自15日0時至16日20時出現較大累積雨量如下:臺北市擎天崗989.0毫米,宜蘭縣樂水分校973.5毫米,新北市汐止579.5毫米,基隆市五堵578.0毫米,桃園市嘎拉賀555.0毫米,新竹縣西丘斯山478.0毫米,臺中市南湖圈谷394.5毫米,花蓮縣和平林道361.0毫米。*本警報單之颱風半徑為平均半徑,第20號颱風之7級風暴風半徑北半象限約220公里,南半象限約180公里,平均半徑約為200公里。颱風詳細特性請參考本局颱風輔助說明(https://www.cwb.gov.tw/Data/typhoon/TY_ PDF.pdf)。*此為第20號颱風警報最後一次報告。 + + + + https://www.cwb.gov.tw/V8/C/P/Warning/FIFOWS.html + + alert_title + 颱風警報 + + + + 基隆市 + + Taiwan_Geocode_103 + 10017 + + + + 臺北市 + + Taiwan_Geocode_103 + 63 + + + + 新北市 + + Taiwan_Geocode_103 + 65 + + + + 桃園市 + + Taiwan_Geocode_103 + 68 + + + + 新竹市 + + Taiwan_Geocode_103 + 10018 + + + + 新竹縣 + + Taiwan_Geocode_103 + 10004 + + + + 苗栗縣 + + Taiwan_Geocode_103 + 10005 + + + + 臺中市 + + Taiwan_Geocode_103 + 66 + + + + 彰化縣 + + Taiwan_Geocode_103 + 10007 + + + + 雲林縣 + + Taiwan_Geocode_103 + 10009 + + + + 南投縣 + + Taiwan_Geocode_103 + 10008 + + + + 嘉義縣 + + Taiwan_Geocode_103 + 10010 + + + + 嘉義市 + + Taiwan_Geocode_103 + 10020 + + + + 臺南市 + + Taiwan_Geocode_103 + 67 + + + + 高雄市 + + Taiwan_Geocode_103 + 64 + + + + 屏東縣 + + Taiwan_Geocode_103 + 10013 + + + + 宜蘭縣 + + Taiwan_Geocode_103 + 10002 + + + + 花蓮縣 + + Taiwan_Geocode_103 + 10015 + + + + 臺東縣 + + Taiwan_Geocode_103 + 10014 + + + + 澎湖縣 + + Taiwan_Geocode_103 + 10016 + + + + 金門縣 + + Taiwan_Geocode_103 + 09020 + + + + 連江縣 + + Taiwan_Geocode_103 + 09007 + + + + \ No newline at end of file diff --git a/FrontendWebApi/ApiControllers/BuildController.cs b/FrontendWebApi/ApiControllers/BuildController.cs index 4739007..c751dc4 100644 --- a/FrontendWebApi/ApiControllers/BuildController.cs +++ b/FrontendWebApi/ApiControllers/BuildController.cs @@ -44,25 +44,29 @@ namespace FrontendWebApi.ApiControllers var sql = $@" SELECT ( - SELECT TOP(1) w.get_value + SELECT w.get_value FROM api_weateher w WHERE w.weather_type = 'Wx' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC + limit 1 ) AS WxText, ( - SELECT TOP(1) wd.WeatherKey + SELECT wd.WeatherKey FROM api_weateher w LEFT JOIN weather_description wd ON w.get_value = wd.WeatherValue WHERE w.weather_type = 'WxV' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC + limit 1 ) AS Wx, ( - SELECT TOP(1) w.get_value + SELECT w.get_value FROM api_weateher w WHERE w.weather_type = 'T' AND @DateNow < w.start_time + limit 1 ) AS Temp, ( - SELECT TOP(1) w.get_value + SELECT w.get_value FROM api_weateher w WHERE w.weather_type = 'RH' AND @DateNow < w.start_time + limit 1 ) AS RH "; var dateNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:00"); @@ -163,86 +167,84 @@ namespace FrontendWebApi.ApiControllers } try { - var buildmenusql = await backendRepository.GetAllAsync(@$" select - me.* , - b.full_name bfull_name, - b.ip_address, - b.priority bpriority, - ma.full_name mafull_name, - ma.priority mapriority, - ma.code, - sub.full_name subfull_name, - sub.priority subpriority + me.* , + b.full_name bfull_name, + b.ip_address, + b.priority bpriority, + v1.system_key mafull_name, + v1.system_priority mapriority, + v1.system_value, + v2.system_key subfull_name, + v2.system_priority subpriority from building_menu me - left join building b on b.building_guid = me.building_guid - left join main_system ma on ma.main_system_guid = me.main_system_guid - left join sub_system sub on sub.sub_system_guid = me.sub_system_guid + left join building b on b.building_tag = me.building_tag + left join variable v1 on me.main_system_tag = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2' + left join variable v2 on me.sub_system_tag = v2.system_value and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3' inner join ( - SELECT - ap.building_guid, - ap.ShowView - FROM - ( - SELECT * - FROM role_auth ra - WHERE ra.role_guid = (SELECT ui.role_guid from userinfo ui where account = @Account) - ) ra - left join auth_page ap on ra.AuthCode = ap.AuthCode - where ap.AuthType = 1 - ) shower on shower.building_guid = me.building_guid and shower.ShowView = me.sub_system_guid - order by b.priority, ma.priority,sub.priority, sub.created_at DESC", new { Account = account }); + SELECT + ap.building_tag, + ap.ShowView + FROM + ( + SELECT * + FROM role_auth ra + WHERE ra.role_guid = (SELECT ui.role_guid from userinfo ui where account = @Account) + ) ra + left join auth_page ap on ra.AuthCode = ap.AuthCode + where ap.AuthType = 1 + ) shower on shower.building_tag = me.building_tag and shower.ShowView = v2.id + order by b.priority, v1.system_priority, v2.system_priority, v2.created_at DESC", new { Account = account }); var floorsql = await backendRepository.GetAllAsync(@" select * from (select * from sub_system_floor ssf where ssf.deleted = 0 and ssf.status = 0) a - left join floor on floor.floor_guid = a.floor_guid order by floor.priority"); + left join floor on floor.full_name = a.floor_tag order by floor.priority;"); - var common = await backendRepository.GetAllAsync($@"select ap.building_guid Name,ap.ShowView Value from auth_page ap + var common = await backendRepository.GetAllAsync($@"select ap.building_tag Name,ap.ShowView Value from auth_page ap left join role_auth ra on ra.AuthCode = ap.AuthCode right join userinfo ui on ui.role_guid = ra.role_guid where SUBSTRING(ap.AuthCode,1,1) = 'C' and ui.account = '{account}' - "); + "); - var building = buildmenusql.GroupBy(a => a.building_guid).ToList(); + var building = buildmenusql.GroupBy(a => a.building_tag).ToList(); List buildingMenus = new List(); foreach (var menu in building) { Building building1 = new Building() { - building_guid = menu.Select(a => a.building_guid).FirstOrDefault(), full_name = menu.Select(a => a.bfull_name).FirstOrDefault(), ip_address = menu.Select(a => a.ip_address).FirstOrDefault(), priority = menu.Select(a => a.bpriority).FirstOrDefault(), - device_building_tag = menu.Select(a => a.device_building_tag).FirstOrDefault(), + building_tag = menu.Select(a => a.device_building_tag).FirstOrDefault(), main_system = new List(), common = new List() }; - var commonlist = common.Where(a => a.Name == building1.building_guid).Select(a => a.Value).ToList(); + var commonlist = common.Where(a => a.Name == building1.building_tag).Select(a => a.Value).ToList(); building1.common = commonlist; - var mainsystem = menu.GroupBy(a => a.main_system_guid).ToList(); + var mainsystem = menu.GroupBy(a => a.main_system_tag).ToList(); foreach (var ma in mainsystem) { Main_system main_System = new Main_system() { code = ma.Select(a => a.code).FirstOrDefault(), - main_system_guid = ma.Select(a => a.main_system_guid).FirstOrDefault(), + main_system_tag = ma.Select(a => a.main_system_tag).FirstOrDefault(), full_name = ma.Select(a => a.mafull_name).FirstOrDefault(), priority = ma.Select(a => a.mapriority).FirstOrDefault(), Sub_system = new List() }; - var subsystem = ma.GroupBy(a => a.sub_system_guid).ToList(); + var subsystem = ma.GroupBy(a => a.sub_system_tag).ToList(); foreach (var sub in subsystem) { Sub_systemGuid sub_System = new Sub_systemGuid() { - sub_system_guid = sub.Select(a => a.sub_system_guid).FirstOrDefault(), + sub_system_tag = sub.Select(a => a.sub_system_tag).FirstOrDefault(), full_name = sub.Select(a => a.subfull_name).FirstOrDefault(), priority = sub.Select(a => a.subpriority).FirstOrDefault(), device_system_tag = sub.Select(a => a.device_system_tag).FirstOrDefault(), OpenTab = sub.Select(a => a.OpenTab).FirstOrDefault(), - system_url = sub.Select(a => a.system_url).FirstOrDefault() + system_url = sub.Select(a => a.left_system_url).FirstOrDefault() }; main_System.Sub_system.Add(sub_System); } @@ -279,26 +281,26 @@ namespace FrontendWebApi.ApiControllers } try { - var sub_system = await backendRepository.GetOneAsync(@$"select ss.full_name subfull_name,me.* from building_menu me - left join sub_system ss on ss.sub_system_tag = me.sub_system_tag - where me.building_tag = '{get.building_tag}' and me.main_system_tag = '{get.main_system_tag}' and me.sub_system_tag = '{get.sub_system_tag}' order by ss.priority"); + var sub_system = await backendRepository.GetOneAsync(@$"select v.system_key subfull_name,me.* from building_menu me + left join variable v on v.system_value = me.sub_system_tag and v.system_type = 'device_system_category_layer3' and v.deleted = 0 + where me.building_tag = '{get.building_tag}' and me.main_system_tag = '{get.main_system_tag}' and me.sub_system_tag = '{get.sub_system_tag}' order by v.system_priority"); List Floors = new List(); var floorsql = await backendRepository.GetAllAsync($@" - select * from (select * from sub_system_floor ssf where ssf.deleted = 0 and ssf.status = 0 and ssf.building_tag = '{get.building_tag}' and ssf.main_system_guid = '{get.main_system_tag}' and ssf.sub_system_tag = '{get.sub_system_tag}') a - left join floor on floor.floor_guid = a.floor_guid order by floor.priority"); + select * from (select * from sub_system_floor ssf where ssf.deleted = 0 and ssf.status = 0 and ssf.building_tag = '{get.building_tag}' and ssf.main_system_tag = '{get.main_system_tag}' and ssf.sub_system_tag = '{get.sub_system_tag}') a + left join floor on floor.full_name = a.floor_tag order by floor.priority"); Sub_system sub_System = new Sub_system() { - sub_system_guid = sub_system.sub_system_guid, - system_url = sub_system.system_url, - drawing = sub_system.drawing, + sub_system_tag = sub_system.sub_system_tag, + left_system_url = sub_system.left_system_url, + left_drawing = sub_system.left_drawing, Floors = new List(), full_name = sub_system.subfull_name, - icon_click = sub_system.icon_click, - icon_click_url = sub_system.icon_click_url, - planimetric_click = sub_system.planimetric_click, - planimetric_floor_guid = sub_system.planimetric_floor_guid, - riser_diagram_url = sub_system.riser_diagram_url, + left_icon_click = sub_system.left_icon_click, + left_icon_click_url = sub_system.left_icon_click_url, + left_planimetric_click = sub_system.left_planimetric_click, + left_planimetric_floor_guid = sub_system.left_planimetric_floor_guid, + left_riser_diagram_url = sub_system.left_riser_diagram_url, priority = sub_system.subpriority }; foreach (var floor in floorsql) @@ -307,6 +309,7 @@ namespace FrontendWebApi.ApiControllers { devices = null, floor_guid = floor.floor_guid, + Floor_map_name = floor.Floor_map_name, full_name = floor.full_name, InitMapName = floor.InitMapName, priority = floor.priority @@ -378,11 +381,11 @@ namespace FrontendWebApi.ApiControllers string sql = $@" SELECT device_building_tag, - device_system_tag + sub_system_tag FROM building_menu - WHERE building_guid = @building_guid - AND main_system_guid = @main_system_guid - AND sub_system_guid = @sub_system_guid + WHERE building_tag = @building_tag + AND main_system_tag = @main_system_tag + AND sub_system_tag = @sub_system_tag "; var tagName = await backendRepository.GetOneAsync(sql, post); @@ -513,13 +516,14 @@ namespace FrontendWebApi.ApiControllers END AS device_master_number, dm.device_master_full_name, dm.device_master_icon, - bm.icon_click, - bm.icon_click_url, - bm.icon_click_url_width, - bm.icon_click_url_height, + bm.left_icon_click, + bm.left_icon_click_url, + bm.left_icon_click_url_width, + bm.left_icon_click_url_height, di.full_name as point_name, di.points, - di.is_bool as points_is_bool + di.is_bool as points_is_bool, + f.floor_guid from device d left join device_kind dk on d.device_building_tag = dk.device_building_tag and d.device_system_tag = dk.device_system_tag @@ -530,6 +534,7 @@ namespace FrontendWebApi.ApiControllers left join device_item di ON d.device_name_tag = di.device_name_tag AND di.deleted = 0 AND di.is_show_riserDiagram = 1 + left join floor f on d.device_floor_tag = f.full_name and f.deleted = 0 {disasterjoinsql} LEFT JOIN building_menu bm ON d.device_building_tag = bm.building_tag AND d.device_system_tag = bm.main_system_tag AND d.device_name_tag = bm.sub_system_tag where d.deleted = 0 and d.device_building_tag = '{post.building_tag}' {sWhere} @@ -685,5 +690,37 @@ namespace FrontendWebApi.ApiControllers return Ok(apiResult); } + + [HttpPost] + [Route("api/GetAllfloor")] + public async Task>>> GetAllfloor(string building_tag) + { + ApiResult> apiResult = new ApiResult>(jwt_str); + if (!jwtlife) + { + apiResult.Code = "5000"; + return BadRequest(apiResult); + } + try + { + string sWhere = $@" + SELECT + floor_guid,full_name,building_tag + FROM floor + where building_tag = @building_tag and deleted = 0 order by priority"; + var floor = await backendRepository.GetAllAsync(sWhere, new { building_tag = building_tag }); + + apiResult.Data = floor; + apiResult.Code = "0000"; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + return Ok(apiResult); + } + return Ok(apiResult); + + } } } diff --git a/FrontendWebApi/ApiControllers/HiNetController.cs b/FrontendWebApi/ApiControllers/HiNetController.cs new file mode 100644 index 0000000..30b901a --- /dev/null +++ b/FrontendWebApi/ApiControllers/HiNetController.cs @@ -0,0 +1,805 @@ +using System; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using FrontendWebApi.Models; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +/// +/// HiNet 企業簡訊 API for .NetCore 2.0 +/// Web : https://sms.hinet.net +/// Email : hiair@hinet.net +/// +/// Changelog : +/// 2018/04/19 - 初版 +/// + +namespace FrontendWebApi.ApiControllers +{ + /// + /// Request類別 + /// + enum RequestType : byte + { + LOGIN = 0, + SEND = 1, + QUERY = 2, + SENDLONG = 11, + QUERYLONG = 12, + SENDFOREIGN = 15, + CANCEL = 16, + CANCELLONG = 17, + SENDFOREIGNLONG = 18 + } + + /// + /// 訊息編碼 + /// + enum MsgCoding : byte + { + BIG5 = 1, + BINARY = 2, + UCS2 = 3, + UTF8 = 4 + } + + /// + /// 其他定數常數 + /// + enum MsgConst : byte + { + UNUSED = 0 + } + + /// + /// 資料長度定義 + /// + enum LENGTH : int + { + RESPSET = 80, + REQSET = 100, + CONTENT = 160, + REQUEST = 266, + RESPONSE = 244, + SMS_LEN = 70, + ASCII_SMS_LEN = 159, + LONG_ASCII_MSG_LEN = 153, + LONG_MSG_LEN = 67, + MAX_LONG_SPLIT = 10 + } + + [Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + /// + /// 傳送資料到hiAirV2的資料結構 + /// + struct MsgRequest + { + public byte type; //訊息型態 + public byte coding; //訊息編碼種類 + public byte priority; //訊息優先權 + public byte countryCode; //手機國碼 + public byte setLen; //set[] 訊息內容的長度 + public byte contentLen; //content[]訊息內容的長度 + + // 訊息相關資料設定 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)LENGTH.REQSET)] + public byte[] set; + + // 簡訊內容 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)LENGTH.CONTENT)] + public byte[] content; + } + + [Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 1)] + /// + /// 從hiAirV2接收資料的資料結構 + /// + struct MsgResponse + { + public byte code; //回傳訊息代碼 + public byte coding; //訊息編碼種類 + public byte setLen; //set[] 訊息內容的長度 + public byte contentLen; //content[]訊息內容的長度 + + // 訊息相關資料 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)LENGTH.RESPSET)] + public byte[] set; + + // MessageID或其他文字描述 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)LENGTH.CONTENT)] + public byte[] content; + } + + /// + /// HiNet企業簡訊 Hiair .Net Core API + /// + public class HiNetController : MyBaseApiController + { + + public Socket socket; + + // 傳送型態 + private const String SEND_NOW = "01"; //即時傳送 + private const String SEND_EXPIRE = "02"; //截止重送時間 + private const String SEND_RESERVE = "03"; //預約傳送 + private const String SEND_RESERVE_EXPIRE = "04"; //預約傳送+截止重送時間 + + // 回覆結果的訊息說明 + private StringBuilder retMessage = new StringBuilder(); + + public HiNetController() { } + + /// + /// 將MsgRequest結構轉為byte array + /// + /// MsgRequest結構 + /// byte array + byte[] encode(MsgRequest req) + { + int size = Marshal.SizeOf(req); + byte[] buf = new byte[size]; + + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(req, ptr, true); + Marshal.Copy(ptr, buf, 0, size); + Marshal.FreeHGlobal(ptr); + return buf; + } + + /// + /// 將byte array轉為MsgResponse結構 + /// + /// byte array + /// MsgResponse結構 + MsgResponse decode(byte[] buf) + { + MsgResponse rep = new MsgResponse(); + int size = buf.Length; + + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.Copy(buf, 0, ptr, size); + rep = (MsgResponse)Marshal.PtrToStructure(ptr, rep.GetType()); + Marshal.FreeHGlobal(ptr); + return rep; + } + + /// + /// 建立與hiAirV2的連線 + /// + /// Server IP + /// Server Port + /// 登入帳號 + /// 登入密碼 + /// 0表示連線正常,-3,-4表示異常或斷線。其餘回傳值請參考規格書 + public int StartCon(String serverName, int port, String userID, String passwd) + { + // 回傳值變數 + int ret = 0; + + int timeout = 1000 * 60; //60sec + + socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + socket.ReceiveTimeout = timeout; + socket.SendTimeout = timeout; + + // 將資料清空 + retMessage.Clear(); + + try + { + socket.Connect(serverName, port); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine(ex.Message); + retMessage = new StringBuilder("Socket Create Error!"); + return -3; + } + + // 設定登入帳號與密碼 + String msgSet = String.Format("{0}\0{1}\0", userID, passwd); + String msgContent = String.Empty; + + // 設定Request資料 + MsgRequest req = new MsgRequest(); + req.type = (byte)RequestType.LOGIN; + req.coding = (byte)MsgCoding.BIG5; + req.priority = (byte)MsgConst.UNUSED; + req.countryCode = (byte)MsgConst.UNUSED; + req.setLen = (byte)msgSet.Length; + req.contentLen = (byte)msgContent.Length; + req.set = Encoding.ASCII.GetBytes(msgSet.PadRight((int)LENGTH.REQSET, '\0')); + req.content = Encoding.ASCII.GetBytes(msgContent.PadRight((int)LENGTH.CONTENT, '\0')); + + // 傳送與接收資料 + ret = sendToserver(req); + + return ret; + } + + /// + /// 立即傳送文字簡訊 + /// + /// 門號 + /// 簡訊內容 + /// 0表示訊息成功傳送至主機,其餘回傳值請參考規格書 + public int SendMsg(String mobileNum, String SMSMessage) + { + return this.Send(mobileNum, SMSMessage, String.Empty, String.Empty); + } + + /// + /// 預約傳送文字簡訊 + /// + /// 門號 + /// 簡訊內容 + /// 預約傳送時間,格式yymmddhhmmss + /// 0表示訊息成功傳送至主機,其餘回傳值請參考規格書 + public int SendMsg_Reserve(String mobileNum, String SMSMessage, String reserveTime) + { + return this.Send(mobileNum, SMSMessage, reserveTime, String.Empty); + } + + /// + /// 立即傳送文字簡訊加重送截止時間 + /// + /// 門號 + /// 簡訊內容 + /// 重送截止時間,單位分鐘0001 ~ 1440 + /// 0表示訊息成功傳送至主機,其餘回傳值請參考規格書 + public int SendMsg_Expire(String mobileNum, String SMSMessage, String expireTime) + { + return this.Send(mobileNum, SMSMessage, String.Empty, expireTime); + } + + /// + /// 預約傳送文字簡訊加重送截止時間 + /// + /// 門號 + /// 簡訊內容 + /// 預約傳送時間,格式yymmddhhmmss + /// 重送截止時間,單位分鐘0001 ~ 1440 + /// 0表示訊息成功傳送至主機,其餘回傳值請參考規格書 + public int SendMsg_Reserve_Expire(String mobileNum, String SMSMessage, String reserveTime, String expireTime) + { + return this.Send(mobileNum, SMSMessage, reserveTime, expireTime); + } + + /// + /// 傳送文字簡訊(封裝程式僅供內部呼叫用) + /// + /// 門號 + /// 簡訊內容 + /// 預約傳送時間,格式yymmddhhmmss + /// 重送截止時間,單位分鐘0001 ~ 1440 + /// 0表示訊息成功傳送至主機,其餘回傳值請參考規格書 + private int Send(String mobileNum, String SMSMessage, String reserveTime, String expireTime) + { + + int ret = 0; + retMessage.Clear(); + + byte[] utf8 = Encoding.UTF8.GetBytes(SMSMessage); + byte[] ucs2 = Encoding.GetEncoding("UTF-16BE").GetBytes(SMSMessage); + + int contentLength = 0; + + MsgRequest req = new MsgRequest(); + + // 若UTF8 Bytes長度與原資料長度相等,表示為純英數字 + if (utf8.Length == SMSMessage.Length) + { //純英數 + req.coding = (byte)MsgCoding.BIG5; + contentLength = SMSMessage.Length; + if (SMSMessage.Length > (int)LENGTH.ASCII_SMS_LEN) + { + retMessage = new StringBuilder("message content length exceeded"); + return -5; + } + } + else + { + req.coding = (byte)MsgCoding.UCS2; //非純英數 + contentLength = ucs2.Length; + + if (SMSMessage.Length > (int)LENGTH.SMS_LEN) + { + retMessage = new StringBuilder("message content length exceeded"); + return -5; + } + + } + + // 帶+號為國外文字簡訊,否則為國內簡訊 + byte msgType = mobileNum.StartsWith("+") ? (byte)RequestType.SENDFOREIGN : (byte)RequestType.SEND; + + String msgSet; + + if (String.IsNullOrEmpty(reserveTime) && String.IsNullOrEmpty(expireTime) == false) + { + // 立即傳送 + msgSet = String.Format("{0}\0{1}\0{2}\0", mobileNum, SEND_EXPIRE, expireTime); + } + else if (String.IsNullOrEmpty(reserveTime) == false && String.IsNullOrEmpty(expireTime)) + { + // 立即傳送加重送截止時間 + msgSet = String.Format("{0}\0{1}\0{2}\0", mobileNum, SEND_RESERVE, reserveTime); + } + else if (String.IsNullOrEmpty(reserveTime) == false && String.IsNullOrEmpty(expireTime) == false) + { + // 預約傳送 + msgSet = String.Format("{0}\0{1}\0{2}\0{3}\0", mobileNum, SEND_RESERVE_EXPIRE, reserveTime, expireTime); + } + else + { + // 預約傳送加重送截止時間 + msgSet = String.Format("{0}\0{1}\0", mobileNum, SEND_NOW); + } + + // 設定Request資料 + req.type = msgType; + req.priority = (byte)MsgConst.UNUSED; + req.countryCode = (byte)MsgConst.UNUSED; + req.setLen = (byte)msgSet.Length; + req.contentLen = (byte)contentLength; + req.set = Encoding.ASCII.GetBytes(msgSet.PadRight((int)LENGTH.REQSET, '\0')); + if (req.coding == (byte)MsgCoding.UCS2) + { + //非純英數字以UCS2 byte傳送 + req.content = Encoding.GetEncoding("UTF-16BE").GetBytes(SMSMessage.PadRight((int)LENGTH.CONTENT, '\0')); + } + else + { + //純英數字以BIG5 byte傳送 + req.content = Encoding.ASCII.GetBytes(SMSMessage.PadRight((int)LENGTH.CONTENT, '\0')); + } + + // 傳送與接收資料 + ret = this.sendToserver(req); + + return ret; + + } + + /// + /// 立即傳送長簡訊 + /// 長簡訊中文每個分則長度為67個字,純英數字每個為則為153個字。 + /// 若中文簡訊沒大於70個字,或是純英數字沒大於159個字,請使用一般簡訊SendMsg相關Method。 + /// 否則將被拆為多則傳送或依實際使用則數計費 + /// + /// 門號 + /// 簡訊內容 + /// + public int SendMsg_Long(String mobileNum, String SMSMessage) + { + return this.SendLong(mobileNum, SMSMessage, String.Empty, String.Empty); + } + + /// + /// 傳送長簡訊加重送期限 + /// 長簡訊中文每個分則長度為67個字,純英數字每個為則為153個字。 + /// 若中文簡訊沒大於70個字,或是純英數字沒大於159個字,請使用一般簡訊SendMsg相關Method。 + /// 否則將被拆為多則傳送或依實際使用則數計費 + /// + /// 門號 + /// 簡訊內容 + /// 重送截止時間,單位分鐘0001 ~ 1440 + /// + public int SendMsg_Long_Expire(String mobileNum, String SMSMessage, String expireTime) + { + return this.SendLong(mobileNum, SMSMessage, String.Empty, expireTime); + } + + /// + /// 傳送長簡訊加預約時間 + /// 長簡訊中文每個分則長度為67個字,純英數字每個為則為153個字。 + /// 若中文簡訊沒大於70個字,或是純英數字沒大於159個字,請使用一般簡訊SendMsg相關Method。 + /// 否則將被拆為多則傳送或依實際使用則數計費 + /// + /// 門號 + /// 簡訊內容 + /// 預約傳送時間,格式yymmddhhmmss + /// + public int SendMsg_Long_Reserve(String mobileNum, String SMSMessage, String reserveTime) + { + return this.SendLong(mobileNum, SMSMessage, reserveTime, String.Empty); + } + + /// + /// 傳送長簡訊加預約時間與重送期限 + /// 長簡訊中文每個分則長度為67個字,純英數字每個為則為153個字。 + /// 若中文簡訊沒大於70個字,或是純英數字沒大於159個字,請使用一般簡訊SendMsg相關Method。 + /// 否則將被拆為多則傳送或依實際使用則數計費 + /// + /// 門號 + /// 簡訊內容 + /// 預約傳送時間,格式yymmddhhmmss + /// 重送截止時間,單位分鐘0001 ~ 1440 + /// + public int SendMsg_Long_Reserve_Expire(String mobileNum, String SMSMessage, String reserveTime, String expireTime) + { + return this.SendLong(mobileNum, SMSMessage, reserveTime, expireTime); + } + + /// + /// 傳送長簡訊(封裝程式僅供內部呼叫用) + /// 長簡訊中文每個分則長度為67個字,純英數字每個為則為153個字。 + /// 若中文簡訊沒大於70個字,或是純英數字沒大於159個字,請使用一般簡訊SendMsg*。 + /// 否則將被拆為多則傳送或依實際使用則數計費 + /// + /// 門號 + /// 簡訊內容 + /// 預約傳送時間,格式yymmddhhmmss + /// 重送截止時間,單位分鐘0001 ~ 1440 + /// + private int SendLong(String mobileNum, String SMSMessage, String reserveTime, String expireTime) + { + int ret = 0; + retMessage.Clear(); + + byte[] utf8 = Encoding.UTF8.GetBytes(SMSMessage); + byte[] ucs2 = Encoding.GetEncoding("UTF-16BE").GetBytes(SMSMessage); + int msg_len = 0; + + MsgCoding coding; + if (utf8.Length == SMSMessage.Length) + { + coding = MsgCoding.BIG5; + msg_len = (int)LENGTH.LONG_ASCII_MSG_LEN; // 純英數字每則分則最長153個字 + } + else + { + coding = MsgCoding.UCS2; + msg_len = (int)LENGTH.LONG_MSG_LEN; // 非純英數字每則分則最長67個字 + } + + // 計算需要拆成多少則分則 + double n = Math.Ceiling((double)SMSMessage.Length / (double)msg_len); + double numOfMsg = Math.Round(n); + + // 需要發送numOfMsg+1則 + for (int cnt = 0; cnt <= numOfMsg; cnt++) + { + + if (cnt == 0) + { + // 第一則發送metadata + + MsgRequest req = new MsgRequest(); + // 判斷是否為國外門號 + req.type = mobileNum.StartsWith("+") ? (byte)RequestType.SENDFOREIGNLONG : (byte)RequestType.SENDLONG; + + String msgSet; + if (String.IsNullOrEmpty(reserveTime) && String.IsNullOrEmpty(expireTime) == false) + { + // 立即傳送 + msgSet = String.Format("{0}\0{1}\0{2}\0", mobileNum, SEND_EXPIRE, expireTime); + } + else if (String.IsNullOrEmpty(reserveTime) == false && String.IsNullOrEmpty(expireTime)) + { + // 立即傳送加重送截止時間 + msgSet = String.Format("{0}\0{1}\0{2}\0", mobileNum, SEND_RESERVE, reserveTime); + } + else if (String.IsNullOrEmpty(reserveTime) == false && String.IsNullOrEmpty(expireTime) == false) + { + // 預約傳送 + msgSet = String.Format("{0}\0{1}\0{2}\0{3}\0", mobileNum, SEND_RESERVE_EXPIRE, reserveTime, expireTime); + } + else + { + // 預約傳送加重送截止時間 + msgSet = String.Format("{0}\0{1}\0", mobileNum, SEND_NOW); + } + + // 第一則用不到 + String msgContent = String.Format("\0"); + + req.coding = (byte)coding; + req.priority = (byte)MsgConst.UNUSED; + req.countryCode = (byte)MsgConst.UNUSED; + req.setLen = (byte)msgSet.Length; + req.contentLen = (byte)numOfMsg; // 填通數 + req.set = Encoding.ASCII.GetBytes(msgSet.PadRight((int)LENGTH.REQSET, '\0')); + req.content = Encoding.ASCII.GetBytes(msgContent.PadRight((int)LENGTH.CONTENT, '\0')); + + ret = sendToserver(req); + + } + else + { + // 第二則開始送簡訊內容 + MsgRequest req = new MsgRequest(); + req.type = (byte)cnt; // 填第幾通 + req.coding = (byte)coding; + req.priority = (byte)MsgConst.UNUSED; + req.countryCode = (byte)MsgConst.UNUSED; + + // 用不到 + String msgSet = String.Format("\0"); + req.setLen = (byte)msgSet.Length; + req.set = Encoding.ASCII.GetBytes(msgSet.PadRight((int)LENGTH.REQSET, '\0')); + + // 取分則內容 + String partial_msg; + try + { + partial_msg = SMSMessage.Substring((cnt - 1) * msg_len, msg_len); + } + catch + { + // ArgumentOutOfRangeException: 超過指定長度就取到字串結尾 + partial_msg = SMSMessage.Substring((cnt - 1) * msg_len); + } + + if (req.coding == (byte)MsgCoding.UCS2) + { + // 非純英數字以UCS2 byte傳送 + byte[] buf = Encoding.GetEncoding("UTF-16BE").GetBytes(partial_msg); + req.content = Encoding.GetEncoding("UTF-16BE").GetBytes(partial_msg.PadRight((int)LENGTH.CONTENT, '\0')); + req.contentLen = (byte)buf.Length; + } + else + { + // 純英數字以BIG5 byte傳送 + byte[] buf = Encoding.ASCII.GetBytes(partial_msg); + req.content = Encoding.ASCII.GetBytes(partial_msg.PadRight((int)LENGTH.CONTENT, '\0')); + req.contentLen = (byte)buf.Length; + } + + ret = sendToserver(req); + + } + + if (ret != 0) + { + // 若中途有錯誤直接中斷迴圈不送 + System.Diagnostics.Debug.WriteLine(String.Format("SendLong() Exit => {0} : {1}", ret, retMessage)); + return ret; + } + } + + return ret; + } + + /// + /// 傳送與接收資料 + /// + /// Request結構 + /// 回應代碼 + private int sendToserver(MsgRequest req) + { + + int ret; + retMessage.Clear(); + + // 將MsgRequest結構轉byte array後傳送 + byte[] data = encode(req); + try + { + int sent = socket.Send(data); + if (sent != (int)LENGTH.REQUEST) + { + retMessage = new StringBuilder("Socket Send Data Error!"); + System.Diagnostics.Debug.WriteLine("sent length:" + sent); + return -4; + } + } + catch + { + retMessage = new StringBuilder("Socket Send Data Error!"); + return -4; + } + + + // 將接收到的byte arry轉為MsgResponse結構 + byte[] buf = new byte[(int)LENGTH.RESPONSE]; + try + { + int recv = socket.Receive(buf); + if (recv != (int)LENGTH.RESPONSE) + { + retMessage = new StringBuilder("Socket Receive Data Error!"); + System.Diagnostics.Debug.WriteLine("recv length:" + recv); + return -4; + } + } + catch + { + retMessage = new StringBuilder("Socket Receive Data Error!"); + return -4; + } + + MsgResponse rep = decode(buf); + // 回傳代碼 + ret = rep.code; + // 回傳的文字描述或MessageID + retMessage = new StringBuilder(Encoding.ASCII.GetString(rep.content).TrimEnd((Char)0)); + + System.Diagnostics.Debug.WriteLine(String.Format("sendToServer() result => {0} : {1}", ret, retMessage)); + + return ret; + + } + + /// + /// 查詢一般簡訊狀態 + /// + /// 訊息ID + /// 0表示訊息已成功送達對方,其餘回傳值請參考規格書 + public int QueryMsg(String messageID) + { + retMessage.Clear(); + + return this.Query(RequestType.QUERY, messageID); + + } + + /// + /// 查詢長簡訊狀態 + /// + /// 訊息ID + /// 0表示訊息已成功送達對方,其餘回傳值請參考規格書 + public int QueryLongMsg(String messageID) + { + retMessage.Clear(); + + return this.Query(RequestType.QUERYLONG, messageID); + } + + /// + /// 查詢簡訊狀態 + /// + /// 查詢類別 + /// 訊息ID + /// 0表示訊息已成功送達對方,其餘回傳值請參考規格書 + private int Query(RequestType type, String messageID) + { + int ret = 0; + retMessage.Clear(); + + + String msgSet = String.Format("{0}\0", messageID); + String msgContent = String.Empty; + + // 設定Request資料 + MsgRequest req = new MsgRequest(); + req.type = (byte)type; + req.coding = (byte)MsgCoding.BIG5; + req.priority = (byte)MsgConst.UNUSED; + req.countryCode = (byte)MsgConst.UNUSED; + req.setLen = (byte)msgSet.Length; + req.contentLen = (byte)msgContent.Length; + req.set = Encoding.ASCII.GetBytes(msgSet.PadRight((int)LENGTH.REQSET, '\0')); + req.content = Encoding.ASCII.GetBytes(msgContent.PadRight((int)LENGTH.CONTENT, '\0')); + + ret = sendToserver(req); + return ret; + } + + /// + /// 取消預約一般簡訊 + /// + /// 訊息ID + /// 0表示訊息已取消成功,其餘回傳值請參考規格書 + public int CancelMsg(String messageID) + { + retMessage.Clear(); + + return this.Cancel(RequestType.CANCEL, messageID); + } + + /// + /// 取消預約長簡訊 + /// + /// 訊息ID + /// 0表示訊息已取消成功,其餘回傳值請參考規格書 + public int CancelLongMsg(String messageID) + { + retMessage.Clear(); + + return this.Cancel(RequestType.CANCELLONG, messageID); + } + + /// + /// 取消預約簡訊(封裝程式僅供內部呼叫用) + /// + /// 預約類別 + /// 訊息ID + /// 0表示訊息已取消成功,其餘回傳值請參考規格書 + private int Cancel(RequestType type, String messageID) + { + int ret = 0; + retMessage.Clear(); + + String msgSet = String.Format("{0}\0", messageID); + String msgContent = String.Empty; + + // 設定Request資料 + MsgRequest req = new MsgRequest(); + req.type = (byte)type; + req.coding = (byte)MsgCoding.BIG5; + req.priority = (byte)MsgConst.UNUSED; + req.countryCode = (byte)MsgConst.UNUSED; + req.setLen = (byte)msgSet.Length; + req.contentLen = (byte)msgContent.Length; + req.set = Encoding.ASCII.GetBytes(msgSet.PadRight((int)LENGTH.REQSET, '\0')); + req.content = Encoding.ASCII.GetBytes(msgContent.PadRight((int)LENGTH.CONTENT, '\0')); + + ret = sendToserver(req); + return ret; + } + + /// + /// 取得描述文字或MessageID + /// + /// 文字或MessageID + public String Get_Message() + { + return this.retMessage.ToString(); + } + + /// + /// 與簡訊主機中斷連線 + /// + public void EndCon() + { + retMessage.Clear(); + if (socket.Connected) + { + socket.Disconnect(false); + } + } + + /// + /// hinet發送信息 + /// + /// + /// + [HttpPost] + [Route("api/HiNetMsg")] + public ActionResult> HiNetMsg(HiNetInput input) + { + ApiResult apiResult = new ApiResult(jwt_str); + //if (!jwtlife) + //{ + // apiResult.Code = "5000"; + // return BadRequest(apiResult); + //} + + try + { + var hiair = new HiNetController(); + int retCode = hiair.StartCon("202.39.54.130", 8000, "airtest6", "95929ALz"); + string retContent = string.Empty; + if (retCode == 0) + { + //發送文字簡訊並回傳狀態碼 + retCode = hiair.SendMsg(input.Number, input.Msg); + //取得messageID或文字描述 + retContent = hiair.Get_Message(); + apiResult.Data = retCode + " : " + retContent; + } + else + { + apiResult.Code = "5000"; + apiResult.Msg = retCode + " : " + retContent; + return BadRequest(apiResult); + } + this.EndCon(); + } + catch (Exception exception) + { + apiResult.Code = "9999"; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + return Ok(apiResult); + } + + return Ok(apiResult); + } + } +} \ No newline at end of file diff --git a/FrontendWebApi/ApiControllers/HistoryController.cs b/FrontendWebApi/ApiControllers/HistoryController.cs index 7ed5160..ff8622a 100644 --- a/FrontendWebApi/ApiControllers/HistoryController.cs +++ b/FrontendWebApi/ApiControllers/HistoryController.cs @@ -26,15 +26,18 @@ namespace FrontendWebApi.ApiControllers { private readonly IBackendRepository backendRepository; private readonly IFrontendRepository frontendRepository; + private readonly IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository; public HistoryController ( IBackendRepository backendRepository, - IFrontendRepository frontendRepository + IFrontendRepository frontendRepository, + IBackgroundServiceMsSqlRepository backgroundServiceMsSqlRepository ) { this.backendRepository = backendRepository; this.frontendRepository = frontendRepository; + this.backgroundServiceMsSqlRepository = backgroundServiceMsSqlRepository; } /// @@ -206,11 +209,11 @@ namespace FrontendWebApi.ApiControllers join variable v1 on v1.id = v2.system_parent_id and v1.system_type = @main_system_type join device d on v1.system_value = d.device_system_tag and v2.system_value = d.device_name_tag and d.deleted = 0 and d.visible = 1 join device_item di on d.device_system_tag=di.device_system_tag and d.device_name_tag=di.device_name_tag - and di.is_link = 1 + and di.is_link = 1 and di.is_show_history = 1 where c.account = @account order by v1.system_priority, v2.system_priority", new { @account = myUser.account, @sub_system_type = sub_system_type, @main_system_type = main_system_type }); var dbbuilding = await frontendRepository.GetAllAsync( - @$"select distinct d.building_guid,d.full_name,d.priority from role_auth a + @$"select distinct d.building_tag,d.full_name,d.priority from role_auth a join auth_page b on a.AuthCode = b.AuthCode join userinfo c on c.role_guid = a.role_guid join building d on d.building_tag = b.building_tag @@ -335,7 +338,7 @@ namespace FrontendWebApi.ApiControllers wheres.Add("d.deleted = 0"); if (postDevice.SelectBuildings != null && postDevice.SelectBuildings.Count() > 0) { - wheres.Add("d.building_guid in @builds"); + wheres.Add("d.device_building_tag in @builds"); } if (postDevice.SelectFloors != null && postDevice.SelectFloors.Count() > 0) @@ -345,7 +348,7 @@ namespace FrontendWebApi.ApiControllers if (postDevice.SelectSub != null && postDevice.SelectSub.Count() > 0) { - wheres.Add("d.sub_system_guid in @syss"); + wheres.Add("d.device_name_tag in @syss"); } if (!string.IsNullOrEmpty(postDevice.Device_name)) @@ -358,18 +361,17 @@ namespace FrontendWebApi.ApiControllers var sql = $@"SELECT a.device_guid, b.full_name building_name, - c.full_name main_name, - d.full_name sub_name, - d.full_name sub_name, + v1.system_key main_name, + v2.system_key sub_name, a.full_name device_name, a.device_number from (SELECT * FROM device d WHERE {wheres_str}) a - join building b on b.building_guid = a.building_guid - join main_system c on c.main_system_guid = a.main_system_guid - join sub_system d on d.sub_system_guid = a.sub_system_guid - order by b.priority,c.priority,d.priority,a.priority"; + join building b on b.building_tag = a.device_building_tag + join variable v1 on v1.system_value = a.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2' + join variable v2 on v2.system_value = a.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3' + order by b.priority,v1.system_priority,v2.system_priority,a.priority"; var dbDevice = await backendRepository.GetAllAsync(sql, new { builds = postDevice.SelectBuildings, floor_guid = postDevice.SelectFloors, syss = postDevice.SelectSub, device_name = postDevice.Device_name }); apiResult.Data = dbDevice; @@ -404,11 +406,11 @@ namespace FrontendWebApi.ApiControllers var dbDevice = await backendRepository.GetAllAsync( @$"select c.full_name building_name,b.device_number,b.full_name device_name,a.full_name item_name,a.points,a.unit from device_item a - join device b on a.sub_system_guid = b.sub_system_guid - join building c on c.building_guid = b.building_guid - join sub_system d on d.sub_system_guid = b.sub_system_guid - join main_system e on e.main_system_guid = b.main_system_guid - where a.deleted = 0 and b.deleted = 0 and d.deleted = 0 and e.deleted = 0 + join device b on a.device_system_tag = b.device_system_tag + join building c on c.building_tag = b.device_building_tag + join variable v1 on v1.system_value = b.device_system_tag and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2' + join variable v2 on v2.system_value = b.device_name_tag and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3' + where a.deleted = 0 and b.deleted = 0 and v2.deleted = 0 and v1.deleted = 0 and a.unit is not null and b.device_number in @Device_number order by c.priority,b.priority " @@ -445,29 +447,29 @@ namespace FrontendWebApi.ApiControllers { var sql = $@" SELECT - rc.combination_guid, - rc.full_name AS combination_full_name, - rcd.device_guid, - d.device_number, - d.full_name AS Device_full_name, - b.full_name AS Building_full_name, - ms.full_name AS Main_system_full_name, - ss.full_name AS Sub_system_full_name - FROM realtime_combination_detail rcd - LEFT JOIN - (SELECT - rc.* - FROM realtime_combination rc - WHERE building_guid = @building_guid - AND userinfo_guid = @userinfo_guid - ) rc ON rcd.combination_guid = rc.combination_guid - JOIN device d ON d.deleted = 0 AND d.device_guid = rcd.device_guid - JOIN building b ON b.deleted = 0 AND b.building_guid = d.building_guid - JOIN main_system ms ON ms.deleted = 0 AND ms.main_system_guid = d.main_system_guid - JOIN sub_system ss ON ss.deleted = 0 AND ss.sub_system_guid = d.sub_system_guid - WHERE rc.deleted = 0"; + rc.combination_guid, + rc.full_name AS combination_full_name, + rcd.device_guid, + d.device_number, + d.full_name AS Device_full_name, + b.full_name AS Building_full_name, + v1.system_key AS Main_system_full_name, + v2.system_key AS Sub_system_full_name + FROM realtime_combination_detail rcd + LEFT JOIN + (SELECT + rc.* + FROM realtime_combination rc + WHERE building_tag = @building_tag + AND userinfo_guid = @userinfo_guid + ) rc ON rcd.combination_guid = rc.combination_guid + JOIN device d ON d.deleted = 0 AND d.device_guid = rcd.device_guid + JOIN building b ON b.deleted = 0 AND b.building_tag = d.device_building_tag + JOIN variable v1 ON v1.deleted = 0 AND v1.system_value = d.device_system_tag and v1.system_type = 'device_system_category_layer2' + JOIN variable v2 ON v2.deleted = 0 AND v2.system_value = d.device_name_tag and v2.system_type = 'device_system_category_layer3' + WHERE rc.deleted = 0"; - var rawDatas = await frontendRepository.GetAllAsync(sql, new { building_guid = post.building_guid, userinfo_guid = myUser.userinfo_guid }); + var rawDatas = await frontendRepository.GetAllAsync(sql, new { building_tag = post.building_tag, userinfo_guid = myUser.userinfo_guid }); var rawDatas_groups = rawDatas.GroupBy(x => x.Combination_guid).ToList(); @@ -536,7 +538,7 @@ namespace FrontendWebApi.ApiControllers combination = new Dictionary() { { "@combination_guid", guid}, - { "@building_guid", post.Building_guid}, + { "@building_tag", post.Building_tag}, { "@userinfo_guid", myUser.userinfo_guid}, { "@full_name", post.Full_name}, { "@created_by", myUser.userinfo_guid} @@ -808,17 +810,17 @@ namespace FrontendWebApi.ApiControllers { #region 取得區域樓層 var sqlBuildingFloor = $@"SELECT - b.building_guid, + b.building_tag, b.full_name AS building_name, b.priority, f.floor_guid, f.full_name AS floor_name, f.priority FROM building b - JOIN floor f ON f.deleted = 0 AND f.building_guid = b.building_guid - WHERE b.building_guid IN ( + JOIN floor f ON f.deleted = 0 AND f.building_tag = b.building_tag + WHERE b.building_tag IN ( SELECT - ap.building_guid + ap.building_tag FROM role_auth ra JOIN auth_page ap ON ra.AuthCode = ap.AuthCode JOIN userinfo u ON u.role_guid = ra.role_guid WHERE u.account = @Account @@ -827,7 +829,7 @@ namespace FrontendWebApi.ApiControllers var buildingFloorRawDatas = await frontendRepository.GetAllAsync(sqlBuildingFloor, post); - var buildingFloorRawDatas_GroupBy_building_guid = buildingFloorRawDatas.GroupBy(x => x.building_guid).ToList(); + var buildingFloorRawDatas_GroupBy_building_guid = buildingFloorRawDatas.GroupBy(x => x.building_tag).ToList(); List history_Builds = new List(); foreach (var buildingFloorRawData in buildingFloorRawDatas_GroupBy_building_guid) @@ -846,7 +848,7 @@ namespace FrontendWebApi.ApiControllers History_Build history_Build = new History_Build() { - building_guid = buildingFloorRawData.Key, + building_tag = buildingFloorRawData.Key, full_name = buildingFloorRawData.First().building_name, history_Floors = history_Floors }; @@ -856,22 +858,19 @@ namespace FrontendWebApi.ApiControllers #endregion #region 取得系統大小類 - var sqlMainSubSystem = $@"SELECT - ms.main_system_guid, - ms.full_name AS main_name, - ss.sub_system_guid, - ss.full_name AS sub_name - FROM sub_system ss - JOIN main_system ms ON ms.deleted = 0 AND ss.main_system_guid = ms.main_system_guid - WHERE ss.deleted = 0 - AND ss.sub_system_guid IN ( - SELECT - ap.ShowView - FROM role_auth ra - JOIN auth_page ap ON ra.AuthCode = ap.AuthCode - JOIN userinfo u ON u.role_guid = ra.role_guid WHERE u.account = @Account - ) - ORDER BY ms.priority, ss.priority"; + var sqlMainSubSystem = $@"select + v1.system_value as main_system_tag, v1.system_key as main_name, v2.system_value as sub_system_tag, v2.system_key as sub_name + from variable v2 + inner join variable v1 on v2.system_parent_id = v1.id + where v2.deleted = 0 and + v2.system_value in ( + select ap.ShowView + from role_auth ra + inner join auth_page ap on ra.AuthCode = ap.AuthCode + inner join userinfo ui on ra.role_guid = ui.role_guid + where ui.account = @Account + ) + order by v1.system_priority, v2.system_priority;"; var mainSubSystemRawDatas = await frontendRepository.GetAllAsync(sqlMainSubSystem, post); @@ -956,30 +955,30 @@ namespace FrontendWebApi.ApiControllers var device_numbers = post.HistoryItems.Select(x => x.Device_number_point.Split(":")[0]).Distinct().ToList(); //依據被選擇的設備找出相對應資料 - var sqlDeviceItemInfo = $@"SELECT - b.full_name AS building_name, - ms.full_name AS Main_system_name, - ss.full_name AS Sub_system_name, - temp.device_number, - temp.device_name, - temp.full_name AS item_name, - temp.points, - temp.unit - FROM ( SELECT - di.*, - d.building_guid, - d.main_system_guid, - -- d.sub_system_guid, - d.device_number, - d.full_name AS device_name, - d.priority - FROM device_item di - JOIN device d ON d.deleted = 0 AND di.sub_system_guid = d.sub_system_guid - WHERE di.deleted = 0 AND di.unit IS NOT NULL AND d.device_number IN @Device_number) temp - JOIN building b ON b.deleted = 0 AND temp.building_guid = b.building_guid - JOIN main_system ms ON ms.deleted = 0 AND temp.main_system_guid = ms.main_system_guid - JOIN sub_system ss ON ss.deleted = 0 AND temp.sub_system_guid = ss.sub_system_guid - ORDER BY b.priority, ms.priority, ss.priority, temp.priority"; + var sqlDeviceItemInfo = $@"select + b.full_name as building_name, + v1.system_key as Main_system_name, + v2.system_key as Sub_system_name, + temp.device_number, + temp.device_name, + temp.full_name as item_name, + temp.points, + temp.unit + from ( + select + di.*, + d.device_building_tag, + d.device_number, + d.full_name as device_name, + d.priority + from device_item di + inner join device d on di.device_name_tag = d.device_name_tag and d.deleted = 0 + where di.deleted = 0 and di.unit is not null and d.device_number IN @Device_number + ) temp + inner join building b on temp.device_building_tag = b.building_tag and b.deleted = 0 + inner join variable v1 on temp.device_system_tag = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2' + inner join variable v2 on temp.device_name_tag = v2.system_value and v2.deleted = 0 and v2.system_type = 'device_system_category_layer3' + order by b.priority, v1.system_priority, v2.system_priority, temp.priority"; var device_item_infos = await frontendRepository.GetAllAsync(sqlDeviceItemInfo, new { Device_number = device_numbers }); @@ -1087,5 +1086,57 @@ namespace FrontendWebApi.ApiControllers } return Ok(apiResult); } + + /// + /// 即使歷史資料(前7天) + /// + /// + /// + [HttpPost] + [Route("api/HistoryRealTime")] + public async Task>>> GetHistoryRealTime ([FromBody] HistoryRealTimeInput input) + { + ApiResult> apiResult = new ApiResult>(jwt_str); + apiResult.Data = new List(); + if (!jwtlife) + { + apiResult.Code = "5000"; + return BadRequest(apiResult); + } + if (input.tableDeviceName.Count == 0) + { + apiResult.Code = "9998"; + apiResult.Msg = "沒有設備被選擇"; + return BadRequest(apiResult); + } + + try + { + List tableName = new List(); + foreach (var dn in input.tableDeviceName) + { + tableName.AddRange(await backgroundServiceMsSqlRepository.GetAllAsync($"select table_name from INFORMATION_SCHEMA.TABLES where table_name like '{dn}%'")); + } + + if (tableName.Count > 0) + { + foreach (var tn in tableName) + { + var sql = $@"select timestamp as timeStamp, round(value, 2) as value from {tn} where replace(convert(varchar, [timestamp], 111), '/', '-') >= @startTime and replace(convert(varchar, [timestamp], 111), '/', '-') <= @endTime ordr by timestamp"; + apiResult.Data.AddRange( + await backgroundServiceMsSqlRepository.GetAllAsync(sql, new { startTime = input.startTime, endTime = input.endTime }) + ); + } + } + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + return Ok(apiResult); + } + return Ok(apiResult); + } } } diff --git a/FrontendWebApi/ApiControllers/HydroMeterController.cs b/FrontendWebApi/ApiControllers/HydroMeterController.cs new file mode 100644 index 0000000..281bfd0 --- /dev/null +++ b/FrontendWebApi/ApiControllers/HydroMeterController.cs @@ -0,0 +1,608 @@ +using FrontendWebApi.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using NPOI.SS.UserModel; +using NPOI.XSSF.UserModel; +using Repository.BackendRepository.Interface; +using Repository.FrontendRepository.Interface; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace FrontendWebApi.ApiControllers +{ + public class HydroMeterController : MyBaseApiController + { + private readonly IBackendRepository backendRepository; + private readonly IFrontendRepository frontendRepository; + + public HydroMeterController(IBackendRepository backendRepository, IFrontendRepository frontendRepository) + { + this.backendRepository = backendRepository; + this.frontendRepository = frontendRepository; + } + + /// + /// 電表 + /// + /// + /// + [HttpPost] + [Route("api/ElectricList")] + public async Task>>> ElectricList([FromBody] HydroMeterInput input) + { + ApiResult> apiResult = new ApiResult>(jwt_str); + if (!jwtlife) + { + apiResult.Code = "5000"; + return BadRequest(apiResult); + } + + string tableType = "day week month year"; + if (input.building_tag == null) + { + apiResult.Code = "9999"; + apiResult.Msg = "棟別沒有被選取"; + return BadRequest(apiResult); + } + else if (input.tableType == null || !tableType.Contains(input.tableType)) + { + apiResult.Code = "9999"; + apiResult.Msg = "表單類別錯誤"; + return BadRequest(apiResult); + } + else if (input.floor_tag.Count == 0) + { + apiResult.Code = "0000"; + apiResult.Data = new List() { }; + return Ok(apiResult); + } + + try + { + var startTime = input.tableType == "day" || input.tableType == "week" + ? input.startTime + "-01" + : input.tableType == "month" || input.tableType == "year" ? input.startTime + "-01-01" + : null; + var endTime = input.tableType == "day" || input.tableType == "week" + ? input.startTime.Split("-")[0] + "-" + (Int32.Parse(input.startTime.Split("-")[1]) + 1).ToString().PadLeft(2, '0') + "-01" + : input.tableType == "month" ? (Int32.Parse(input.startTime.Split("-")[0]) + 1) + "-01-01" + : input.tableType == "year" ? input.endTime + "-01-01" + : null; + string sqlWhere = ""; + string sqlGroup = ""; + string sqlAvgRawData = ""; + if (input.floor_tag.Count > 0) + sqlWhere = $@" and substring_index(substring_index(device_number, '_', 3), '_', -1) in @floor_tag "; + + if (input.tableType == "year") + { + sqlGroup = $@" group by year(start_timestamp), year(end_timestamp), device_number "; + sqlAvgRawData = " round(avg(avg_rawdata), 2) as avg_rawdata, year(start_timestamp) as start_timestamp, year(end_timestamp) as end_timestamp "; + } + else + sqlAvgRawData = " round(avg_rawdata, 2) as avg_rawdata, start_timestamp, end_timestamp "; + + var table = input.tableType == "year" ? "archive_electric_meter_day" : "archive_electric_meter_" + input.tableType; + var dateFormat = input.tableType == "day" || input.tableType == "week" ? "%Y-%m-%d" : input.tableType == "month" ? "%Y-%m" : input.tableType == "year" ? "%Y" : null; + var sql = $@"set @i = -1; + select fd.device_number, aemm.avg_rawdata, DATE_FORMAT(fd.date, @dateFormat) as timestamp + from ( + select * + from ( + ( + SELECT DATE(ADDDATE(@startTime, INTERVAL @i:=@i+1 {input.tableType})) AS date + FROM {table} + HAVING @i < TIMESTAMPDIFF({input.tableType}, @startTime, ADDDATE(@endTime, INTERVAL -1 DAY)) + ) d, + ( + select device_number + from {table} + where start_timestamp >= @startTime and end_timestamp < @endTime and point = 'KWH' and SUBSTRING_INDEX(device_number, '_', 1) = @building_tag + {sqlWhere} + group by device_number + ) dn + ) + ) fd + left join ( + select device_number, {sqlAvgRawData} + from {table} + where start_timestamp >= @startTime and end_timestamp < @endTime and point = 'KWH' and SUBSTRING_INDEX(device_number, '_', 1) = @building_tag + {sqlWhere} {sqlGroup} + ) aemm on aemm.start_timestamp >= fd.date and aemm.end_timestamp < DATE_ADD(fd.date, INTERVAL +1 {input.tableType}) and aemm.device_number = fd.device_number + order by fd.device_number, fd.date"; + var rawData = await backendRepository.GetAllAsync(sql, + new { startTime = startTime, endtime = endTime, building_tag = input.building_tag, floor_tag = input.floor_tag, dateFormat = dateFormat }); + var list = rawData + .GroupBy(x => new { building_tag = x.device_number.Split("_")[0], floor_tag = x.device_number.Split("_")[2], device_serial_tag = x.device_number.Split("_")[4] }) + .Select(x => new HydroMeterOutput { building_tag = x.Key.building_tag, floor_tag = x.Key.floor_tag, device_serial_tag = x.Key.device_serial_tag }) + .ToList(); + + foreach (var l in list) + { + l.rawData = new List(); + l.rawData.AddRange( + rawData.Where(x => x.device_number.Split("_")[0] == l.building_tag && x.device_number.Split("_")[2] == l.floor_tag && x.device_number.Split("_")[4] == l.device_serial_tag) + ); + l.building_name = await backendRepository.GetOneAsync("select full_name from building where building_tag = @building_tag and deleted = 0", + new { building_tag = l.building_tag }); + l.total = l.rawData.Sum(x => x.avg_rawdata).ToString(); + l.price = input.price.HasValue + ? (Math.Round(input.price.Value, 2)).ToString() + : Math.Round((await backendRepository.GetOneAsync("select system_value from variable where system_type = 'ElectricPrice' and deleted = 0")), 2).ToString(); + l.total_price = Math.Round((Decimal.Parse(l.total) * Decimal.Parse(l.price)), 2).ToString(); + } + + apiResult.Code = "0000"; + apiResult.Data = list; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + string json = System.Text.Json.JsonSerializer.Serialize(input); + Logger.LogError("【" + controllerName + "/" + actionName + "】" + json); + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + return apiResult; + } + + /// + /// 水表 + /// + /// + /// + [HttpPost] + [Route("api/WaterList")] + public async Task>>> WaterList([FromBody] HydroMeterInput input) + { + ApiResult> apiResult = new ApiResult>(jwt_str); + if (!jwtlife) + { + apiResult.Code = "5000"; + return BadRequest(apiResult); + } + + string tableType = "day week month year"; + if (input.building_tag == null) + { + apiResult.Code = "9999"; + apiResult.Msg = "棟別沒有被選取"; + return BadRequest(apiResult); + } + else if (input.tableType == null || !tableType.Contains(input.tableType)) + { + apiResult.Code = "9999"; + apiResult.Msg = "表單類別錯誤"; + return BadRequest(apiResult); + } + else if (input.floor_tag.Count == 0) + { + apiResult.Code = "0000"; + apiResult.Data = new List() { }; + return Ok(apiResult); + } + + try + { + var startTime = input.tableType == "day" || input.tableType == "week" + ? input.startTime + "-01" + : input.tableType == "month" || input.tableType == "year" ? input.startTime + "-01-01" + : null; + var endTime = input.tableType == "day" || input.tableType == "week" + ? input.startTime.Split("-")[0] + "-" + (Int32.Parse(input.startTime.Split("-")[1]) + 1).ToString().PadLeft(2, '0') + "-01" + : input.tableType == "month" ? (Int32.Parse(input.startTime.Split("-")[0]) + 1) + "-01-01" + : input.tableType == "year" ? input.endTime + "-01-01" + : null; + string sqlWhere = ""; + string sqlGroup = ""; + string sqlAvgRawData = ""; + if (input.floor_tag.Count > 0) + sqlWhere = $@" and substring_index(substring_index(device_number, '_', 3), '_', -1) in @floor_tag "; + + if (input.tableType == "year") + { + sqlGroup = $@" group by year(start_timestamp), year(end_timestamp), device_number "; + sqlAvgRawData = " round(avg(avg_rawdata), 2) as avg_rawdata, year(start_timestamp) as start_timestamp, year(end_timestamp) as end_timestamp "; + } + else + sqlAvgRawData = " round(avg_rawdata, 2) as avg_rawdata, start_timestamp, end_timestamp "; + + var table = input.tableType == "year" ? "archive_water_meter_day" : "archive_water_meter_" + input.tableType; + var dateFormat = input.tableType == "day" || input.tableType == "week" ? "%Y-%m-%d" : input.tableType == "month" ? "%Y-%m" : input.tableType == "year" ? "%Y" : null; + var sql = $@"set @i = -1; + select fd.device_number, aemm.avg_rawdata, DATE_FORMAT(fd.date, @dateFormat) as timestamp + from ( + select * + from ( + ( + SELECT DATE(ADDDATE(@startTime, INTERVAL @i:=@i+1 {input.tableType})) AS date + FROM {table} + HAVING @i < TIMESTAMPDIFF({input.tableType}, @startTime, ADDDATE(@endTime, INTERVAL -1 DAY)) + ) d, + ( + select device_number + from {table} + where start_timestamp >= @startTime and end_timestamp < @endTime and point = 'RCV' and SUBSTRING_INDEX(device_number, '_', 1) = @building_tag + {sqlWhere} + group by device_number + ) dn + ) + ) fd + left join ( + select device_number, {sqlAvgRawData} + from {table} + where start_timestamp >= @startTime and end_timestamp < @endTime and point = 'RCV' and SUBSTRING_INDEX(device_number, '_', 1) = @building_tag + {sqlWhere} {sqlGroup} + ) aemm on aemm.start_timestamp >= fd.date and aemm.end_timestamp < DATE_ADD(fd.date, INTERVAL +1 {input.tableType}) and aemm.device_number = fd.device_number + order by fd.device_number, fd.date"; + + var rawData = await backendRepository.GetAllAsync(sql, + new { startTime = startTime, endTime = endTime, building_tag = input.building_tag, floor_tag = input.floor_tag, dateFormat = dateFormat }); + var list = rawData + .GroupBy(x => new { building_tag = x.device_number.Split("_")[0], floor_tag = x.device_number.Split("_")[2], device_serial_tag = x.device_number.Split("_")[4] }) + .Select(x => new HydroMeterOutput { building_tag = x.Key.building_tag, floor_tag = x.Key.floor_tag, device_serial_tag = x.Key.device_serial_tag }) + .ToList(); + + foreach (var l in list) + { + l.rawData = new List(); + l.rawData.AddRange( + rawData.Where(x => x.device_number.Split("_")[0] == l.building_tag && x.device_number.Split("_")[2] == l.floor_tag && x.device_number.Split("_")[4] == l.device_serial_tag) + ); + l.building_name = await backendRepository.GetOneAsync("select full_name from building where building_tag = @building_tag and deleted = 0", + new { building_tag = l.building_tag }); + l.total = l.rawData.Sum(x => x.avg_rawdata).ToString(); + l.price = input.price.HasValue + ? (Math.Round(input.price.Value, 2)).ToString() + : Math.Round((await backendRepository.GetOneAsync("select system_value from variable where system_type = 'WaterPrice' and deleted = 0")), 2).ToString(); + l.total_price = Math.Round((Decimal.Parse(l.total) * Decimal.Parse(l.price)), 2).ToString(); + } + + apiResult.Code = "0000"; + apiResult.Data = list; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + string json = System.Text.Json.JsonSerializer.Serialize(input); + Logger.LogError("【" + controllerName + "/" + actionName + "】" + json); + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + return apiResult; + } + + /// + /// 水電表費用 + /// + /// + /// + [HttpPost] + [Route("api/HydroMeterPrice")] + public async Task>> Price([FromBody] HydroMeterPriceInput input) + { + ApiResult apiResult = new ApiResult(jwt_str); + if (!jwtlife) + { + apiResult.Code = "5000"; + return BadRequest(apiResult); + } + + try + { + apiResult.Code = "0000"; + apiResult.Data = await backendRepository.GetOneAsync($@"select system_value from variable where system_type = '{input.type}Price' and deleted = 0"); + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + string json = System.Text.Json.JsonSerializer.Serialize(input); + Logger.LogError("【" + controllerName + "/" + actionName + "】" + json); + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + return apiResult; + } + + [HttpPost] + [Route("api/ExportElectricList")] + public FileResult OpeExportExcelElec([FromBody] HydroMeterInput input) + { + var result = this.ElectricList(input).Result.Value.Data.ToList(); + + var workbook = new XSSFWorkbook(); + #region excel設定 + IFont font12 = workbook.CreateFont(); + font12.FontName = "新細明體"; + font12.FontHeightInPoints = 12; + ICellStyle style12 = workbook.CreateCellStyle(); + style12.SetFont(font12); + style12.Alignment = HorizontalAlignment.Center; + style12.VerticalAlignment = VerticalAlignment.Center; + IFont font12Times = workbook.CreateFont(); + font12Times.FontName = "Times New Roman"; + font12Times.FontHeightInPoints = 12; + IFont font18 = workbook.CreateFont(); + font18.FontName = "新細明體"; + font18.FontHeightInPoints = 18; + font18.IsBold = true; + ICellStyle styleTitle18 = workbook.CreateCellStyle(); + styleTitle18.SetFont(font18); + styleTitle18.Alignment = HorizontalAlignment.Center; + styleTitle18.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLeft12 = workbook.CreateCellStyle(); + styleLeft12.SetFont(font12); + styleLeft12.Alignment = HorizontalAlignment.Left; + styleLeft12.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLine12 = workbook.CreateCellStyle(); + styleLine12.SetFont(font12); + styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; + styleLine12.VerticalAlignment = VerticalAlignment.Center; + styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + ICellStyle stylein12 = workbook.CreateCellStyle(); + stylein12.SetFont(font12Times); + stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; + stylein12.VerticalAlignment = VerticalAlignment.Center; + stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.WrapText = true; + #endregion + + var sheet = workbook.CreateSheet("電表報表"); + int RowPosition = 0; + if (result.Count > 0) + { + #region set cell + IRow row = sheet.CreateRow(RowPosition); + sheet.SetColumnWidth(0, 4 * 160 * 12); + sheet.SetColumnWidth(1, 4 * 160 * 12); + sheet.SetColumnWidth(2, 4 * 160 * 12); + + int i = 0; + ICell cell = row.CreateCell(i++); + cell.SetCellValue("東別"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("樓層"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("設備"); + cell.CellStyle = styleLine12; + + foreach (var rr in result.FirstOrDefault().rawData) + { + cell = row.CreateCell(i++); + cell.SetCellValue(rr.timeStamp); + cell.CellStyle = styleLine12; + } + + cell = row.CreateCell(i++); + cell.SetCellValue("小計"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("單價"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("金額總計"); + cell.CellStyle = styleLine12; + #endregion + + foreach (var r in result) + { + RowPosition += 1; + int k = 3; + row = sheet.CreateRow(RowPosition); + for (int j = 0; j <= i; j++) + { + cell = row.CreateCell(j); + if (j == 0) + { + cell.SetCellValue(r.building_name); + } + if (j == 1) + { + cell.SetCellValue(r.floor_tag); + } + if (j == 2) + { + cell.SetCellValue(r.device_serial_tag); + } + + if (j == 3) + { + foreach (var rr in r.rawData) + { + cell.SetCellValue(rr.avg_rawdata.ToString()); + j++; + k++; + cell = row.CreateCell(j); + } + } + + if (j == k) + { + cell.SetCellValue(r.total); + } + if (j == k+1) + { + cell.SetCellValue(r.price); + } + if (j == k+2) + { + cell.SetCellValue(r.total_price); + } + + cell.CellStyle = style12; + } + } + } + + var ms = new NpoiMemoryStream + { + AllowClose = false + }; + workbook.Write(ms); + ms.Flush(); + ms.Seek(0, SeekOrigin.Begin); + + return File(ms, "application/vnd.ms-excel", "電表報表.xlsx"); + } + + [HttpGet] + [Route("api/ExportWaterList")] + public FileResult OpeExportExcelWater([FromBody] HydroMeterInput input) + { + var result = this.WaterList(input).Result.Value.Data.ToList(); + + var workbook = new XSSFWorkbook(); + #region excel設定 + IFont font12 = workbook.CreateFont(); + font12.FontName = "新細明體"; + font12.FontHeightInPoints = 12; + ICellStyle style12 = workbook.CreateCellStyle(); + style12.SetFont(font12); + style12.Alignment = HorizontalAlignment.Center; + style12.VerticalAlignment = VerticalAlignment.Center; + IFont font12Times = workbook.CreateFont(); + font12Times.FontName = "Times New Roman"; + font12Times.FontHeightInPoints = 12; + IFont font18 = workbook.CreateFont(); + font18.FontName = "新細明體"; + font18.FontHeightInPoints = 18; + font18.IsBold = true; + ICellStyle styleTitle18 = workbook.CreateCellStyle(); + styleTitle18.SetFont(font18); + styleTitle18.Alignment = HorizontalAlignment.Center; + styleTitle18.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLeft12 = workbook.CreateCellStyle(); + styleLeft12.SetFont(font12); + styleLeft12.Alignment = HorizontalAlignment.Left; + styleLeft12.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLine12 = workbook.CreateCellStyle(); + styleLine12.SetFont(font12); + styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; + styleLine12.VerticalAlignment = VerticalAlignment.Center; + styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + ICellStyle stylein12 = workbook.CreateCellStyle(); + stylein12.SetFont(font12Times); + stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; + stylein12.VerticalAlignment = VerticalAlignment.Center; + stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.WrapText = true; + #endregion + + var sheet = workbook.CreateSheet("電表報表"); + int RowPosition = 0; + if (result.Count > 0) + { + #region set cell + IRow row = sheet.CreateRow(RowPosition); + sheet.SetColumnWidth(0, 4 * 160 * 12); + sheet.SetColumnWidth(1, 4 * 160 * 12); + sheet.SetColumnWidth(2, 4 * 160 * 12); + + int i = 0; + ICell cell = row.CreateCell(i++); + cell.SetCellValue("東別"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("樓層"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("設備"); + cell.CellStyle = styleLine12; + + foreach (var rr in result.FirstOrDefault().rawData) + { + cell = row.CreateCell(i++); + cell.SetCellValue(rr.timeStamp); + cell.CellStyle = styleLine12; + } + + cell = row.CreateCell(i++); + cell.SetCellValue("小計"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("單價"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(i++); + cell.SetCellValue("金額總計"); + cell.CellStyle = styleLine12; + #endregion + + foreach (var r in result) + { + RowPosition += 1; + int k = 3; + row = sheet.CreateRow(RowPosition); + for (int j = 0; j <= i; j++) + { + cell = row.CreateCell(j); + if (j == 0) + { + cell.SetCellValue(r.building_name); + } + if (j == 1) + { + cell.SetCellValue(r.floor_tag); + } + if (j == 2) + { + cell.SetCellValue(r.device_serial_tag); + } + + if (j == 3) + { + foreach (var rr in r.rawData) + { + cell.SetCellValue(rr.avg_rawdata.ToString()); + j++; + k++; + cell = row.CreateCell(j); + } + } + + if (j == k) + { + cell.SetCellValue(r.total); + } + if (j == k + 1) + { + cell.SetCellValue(r.price); + } + if (j == k + 2) + { + cell.SetCellValue(r.total_price); + } + + cell.CellStyle = style12; + } + } + } + + var ms = new NpoiMemoryStream + { + AllowClose = false + }; + workbook.Write(ms); + ms.Flush(); + ms.Seek(0, SeekOrigin.Begin); + + return File(ms, "application/vnd.ms-excel", "水表報表.xlsx"); + } + } +} diff --git a/FrontendWebApi/ApiControllers/MyBaseApiController.cs b/FrontendWebApi/ApiControllers/MyBaseApiController.cs index 2611d2a..891da48 100644 --- a/FrontendWebApi/ApiControllers/MyBaseApiController.cs +++ b/FrontendWebApi/ApiControllers/MyBaseApiController.cs @@ -79,18 +79,18 @@ namespace FrontendWebApi.ApiControllers jwt_str = jwt.GenerateToken(jwtLoing).token; } } - //if (myUser.exp <= DateTime.Now.AddHours(-8).AddMinutes(10).Subtract(new DateTime(1970, 1, 1)).TotalSeconds) - //{ - // jwtlife = true; - // JwtLogin jwtLoing = new JwtLogin() - // { - // account ="webUser", - // email = "webUser@gmail.com", - // full_name = "webUser", - // userinfo_guid = "6ac24708-3a40-4199-88c5-22df310cd1a8" - // }; - // jwt_str = jwt.GenerateToken(jwtLoing).token; - //} + if (myUser.exp <= DateTime.Now.AddHours(-8).AddMinutes(10).Subtract(new DateTime(1970, 1, 1)).TotalSeconds) + { + jwtlife = true; + JwtLogin jwtLoing = new JwtLogin() + { + account = "webUser", + email = "webUser@gmail.com", + full_name = "webUser", + userinfo_guid = "6ac24708-3a40-4199-88c5-22df310cd1a8" + }; + jwt_str = jwt.GenerateToken(jwtLoing).token; + } base.OnActionExecuting(filterContext); } } diff --git a/FrontendWebApi/Models/Build.cs b/FrontendWebApi/Models/Build.cs index 88e80f5..d072fd8 100644 --- a/FrontendWebApi/Models/Build.cs +++ b/FrontendWebApi/Models/Build.cs @@ -21,36 +21,35 @@ namespace FrontendWebApi.Models public class Buildingsql { - public string building_guid { get; set; } + public string building_tag { get; set; } public string bfull_name { get; set; } public string ip_address { get; set; } public int bpriority { get; set; } } public class BuildMenuSql : Buildingsql { - public string main_system_guid { get; set; } - public string sub_system_guid { get; set; } - public byte drawing { get; set; } - public byte icon_click { get; set; } - public string icon_click_url { get; set; } - public string system_url { get; set; } + public string main_system_tag { get; set; } + public string sub_system_tag { get; set; } + public byte left_drawing { get; set; } + public byte left_icon_click { get; set; } + public string left_icon_click_url { get; set; } + public string left_system_url { get; set; } public string mafull_name { get; set; } public int mapriority { get; set; } public string code { get; set; } public string subfull_name { get; set; } public int subpriority { get; set; } - public byte planimetric_click { get; set; } - public string planimetric_floor_guid { get; set; } - public string riser_diagram_url { get; set; } + public byte left_planimetric_click { get; set; } + public string left_planimetric_floor_guid { get; set; } + public string left_riser_diagram_url { get; set; } public string device_building_tag { get; set; } public string device_system_tag { get; set; } public byte OpenTab { get; set; } } public class Floorsql : Floor { - public string main_system_guid { get; set; } - public string sub_system_guid { get; set; } - public string building_guid { get; set; } + public string main_system_tag { get; set; } + public string sub_system_tag { get; set; } } public class Devicesql : Device { @@ -72,17 +71,16 @@ namespace FrontendWebApi.Models public class Building { - public string building_guid { get; set; } + public string building_tag { get; set; } public string full_name { get; set; } public string ip_address { get; set; } public int priority { get; set; } - public string device_building_tag { get; set; } public List main_system { get; set; } public List common { get; set; } } public class Main_system { - public string main_system_guid { get; set; } + public string main_system_tag { get; set; } public string full_name { get; set; } public int priority { get; set; } public string code { get; set; } @@ -90,7 +88,7 @@ namespace FrontendWebApi.Models } public class Sub_systemGuid { - public string sub_system_guid { get; set; } + public string sub_system_tag { get; set; } public string full_name { get; set; } public int priority { get; set; } public string device_system_tag { get; set; } @@ -99,23 +97,22 @@ namespace FrontendWebApi.Models } public class Sub_system { - public string sub_system_guid { get; set; } + public string sub_system_tag { get; set; } public string full_name { get; set; } public int priority { get; set; } - public byte drawing { get; set; } - public byte icon_click { get; set; } - public string icon_click_url { get; set; } - public string system_url { get; set; } + public byte left_drawing { get; set; } + public byte left_icon_click { get; set; } + public string left_icon_click_url { get; set; } + public string left_system_url { get; set; } public List Floors { get; set; } - public byte planimetric_click { get; set; } - public string planimetric_floor_guid { get; set; } - public string riser_diagram_url { get; set; } + public byte left_planimetric_click { get; set; } + public string left_planimetric_floor_guid { get; set; } + public string left_riser_diagram_url { get; set; } } public class Floor { public string floor_guid { get; set; } - public string building_tag { get; set; } public string full_name { get; set; } public string InitMapName { get; set; } @@ -126,20 +123,19 @@ namespace FrontendWebApi.Models public class PostTagName { - public string building_guid { get; set; } - public string main_system_guid { get; set; } - public string sub_system_guid { get; set; } + public string building_tag { get; set; } + public string main_system_tag { get; set; } + public string sub_system_tag { get; set; } } public class BuildingSystemTagName { public string device_building_tag { get; set; } - public string device_system_tag { get; set; } + public string sub_system_tag { get; set; } } public class DeviceFloor : Device { - public string floor_guid { get; set; } } diff --git a/FrontendWebApi/Models/HiNet.cs b/FrontendWebApi/Models/HiNet.cs new file mode 100644 index 0000000..0cbd5fb --- /dev/null +++ b/FrontendWebApi/Models/HiNet.cs @@ -0,0 +1,12 @@ +namespace FrontendWebApi.Models +{ + public class HiNet + { + } + + public class HiNetInput + { + public string Msg { get; set; } + public string Number { get; set; } + } +} diff --git a/FrontendWebApi/Models/HistoryClass.cs b/FrontendWebApi/Models/HistoryClass.cs index 8a9ffe9..2c97502 100644 --- a/FrontendWebApi/Models/HistoryClass.cs +++ b/FrontendWebApi/Models/HistoryClass.cs @@ -96,7 +96,7 @@ namespace FrontendWebApi.Models } public class BuildingFloorRawData { - public string building_guid { get; set; } + public string building_tag { get; set; } public string building_name { get; set; } public string floor_guid { get; set; } public string floor_name { get; set; } @@ -110,7 +110,7 @@ namespace FrontendWebApi.Models public class History_Build { - public string building_guid { get; set; } + public string building_tag { get; set; } public string full_name { get; set; } public List history_Floors { get; set; } } @@ -195,7 +195,7 @@ namespace FrontendWebApi.Models public class PostRealTimeCombination { public string account { get; set; } - public string building_guid { get; set; } + public string building_tag { get; set; } } public class RealTimeCombinationRawData @@ -238,7 +238,7 @@ namespace FrontendWebApi.Models public class PostSaveRealTimeCombination { - public string Building_guid { get; set; } + public string Building_tag { get; set; } public string Combination_guid { get; set; } public byte Save_type { get; set; } public string Full_name { get; set; } @@ -295,4 +295,17 @@ namespace FrontendWebApi.Models public string dateType { get; set; } public string type { get; set; } } + + public class HistoryRealTimeInput + { + public List tableDeviceName { get; set; } + public string startTime { get; set; } + public string endTime { get; set; } + } + + public class HistoryRealTimeOutput + { + public double value { get; set; } + public DateTime timeStamp { get; set; } + } } diff --git a/FrontendWebApi/Models/HydroMeter.cs b/FrontendWebApi/Models/HydroMeter.cs new file mode 100644 index 0000000..7d9a582 --- /dev/null +++ b/FrontendWebApi/Models/HydroMeter.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; + +namespace FrontendWebApi.Models +{ + public class HydroMeter + { + } + + public class HydroMeterInput + { + public string tableType { get; set; } //day, week, month, year + public string building_tag { get; set; } + public List floor_tag { get; set; } + public string startTime { get; set; } + public string endTime { get; set; } + public decimal? price { get; set; } + } + + public class HydroMeterOutput + { + public string building_name { get; set; } + public string building_tag { get; set; } + public string floor_tag { get; set; } + public string device_serial_tag { get; set; } + public string total { get; set; } + public string price { get; set; } + public string total_price { get; set; } + public List rawData { get; set; } + } + + public class HydroMeterRawDataOutput + { + public string timeStamp { get; set; } + public string device_number { get; set; } + public decimal avg_rawdata { get; set; } + } + + public class HydroMeterPriceInput + { + public string type { get; set; } + } +} diff --git a/FrontendWebApi/Startup.cs b/FrontendWebApi/Startup.cs index 0b4cf1f..956d4d8 100644 --- a/FrontendWebApi/Startup.cs +++ b/FrontendWebApi/Startup.cs @@ -91,6 +91,7 @@ namespace FrontendWebApi services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); #endregion Repository `J #region JWT `J diff --git a/FrontendWebApi/appsettings.json b/FrontendWebApi/appsettings.json index 2a2253a..eef838c 100644 --- a/FrontendWebApi/appsettings.json +++ b/FrontendWebApi/appsettings.json @@ -29,6 +29,13 @@ "Root": "SzdxEgaJJ7tcTCrUl2zKsA==", "Password": "FVAPxztxpY4gJJKQ/se4bQ==" }, + "MSSqlDBConfig": { + "Server": "bJm+UAtbeaTjDmp/A5ep2w==", //0.130 + "Port": "S5cUXKnKOacFtFy9+0dtpw==", + "Database": "VvfWH/59gQguY2eA2xBCug==", //taipei_dome + "Root": "sD8GZ9UPiIQGU6dU011/4A==", + "Password": "0O24es2ZRF5uoJ4aU+YCdg==" + } //"MSSqlDBConfig": { // "Server": "avZg8PA8C9GVgYZBgEKzCg==", // "Port": "lJA0KPkG6RvFfTgWiXFyUw==", diff --git a/Repository/BackendRepository/Implement/BackgroundServiceMsSqlRepository.cs b/Repository/BackendRepository/Implement/BackgroundServiceMsSqlRepository.cs new file mode 100644 index 0000000..7d5b910 --- /dev/null +++ b/Repository/BackendRepository/Implement/BackgroundServiceMsSqlRepository.cs @@ -0,0 +1,18 @@ +using Repository.BackendRepository.Interface; +using Repository.Helper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Repository.BackendRepository.Implement +{ + public class BackgroundServiceMsSqlRepository : BackendRepository, IBackgroundServiceMsSqlRepository + { + public BackgroundServiceMsSqlRepository(IDatabaseHelper databaseHelper) : base(databaseHelper) + { + UseDB = "MSSQL"; + } + + } +} diff --git a/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs b/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs index cd34f0f..674fef8 100644 --- a/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs +++ b/Repository/BackendRepository/Implement/NiagaraDataSynchronizeRepository.cs @@ -27,7 +27,7 @@ namespace Repository.BackendRepository.Implement /// /// /// - public async Task InsertNiagaraTagList(List ds, string building, string tag_quantity) + public async Task InsertNiagaraTagList(List ds, List building, string tag_quantity) { using (IDbConnection conn = GetDbConnection()) { @@ -36,25 +36,28 @@ namespace Repository.BackendRepository.Implement { try { - string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_tag` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `db_tags` varchar(50) DEFAULT NULL, - `niagara_tags` varchar(50) DEFAULT NULL, - `device_area_tag` varchar(50) DEFAULT NULL, - `device_building_tag` varchar(50) DEFAULT NULL, - `device_system_tag` varchar(50) DEFAULT NULL, - `device_name_tag` varchar(50) DEFAULT NULL, - `device_floor_tag` varchar(50) DEFAULT NULL, - `device_master_tag` varchar(50) DEFAULT NULL, - `device_last_name_tag` varchar(50) DEFAULT NULL, - `device_serial_tag` varchar(50) DEFAULT NULL, - `atDateTime` datetime(1) DEFAULT NULL, - `is_used` smallint(1) DEFAULT 0, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; - await conn.ExecuteAsync(sql); - sql = "delete from import_niagara_tag where device_building_tag = '" + building + "'"; - await conn.ExecuteAsync(sql); + foreach(var b in building) + { + string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_tag` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `db_tags` varchar(50) DEFAULT NULL, + `niagara_tags` varchar(50) DEFAULT NULL, + `device_area_tag` varchar(50) DEFAULT NULL, + `device_building_tag` varchar(50) DEFAULT NULL, + `device_system_tag` varchar(50) DEFAULT NULL, + `device_name_tag` varchar(50) DEFAULT NULL, + `device_floor_tag` varchar(50) DEFAULT NULL, + `device_master_tag` varchar(50) DEFAULT NULL, + `device_last_name_tag` varchar(50) DEFAULT NULL, + `device_serial_tag` varchar(50) DEFAULT NULL, + `atDateTime` datetime(1) DEFAULT NULL, + `is_used` smallint(1) DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; + await conn.ExecuteAsync(sql); + sql = "delete from import_niagara_tag where device_building_tag = '" + b + "'"; + await conn.ExecuteAsync(sql); + } //N4資料groupBy後放入import_niagara_tag資料表 var ds2 = ds.GroupBy(x => new @@ -170,7 +173,7 @@ namespace Repository.BackendRepository.Implement /// /// - public async Task InsertItemFromNiagara(List ds, string building) + public async Task InsertItemFromNiagara(List ds, List building) { using (IDbConnection conn = GetDbConnection()) { @@ -180,21 +183,24 @@ namespace Repository.BackendRepository.Implement try { #region 刪除 import_niagara_item資料表中選取的棟別 - string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `device_area_tag` varchar(50) DEFAULT NULL, - `device_building_tag` varchar(50) DEFAULT NULL, - `device_system_tag` varchar(50) DEFAULT NULL, - `device_name_tag` varchar(50) DEFAULT NULL, - `device_point_name` varchar(50) DEFAULT NULL, - `check_status` varchar(50) DEFAULT NULL, - `parent_path` varchar(50) DEFAULT NULL, - `full_name` varchar(50) DEFAULT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; - await conn.ExecuteAsync(sql); - sql = "delete from import_niagara_item where device_building_tag = '" + building + "'"; - await conn.ExecuteAsync(sql); + foreach(var b in building) + { + string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `device_area_tag` varchar(50) DEFAULT NULL, + `device_building_tag` varchar(50) DEFAULT NULL, + `device_system_tag` varchar(50) DEFAULT NULL, + `device_name_tag` varchar(50) DEFAULT NULL, + `device_point_name` varchar(50) DEFAULT NULL, + `check_status` varchar(50) DEFAULT NULL, + `parent_path` varchar(50) DEFAULT NULL, + `full_name` varchar(50) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"; + await conn.ExecuteAsync(sql); + sql = "delete from import_niagara_item where device_building_tag = '" + b + "'"; + await conn.ExecuteAsync(sql); + } #endregion ds = ds.GroupBy(x => new { device_area_tag = x.device_area_tag, @@ -270,7 +276,7 @@ namespace Repository.BackendRepository.Implement using (IDbConnection conn = GetDbConnection()) { conn.Open(); - using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) + using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled, new TimeSpan(0, 0, 200))) { try { @@ -398,19 +404,21 @@ namespace Repository.BackendRepository.Implement } #endregion - //device有,niagara沒有,is_link 更新成 0 - sb.Append($@" SET SQL_SAFE_UPDATES = 0; - UPDATE device d LEFT JOIN import_niagara_tag m ON d.device_number = m.niagara_tags - SET d.is_link = 0 - WHERE m.niagara_tags IS NULL;"); - await conn.ExecuteAsync(sb.ToString()); + //device有,niagara沒有,is_link 更新成 0 + sb.Append($@" SET SQL_SAFE_UPDATES = 0; + UPDATE device d + SET d.is_link = 0 + WHERE d.is_link = 1 and not exists (select niagara_tags from import_niagara_tag where niagara_tags = d.device_number);"); + await conn.ExecuteAsync(sb.ToString(), commandTimeout: 100); + + sb.Clear(); // device_node 有, niagara沒有, is_link 更新成 0 sb.Append($@" SET SQL_SAFE_UPDATES = 0; - UPDATE device_node d LEFT JOIN import_niagara_tag m ON d.device_number = m.niagara_tags + UPDATE device_node d SET d.is_link = 0 - WHERE m.niagara_tags IS NULL;"); - await conn.ExecuteAsync(sb.ToString()); + WHERE d.is_link = 1 and not exists (select niagara_tags from import_niagara_tag where niagara_tags = d.device_number);"); + await conn.ExecuteAsync(sb.ToString(), commandTimeout: 100); } catch (Exception exception) { @@ -463,7 +471,7 @@ namespace Repository.BackendRepository.Implement isBool = 1; } sb.Append($@"insert device_item(deleted, points, is_show, is_show_riserDiagram, is_controll, is_bool, is_show_history, is_link, - device_system_tag, device_name_tag, full_name, parent_path, created_at, updated_at) + device_system_tag, device_name_tag, device_building_tag, full_name, parent_path, created_at, updated_at) VALUES (0, '" + data.device_point_name + "', 1, 0, " + isControll + "," + @@ -472,6 +480,7 @@ namespace Repository.BackendRepository.Implement ", 1, '" + data.device_system_tag + "', '" + data.device_name_tag + "', '" + + data.device_building_tag + "', '" + data.full_name + "', '" + data.parent_path + "', " + "now(), now());"); @@ -738,7 +747,7 @@ namespace Repository.BackendRepository.Implement using (IDbConnection conn = GetDbConnection()) { conn.Open(); - using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) + using (TransactionScope scope = new TransactionScope((TransactionScopeOption)TransactionScopeAsyncFlowOption.Enabled, new TimeSpan (0, 0, 200))) { try { @@ -746,7 +755,7 @@ namespace Repository.BackendRepository.Implement sb.Append("update device d inner JOIN import_niagara_tag m ON m.niagara_tags = d.device_number " + "set d.full_name=m.device_full_name " + "where m.device_full_name<>d.full_name;"); - await conn.ExecuteAsync(sb.ToString()); + await conn.ExecuteAsync(sb.ToString(), commandTimeout: 200); } catch (Exception exception) { diff --git a/Repository/BackendRepository/Interface/IBackgroundServiceMsSqlRepository.cs b/Repository/BackendRepository/Interface/IBackgroundServiceMsSqlRepository.cs new file mode 100644 index 0000000..9c1af7c --- /dev/null +++ b/Repository/BackendRepository/Interface/IBackgroundServiceMsSqlRepository.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Repository.BackendRepository.Interface +{ + public interface IBackgroundServiceMsSqlRepository : IBackendRepository + { + + } +} diff --git a/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs b/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs index 078c92f..ef2688a 100644 --- a/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs +++ b/Repository/BackendRepository/Interface/INiagaraDataSynchronizeRepository.cs @@ -12,7 +12,7 @@ namespace Repository.BackendRepository.Interface /// /// /// - Task InsertNiagaraTagList(List ds, string building, string tag_quantity); + Task InsertNiagaraTagList(List ds, List building, string tag_quantity); /// @@ -27,7 +27,7 @@ namespace Repository.BackendRepository.Interface /// /// /// - Task InsertItemFromNiagara(List ds, string building); + Task InsertItemFromNiagara(List ds, List building); /// /// 比對 device ///