From e8e52fda1b550ea9f7e7249e9f404814bec9ae5a Mon Sep 17 00:00:00 2001 From: "wanling040@gmail.com" Date: Sun, 21 Aug 2022 22:32:40 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B6=B2=E9=A0=81=E6=AF=8F=E5=B0=8F=E6=99=82?= =?UTF-8?q?=E6=9B=B4=E6=96=B0:=20=E6=9B=B4=E6=8F=9B=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E6=AF=8F=E5=B0=8F=E6=99=82=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Quartz/Jobs/CalcPowerStationJobV2.cs | 852 ++++++++++++++++++ .../Services/Implement/SensorHourlyService.cs | 107 +++ SolarPower/Startup.cs | 14 +- SolarPower/appsettings.Development.json | 4 +- SolarPower/appsettings.json | 1 + 5 files changed, 974 insertions(+), 4 deletions(-) create mode 100644 SolarPower/Quartz/Jobs/CalcPowerStationJobV2.cs create mode 100644 SolarPower/Services/Implement/SensorHourlyService.cs diff --git a/SolarPower/Quartz/Jobs/CalcPowerStationJobV2.cs b/SolarPower/Quartz/Jobs/CalcPowerStationJobV2.cs new file mode 100644 index 0000000..f3c2c2b --- /dev/null +++ b/SolarPower/Quartz/Jobs/CalcPowerStationJobV2.cs @@ -0,0 +1,852 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Quartz; +using SolarPower.Models.PowerStation; +using SolarPower.Repository.Interface; +using SolarPower.Services.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; + +namespace SolarPower.Quartz.Jobs +{ + [DisallowConcurrentExecution] + public class CalcPowerStationJobV2 : IJob + { + private readonly ILogger logger; + private readonly IPowerStationRepository powerStationRepository; + private readonly IConfiguration Configuration; + + public IWebHostEnvironment environment; + + private double carbonRate; + string calcPowerStationTime = ""; + + public CalcPowerStationJobV2( + ILogger logger, + IPowerStationRepository powerStationRepository, + IWebHostEnvironment environment, + IConfiguration Configuration) + { + this.logger = logger; + this.powerStationRepository = powerStationRepository; + this.environment = environment; + this.Configuration = Configuration; + } + + public async Task Execute(IJobExecutionContext context) + { + try + { + var DateTimeNow = DateTime.Now; + var dateTime = DateTimeNow.AddHours(-1).ToString("yyyy-MM-dd HH"); + logger.LogInformation("【CalcPowerStationJobV2】【任務開始】"); + + #region step1. 找出所有電站 + logger.LogInformation("【CalcPowerStationJobV2】【開始取得電站資料】"); + var powerStations = await powerStationRepository.GetAllAsync(); + logger.LogInformation("【CalcPowerStationJobV2】【取得成功電站資料】"); + logger.LogInformation("【CalcPowerStationJobV2】【電站資料"); + #endregion + + await ArchiveStation(powerStations, dateTime); + await ArchiveStationForPowerStationWithWinForm(powerStations, dateTime); + await ArchiveSensorWithWinForm(powerStations, dateTime); + await ArchiveInverter(powerStations, dateTime); + await ArchiveSensoravg(powerStations, dateTime); + await ArchiveMeter(powerStations, dateTime); + await ArchiveWeather(powerStations, dateTime); + + logger.LogInformation("【CalcPowerStationJobV2】【任務完成】"); + } + catch (Exception exception) + { + logger.LogError("【CalcPowerStationJobV2】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + logger.LogError("【CalcPowerStationJobV2】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + + private async Task ArchiveStation(List powerStations, string dateTime) + { + List powerStationHistoriesHour = new List(); + List calcPowerStations = new List(); + foreach (var powerStation in powerStations) + { + try + { + #region step2-1. 取得該電站的當前這小時的歷史資料 + var table_name = String.Format("s{1}01_station", powerStation.SiteDB, powerStation.Code); + var full_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, table_name); + var exist = await powerStationRepository.ExistTable(powerStation.SiteDB, table_name); + + if (string.IsNullOrEmpty(exist)) + { + logger.LogError($"【CalcPowerStationJobV2】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_station資料表】"); + } + else + { + logger.LogInformation("【CalcPowerStationJobV2】【開始取得電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); + var history = await powerStationRepository.GetPowerStationHistoryPerHour(dateTime, full_table_name); + + if (history == null) + { + logger.LogWarning("【CalcPowerStationJobV2】【查無電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); + } + else + { + logger.LogInformation("【CalcPowerStationJobV2】【取得成功電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); + logger.LogInformation("【CalcPowerStationJobV2】【電站[{0}]在{1}的每小時歷史資料】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(history)); + + logger.LogInformation("【CalcPowerStationJobV2】【開始計算電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); + history.PowerStationId = powerStation.Id; + history.Timestamp = Convert.ToDateTime(history.Timestamp + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); + + #region 計算單一電站每小時發電量、發電金額等資料 for history + + #region 發電金額 + history.MONEY = history.KWH * powerStation.PowerRate; + history.TODAYMONEY = history.TodayKWh * powerStation.PowerRate; + history.TOTALMONEY = history.TotalKWH * powerStation.PowerRate; + #endregion + + #region 減碳量 + carbonRate = Convert.ToDouble(await powerStationRepository.GetOneVariableByName("CarbonRate")); + history.CARBON = history.KWH * carbonRate; + history.TODAYCARBON = history.TodayKWh * carbonRate; + history.TOTALCARBON = history.TotalKWH * carbonRate; + #endregion + + #endregion + + powerStationHistoriesHour.Add(history); + + logger.LogInformation("【CalcPowerStationJobV2】【計算完成電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); + } + } + #endregion + } + catch (Exception exception) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveStation】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveStation】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + if (!environment.IsDevelopment()) + { + #region step3. 將historiers INSERT 到 power_station_history_hour 資料表 + List history_properties = new List() + { + "PowerStationId", + "TIMESTAMP", + "SITEID", + "SITETYPE", + "KWH", + "TODAYKWH", + "TOTALKWH", + "KWHKWP", + "PR", + "MP", + "SolarHour", + "MONEY", + "CARBON", + "TODAYMONEY", + "TOTALMONEY", + "TODAYCARBON", + "TOTALCARBON" + }; + logger.LogInformation("【Insert PowerStationHistoryHour】【ArchiveStation】【開始寫入 PowerStationHistoryHour 資料】- {0}", dateTime); + await powerStationRepository.AddPowerStationHistory(powerStationHistoriesHour, history_properties); + logger.LogInformation("【Insert PowerStationHistoryHour】【ArchiveStation】【完成寫入 PowerStationHistoryHour 資料】- {0}", dateTime); + #endregion + } + } + + private async Task ArchiveStationForPowerStation(List powerStations, string dateTime) + { + List powerStationHistoriesHour = new List(); + List calcPowerStations = new List(); + foreach (var powerStation in powerStations) + { + try + { + var calcPowerStation = new PowerStation(); + calcPowerStation.Id = powerStation.Id; + #region step2-1. 取得該電站的當前這小時的歷史資料 + var table_name = String.Format("s{1}01_station", powerStation.SiteDB, powerStation.Code); + var full_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, table_name); + var exist = await powerStationRepository.ExistTable(powerStation.SiteDB, table_name); + + if (string.IsNullOrEmpty(exist)) + { + logger.LogError($"【CalcPowerStationJobV2】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_station資料表】"); + } + else + { + #region 計算單一電站每小時發電量、發電金額等資料 for calcPowerStation + var dateTimeforPowerStation = DateTime.Now.AddHours(-1).ToString("yyyy-MM-dd");//取當天 + logger.LogInformation("【CalcPowerStationJobV2】【開始取得電站[{0}]在{1}的每小時歷史資料 for calcPowerStation】", powerStation.Code, dateTimeforPowerStation); + var history_for_powerStation = await powerStationRepository.GetPowerStationHistoryPerHourForPowerStation(dateTimeforPowerStation, full_table_name); + if (history_for_powerStation == null) + { + logger.LogWarning("【CalcPowerStationJobV2】【查無電站[{0}]在{1}的每小時歷史資料 for calcPowerStation;發電量、發電金額等資料設定為0】", powerStation.Code, dateTimeforPowerStation); + calcPowerStation.kwh = 0; + calcPowerStation.Today_kWh = 0; + calcPowerStation.Total_kWh = 0; + calcPowerStation.Today_Money = 0; + calcPowerStation.Total_Money = 0; + calcPowerStation.Today_kwhkwp = 0; + calcPowerStation.Today_PR = 0; + calcPowerStation.Today_Carbon = 0; + calcPowerStation.Total_Carbon = 0; + calcPowerStation.SolarHour = 0; + } + else + { + logger.LogInformation("【CalcPowerStationJobV2】【開始計算電站[{0}]在{1}的每小時歷史資料 for calcPowerStation】", powerStation.Code, dateTimeforPowerStation); + #region 發電量 + //每小時發電量(直接填寫 + calcPowerStation.kwh = history_for_powerStation.KWH; + //今日發電量(直接填寫 + calcPowerStation.Today_kWh = history_for_powerStation.TodayKWh; + //總發電量(直接填寫 + calcPowerStation.Total_kWh = history_for_powerStation.TotalKWH; + #endregion + + #region 發電金額 + history_for_powerStation.MONEY = history_for_powerStation.KWH * powerStation.PowerRate; + history_for_powerStation.TODAYMONEY = history_for_powerStation.TodayKWh * powerStation.PowerRate; + history_for_powerStation.TOTALMONEY = history_for_powerStation.TotalKWH * powerStation.PowerRate; + + //即時發電金額 + switch (powerStation.SolarType) + { + case (int)SolarTypeEnum.SelfSold: //自建躉售 + //今日發電金額 計算方式:todaykWh * 授電費率 + calcPowerStation.Today_Money = history_for_powerStation.TodayKWh * powerStation.PowerRate; + + ////總發電金額 計算方式:totalkWh * 授電費率 + calcPowerStation.Total_Money = history_for_powerStation.TotalKWH * powerStation.PowerRate; + break; + case (int)SolarTypeEnum.HireSold: //租建躉售 + //找出該電站的所有土地房屋資訊 + var landBuildings = await powerStationRepository.GetAllLandBuildingInfoByPowerStationId(powerStation.Id, powerStation.SiteDB); + var sumLeaseRate = 0.00; + var avgLeaseRate = 0.00; + + foreach (var landBuilding in landBuildings) + { + sumLeaseRate += landBuilding.LeaseRate; + } + + calcPowerStation.Today_Money = history_for_powerStation.TodayKWh * powerStation.PowerRate * sumLeaseRate / 100; + calcPowerStation.Total_Money = history_for_powerStation.TotalKWH * powerStation.PowerRate * sumLeaseRate / 100; + + break; + case (int)SolarTypeEnum.SelfUse: //自建自用 + + //今日發電金額 計算方式:todaykWh * 授電費率 + calcPowerStation.Today_Money = history_for_powerStation.TodayKWh * powerStation.PowerRate; + + //總發電金額 計算方式:totalkWh * 授電費率 + calcPowerStation.Total_Money = history_for_powerStation.TotalKWH * powerStation.PowerRate; + break; + } + #endregion + + #region kWh/kWp + ////直接填寫 + calcPowerStation.Today_kwhkwp = history_for_powerStation.KWHKWP; + #endregion + + #region PR + //直接填寫 + calcPowerStation.Today_PR = history_for_powerStation.PR; + #endregion + + #region 減碳量 + carbonRate = Convert.ToDouble(await powerStationRepository.GetOneVariableByName("CarbonRate")); + history_for_powerStation.CARBON = history_for_powerStation.KWH * carbonRate; + history_for_powerStation.TODAYCARBON = history_for_powerStation.TodayKWh * carbonRate; + history_for_powerStation.TOTALCARBON = history_for_powerStation.TotalKWH * carbonRate; + + //今日減碳量( 今日發電量 * (0.554/1000)[抓資料庫值] + calcPowerStation.Today_Carbon = history_for_powerStation.TodayKWh * carbonRate; + + //總減碳量(總發電量 * (0.554/1000)[抓資料庫值] + calcPowerStation.Total_Carbon = history_for_powerStation.TotalKWH * carbonRate; + #endregion + + #region 發電時間 + calcPowerStation.SolarHour = history_for_powerStation.SolarHour; + #endregion + + #region 取拿到資料的時間 + calcPowerStationTime = history_for_powerStation.Timestamp; + #endregion + } + #endregion + + string dateTimeForCalc; + if (calcPowerStationTime != "") + { + dateTimeForCalc = calcPowerStationTime; + } + else + { + dateTimeForCalc = dateTime; + } + + logger.LogInformation("【CalcPowerStationJobV2】【開始取得電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime); + var deviceInfos = await powerStationRepository.GetListPyrheliometerByPowerStationId(powerStation.Id, powerStation.SiteDB); + logger.LogInformation("【CalcPowerStationJobV2】【取得成功電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime); + logger.LogInformation("【CalcPowerStationJobV2】【電站[{0}]在{1}的日照計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(deviceInfos)); + + if (deviceInfos != null && deviceInfos.Count() > 0) + { + var pyrheliometerHistory_for_calcPowerStation = await powerStationRepository.CalcSensorHistoryPerHour(dateTimeForCalc, deviceInfos, Convert.ToInt32(SensorTypeEnum.PYR)); + if (pyrheliometerHistory_for_calcPowerStation != null) + { + calcPowerStation.Today_irradiance = pyrheliometerHistory_for_calcPowerStation.Irradiance; + logger.LogInformation("【CalcPowerStationJobV2】【計算完成電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime); + } + else + { + logger.LogWarning("【CalcPowerStationJobV2】【查無結果電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime); + } + } + calcPowerStations.Add(calcPowerStation); + logger.LogInformation("【CalcPowerStationJobV2】【計算完成電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); + } + #endregion + } + catch (Exception exception) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveStation】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveStation】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + if (!environment.IsDevelopment()) + { + #region step5. calcPowerStations UPDATE 到 power_station 資料表 + List power_station_properties = new List() + { + "Id", + "kwh", + "Today_kwh", + "Total_kwh", + "today_kwhkwp", + "today_money", + "total_money", + "today_PR", + "today_carbon", + "total_carbon", + "today_irradiance", + "SolarHour", + "WeathersStationId", + "TodayWeatherTemp", + "TodayWeather", + "RateOfRain" + }; + logger.LogInformation("【update Power_Station】【ArchiveStation】【開始更新 Power_Station 資料】- {0}", dateTime); + await powerStationRepository.UpdateList(calcPowerStations, power_station_properties); + logger.LogInformation("【update Power_Station】【ArchiveStation】【完成更新 Power_Station 資料】- {0}", dateTime); + #endregion + } + } + + private async Task ArchiveStationForPowerStationWithWinForm(List powerStations, string dateTime) + { + logger.LogInformation("【CalcPowerStationJobV2】【開始計算全電站在{0}的發電量等資訊】", dateTime); + #region step2-2. 取得該電站的當前這小時的發電量等歷史資料 + //使用winform function + var Connection_string = Configuration.GetValue("mySql"); + SensorHourlyService sensorHourlyService = new SensorHourlyService(Connection_string); + await sensorHourlyService.ArchiveStationHourly(); + logger.LogInformation("【CalcPowerStationJobV2】【更新完成全電站在{0}的發電量等資訊】", dateTime); + #endregion + } + + private async Task ArchiveSensorWithWinForm(List powerStations, string dateTime) + { + foreach (var powerStation in powerStations) + { + try + { + var sensoravg_table_name = String.Format("s{1}01_sensoravg", powerStation.SiteDB, powerStation.Code); + var full_sensoravg_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, sensoravg_table_name); + var sensoravg_table_exist = await powerStationRepository.ExistTable(powerStation.SiteDB, sensoravg_table_name); + if (string.IsNullOrEmpty(sensoravg_table_exist)) + { + logger.LogError($"【CalcPowerStationJobV2】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_sensoravg資料表】"); + } + else + { + logger.LogInformation("【CalcPowerStationJobV2】【開始計算電站[{0}]在{1}的設備資訊】", powerStation.Code, dateTime); + #region step2-2. 取得該電站的當前這小時的設備歷史資料 + //使用winform function + var Connection_string = Configuration.GetValue("mySql"); + SensorHourlyService sensorHourlyService = new SensorHourlyService(Connection_string); + sensorHourlyService.ArchiveSensorHourly(powerStation.Code, dateTime); + logger.LogInformation("【CalcPowerStationJobV2】【更新完成電站[{0}]在{1}的設備資訊】", powerStation.Code, dateTime); + #endregion + } + } + catch (Exception exception) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveSensor】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveSensor】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + } + + private async Task ArchiveInverter(List powerStations, string dateTime) + { + List inverterHistoriesHour = new List(); + foreach (var powerStation in powerStations) + { + #region step2-3. 計算該電站所有逆變器每小時值 + + var inverter_table_name = String.Format("s{0}01_inv", powerStation.Code); + var full_inverter_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, inverter_table_name); + var inverter_exist = await powerStationRepository.ExistTable(powerStation.SiteDB, inverter_table_name); + if (string.IsNullOrEmpty(inverter_exist)) + { + logger.LogError("【CalcPowerStationJobV2】【查無電站[0]的s{0}01_inv資料表】", powerStation.Code); + } + else + { + try + { + logger.LogInformation("【CalcPowerStationJobV2】【開始取得電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateTime); + var controllers = await powerStationRepository.GetAllDeviceControllerId(powerStation.Id, powerStation.SiteDB); + var inverters = await powerStationRepository.InverterTable(controllers, powerStation.SiteDB); + var inverterIds = inverters.Where(x => x.Enabled == 1 && x.Status != 0).Select(x => x.InverterId).ToList(); + logger.LogInformation("【CalcPowerStationJobV2】【取得成功電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateTime); + logger.LogInformation("【CalcPowerStationJobV2】【電站[{0}]在{1}的逆變器設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(inverterIds)); + + if (inverterIds != null && inverterIds.Count() > 0) + { + logger.LogInformation("【CalcPowerStationJobV2】【開始計算電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime); + var inverterHistories = await powerStationRepository.CalcInverterHisyortHourData(dateTime, powerStation.SiteDB, full_inverter_table_name, inverterIds); + //取得日照計要找的欄位資訊 + var pyrheliometer = await powerStationRepository.GetFirstPyrheliometerInfo(powerStation.Id, powerStation.SiteDB); + var pyrheliometerValue = await powerStationRepository.GetFirstPyrheliometerValue(dateTime, pyrheliometer.DBName, pyrheliometer.TableName, pyrheliometer.ColName); + foreach (var inverterHistory in inverterHistories) + { + inverterHistory.Irradiance = pyrheliometerValue; + inverterHistory.DC1KW = inverterHistory.DC1W / 1000; + inverterHistory.DC2KW = inverterHistory.DC2W / 1000; + inverterHistory.DC3KW = inverterHistory.DC3W / 1000; + inverterHistory.DC4KW = inverterHistory.DC4W / 1000; + inverterHistory.DC5KW = inverterHistory.DC5W / 1000; + + inverterHistory.DCKW = (inverterHistory.DC1W + inverterHistory.DC2W + inverterHistory.DC3W + inverterHistory.DC4W + inverterHistory.DC5W) / 1000; + inverterHistory.ACKW = (inverterHistory.AC1W + inverterHistory.AC2W + inverterHistory.AC3W) / 1000; + + inverterHistory.TIMESTAMP = Convert.ToDateTime(inverterHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); + inverterHistory.PowerStationId = powerStation.Id; + + inverterHistoriesHour.Add(inverterHistory); + } + logger.LogInformation("【CalcPowerStationJobV2】【計算完成電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime); + } + } + catch (Exception ex) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveInverter】【計算失敗電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime); + logger.LogError("【CalcPowerStationJobV2】【ArchiveInverter】【失敗原因】- {0}", ex.Message); + } + } + #endregion + } + if (!environment.IsDevelopment()) + { + #region step6. 將 inverter INSERT 到 inverter_history_hour 資料表 + List inverter_history_properties = new List() + { + "PowerStationId", + "INVERTERID", + "TIMESTAMP", + "Irradiance", + "AC1V", + "AC1A", + "AC1W", + "AC1F", + "AC1WH", + "AC2V", + "AC2A", + "AC2W", + "AC2F", + "AC2WH", + "AC3V", + "AC3A", + "AC3W", + "AC3F", + "AC3WH", + "DC1V", + "DC1A", + "DC1W", + "DC1KW", + "DC1WH", + "DC2V", + "DC2A", + "DC2W", + "DC2KW", + "DC2WH", + "DC3V", + "DC3A", + "DC3W", + "DC3KW", + "DC3WH", + "DC4V", + "DC4A", + "DC4W", + "DC4KW", + "DC4WH", + "DC5V", + "DC5A", + "DC5W", + "DC5KW", + "DC5WH", + "PR", + "RA1", + "RA2", + "RA3", + "RA4", + "RA5", + "DCKW", + "ACKW", + "KWH", + "TODAYKWH", + "TOTALKWH", + "KWHKWP", + }; + logger.LogInformation("【Insert InverterHistoryHour】【ArchiveInverter】【開始寫入 inverter_history_hour 資料】- {0}", dateTime); + await powerStationRepository.AddInverterHistory(inverterHistoriesHour, inverter_history_properties); + logger.LogInformation("【Insert InverterHistoryHour】【ArchiveInverter】【完成寫入 inverter_history_hour 資料】- {0}", dateTime); + #endregion + } + } + + private async Task ArchiveSensoravg(List powerStations, string dateTime) + { + List sensorAvgHistoryHour = new List(); + foreach (var powerStation in powerStations) + { + try + { + var sensoravg_table_name = String.Format("s{1}01_sensoravg", powerStation.SiteDB, powerStation.Code); + var full_sensoravg_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, sensoravg_table_name); + var sensoravg_table_exist = await powerStationRepository.ExistTable(powerStation.SiteDB, sensoravg_table_name); + #region step2-4. 計算該電站所有sensoravg + try + { + if (!string.IsNullOrEmpty(sensoravg_table_exist)) + { + logger.LogInformation("【CalcPowerStationJobV2】【開始計算電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime); + var sensorAvgHistory = await powerStationRepository.CalcSensorAvgHistory(dateTime, full_sensoravg_table_name); + logger.LogInformation("【CalcPowerStationJobV2】【計算完成電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime); + + if (sensorAvgHistory != null) + { + sensorAvgHistory.PowerStationId = powerStation.Id; + sensorAvgHistory.TIMESTAMP = Convert.ToDateTime(sensorAvgHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); + + sensorAvgHistoryHour.Add(sensorAvgHistory); + } + } + } + catch (Exception ex) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveSensoravg】【計算失敗電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime); + logger.LogError("【CalcPowerStationJobV2】【ArchiveSensoravg】【失敗原因】- {0}", ex.Message); + } + #endregion + } + catch (Exception exception) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveSensoravg】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveSensoravg】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + if (!environment.IsDevelopment()) + { + #region step7. 將 sensoravg INSERT 到 sensoravg_history_hour 資料表 + List sensoravg_history_properties = new List() + { + "PowerStationId", + "TIMESTAMP", + "SENSORAVG01", + "SENSORAVG02", + "SENSORAVG03", + "SENSORAVG04", + "SENSORAVG05", + "SENSORAVG06", + "SENSORAVG07", + "SENSORAVG08", + "SENSORAVG09", + "SENSORAVG10", + "SENSORAVG11", + "SENSORAVG12", + "SENSORAVG13", + "SENSORAVG14", + "SENSORAVG15", + "SENSORAVG16", + "SENSORAVG17", + "SENSORAVG18", + "SENSORAVG19", + "SENSORAVG20", + "SENSORAVG21", + "SENSORAVG22", + "SENSORAVG23", + "SENSORAVG24", + "SENSORAVG25", + "SENSORAVG26", + "SENSORAVG27", + "SENSORAVG28", + "SENSORAVG29", + "SENSORAVG30", + "SENSORAVG31", + "SENSORAVG32", + "SENSORAVG33", + "SENSORAVG34", + "SENSORAVG35", + "SENSORAVG36", + "SENSORAVG37", + "SENSORAVG38", + "SENSORAVG39", + "SENSORAVG40", + "SENSORAVG41", + "SENSORAVG42", + "SENSORAVG43", + "SENSORAVG44", + "SENSORAVG45", + "SENSORAVG46", + "SENSORAVG47", + "SENSORAVG48", + "SENSORAVG49", + "SENSORAVG50", + }; + logger.LogInformation("【Insert SensoravgHistoryHour】【ArchiveSensoravg】【開始寫入 sensoravg_history_hour 資料】- {0}", dateTime); + await powerStationRepository.AddSensorAvgHistory(sensorAvgHistoryHour, sensoravg_history_properties); + logger.LogInformation("【Insert SensoravgHistoryHour】【ArchiveSensoravg】【完成寫入 sensoravg_history_hour 資料】- {0}", dateTime); + #endregion + } + } + + private async Task ArchiveMeter(List powerStations, string dateTime) + { + List meterHistoriesHour = new List(); + foreach (var powerStation in powerStations) + { + try + { + var meter_table_name = String.Format("s{0}01_meter", powerStation.Code); + var full_meter_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, meter_table_name); + var exist_meter_table = await powerStationRepository.ExistTable(powerStation.SiteDB, meter_table_name); + #region step2-5. 計算該電站meter + try + { + if (string.IsNullOrEmpty(exist_meter_table)) + { + logger.LogError($"【CalcPowerStationJobV2】【查無電站[{powerStation.Code}]的s{powerStation.Code}01_meter資料表】"); + } + else + { + logger.LogInformation("【CalcPowerStationJobV2】【開始計算電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime); + var meterHistory = await powerStationRepository.CalcMeterHistory(dateTime, full_meter_table_name); + logger.LogInformation("【CalcPowerStationJobV2】【計算完成電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime); + + if (meterHistory != null) + { + meterHistory.PowerStationId = powerStation.Id; + meterHistory.TIMESTAMP = Convert.ToDateTime(meterHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); + + meterHistoriesHour.Add(meterHistory); + } + } + } + catch (Exception ex) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveMeter】【計算失敗電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime); + logger.LogError("【CalcPowerStationJobV2】【ArchiveMeter】【失敗原因】- {0}", ex.Message); + } + #endregion + } + catch (Exception exception) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveMeter】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveMeter】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + if (!environment.IsDevelopment()) + { + #region step8. 將 meter INSERT 到 meter_history_hour 資料表 + List memter_history_properties = new List() + { + "PowerStationId", + "TIMESTAMP", + "METERID", + "V_AB", + "V_BC", + "V_CA", + "I_A", + "I_B", + "I_C", + "I_C", + "P", + "F", + "INPUT_KWH", + "OUTPUT_KWH" + }; + logger.LogInformation("【Insert MeterHistoryHour】【ArchiveMeter】【開始寫入 meter_history_hour 資料】- {0}", dateTime); + await powerStationRepository.AddMeterHistory(meterHistoriesHour, memter_history_properties); + logger.LogInformation("【Insert MeterHistoryHour】【ArchiveMeter】【完成寫入 meter_history_hour 資料】- {0}", dateTime); + #endregion + } + } + + private async Task ArchiveWeather(List powerStations, string dateTime) + { + Root2 observation = null; + List weatherObservations = new List(); + #region 氣象觀測(取資料) + try + { + logger.LogInformation("【CalcPowerStationJobV2】【開始取得氣象觀測】"); + var client = new HttpClient(); + var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/O-A0003-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&elementName=TIME,TEMP"; + HttpResponseMessage response = client.GetAsync(UVUri).Result; + String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString(); + observation = JsonConvert.DeserializeObject(jsonUVs); + logger.LogInformation("【CalcPowerStationJobV2】【取得成功氣象觀測】"); + } + catch (Exception ex) + { + logger.LogError("【CalcPowerStationJobV2】【取得失敗氣象觀測】"); + logger.LogError("【{0}】{1}", "CalcPowerStationJobV2", ex.Message); + observation = null; + } + #endregion + foreach (var powerStation in powerStations) + { + try + { + var calcPowerStation = new PowerStation(); + calcPowerStation.Id = powerStation.Id; + #region 確認是否有觀測站(沒有則新增) + try + { + if (powerStation.WeathersStationId == null) + { + var weatherStationId = ""; + double shortLocation = 9999; + foreach (var Location in observation.Records.Location) + { + + if (powerStation.Coordinate != null) + { + var powerLocation = powerStation.Coordinate.Split(','); + double p1 = Convert.ToDouble(powerLocation[0].Replace("°", string.Empty)); + double p2 = Convert.ToDouble(powerLocation[1].Replace("°", string.Empty)); + double dLat = Convert.ToDouble(Location.Lat); + double dLon = Convert.ToDouble(Location.Lon); + double x = Math.Pow(p1 - dLat, 2); + double y = Math.Pow(p2 - dLon, 2); + var nowLocation = Math.Sqrt(x + y); + if (nowLocation < shortLocation) + { + shortLocation = nowLocation; + weatherStationId = Location.StationId; + calcPowerStation.TodayWeatherTemp = Convert.ToDouble(Location.WeatherElement[0].ElementValue); + } + } + } + + calcPowerStation.WeathersStationId = weatherStationId; + } + + WeatherObservation weatherObservation = new WeatherObservation(); + if (powerStation.WeathersStationId != null && observation != null) + { + foreach (var Location in observation.Records.Location) + { + if (Location.StationId == powerStation.WeathersStationId) + { + calcPowerStation.TodayWeatherTemp = Convert.ToDouble(Location.WeatherElement[0].ElementValue); + weatherObservation.PowerStationId = powerStation.Id; + weatherObservation.Temp = Convert.ToDouble(Location.WeatherElement[0].ElementValue); + weatherObservation.ObsTime = !string.IsNullOrEmpty(Location.Time.ObsTime) ? Convert.ToInt32(Location.Time.ObsTime.Substring(0, 4)) >= 1971 ? Location.Time.ObsTime : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") : DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + calcPowerStation.WeathersStationId = powerStation.WeathersStationId; + break; + } + } + weatherObservations.Add(weatherObservation); + } + + logger.LogInformation("【CalcPowerStationJobV2】【開始取得電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime); + var weather = await powerStationRepository.SelectNowWeather(powerStation.CityId); + logger.LogInformation("【CalcPowerStationJobV2】【取得成功電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime); + if (weather != null) + { + calcPowerStation.TodayWeather = weather.WeatherKey; + calcPowerStation.RateOfRain = weather.PoP; + } + } + catch (Exception ex) + { + logger.LogError("【CalcPowerStationJobV2】【ArchiveWeather】【取得失敗電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime); + logger.LogError("【CalcPowerStationJobV2】【ArchiveWeather】【失敗原因】- {0}", ex.Message); + } + #endregion + } + catch (Exception exception) + { + //logger.LogError("【CalcPowerStationJobV2】[Exception] - {0}", exception.Message); + if (exception.InnerException != null) + { + //logger.LogError("【CalcPowerStationJobV2】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + if (!environment.IsDevelopment()) + { + #region step9. 新增天氣資訊 + List weather_observation_properties = new List() + { + "PowerStationId", + "ObsTime", + "Temp" + }; + logger.LogInformation("【Insert WeatherObservation】【ArchiveWeather】【開始寫入 weather_observation 資料】- {0}", dateTime); + await powerStationRepository.AddWeatherObservation(weatherObservations, weather_observation_properties); + logger.LogInformation("【Insert WeatherObservation】【ArchiveWeather】【完成寫入 weather_observation 資料】- {0}", dateTime); + #endregion + } + } + + } +} diff --git a/SolarPower/Services/Implement/SensorHourlyService.cs b/SolarPower/Services/Implement/SensorHourlyService.cs new file mode 100644 index 0000000..b57d3f6 --- /dev/null +++ b/SolarPower/Services/Implement/SensorHourlyService.cs @@ -0,0 +1,107 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using solarApp.Service; +using Microsoft.Extensions.Logging; +using System.Configuration; + +namespace SolarPower.Services.Implement +{ + public class SensorHourlyService + { + ILogger _logger; + procArchiveSensorHourly sensorSvc; + procArchiveHourly HourSvc; + string Connection1 = string.Empty; + + public SensorHourlyService(string Connection_parame = null, ILogger logger = null) + { + if (!string.IsNullOrEmpty(Connection_parame)) + { + Connection1 = Connection_parame; + } + else + { + Connection1 = ConfigurationManager.ConnectionStrings["mySql"].ConnectionString; + } + sensorSvc = new procArchiveSensorHourly(Connection1); + HourSvc = new procArchiveHourly(Connection1); + if (logger != null) + { + _logger = logger; + } + } + + + + public void ArchiveSensorHourly(string code, string dateTime) + { + #region 歸檔 Sensor + try + { + if (_logger != null) + { + _logger.LogInformation("【SenSorHourlyService】【ArchiveSensorHourly】使用winform,開始執行[{0}]在{1}寫入資料", code, dateTime); + } + sensorSvc.insertData(code, dateTime); + if (_logger != null) + { + _logger.LogInformation("【SenSorHourlyService】【ArchiveSensorHourly】完成執行[{0}]在{1}寫入資料", code, dateTime); + } + } + catch (Exception exception) + { + if (_logger != null) + { + _logger.LogError("【SenSorHourlyService】【ArchiveSensorHourly】[Exception] - {0}", exception.Message); + } + if (exception.InnerException != null) + { + if (_logger != null) + { + _logger.LogError("【SenSorHourlyService】【ArchiveSensorHourly】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + #endregion + if (_logger != null) + { + _logger.LogInformation("【SenSorHourlyService】【ArchiveSensorHourly】[執行完成] "); + } + } + + public Task ArchiveStationHourly() + { + bool result = false; + #region 歸檔 Station + try + { + HourSvc.proc_s1_site(); + result = true; + } + catch (Exception exception) + { + if (_logger != null) + { + _logger.LogError("【SenSorHourlyService】【ArchiveStationHourly】[Exception] - {0}", exception.Message); + } + if (exception.InnerException != null) + { + if (_logger != null) + { + _logger.LogError("【SenSorHourlyService】【ArchiveStationHourly】[InnerException] - {0}", exception.InnerException.Message); + } + } + } + #endregion + if (_logger != null) + { + _logger.LogInformation("【SenSorHourlyService】【ArchiveStationHourly】[執行完成] "); + } + return Task.FromResult(result); + } + + } +} diff --git a/SolarPower/Startup.cs b/SolarPower/Startup.cs index 6b749ed..fcc705c 100644 --- a/SolarPower/Startup.cs +++ b/SolarPower/Startup.cs @@ -116,11 +116,19 @@ namespace SolarPower ); //#endregion + ////#region pqoqqT(CI5) + //services.AddSingleton(); + //services.AddSingleton( + //new JobSchedule(jobType: typeof(CalcPowerStationJob), cronExpression: Configuration.GetValue("BackgroundServiceCron:CalcPowerStationJob")) + ////new JobSchedule(jobType: typeof(CalcPowerStationJob), cronExpression: "0/10 * * * * ?") + //); + ////#endregion + //#region pqoqqT(CI5) - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton( - new JobSchedule(jobType: typeof(CalcPowerStationJob), cronExpression: Configuration.GetValue("BackgroundServiceCron:CalcPowerStationJob")) - //new JobSchedule(jobType: typeof(CalcPowerStationJob), cronExpression: "0/10 * * * * ?") + new JobSchedule(jobType: typeof(CalcPowerStationJobV2), cronExpression: Configuration.GetValue("BackgroundServiceCron:CalcPowerStationJobV2")) + //new JobSchedule(jobType: typeof(CalcPowerStationJobV2), cronExpression: "0/10 * * * * ?") ); //#endregion diff --git a/SolarPower/appsettings.Development.json b/SolarPower/appsettings.Development.json index 61c6373..a99f73e 100644 --- a/SolarPower/appsettings.Development.json +++ b/SolarPower/appsettings.Development.json @@ -15,7 +15,8 @@ // "Root": "mWlR2HshQNhRRE34jg4kdg==", // "Password": "y4uPqlH9ncTgR/I07qpwaA==" //}, - "mySql": "server=210.61.91.43;user=idafenweb;Database=solar_master;Port=10068;password=P@ssw0rd;charset='utf8';pooling=true;sslmode=none;", + //"mySql": "server=210.61.91.43;user=idafenweb;Database=solar_master;Port=10068;password=P@ssw0rd;charset='utf8';pooling=true;sslmode=none;", + "mySql": "server=60.251.164.103;user=webuser;Database=solar_master;Port=11306;password=FICadmin99;charset='utf8';pooling=true;sslmode=none;", // "DBConfig": { "Server": "AVXfxd+IRlLtJ0MCi9HU1g==", @@ -34,6 +35,7 @@ //}, "BackgroundServiceCron": { "CalcPowerStationJob": "0 05 * * * ?", + "CalcPowerStationJobV2": "0 05 * * * ?", "CalcAvgPowerStationJob": "0 12 0 * * ?", "OperationScheduleJob": "0 0 8 * * ?", "CalcInverter15minJob": "0 2/15 * * * ?", diff --git a/SolarPower/appsettings.json b/SolarPower/appsettings.json index 5d1ba96..3153171 100644 --- a/SolarPower/appsettings.json +++ b/SolarPower/appsettings.json @@ -36,6 +36,7 @@ }, "BackgroundServiceCron": { "CalcPowerStationJob": "0 05 * * * ?", + "CalcPowerStationJobV2": "0 05 * * * ?", "CalcAvgPowerStationJob": "0 12 0 * * ?", "OperationScheduleJob": "0 0 8 * * ?", "CalcInverter15minJob": "0 2/15 * * * ?",