1. 電站總覽 單一電站內容加入左邊選單

2. 背景執行加入 log說明
3. bug fix
This commit is contained in:
Kai 2021-07-16 14:04:57 +08:00
parent 3e04132b06
commit 2490884c8a
20 changed files with 649 additions and 389 deletions

View File

@ -65,6 +65,26 @@ namespace SolarPower.Controllers
return apiResult;
}
[HttpPost]
public ApiResult<List<MyPowerStationSummary>> GetPowerStationCollapse(string filter)
{
ApiResult<List<MyPowerStationSummary>> apiResult = new ApiResult<List<MyPowerStationSummary>>();
try
{
apiResult.Code = "0000";
var powerStationSummary = powerStationRepository.GetMyPowerStationSummary(myUser, filter);
apiResult.Data = powerStationSummary;
}
catch (Exception exception)
{
apiResult.Code = "9999";
apiResult.Msg = exception.ToString();
}
return apiResult;
}
[HttpPost]
public async Task<ApiResult<MapOverview>> GetStationCard(StationIds post)
{

View File

@ -1579,6 +1579,24 @@ ALTER TABLE `operation_plan_create`
ALTER TABLE `operation_record`
CHANGE COLUMN `FixDo` `FixDo` VARCHAR(50) NULL DEFAULT NULL COMMENT '維修項目' COLLATE 'utf8mb4_unicode_ci' AFTER `ErrorCode`;
-- 各電站每15min的逆變器歷史記錄 20210715
CREATE TABLE `inverter_history_15min` (
`Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`PowerStationId` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`INVERTERID` VARCHAR(500) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`TIMESTAMP` TIMESTAMP NULL DEFAULT NULL,
`KWH` DOUBLE NULL DEFAULT NULL,
`TODAYKWH` DOUBLE NULL DEFAULT NULL,
`KWHKWP` DOUBLE NULL DEFAULT NULL,
PRIMARY KEY (`Id`) USING BTREE,
INDEX `IDX_01` (`PowerStationId`) USING BTREE
)
COMMENT='各電站每15min的逆變器歷史記錄'
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@ -28,7 +28,10 @@ namespace SolarPower.Quartz.Jobs
try
{
#region step1.
logger.LogInformation("【CalcAvgPowerStationJob】【開始取得電站資料】");
var powerStations = await powerStationRepository.GetAllAsync();
logger.LogInformation("【CalcAvgPowerStationJob】【取得成功電站資料】");
logger.LogInformation("【CalcAvgPowerStationJob】【電站資料】 - {0}", System.Text.Json.JsonSerializer.Serialize(powerStations));
#endregion
List<PowerStation> calcAvgPowerStations = new List<PowerStation>();
@ -52,14 +55,16 @@ namespace SolarPower.Quartz.Jobs
var count = 0;
#region ()
logger.LogInformation("【CalcAvgPowerStationJob】【開始取得氣象觀測】");
var client = new HttpClient();
var UVUri = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=CWB-EA24220B-DDCC-4188-84E5-AD37A0E03F80&elementName=Wx,PoP&sort=time";
HttpResponseMessage response = client.GetAsync(UVUri).Result;
String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString();
Root2 observation = JsonConvert.DeserializeObject<Root2>(jsonUVs);
logger.LogInformation("【CalcAvgPowerStationJob】【取得成功氣象觀測】");
#endregion
foreach(var location in observation.Records.Location)
foreach (var location in observation.Records.Location)
{
WeatherForecast weatherForecast = new WeatherForecast();
weatherForecast.LocationName = location.LocationName;
@ -149,10 +154,14 @@ namespace SolarPower.Quartz.Jobs
var dateNowDay = DateTimeNow.AddDays(-1).ToString("yyyy-MM-dd");
#region step2-1. 30
var table_name = String.Format("`{0}`.`{1}01_station`", powerStation.SiteDB, powerStation.Code);
var table_name = String.Format("`{0}`.`s{1}01_station`", powerStation.SiteDB, powerStation.Code);
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的30天平均資料】", powerStation.Code, dateNowDay);
var history = await powerStationRepository.CalcAvgPowerStationHistory30day(dateNowDay, table_name);
logger.LogInformation("【CalcAvgPowerStationJob】【取得成功電站[{0}]在{1}的30天平均資料】", powerStation.Code, dateNowDay);
logger.LogInformation("【CalcAvgPowerStationJob】【電站[{0}]在{1}的30天平均資料】 - {2}", powerStation.Code, dateNowDay, System.Text.Json.JsonSerializer.Serialize(history));
if (history != null)
{
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的30天平均資料】", powerStation.Code, dateNowDay);
history.PowerStationId = powerStation.Id;
#region 30 kWh/kWp PR
@ -169,11 +178,15 @@ namespace SolarPower.Quartz.Jobs
#endregion
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的30天平均資料】", powerStation.Code, dateNowDay);
}
#endregion
#region step2-2 30
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的30天日照計平均資料】", powerStation.Code, dateNowDay);
var avgPyrheliometerHistory = await powerStationRepository.CalcAvgPyrheliometerHistory30day(dateNowDay, powerStation.Id);
logger.LogInformation("【CalcAvgPowerStationJob】【取得成功電站[{0}]在{1}的30天日照計平均資料】", powerStation.Code, dateNowDay);
logger.LogInformation("【CalcAvgPowerStationJob】【電站[{0}]在{1}的30天日照計平均資料】 - {2}", powerStation.Code, dateNowDay, System.Text.Json.JsonSerializer.Serialize(avgPyrheliometerHistory));
if (avgPyrheliometerHistory != null)
{
calcPowerStation.Avg_irradiance = avgPyrheliometerHistory.AvgIrradiance;
@ -184,7 +197,10 @@ namespace SolarPower.Quartz.Jobs
#region step2-3.
//電站資訊
logger.LogInformation("【CalcAvgPowerStationJob】【開始取得電站[{0}]在{1}的所有值的總和】", powerStation.Code, dateNowDay);
var historyDay = await powerStationRepository.GetLastOnePowerStationHistoryByDay(dateNowDay, table_name);
logger.LogInformation("【CalcAvgPowerStationJob】【取得成功電站[{0}]在{1}的所有值的總和】", powerStation.Code, dateNowDay);
logger.LogInformation("【CalcAvgPowerStationJob】【電站[{0}]在{1}的所有值的總和】 - {2}", powerStation.Code, dateNowDay, System.Text.Json.JsonSerializer.Serialize(historyDay));
if (historyDay != null)
{
historyDay.PowerStationId = powerStation.Id;
@ -192,14 +208,18 @@ namespace SolarPower.Quartz.Jobs
}
//日照計
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的日照計所有值的平均】", powerStation.Code, dateNowDay);
var pyrheliometerHistorDay = await powerStationRepository.CalcPyrheliometerHistoryDayDataByPowerStationId(dateNowDay, powerStation.Id);
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的日照計所有值的平均】", powerStation.Code, dateNowDay);
if (pyrheliometerHistorDay != null)
{
pyrheliometerHistoryDays.Add(pyrheliometerHistorDay);
}
//逆變器
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的逆變器所有值的平均】", powerStation.Code, dateNowDay);
var inverterHistoriesDay = await powerStationRepository.CalcInverterHistoryDayDataByPowerStationId(dateNowDay, powerStation.SiteDB, powerStation.Id);
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的逆變器所有值的平均】", powerStation.Code, dateNowDay);
if (inverterHistoriesDay != null)
{
foreach(var inverterHistoryDay in inverterHistoriesDay)
@ -214,6 +234,7 @@ namespace SolarPower.Quartz.Jobs
var dateNowMonth = DateTimeNow.ToString("yyyy-MM");
//電站該月份的歷史資料
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}月份的歷史資料總和】", powerStation.Code, dateNowMonth);
var exist_history = await powerStationRepository.GetOnePowerStationHistoryByPowerStationIdAndMonth(powerStation.Id, dateNowMonth);
if (exist_history == null)
{ //新增
@ -224,6 +245,7 @@ namespace SolarPower.Quartz.Jobs
insertPowerStationHistoryMonths.Add(historyMonth);
}
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的歷史資料總和】", powerStation.Code, dateNowMonth);
}
else
{ //修改
@ -232,9 +254,12 @@ namespace SolarPower.Quartz.Jobs
{
updatePowerStationHistoryMonths.Add(historyMonth);
}
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的歷史資料總和】", powerStation.Code, dateNowMonth);
}
//電站該月份的的日照度歷史資料
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}月份的日照度歷史資料】", powerStation.Code, dateNowMonth);
var exist_pyrheliometer_history = await powerStationRepository.GetOnePyrheliometerHistoryByMonth(dateNowMonth, powerStation.Id);
if (exist_pyrheliometer_history == null)
{ //新增
@ -244,6 +269,7 @@ namespace SolarPower.Quartz.Jobs
pyrheliometerHistoryMonth.Timestamp = Convert.ToDateTime(pyrheliometerHistoryMonth.Timestamp).ToString("yyyy-MM-dd");
insertPyrheliometerHistoryMonths.Add(pyrheliometerHistoryMonth);
}
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的日照度歷史資料】", powerStation.Code, dateNowMonth);
}
else
{ //修改
@ -252,9 +278,11 @@ namespace SolarPower.Quartz.Jobs
{
updatePyrheliometerHistoryMonths.Add(pyrheliometerHistoryMonth);
}
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的日照度歷史資料】", powerStation.Code, dateNowMonth);
}
//電站該月份的的逆變器歷史資料
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}月份的逆變器歷史資料】", powerStation.Code, dateNowMonth);
var exist_inverter_histories = await powerStationRepository.GetInverterHistoryByPowerStationIdAndMonth(dateNowMonth, powerStation.Id);
if (exist_inverter_histories.Count == 0 )
{ //新增
@ -267,6 +295,7 @@ namespace SolarPower.Quartz.Jobs
insertInverterHistoryMonths.Add(inverterHistoryMonth);
}
}
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的逆變器歷史資料】", powerStation.Code, dateNowMonth);
}
else
{ //修改
@ -279,6 +308,7 @@ namespace SolarPower.Quartz.Jobs
updateInverterHistoryMonths.Add(inverterHistoryMonth);
}
}
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的逆變器歷史資料】", powerStation.Code, dateNowMonth);
}
#endregion

View File

@ -25,9 +25,11 @@ namespace SolarPower.Quartz.Jobs
{
try
{
/*
#region step1.
logger.LogInformation("【CalcInverter15minJob】【開始取得電站資料】");
var powerStations = await powerStationRepository.GetAllAsync();
logger.LogInformation("【CalcPowerStationJob】【取得成功電站資料】");
logger.LogInformation("【CalcPowerStationJob】【電站資料】 - {0}", System.Text.Json.JsonSerializer.Serialize(powerStations));
#endregion
List<InverterHistory> calcInverter15mins = new List<InverterHistory>();
@ -44,47 +46,28 @@ namespace SolarPower.Quartz.Jobs
break;
}
//取得所有該電站的逆變器
var controllers = await powerStationRepository.GetAllDeviceControllerId(powerStation.Id, powerStation.SiteDB);
var inverters = await powerStationRepository.InverterTable(controllers, powerStation.SiteDB);
var inverterIds = inverters.Select(x => x.InverterId.Replace("s", "")).ToList();
var calcInverter15min = new InverterHistory();
var dateNowTime = DateTimeNow.ToString("yyyy-MM-dd HH:mm");
#region step2-1. 30
var table_name = String.Format("`{0}`.`{1}01_inv`", powerStation.SiteDB, powerStation.Code);
var history = await powerStationRepository.CalcInverterHisyort15minData(dateNowTime, table_name, inverterIds);
if (history != null)
//取得所有該電站的逆變器
logger.LogInformation("【CalcInverter15minJob】【開始取得電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateNowTime);
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("【CalcInverter15minJob】【取得成功電站[{0}]在{1}的逆變器設備資訊】", powerStation.Code, dateNowTime);
var calcInverter15min = new InverterHistory();
#region step2-1. 15min
var table_name = String.Format("`{0}`.`s{1}01_inv`", powerStation.SiteDB, powerStation.Code);
logger.LogInformation("【CalcInverter15minJob】【開始計算電站[{0}]在{1}的每15分鐘逆變器資訊】", powerStation.Code, dateNowTime);
calcInverter15mins = await powerStationRepository.CalcInverterHisyort15minData(dateNowTime, powerStation.SiteDB, table_name, inverterIds);
logger.LogInformation("【CalcInverter15minJob】【計算完成電站[{0}]在{1}的每15分鐘逆變器資訊】", powerStation.Code, dateNowTime);
if (calcInverter15mins.Count() > 0)
{
history.PowerStationId = powerStation.Id;
#region 30 kWh/kWp PR
#region kWh/kWp
//直接填寫
calcPowerStation.Avg_kwhkwp = history.AvgKWHKWP;
#endregion
#region PR
//直接填寫
calcPowerStation.Avg_PR = history.AvgPR;
#endregion
#endregion
}
#endregion
#region step2-2.
//逆變器
var inverterHistoriesDay = await powerStationRepository.CalcInverterHistoryDayDataByPowerStationId(dateNowDay, powerStation.SiteDB, powerStation.Id);
if (inverterHistoriesDay != null)
foreach (var inverterHistory in calcInverter15mins)
{
foreach (var inverterHistoryDay in inverterHistoriesDay)
{
allofInverterHistorDays.Add(inverterHistoryDay);
inverterHistory.TIMESTAMP = Convert.ToDateTime(inverterHistory.TIMESTAMP + ":00").ToString("yyyy-MM-dd HH:mm:ss");
inverterHistory.PowerStationId = powerStation.Id;
}
}
#endregion
@ -93,115 +76,24 @@ namespace SolarPower.Quartz.Jobs
}
#endregion
#region step3. calcPowerStations UPDATE power_station
List<string> power_station_properties = new List<string>()
{
"Id",
"avg_kwhkwp",
"avg_PR",
"avg_irradiance"
};
await powerStationRepository.UpdateList(calcAvgPowerStations, power_station_properties);
#endregion
#region step4. insert or update
//每日
List<string> history_properties_day = new List<string>()
{
"PowerStationId",
"TIMESTAMP",
"SITEID",
"SITETYPE",
"TODAYKWH",
"TOTALKWH",
"KWHKWP",
"PR",
"MP",
"SolarHour"
};
await powerStationRepository.AddPowerStationHistoryDayList(powerStationHistoryDays, history_properties_day);
//每月
List<string> history_properties_month = new List<string>()
{
"PowerStationId",
"TIMESTAMP",
"SITEID",
"SITETYPE",
"MonthKWh",
"TOTALKWH",
"KWHKWP",
"PR",
"MP",
"SolarHour"
};
if (insertPowerStationHistoryMonths.Count > 0)
{
await powerStationRepository.AddPowerStationHistoryMonthList(insertPowerStationHistoryMonths, history_properties_month);
}
if (updatePowerStationHistoryMonths.Count > 0)
{
await powerStationRepository.UpdatePowerStationHistoryMonthList(updatePowerStationHistoryMonths);
}
#endregion
#region step5. insert or update
List<string> pyrheliometer_history_properties = new List<string>()
{
"PowerStationId",
"Timestamp",
"Irradiance",
"Temperature"
};
//每日
await powerStationRepository.AddPyrheliometerHistoryDayList(pyrheliometerHistoryDays, pyrheliometer_history_properties);
//每月
if (insertPyrheliometerHistoryMonths.Count > 0)
{
await powerStationRepository.AddPyrheliometerHistoryMonthList(insertPyrheliometerHistoryMonths, pyrheliometer_history_properties);
}
if (updatePyrheliometerHistoryMonths.Count > 0)
{
await powerStationRepository.UpdatePyrheliometerHistoryMonthList(updatePyrheliometerHistoryMonths);
}
#endregion
#region step6. insert or update
#region step3. inverter INSERT inverter_history_hour
List<string> inverter_history_properties = new List<string>()
{
"PowerStationId",
"TIMESTAMP",
"INVERTERID",
"TIMESTAMP",
"KWH",
"TODAYKWH",
"KWHKWP",
};
//每日
await powerStationRepository.AddInverterHistoryDayList(allofInverterHistorDays, inverter_history_properties);
//每月
if (insertInverterHistoryMonths.Count > 0)
{
await powerStationRepository.AddInverterHistoryMonthList(insertInverterHistoryMonths, inverter_history_properties);
}
if (updateInverterHistoryMonths.Count > 0)
{
await powerStationRepository.UpdateInverterHistoryMonthList(updateInverterHistoryMonths);
}
await powerStationRepository.AddInverter15minHistory(calcInverter15mins, inverter_history_properties);
#endregion
*/
}
catch (Exception exception)
{
logger.LogError("【{0}】{1}", "CalcAvgPowerStationJob", exception.Message);
logger.LogError("【{0}】{1}", "CalcInverter15minJob", exception.Message);
}
}
}

View File

@ -30,10 +30,10 @@ namespace SolarPower.Quartz.Jobs
try
{
#region step1.
logger.LogInformation("【CalcPowerStationJob】【開始取得電站資料】");
var powerStations = await powerStationRepository.GetAllAsync();
string json = System.Text.Json.JsonSerializer.Serialize(powerStations);
logger.LogError("【{0}】{1}", "CalcPowerStationJob - step1", json);
logger.LogInformation("【CalcPowerStationJob】【取得成功電站資料】");
logger.LogInformation("【CalcPowerStationJob】【電站資料】 - {0}", System.Text.Json.JsonSerializer.Serialize(powerStations));
#endregion
List<PowerStationHistory> powerStationHistoriesHour = new List<PowerStationHistory>();
@ -47,11 +47,13 @@ namespace SolarPower.Quartz.Jobs
var count = 0;
#region ()
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";
HttpResponseMessage response = client.GetAsync(UVUri).Result;
String jsonUVs = response.Content.ReadAsStringAsync().Result.ToString();
Root2 observation = JsonConvert.DeserializeObject<Root2>(jsonUVs);
logger.LogInformation("【CalcPowerStationJob】【取得成功氣象觀測】");
#endregion
@ -69,15 +71,16 @@ namespace SolarPower.Quartz.Jobs
var dateTime = DateTimeNow.AddHours(-1).ToString("yyyy-MM-dd HH");
#region step2-1.
var table_name = String.Format("`{0}`.{1}01_station", powerStation.SiteDB, powerStation.Code);
logger.LogError("【{0}】{1}", "CalcPowerStationJob - time & dataTable", dateTime + "======" + table_name);
var table_name = String.Format("`{0}`.s{1}01_station", powerStation.SiteDB, powerStation.Code);
logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
var history = await powerStationRepository.GetPowerStationHistoryPerHour(dateTime, table_name);
json = System.Text.Json.JsonSerializer.Serialize(history);
logger.LogError("【{0}】{1}", "CalcPowerStationJob - history", json);
logger.LogInformation("【CalcPowerStationJob】【取得成功電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
logger.LogInformation("【CalcPowerStationJob】【電站[{0}]在{1}的每小時歷史資料】 - {2}", powerStation.Code, dateTime, System.Text.Json.JsonSerializer.Serialize(history));
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");
@ -153,17 +156,22 @@ namespace SolarPower.Quartz.Jobs
#endregion
powerStationHistoriesHour.Add(history);
logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的每小時歷史資料】", powerStation.Code, dateTime);
}
#endregion
#region step2-2.
//1. 找出該電站所有日照計設備(包含共享
logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的日照計設備資訊】", powerStation.Code, dateTime);
var deviceInfos = await powerStationRepository.GetListPyrheliometerByPowerStationId(powerStation.Id, powerStation.SiteDB);
// 找出該電站所有溫度計設備(包含共享
var tempdeviceInfos = await powerStationRepository.GetListTempByPowerStationId(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)
{
//2. 計算該電站所有日照計設的每小時的平均在依照日照計數量平均
logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的日照計的日照度】", powerStation.Code, dateTime);
var pyrheliometerHistory = await powerStationRepository.GetPyrheliometerHistoryPerHour(dateTime, deviceInfos, 0);
if (pyrheliometerHistory != null)
@ -174,32 +182,47 @@ namespace SolarPower.Quartz.Jobs
pyrheliometerHistory.PowerStationId = powerStation.Id;
pyrheliometerHistoriesHour.Add(pyrheliometerHistory);
}
logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的日照計的日照度】", powerStation.Code, dateTime);
}
//2. 計算該電站所有溫度計設的每小時的平均在依照溫度計數量平均
// 找出該電站所有溫度計設備(包含共享
logger.LogInformation("【CalcPowerStationJob】【開始取得電站[{0}]在{1}的溫度計設備資訊】", powerStation.Code, dateTime);
var tempdeviceInfos = await powerStationRepository.GetListTempByPowerStationId(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(tempdeviceInfos));
if (tempdeviceInfos != null)
{
logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的溫度計的平均溫度】", powerStation.Code, dateTime);
var tempHistory = await powerStationRepository.GetPyrheliometerHistoryPerHour(dateTime, tempdeviceInfos, 1);
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);
logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的溫度計的平均溫度】", powerStation.Code, dateTime);
}
}
#endregion
#region step2-3.
var inverter_table_name = String.Format("`{0}`.{1}01_inv", powerStation.SiteDB, powerStation.Code);
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.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));
inverterHistories = await powerStationRepository.CalcInverterHisyortHourData(dateTime, powerStation.SiteDB, inverter_table_name);
var inverter_table_name = String.Format("`{0}`.s{1}01_inv", powerStation.SiteDB, powerStation.Code);
logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime);
inverterHistories = await powerStationRepository.CalcInverterHisyortHourData(dateTime, powerStation.SiteDB, inverter_table_name, inverterIds);
foreach (var inverterHistory in inverterHistories)
{
inverterHistory.TIMESTAMP = Convert.ToDateTime(inverterHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");
inverterHistory.PowerStationId = powerStation.Id;
}
logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的逆變器的資訊】", powerStation.Code, dateTime);
#endregion
#region ()
@ -226,9 +249,9 @@ namespace SolarPower.Quartz.Jobs
WeatherObservation weatherObservation = new WeatherObservation();
if (powerStation.WeathersStationId != null)
{
foreach(var Location in observation.Records.Location)
foreach (var Location in observation.Records.Location)
{
if(Location.StationId == powerStation.WeathersStationId)
if (Location.StationId == powerStation.WeathersStationId)
{
calcPowerStation.TodayWeatherTemp = Convert.ToDouble(Location.WeatherElement[0].ElementValue);
weatherObservation.PowerStationId = powerStation.Id;
@ -240,15 +263,19 @@ namespace SolarPower.Quartz.Jobs
}
}
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;
}
weatherObservations.Add(weatherObservation);
calcPowerStations.Add(calcPowerStation);
count++;
}
#endregion
@ -268,9 +295,6 @@ namespace SolarPower.Quartz.Jobs
"SolarHour"
};
json = System.Text.Json.JsonSerializer.Serialize(powerStationHistoriesHour);
logger.LogError("【{0}】{1}", "CalcPowerStationJob - step3", json);
await powerStationRepository.AddPowerStationHistory(powerStationHistoriesHour, history_properties);
#endregion
@ -328,7 +352,7 @@ namespace SolarPower.Quartz.Jobs
"KWHKWP",
};
await powerStationRepository.AddInverterHisyort(inverterHistories, inverter_history_properties);
await powerStationRepository.AddInverterHistory(inverterHistories, inverter_history_properties);
#endregion
List<string> weather_observation_properties = new List<string>()
@ -338,10 +362,6 @@ namespace SolarPower.Quartz.Jobs
"Temp"
};
await powerStationRepository.AddWeatherObservation(weatherObservations, weather_observation_properties);
}
catch (Exception exception)
{

View File

@ -315,7 +315,7 @@ namespace SolarPower.Repository.Implement
{
try
{
var sql = @$"SELECT * FROM inverter_history_hour WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d') = @DateTime";
var sql = @$"SELECT * FROM inverter_history_15min WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d') = @DateTime";
result = (await conn.QueryAsync<InverterHistory>(sql, new { PowerStationId = powerStationId, DateTime = dateTime })).ToList();
}

View File

@ -23,7 +23,7 @@ namespace SolarPower.Repository.Implement
}
public List<MyPowerStationSummary> GetMyPowerStationSummary(MyUser myUser)
public List<MyPowerStationSummary> GetMyPowerStationSummary(MyUser myUser, string filter = "")
{
List<MyPowerStationSummary> results = new List<MyPowerStationSummary>();
@ -35,7 +35,7 @@ namespace SolarPower.Repository.Implement
FROM power_station ps
LEFT JOIN city c ON ps.CityId = c.Id";
if(myUser.Role.Layer == 2)
if (myUser.Role.Layer == 2)
{ //公司管理員
sql += @" WHERE ps.Deleted = 0 AND ps.CompanyId = @CompanyId";
}
@ -49,7 +49,12 @@ namespace SolarPower.Repository.Implement
sql += @" WHERE ps.Deleted = 0";
}
var myPowerStationInfos = conn.Query<MyPowerStationInfo>(sql, new { CompanyId = myUser.CompanyId, UserId = myUser.Id }).ToList();
if (!string.IsNullOrEmpty(filter))
{
sql += @" AND ps.Name LIKE CONCAT('%', @Filter, '%')";
}
var myPowerStationInfos = conn.Query<MyPowerStationInfo>(sql, new { CompanyId = myUser.CompanyId, UserId = myUser.Id, Filter = filter }).ToList();
var myPowerStationInfos_group = myPowerStationInfos.GroupBy(x => x.CityId);
@ -2290,10 +2295,10 @@ namespace SolarPower.Repository.Implement
}
}
//(有修改)
public async Task<PyrheliometerHistory> GetPyrheliometerHistoryPerHour(string dateTime, List<DeviceInfo> deviceInfos,int type)
public async Task<PyrheliometerHistory> GetPyrheliometerHistoryPerHour(string dateTime, List<DeviceInfo> deviceInfos, int type)
{
var typename = "";
if(type == 1)
if (type == 1)
{
typename = "Temperature";//1為溫度計
}
@ -2594,62 +2599,113 @@ namespace SolarPower.Repository.Implement
}
}
//public async Task<List<InverterHistory>> CalcInverterHisyort15minData(string dateTime, string table_name, List<string> inverterIds)
//{
// List<InverterHistory> result;
// using (IDbConnection conn = this._databaseHelper.GetConnection())
// {
// try
// {
// var stratDateTime = Convert.ToDateTime(dateTime + ":00").AddMinutes(-15).ToString("yyyy-MM-dd HH:mm");
// var sql = $@"SELECT
// MAX(DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H:%i')) AS TIMESTAMP,
// s.INVERTERID,
// a.KWH, MAX(s.TODAYKWH) AS TODAYKWH, i.Capacity, (a.KWH/i.Capacity) AS KWHKWP
// FROM {table_name} s
// LEFT JOIN (
// SELECT DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H:%i') AS TIMESTAMP, inv.INVERTERID, SUM(inv.WH)/1000 AS KWH
// FROM {table_name} inv
// WHERE DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H:%i') BETWEEN @StartDateTiime AND @EndDateTime
// GROUP BY DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H'), inv.INVERTERID) a
// ON DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H') = a.TIMESTAMP AND s.INVERTERID = a. INVERTERID
// LEFT JOIN {db_name}.inverter i ON CONCAT('s', s.INVERTERID) = i.InverterId
// WHERE DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H') = @DateTime
// GROUP BY DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H'), s.INVERTERID
// ";
// result = (await conn.QueryAsync<InverterHistory>(sql, new { DateTime = dateTime })).ToList();
// }
// catch (Exception exception)
// {
// throw exception;
// }
// return result;
// }
//}
public async Task<List<InverterHistory>> CalcInverterHisyortHourData(string dateTime, string db_name, string table_name)
public async Task<List<InverterHistory>> CalcInverterHisyort15minData(string dateTime, string db_name, string table_name, List<string> inverterIds)
{
List<InverterHistory> result;
using (IDbConnection conn = this._databaseHelper.GetConnection())
{
try
{
var sql = $@"SELECT MAX(DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H')) AS TIMESTAMP, s.INVERTERID, a.KWH, MAX(s.TODAYKWH) AS TODAYKWH, i.Capacity, (a.KWH/i.Capacity) AS KWHKWP
var stratDateTime = Convert.ToDateTime(dateTime + ":00").AddMinutes(-15).ToString("yyyy-MM-dd HH:mm");
var sql = $@"SELECT
s.TIMESTAMP,
s.INVERTERID,
a.KWH,
s.TODAYKWH,
i.Capacity,
(a.KWH/i.Capacity) AS KWHKWP
FROM (SELECT
MAX(FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i')) AS TIMESTAMP,
sub_inv.INVERTERID,
MAX(sub_inv.TODAYKWH) AS TODAYKWH
FROM {table_name} sub_inv
WHERE FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime
AND sub_inv.INVERTERID IN @InverterIds
GROUP BY sub_inv.INVERTERID) s
LEFT JOIN (
SELECT MAX(FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i')) AS TIMESTAMP,
sub_inv.INVERTERID,
SUM(sub_inv.WH)/1000 AS KWH
FROM {table_name} sub_inv
WHERE FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime
AND sub_inv.INVERTERID IN @InverterIds
GROUP BY sub_inv.INVERTERID) a
ON s.TIMESTAMP = a.TIMESTAMP AND s.INVERTERID = a. INVERTERID
LEFT JOIN {db_name}.inverter i ON s.INVERTERID = REPLACE(i.InverterId, 's', '');";
result = (await conn.QueryAsync<InverterHistory>(sql, new { StartDateTime = stratDateTime, EndDateTime = dateTime, InverterIds = inverterIds })).ToList();
}
catch (Exception exception)
{
throw exception;
}
return result;
}
}
public async Task<int> AddInverter15minHistory(List<InverterHistory> entity, List<string> properties)
{
int count;
using (IDbConnection conn = _databaseHelper.GetConnection())
{
conn.Open();
using (var trans = conn.BeginTransaction())
{
try
{
string sql = GenerateInsertQueryWithCustomTable(properties, "inverter_history_15min");
count = await conn.ExecuteAsync(sql, entity, trans);
trans.Commit();
}
catch (Exception exception)
{
trans.Rollback();
throw exception;
}
finally
{
conn.Close();
}
}
return count;
}
}
public async Task<List<InverterHistory>> CalcInverterHisyortHourData(string dateTime, string db_name, string table_name, List<string> inverterIds)
{
List<InverterHistory> result;
using (IDbConnection conn = this._databaseHelper.GetConnection())
{
try
{
var sql = $@"SELECT
MAX(FROM_UNIXTIME(s.TIMESTAMP/1000, '%Y-%m-%d %H')) AS TIMESTAMP,
s.INVERTERID,
a.KWH,
MAX(s.TODAYKWH) AS TODAYKWH,
i.Capacity,
(a.KWH/i.Capacity) AS KWHKWP
FROM {table_name} s
LEFT JOIN (
SELECT DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H') AS TIMESTAMP, inv.INVERTERID, SUM(inv.WH)/1000 AS KWH
SELECT
FROM_UNIXTIME(inv.TIMESTAMP/1000, '%Y-%m-%d %H') AS TIMESTAMP,
inv.INVERTERID,
SUM(inv.WH)/1000 AS KWH
FROM {table_name} inv
WHERE DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H') = @DateTime
GROUP BY DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H'), inv.INVERTERID) a
ON DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H') = a.TIMESTAMP AND s.INVERTERID = a. INVERTERID
LEFT JOIN {db_name}.inverter i ON CONCAT('s', s.INVERTERID) = i.InverterId
WHERE DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H') = @DateTime
AND inv.INVERTERID IN @InverterIds
GROUP BY FROM_UNIXTIME(inv.TIMESTAMP/1000, '%Y-%m-%d %H'), inv.INVERTERID) a
ON FROM_UNIXTIME(s.TIMESTAMP/1000, '%Y-%m-%d %H') = a.TIMESTAMP AND s.INVERTERID = a. INVERTERID
LEFT JOIN {db_name}.inverter i ON s.INVERTERID = i.InverterId
WHERE FROM_UNIXTIME(s.TIMESTAMP/1000, '%Y-%m-%d %H') = @DateTime
AND s.INVERTERID IN @InverterIds
GROUP BY DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H'), s.INVERTERID
";
result = (await conn.QueryAsync<InverterHistory>(sql, new { DateTime = dateTime })).ToList();
result = (await conn.QueryAsync<InverterHistory>(sql, new { DateTime = dateTime, InverterIds = inverterIds })).ToList();
}
catch (Exception exception)
{
@ -2786,7 +2842,7 @@ namespace SolarPower.Repository.Implement
}
}
public async Task<int> AddInverterHisyort(List<InverterHistory> entity, List<string> properties)
public async Task<int> AddInverterHistory(List<InverterHistory> entity, List<string> properties)
{
int count;
using (IDbConnection conn = _databaseHelper.GetConnection())
@ -2974,7 +3030,7 @@ namespace SolarPower.Repository.Implement
}
}
public async Task<NowWeather> SelectNowWeather (int CityId)
public async Task<NowWeather> SelectNowWeather(int CityId)
{
NowWeather result = new NowWeather();
using (IDbConnection conn = this._databaseHelper.GetConnection())

View File

@ -16,7 +16,7 @@ namespace SolarPower.Repository.Interface
/// </summary>
/// <param name="myUser"></param>
/// <returns></returns>
List<MyPowerStationSummary> GetMyPowerStationSummary(MyUser myUser);
List<MyPowerStationSummary> GetMyPowerStationSummary(MyUser myUser, string filter = "");
/// <summary>
/// 查詢縣市列表
@ -518,9 +518,10 @@ namespace SolarPower.Repository.Interface
Task<A> Getonediv<A>(string where, string db_name, string table_name);
//Task<List<InverterHistory>> CalcInverterHisyort15minData(string dateTime, string table_name, List<string> inverterIds);
Task<List<InverterHistory>> CalcInverterHisyortHourData(string dateTime, string db_name, string table_name);
Task<int> AddInverterHisyort(List<InverterHistory> entity, List<string> properties);
Task<List<InverterHistory>> CalcInverterHisyort15minData(string dateTime, string db_name, string table_name, List<string> inverterIds);
Task<int> AddInverter15minHistory(List<InverterHistory> entity, List<string> properties);
Task<List<InverterHistory>> CalcInverterHisyortHourData(string dateTime, string db_name, string table_name, List<string> inverterIds);
Task<int> AddInverterHistory(List<InverterHistory> entity, List<string> properties);
Task<List<InverterHistory>> CalcInverterHistoryDayDataByPowerStationId(string nowDay, string db_name, int powerStationId);
Task<int> AddInverterHistoryDayList(List<InverterHistory> entity, List<string> properties);
Task<List<InverterHistory>> GetInverterHistoryByPowerStationIdAndMonth(string month, int powerStationId);

View File

@ -98,6 +98,13 @@ namespace SolarPower
);
#endregion
#region (215)
services.AddSingleton<CalcInverter15minJob>();
services.AddSingleton(
new JobSchedule(jobType: typeof(CalcInverter15minJob), cronExpression: Configuration.GetValue<string>("BackgroundServiceCron:CalcInverter15minJob"))
);
#endregion
#region (5)
services.AddSingleton<CalcPowerStationJob>();
services.AddSingleton(

View File

@ -12,7 +12,7 @@
<!-- Your main content goes below here: -->
<div class="row mb-5">
<div class="card-columns col-xl-12">
<div class="card-columns">
<div class="card">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 發電量</h4>

View File

@ -4,7 +4,7 @@
<!-- we wrap header title inside a div tag with utility padding -->
<div class="card-title font-weight-bold">控制器</div>
<div class="text-right ">
<a href="javascript:;" class="btn btn-success waves-effect waves-themed" id="addController-btn" onclick="AddController()">
<a href="javascript:;" class="btn btn-sm btn-success ml-auto waves-effect waves-themed" id="addController-btn" onclick="AddController()">
<span class="fal fa-plus mr-1"></span> 新增
</a>
</div>
@ -32,7 +32,7 @@
<!-- we wrap header title inside a div tag with utility padding -->
<div class="card-title font-weight-bold">逆變器</div>
<div class="text-right">
<a href="javascript:;" class="btn btn-success waves-effect waves-themed" id="addInverter-btn" onclick="AddInverter()">
<a href="javascript:;" class="btn btn-sm btn-success ml-auto waves-effect waves-themed" id="addInverter-btn" onclick="AddInverter()">
<span class="fal fa-plus mr-1"></span> 新增
</a>
</div>
@ -67,7 +67,7 @@
<!-- we wrap header title inside a div tag with utility padding -->
<div class="card-title font-weight-bold">裝置設定</div>
<div class="text-right">
<a href="javascript:;" class="btn btn-success waves-effect waves-themed" id="addDevice-btn" onclick="AddDevice()">
<a href="javascript:;" class="btn btn-sm btn-success ml-auto waves-effect waves-themed" id="addDevice-btn" onclick="AddDevice()">
<span class="fal fa-plus mr-1"></span> 新增
</a>
</div>
@ -105,7 +105,7 @@
<!-- we wrap header title inside a div tag with utility padding -->
<div class="card-title font-weight-bold">共用裝置</div>
<div class="text-right">
<a href="javascript:;" class="btn btn-success waves-effect waves-themed" id="addShareDevice-btn" onclick="AddShareDevice()">
<a href="javascript:;" class="btn btn-sm btn-success ml-auto waves-effect waves-themed" id="addShareDevice-btn" onclick="AddShareDevice()">
<span class="fal fa-plus mr-1"></span> 新增
</a>
</div>

View File

@ -17,7 +17,7 @@
<link id="vendorsbundle" rel="stylesheet" media="screen, print" href="~/css/vendors.bundle.css" asp-append-version="true">
<link id="appbundle" rel="stylesheet" media="screen, print" href="~/css/app.bundle.css" asp-append-version="true">
<link id="mytheme" rel="stylesheet" media="screen, print" href="~/css/themes/cust-theme-15.css" asp-append-version="true">
<link id="myskin" rel="stylesheet" media="screen, print" href="~/css/skins/skin-master.css">
<link id="myskin" rel="stylesheet" media="screen, print" href="~/css/skins/skin-master.css" asp-append-version="true">
<!-- Place favicon.ico in the root directory -->
<link rel="apple-touch-icon" sizes="180x180" href="~/img/favicon/apple-touch-icon.png">
@ -45,6 +45,62 @@
</head>
<body class="mod-bg-1 mod-nav-link">
<script>
/**
* This script should be placed right after the body tag for fast execution
* Note: the script is written in pure javascript and does not depend on thirdparty library
**/
'use strict';
var classHolder = document.getElementsByTagName("BODY")[0],
/**
* Load from localstorage
**/
themeSettings = (localStorage.getItem('themeSettings')) ? JSON.parse(localStorage.getItem('themeSettings')) :
{},
themeURL = themeSettings.themeURL || '',
themeOptions = themeSettings.themeOptions || '';
/**
* Load theme options
**/
if (themeSettings.themeOptions) {
classHolder.className = themeSettings.themeOptions;
console.log("%c✔ Theme settings loaded", "color: #148f32");
}
else {
console.log("%c✔ Heads up! Theme settings is empty or does not exist, loading default settings...", "color: #ed1c24");
}
if (themeSettings.themeURL && !document.getElementById('mytheme')) {
var cssfile = document.createElement('link');
cssfile.id = 'mytheme';
cssfile.rel = 'stylesheet';
cssfile.href = themeURL;
document.getElementsByTagName('head')[0].appendChild(cssfile);
}
else if (themeSettings.themeURL && document.getElementById('mytheme')) {
document.getElementById('mytheme').href = themeSettings.themeURL;
}
/**
* Save to localstorage
**/
var saveSettings = function () {
themeSettings.themeOptions = String(classHolder.className).split(/[^\w-]+/).filter(function (item) {
return /^(nav|header|footer|mod|display)-/i.test(item);
}).join(' ');
if (document.getElementById('mytheme')) {
themeSettings.themeURL = document.getElementById('mytheme').getAttribute("href");
};
localStorage.setItem('themeSettings', JSON.stringify(themeSettings));
}
/**
* Reset settings
**/
var resetSettings = function () {
localStorage.setItem("themeSettings", "");
}
</script>
<!-- BEGIN Page Wrapper -->
<div class="page-wrapper">

View File

@ -78,11 +78,11 @@
<div class="row mb-5">
<div class="card-columns">
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 發電量</h4>
<div class="ml-auto">kWh</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>今日發電量</p>
<p><span class="color-info-700" id="today_kwh">126,161.72</span></p>
@ -94,11 +94,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span> 日照度</h4>
<div class="ml-auto">kW/m<sup>2</sup></div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>即時平均日照度</p>
<p><span class="color-info-700" id="today_irradiance">126,161.72</span></p>
@ -110,11 +110,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> PR值</h4>
<div class="ml-auto">%</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>即時平均 PR 值</p>
<p><span class="color-info-700" id="today_PR">119.04</span></p>
@ -126,11 +126,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span> kWh / kWp</h4>
<div class="ml-auto">hr</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>即時平均 kWh / kWp</p>
<p><span class="color-info-700" id="today_kwhkwp">140.39</span></p>
@ -142,11 +142,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 減碳量</h4>
<div class="ml-auto">kG</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>今日減碳量</p>
<p><span class="color-info-700" id="today_carbon">6,091.78</span></p>

View File

@ -5,15 +5,32 @@
}
@using SolarPower.Models.Role
@model RoleLayerEnum
<ol class="breadcrumb page-breadcrumb" >
@*<ol class="breadcrumb page-breadcrumb" >
<li class="breadcrumb-item"><a href="javascript:void(0);">總覽</a></li>
<li class="breadcrumb-item">@ViewData["Title"]</li>
<li class="breadcrumb-item city-name" id="breadcrumbcity">新竹市</li>
<li class="breadcrumb-item power-station-name active" id="breadcrumbname">新竹巨城站</li>
<li class="position-absolute pos-top pos-right d-none d-sm-block"><span class="js-get-date"></span></li>
</ol>
<div class="row">
</ol>*@
<div class="container-fluid">
<div class="row flex-nowrap wrapper">
<div class="col-md-2 col-1 pl-0 pr-0 collapse width border-right sidebar vh-100">
<div class="list-group border-0 card text-center text-md-left" id="sidebar">
<div class="border bg-light rounded-top">
<div class="form-group p-2 m-0 rounded-top">
<input type="text" class="form-control form-control-lg shadow-inset-2 m-0" id="js_list_accordion_filter" placeholder="">
</div>
<div id="js_list_accordion" class="accordion accordion-hover accordion-clean js-list-filter">
</div>
<span class="filter-message js-filter-message"></span>
</div>
</div>
</div>
<div class="col-auto px-0">
<a href="javascript:;" data-target=".sidebar" data-toggle="collapse" class="btn btn-default btn-xs btn-icon waves-effect waves-themed" style="border-radius: 0;" onclick="ChangePowerStationCollapse(this)"><i class="fal fa-angle-right fa-lg py-3"></i></a>
</div>
<main class="col px-5 pl-md-2 main">
<div class="row">
<div class="col-xl-12">
<div id="panel-5" class="panel">
<div class="panel-container show">
@ -26,7 +43,7 @@
<i class="base-7 icon-stack-2x color-info-700"></i>
<i class="ni ni-graph icon-stack-1x text-white"></i>
</span>
<span id="power-station-title" >新竹巨城站</span>
<span id="power-station-title">新竹巨城站</span>
</h1>
</div>
<div class="col-xl-3 d-flex justify-content-start">
@ -136,13 +153,18 @@
</div>
</div>
</div>
</div>
</main>
</div>
</div>
@section Scripts{
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
<script>
var localurl = this.location.href;
var powerids = new Array(0);//當前選擇電站
var Type = 0; // 項目
var stationId;
@ -160,6 +182,13 @@
var url = new URL(location.href);
stationId = url.searchParams.get('stationId');
GetPowerStationCollapse();
$('#js_list_accordion_filter').change(function () {
var filter = $(this).val();
GetPowerStationCollapse(filter);
});
//#region 即時資訊tab
var url = "/StationOverview/GetOneStationUpToDateInfo";
var send_data = {
@ -795,7 +824,7 @@
//#region 逆變器分析 tab
ChangeInverterkwhBarDaily();
ChangeInverterkwhBarDaily('');
//#region 載入電站逆變器資料
var url = "/StationOverview/GetInverterCheckBox";
@ -928,6 +957,72 @@
getTable();
});
//#region 變更左邊電站Collapse選單箭頭
function ChangePowerStationCollapse(div) {
var className = $(div).children("i").attr("class");
if (className == "fal fa-angle-left fa-lg py-3") {
$(div).children("i").attr("class", "fal fa-angle-right fa-lg py-3");
}
else {
$(div).children("i").attr("class", "fal fa-angle-left fa-lg py-3");
}
}
//#endregion
function GetPowerStationCollapse(filter) {
var url = "/StationOverview/GetPowerStationCollapse"
var send_data = {
Filter: filter
}
$.post(url, send_data, function (rel) {
if (rel.code != "0000") {
toast_error(rel.data.msg);
return;
}
$('#js_list_accordion').empty();
if (rel.data.length <= 0) {
$('#js_list_accordion').append("<div>查無結果</div>");
}
var str = "";
$.each(rel.data, function (index, item) {
str += '<div class="card border-top-left-radius-0 border-top-right-radius-0" id="templateCard">' +
'<div class="card-header">' +
'<a href="javascript:void(0);" class="card-title collapsed" data-toggle="collapse" data-target="#js_list_accordion-' + index + '" aria-expanded="false" data-filter-tags="settings">' +
'<i class="fal fa-globe width-2 fs-xl"></i>' +
'<span class="city-name">' + item.cityName + '</span>' +
'<span class="ml-auto">' +
'<span class="collapsed-reveal"><i class="fal fa-chevron-up fs-xl"></i></span>' +
'<span class="collapsed-hidden"><i class="fal fa-chevron-down fs-xl"></i></span>' +
'</span>' +
'</a>' +
'</div>' +
'<div id="js_list_accordion-' + index + '" class="collapse" data-parent="#js_list_accordion" style="">' +
'<div class="card-body">' +
'<ul class="list-group">';
$.each(item.myPowerStations, function (index, power_station) {
str += '<li class="list-group-item">' +
'<a href="/StationOverview/Info?stationId=' + power_station.powerStationId + '">' + power_station.powerStationName + '</a>' +
'</li>';
});
str += '</ul>';
str += '</div>';
str += '</div>';
});
$('#js_list_accordion').append(str);
$('#js_list_accordion').find('.card').first().addClass(" border-top-left-radius-0 border-top-right-radius-0");
}, 'json');
}
//#region 產生檔案html

View File

@ -1,11 +1,11 @@
<div class="row mb-5">
<div class="card-columns">
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 發電量</h4>
<div class="ml-auto">kwh</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>今日發電量</p>
<p><span class="color-info-700" id="today_kwh">126,161.72</span></p>
@ -17,11 +17,11 @@
</div>
</div>
<div class="card money-card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-dollar-sign mr-1"></span> <span id="money-card-title">發電金額</span></h4>
<div class="ml-auto">NTD</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p id="money-card-subtitle-total">總發金額</p>
<p><span class="color-info-700" id="total_money">126,161.72</span></p>
@ -33,11 +33,11 @@
</div>
</div>
<div class="card irradiance-card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span> 日照度</h4>
<div class="ml-auto">kw/m<sup>2</sup></div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>即時平均日照度</p>
<p><span class="color-info-700" id="today_irradiance">126,161.72</span></p>
@ -49,10 +49,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> PR值</h4>
<div class="ml-auto">%</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>即時平均 PR 值</p>
<p><span class="color-info-700" id="today_PR">119.04</span></p>
@ -64,10 +65,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span> kWh / kWp</h4>
<div class="ml-auto">hr</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>即時平均 kWh / kWp</p>
<p><span class="color-info-700" id="today_kwhkwp">140.39</span></p>
@ -79,11 +81,11 @@
</div>
</div>
<div class="card">
<div class="card-header bg-fusion-25 pr-3 d-flex align-items-center flex-wrap">
<div class="card-header bg-fusion-25 py-2 pr-3 d-flex align-items-center flex-wrap">
<h4 class="mb-0 font-weight-bold"><span class="fal fa-cow mr-1"></span> 減碳量</h4>
<div class="ml-auto">kG</div>
</div>
<div class="card-body" style="min-height: 148px;">
<div class="card-body">
<div class="d-flex justify-content-between">
<p>今日減碳量</p>
<p><span class="color-info-700" id="today_carbon">6,091.78</span></p>

View File

@ -24,7 +24,8 @@
"BackgroundServiceCron": {
"CalcPowerStationJob": "0 5 * * * ?",
"CalcAvgPowerStationJob": "0 0 2 * * ?",
"OperationScheduleJob": "0 0 2 * * ?"
"OperationScheduleJob": "0 0 2 * * ?",
"CalcInverter15minJob": "0 2/15 * * * ?"
},
"SMTPConfig": {
"Host": "smtp.gmail.com",

View File

@ -25,7 +25,8 @@
"BackgroundServiceCron": {
"CalcPowerStationJob": "0 5 * * * ?",
"CalcAvgPowerStationJob": "0 0 2 * * ?",
"OperationScheduleJob": "0 0 2 * * ?"
"OperationScheduleJob": "0 0 2 * * ?",
"CalcInverter15minJob": "0 2/15 * * * ?"
},
"SMTPConfig": {
"Host": "smtp.gmail.com",

View File

@ -866,7 +866,7 @@ html {
/* app logo */
.page-logo {
height: 4.125rem;
width: 16.875rem;
width: 15.29rem;
-webkit-box-shadow: 0px 0px 28px 0px rgba(0, 0, 0, 0.13);
box-shadow: 0px 0px 28px 0px rgba(0, 0, 0, 0.13);
overflow: hidden;
@ -885,8 +885,9 @@ html {
min-height: 1px;
padding: 0 2rem; }
.page-logo img {
/*width: 28px;*/
height: 28px; }
/*width: 28px;
height: 28px; */
}
.page-logo .page-logo-link {
-webkit-box-flex: 1;
-ms-flex: 1 0 auto;
@ -1153,8 +1154,8 @@ html {
-webkit-box-flex: 1;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
width: 16.875rem;
max-width: 16.875rem;
width: 15.29rem;
max-width: 15.29rem;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
@ -1524,7 +1525,7 @@ html {
}*/
@media (min-width: 1399px) {
.page-sidebar .primary-nav .nav-menu > li > a {
font-size: 1.125rem; } }
font-size: 1rem; } }
/* app navigation filter */
.nav-filter {
@ -2431,7 +2432,7 @@ html {
/* app content heading */
.subheader:not(:empty) {
margin-bottom: calc(1.5rem + 0.625rem);
margin-bottom: calc(.5rem + 0.625rem);
position: relative;
display: -webkit-box;
display: -ms-flexbox;
@ -2738,7 +2739,7 @@ html {
.page-breadcrumb {
padding: 0;
background: transparent;
margin: 0 0 1.5rem;
margin: 0 0 1rem;
position: relative;
text-shadow: #fff 0 1px; }

View File

@ -3033,3 +3033,63 @@ body:not(.mod-pace-custom) .pace .pace-progress {
background: #fff; }
/*# sourceMappingURL=cust-theme-15.css.map */
.map-responsive{
overflow:hidden;
padding-bottom:50%;
position:relative;
height:0;
}
.map-responsive iframe{
left:0;
top:0;
height:100%;
width:100%;
position:absolute;
}
.collapse.width {
width: 0;
max-width: 0;
height: 100%;
transition: right 0.3s linear, max-width 0.3s linear;
position: relative;
top: 0;
right: 100%;
left: 0;
display: block;
overflow: hidden;
}
.vh-100 {
min-height: 100vh;
}
.collapsing.width {
transition: right 0.3s linear, max-width 0.7s linear;
width: 0% !important;
height: 100%;
max-width: 0% !important;
min-width: 0;
right: 0;
position: relative;
display: block;
}
.collapse .list-group-item {
white-space:nowrap
}
.collapse.width.show {
transition: right 0.3s linear, max-width 0.3s linear;
width: 100%;
height: 100%;
max-width: 100%;
min-width: 50px;
right: 0;
position: relative;
display: block;
}

View File

@ -6927,7 +6927,7 @@ button.bg-dark:focus {
.mb-5,
.my-5 {
margin-bottom: 2rem !important; }
margin-bottom: 1rem !important; }
.ml-5,
.mx-5 {