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 System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace SolarPower.Quartz.Jobs { [DisallowConcurrentExecution] public class CalcPowerStationJob : IJob { private readonly ILogger logger; private readonly IPowerStationRepository powerStationRepository; public IWebHostEnvironment environment; private double carbonRate; public CalcPowerStationJob( ILogger logger, IPowerStationRepository powerStationRepository, IWebHostEnvironment environment) { this.logger = logger; this.powerStationRepository = powerStationRepository; this.environment = environment; } public async Task Execute(IJobExecutionContext context) { try { var DateTimeNow = DateTime.Now; var dateTime = DateTimeNow.AddHours(-1).ToString("yyyy-MM-dd HH"); Root2 observation = null; if (this.environment.IsDevelopment()) { dateTime = "2021-08-16 09"; } logger.LogInformation("【CalcPowerStationJob】【任務開始】"); #region step1. 找出所有電站 logger.LogInformation("【CalcPowerStationJob】【開始取得電站資料】"); var powerStations = await powerStationRepository.GetAllAsync(); logger.LogInformation("【CalcPowerStationJob】【取得成功電站資料】"); logger.LogInformation("【CalcPowerStationJob】【電站資料】 - {0}", System.Text.Json.JsonSerializer.Serialize(powerStations)); #endregion List powerStationHistoriesHour = new List(); List sensorHistoriesHour = new List(); List pyrheliometerHistoriesHour = new List(); List TempHistoriesHour = new List(); List inverterHistoriesHour = new List(); List calcPowerStations = new List(); List sensorAvgHistoryHour = new List(); List meterHistoriesHour = new List(); List weatherObservations = new List(); #region 氣象觀測(取資料) try { logger.LogInformation("【CalcPowerStationJob】【開始取得氣象觀測】"); 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("【CalcPowerStationJob】【取得成功氣象觀測】"); } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【取得失敗氣象觀測】"); logger.LogError("【{0}】{1}", "CalcPowerStationJob", ex.Message); observation = null; } #endregion #region step2. 從電站的DB及電站編號找出該電站的控制器 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("【CalcPowerStationJob】【查無電站[{0}]的s{0}01_station資料表】", powerStation.Code); } else { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); var history = await powerStationRepository.GetPowerStationHistoryPerHour(dateTime, full_table_name); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的每小時歷史資料】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(history)); var lastmoneyhistorybyhour = await powerStationRepository.GetLastMoneyAndCarbonInHour(powerStation.Id, 0, dateTime); if (history != null) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{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 計算單一電站每小時發電量、發電金額等資料 #region 發電量 //每小時發電量(直接填寫 calcPowerStation.kwh = history.KWH; //今日發電量(直接填寫 calcPowerStation.Today_kWh = history.TodayKWh; //總發電量(直接填寫 calcPowerStation.Total_kWh = history.TotalKWH; #endregion #region 發電金額 history.MONEY = history.KWH * powerStation.PowerRate; //即時發電金額 switch (powerStation.SolarType) { case (int)SolarTypeEnum.SelfSold: //自建躉售 if (lastmoneyhistorybyhour != null) { history.TODAYMONEY = lastmoneyhistorybyhour.TODAYMONEY + history.KWH * powerStation.PowerRate; history.TOTALMONEY = lastmoneyhistorybyhour.TOTALMONEY + history.KWH * powerStation.PowerRate; } else { history.TODAYMONEY = history.KWH * powerStation.PowerRate; history.TOTALMONEY = history.KWH * powerStation.PowerRate; } //今日發電金額 計算方式:todaykWh * 授電費率,如有上筆資料,需累加 上一筆金額 //calcPowerStation.Today_Money = history.TodayKWh * powerStation.PowerRate; calcPowerStation.Today_Money = history.TODAYMONEY; ////總發電金額 計算方式:totalkWh * 授電費率,如有上筆資料,需累加 上一筆金額 //calcPowerStation.Total_Money = history.TotalKWH * powerStation.PowerRate; calcPowerStation.Total_Money = history.TOTALMONEY; 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; } //avgLeaseRate = sumLeaseRate / landBuildings.Count(); if (lastmoneyhistorybyhour != null) { history.TODAYMONEY = lastmoneyhistorybyhour.TODAYMONEY + history.KWH * powerStation.PowerRate; history.TOTALMONEY = lastmoneyhistorybyhour.TOTALMONEY + history.KWH * powerStation.PowerRate; //今日發電金額計算方式:todaykWh * 出借費率(各個土地房屋租借比率平均) calcPowerStation.Today_Money = lastmoneyhistorybyhour.TODAYMONEY + (history.KWH * powerStation.PowerRate * sumLeaseRate); //總發電金額 計算方式:totalkWh * 授電費率 calcPowerStation.Total_Money = lastmoneyhistorybyhour.TOTALMONEY + (history.KWH * powerStation.PowerRate * sumLeaseRate); } else { history.TODAYMONEY = history.KWH * powerStation.PowerRate; history.TOTALMONEY = history.KWH * powerStation.PowerRate; calcPowerStation.Today_Money = history.KWH * powerStation.PowerRate * sumLeaseRate; calcPowerStation.Total_Money = history.KWH * powerStation.PowerRate * sumLeaseRate; } break; case (int)SolarTypeEnum.SelfUse: //自建自用 if (lastmoneyhistorybyhour != null) { history.TODAYMONEY = lastmoneyhistorybyhour.TODAYMONEY + history.KWH * powerStation.PowerRate; history.TOTALMONEY = lastmoneyhistorybyhour.TOTALMONEY + history.KWH * powerStation.PowerRate; } else { history.TODAYMONEY = history.KWH * powerStation.PowerRate; history.TOTALMONEY = history.KWH * powerStation.PowerRate; } //今日發電金額 計算方式:todaykWh * 授電費率 calcPowerStation.Today_Money = history.TODAYMONEY; //總發電金額 計算方式:totalkWh * 授電費率 calcPowerStation.Total_Money = history.TOTALMONEY; break; } #endregion #region kWh/kWp //直接填寫 calcPowerStation.Today_kwhkwp = history.KWHKWP; #endregion #region PR //直接填寫 calcPowerStation.Today_PR = history.PR; #endregion #region 減碳量 carbonRate = Convert.ToDouble(await powerStationRepository.GetOneVariableByName("CarbonRate")); history.CARBON = history.KWH * carbonRate; if (lastmoneyhistorybyhour != null) { history.TODAYCARBON = lastmoneyhistorybyhour.TODAYCARBON + history.KWH * carbonRate; history.TOTALCARBON = lastmoneyhistorybyhour.TOTALCARBON + history.KWH * carbonRate; //今日減碳量( 今日發電量 * (0.554/1000)[抓資料庫值] calcPowerStation.Today_Carbon = history.TODAYCARBON; //總減碳量(總發電量 * (0.554/1000)[抓資料庫值] calcPowerStation.Total_Carbon = history.TOTALCARBON; } else { history.TODAYCARBON = history.KWH * carbonRate; history.TOTALCARBON = history.KWH * carbonRate; //今日減碳量( 今日發電量 * (0.554/1000)[抓資料庫值] calcPowerStation.Today_Carbon = history.TODAYCARBON; history.CARBON = history.KWH * carbonRate; //總減碳量(總發電量 * (0.554/1000)[抓資料庫值] calcPowerStation.Total_Carbon = history.TotalKWH * carbonRate; } #endregion #region 發電時間 calcPowerStation.SolarHour = history.SolarHour; #endregion #endregion powerStationHistoriesHour.Add(history); logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime); } } #endregion #region step2-2. 取得該電站的當前這小時的設備歷史資料 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("【CalcPowerStationJob】【查無電站[0]的s{0}01_sensoravg資料表】", powerStation.Code); } else { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的設備資訊】", powerStation.Code, dateTime); PyrheliometerHistory sensorHistory = new PyrheliometerHistory(); sensorHistory.PowerStationId = powerStation.Id; sensorHistory.Timestamp = Convert.ToDateTime(dateTime + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); //1. 計算該電站sensor平均值 - 日照計(PYR) try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime); var deviceInfos = await powerStationRepository.GetListPyrheliometerByPowerStationId(powerStation.Id, powerStation.SiteDB); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的日照計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(deviceInfos)); if (deviceInfos != null && deviceInfos.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime); var pyrheliometerHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, deviceInfos, Convert.ToInt32(SensorTypeEnum.PYR)); if (pyrheliometerHistory != null) { calcPowerStation.Today_irradiance = pyrheliometerHistory.Irradiance; sensorHistory.Irradiance = pyrheliometerHistory.Irradiance; //pyrheliometerHistory.Timestamp = Convert.ToDateTime(pyrheliometerHistory.Timestamp + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); //pyrheliometerHistory.PowerStationId = powerStation.Id; //pyrheliometerHistoriesHour.Add(pyrheliometerHistory); } logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime); } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的日照計的平均值】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } //2. 計算該電站sensor平均值 - 模組溫度計(MTR) try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的模組溫度計設備資訊】", powerStation.Code, dateTime); var tempdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, "MTR", powerStation.SiteDB); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的模組溫度計設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的模組溫度計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(tempdeviceInfos)); if (tempdeviceInfos != null && tempdeviceInfos.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的模組溫度計的平均值】", powerStation.Code, dateTime); var tempHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, tempdeviceInfos, Convert.ToInt32(SensorTypeEnum.MTR)); if (tempHistory != null) { //tempHistory.Timestamp = Convert.ToDateTime(tempHistory.Timestamp + ":00:00").ToString("yyyy-MM-dd HH:mm:ss"); //tempHistory.PowerStationId = powerStation.Id; //TempHistoriesHour.Add(tempHistory); sensorHistory.Temperature = tempHistory.Temperature; logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的模組溫度計的平均值】", powerStation.Code, dateTime); } } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的模組溫度計的平均值】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } //3. 計算該電站sensor平均值 - 環境溫度計(ETR) try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的環境溫度計設備資訊】", powerStation.Code, dateTime); var ETRdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.ETR.ToString(), powerStation.SiteDB); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的環境溫度計設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的環境溫度計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(ETRdeviceInfos)); if (ETRdeviceInfos != null && ETRdeviceInfos.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的環境溫度計的平均值】", powerStation.Code, dateTime); var ETRHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, ETRdeviceInfos, Convert.ToInt32(SensorTypeEnum.ETR)); if (ETRHistory != null) { sensorHistory.EnvTemperature = ETRHistory.EnvTemperature; logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的環境溫度計的平均溫度】", powerStation.Code, dateTime); } } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的環境溫度計的平均值】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } //4. 計算該電站 - 環境濕度計(EMM) try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的環境濕度計設備資訊】", powerStation.Code, dateTime); var EMMdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.EMM.ToString(), powerStation.SiteDB); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的環境濕度計設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的環境濕度計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(EMMdeviceInfos)); if (EMMdeviceInfos != null && EMMdeviceInfos.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的環境濕度計的平均值】", powerStation.Code, dateTime); var EMMHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, EMMdeviceInfos, Convert.ToInt32(SensorTypeEnum.EMM)); if (EMMHistory != null) { sensorHistory.Humidity = EMMHistory.Humidity; logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的環境濕度計的平均值】", powerStation.Code, dateTime); } } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的環境濕度計的平均值】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } //5. 計算該電站 - 風速計(VAN) try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的風速計設備資訊】", powerStation.Code, dateTime); var VANdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.VAN.ToString(), powerStation.SiteDB); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的風速計設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的風速計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(VANdeviceInfos)); if (VANdeviceInfos != null && VANdeviceInfos.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的風速計的平均值】", powerStation.Code, dateTime); var VANHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, VANdeviceInfos, Convert.ToInt32(SensorTypeEnum.VAN)); if (VANHistory != null) { sensorHistory.Vane = VANHistory.Vane; logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的風速計的平均值】", powerStation.Code, dateTime); } } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的風速計的平均值】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } //5. 計算該電站 - 落塵計(FOM) try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的落塵計設備資訊】", powerStation.Code, dateTime); var FOMdeviceInfos = await powerStationRepository.GetDeviceListByPowerStationIdAndType(powerStation.Id, SensorTypeEnum.FOM.ToString(), powerStation.SiteDB); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的落塵計設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的落塵計設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(FOMdeviceInfos)); if (FOMdeviceInfos != null && FOMdeviceInfos.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的落塵計的平均%】", powerStation.Code, dateTime); var FOMHistory = await powerStationRepository.CalcSensorHistoryPerHour(dateTime, FOMdeviceInfos, Convert.ToInt32(SensorTypeEnum.FOM)); if (FOMHistory != null) { sensorHistory.Dust = FOMHistory.Dust; logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的落塵計的平均值】", powerStation.Code, dateTime); } } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的落塵計的平均值】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } sensorHistoriesHour.Add(sensorHistory); } calcPowerStations.Add(calcPowerStation); #endregion #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("【CalcPowerStationJob】【查無電站[0]的s{0}01_inv資料表】", powerStation.Code); } else { try { logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{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("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateTime); logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的逆變器設備資訊】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(inverterIds)); if (inverterIds != null && inverterIds.Count() > 0) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{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("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime); } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } } #endregion #region step2-4. 計算該電站所有sensoravg try { //var seneoravg_table_name = String.Format("s{0}01_sensoravg", powerStation.Code); //var full_seneoravg_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, seneoravg_table_name); //var exist_seneoravg_table = await powerStationRepository.ExistTable(powerStation.SiteDB, seneoravg_table_name); if (!string.IsNullOrEmpty(sensoravg_table_exist)) { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime); var sensorAvgHistory = await powerStationRepository.CalcSensorAvgHistory(dateTime, full_sensoravg_table_name); logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{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("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } #endregion #region step2-5. 計算該電站meter 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); if (string.IsNullOrEmpty(exist_meter_table)) { logger.LogError("【CalcPowerStationJob】【查無電站[{0}]的s{0}01_meter資料表】", powerStation.Code); } else { logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime); var meterHistory = await powerStationRepository.CalcMeterHistory(dateTime, full_meter_table_name); logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{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("【CalcPowerStationJob】【計算失敗電站[{0}]在{1}的meter的資訊】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } #endregion #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(','); var nowLocation = Math.Sqrt(Math.Pow(Convert.ToDouble(powerLocation[0]) - Convert.ToDouble(Location.Lat), 2) + Math.Pow(Convert.ToDouble(powerLocation[1]) - Convert.ToDouble(Location.Lon), 2)); 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("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime); var weather = await powerStationRepository.SelectNowWeather(powerStation.CityId); logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime); if (weather != null) { calcPowerStation.TodayWeather = weather.WeatherKey; calcPowerStation.RateOfRain = weather.PoP; } } catch (Exception ex) { logger.LogError("【CalcPowerStationJob】【取得失敗電站[{0}]在{1}的天氣預報的資訊】", powerStation.Code, dateTime); logger.LogError("【CalcPowerStationJob】【失敗原因】- {0}", ex.Message); } #endregion } catch (Exception exception) { logger.LogError("【{0}】{1}", "CalcPowerStationJob", exception.Message); } } #endregion if (!this.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" }; await powerStationRepository.AddPowerStationHistory(powerStationHistoriesHour, history_properties); #endregion #region step4. 將sensor History INSERT 到 sensor_history_hour 資料表 List sensor_history_properties = new List() { "PowerStationId", "TIMESTAMP", "Irradiance", "Temperature", "EnvTemperature", "Humidity", "Vane", "Dust" }; await powerStationRepository.AddSensorHistoryHour(sensorHistoriesHour, sensor_history_properties); //List Temp_history_properties = new List() //{ // "PowerStationId", // "TIMESTAMP", // "Temperature" //}; //await powerStationRepository.AddTempHistory(TempHistoriesHour, Temp_history_properties); #endregion #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" }; await powerStationRepository.UpdateList(calcPowerStations, power_station_properties); #endregion #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", }; await powerStationRepository.AddInverterHistory(inverterHistoriesHour, inverter_history_properties); #endregion #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", }; await powerStationRepository.AddSensorAvgHistory(sensorAvgHistoryHour, sensoravg_history_properties); #endregion #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" }; await powerStationRepository.AddMeterHistory(meterHistoriesHour, memter_history_properties); #endregion #region step9. 新增天氣資訊 List weather_observation_properties = new List() { "PowerStationId", "ObsTime", "Temp" }; await powerStationRepository.AddWeatherObservation(weatherObservations, weather_observation_properties); #endregion } logger.LogInformation("【CalcPowerStationJob】【任務完成】"); } catch (Exception exception) { logger.LogError("【CalcPowerStationJob】[Exception] - {0}", exception.Message); if (exception.InnerException != null) { logger.LogError("【CalcPowerStationJob】[InnerException] - {0}", exception.InnerException.Message); } } } } }