1. bug fix

2. 加入寄信背景服務
This commit is contained in:
Kai 2021-08-02 13:47:15 +08:00
parent 8c51ec5e04
commit 69007218b5
10 changed files with 519 additions and 264 deletions

View File

@ -169,6 +169,8 @@ namespace SolarPower.Controllers
var XAxis = new List<string>(); var XAxis = new List<string>();
#region #region
if (selected_powerStationIds.Count() > 0)
{
var powerStationHistories = await powerStationRepository.GetPowerStationHistory(post.SelectedDate, post.SearchType, selected_powerStationIds); var powerStationHistories = await powerStationRepository.GetPowerStationHistory(post.SelectedDate, post.SearchType, selected_powerStationIds);
XAxis.AddRange(powerStationHistories.Select(x => x.Timestamp).Distinct().ToList()); XAxis.AddRange(powerStationHistories.Select(x => x.Timestamp).Distinct().ToList());
@ -283,9 +285,12 @@ namespace SolarPower.Controllers
} }
analysisDevice.Series.Add(modelTemperature); analysisDevice.Series.Add(modelTemperature);
} }
}
#endregion #endregion
#region #region
if (meterDic.Count() > 0)
{
var meterHistories = await powerStationRepository.GetMeterHistory(post.SelectedDate, post.SearchType, meterDic); var meterHistories = await powerStationRepository.GetMeterHistory(post.SelectedDate, post.SearchType, meterDic);
XAxis.AddRange(meterHistories.Select(x => x.TIMESTAMP).Distinct().ToList()); XAxis.AddRange(meterHistories.Select(x => x.TIMESTAMP).Distinct().ToList());
@ -466,6 +471,8 @@ namespace SolarPower.Controllers
} }
analysisDevice.Series.Add(F); analysisDevice.Series.Add(F);
} }
}
#endregion #endregion

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SolarPower.Models
{
public class NoticeSchedule
{
public int Id { get; set; }
public byte Type { get; set; }
public string RecipientName { get; set; }
public string RecipientEmail { get; set; }
public string Subject { get; set; }
public string Content { get; set; }
public string Attachment { get; set; }
public byte IsDelivery { get; set; }
public string DeliveryAt { get; set; }
}
}

View File

@ -0,0 +1,136 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Quartz;
using SolarPower.Models;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Threading.Tasks;
namespace SolarPower.Quartz.Jobs
{
[DisallowConcurrentExecution]
public class SendEmailJob : IJob
{
private readonly ILogger<SendEmailJob> logger;
private readonly IOptions<SMTPConfig> _options;
private readonly INoticeScheduleRepository noticeScheduleRepository;
private SMTPConfig smtp;
public SendEmailJob(
ILogger<SendEmailJob> logger,
IOptions<SMTPConfig> options,
INoticeScheduleRepository noticeScheduleRepository)
{
this.logger = logger;
this.smtp = options.Value;
this.noticeScheduleRepository = noticeScheduleRepository;
}
public async Task Execute(IJobExecutionContext context)
{
try
{
//取得要寄信的列表
logger.LogInformation("【SendEmailJob】【任務開始】");
var noticeSchedules = await noticeScheduleRepository.GetNotYetDelivery();
var updateNoticeSchedules = new List<NoticeSchedule>();
foreach (var notice in noticeSchedules)
{
var attachments = new List<string>();
var recipientEmails = new List<string>()
{
notice.RecipientEmail
};
if (!string.IsNullOrEmpty(notice.Attachment))
{
attachments = notice.Attachment.Split(',').ToList();
}
var result = Send(recipientEmails, notice.Subject, notice.Content, attachments);
if(result)
{
NoticeSchedule noticeSchedule = new NoticeSchedule();
noticeSchedule.Id = notice.Id;
noticeSchedule.IsDelivery = 1;
noticeSchedule.DeliveryAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
updateNoticeSchedules.Add(noticeSchedule);
}
List<string> properties = new List<string>()
{
"Id",
"IsDelivery",
"DeliveryAt"
};
await noticeScheduleRepository.UpdateList(updateNoticeSchedules, properties);
}
logger.LogInformation("【SendEmailJob】【任務完成】");
}
catch (Exception exception)
{
logger.LogError("【{0}】{1}", "SendEmailJob", exception.Message);
}
}
private bool Send(List<string> recipientEmails, string subject, string content, List<string> attachments)
{
MailMessage MyMail = new MailMessage();
MyMail.SubjectEncoding = System.Text.Encoding.UTF8;//郵件標題編碼
MyMail.BodyEncoding = System.Text.Encoding.UTF8; //郵件內容編碼
MyMail.IsBodyHtml = true; //是否使用html格式
MyMail.From = new System.Net.Mail.MailAddress(smtp.UserName); //寄件人
foreach (var email in recipientEmails)
{
MyMail.To.Add(email); //設定收件者Email
}
MyMail.Subject = subject; //主題
MyMail.Body = content; //設定信件內容
foreach(var attachment in attachments)
{
var directoryBase = Directory.GetCurrentDirectory();
var filePath = @$"{directoryBase}/wwwroot{attachment}";
var data = new Attachment(filePath);
MyMail.Attachments.Add(data);
}
//讀取 SMTP Config
SmtpClient MySMTP = new SmtpClient(smtp.Host, smtp.Port);
MySMTP.EnableSsl = smtp.EnableSsl;
MySMTP.Credentials = new System.Net.NetworkCredential(smtp.UserName, smtp.Password);
try
{
MySMTP.Send(MyMail);
MySMTP.Dispose();
MyMail.Dispose(); //釋放資源
return true;
}
catch (Exception ex)
{
string json = System.Text.Json.JsonSerializer.Serialize(recipientEmails);
logger.LogError("【SendEmailJob】 " + "寄送信件失敗");
logger.LogError("【SendEmailJob】 - Emails:" + json);
logger.LogError("【SendEmailJob】 - Exception:" + ex.Message);
return false;
}
}
}
}

View File

@ -0,0 +1,68 @@
using Dapper;
using SolarPower.Helper;
using SolarPower.Models;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
namespace SolarPower.Repository.Implement
{
public class NoticeScheduleRepository : RepositoryBase<NoticeSchedule>, INoticeScheduleRepository
{
public NoticeScheduleRepository(IDatabaseHelper databaseHelper) : base(databaseHelper)
{
tableName = "notice_schedule";
}
public async Task<List<NoticeSchedule>> GetNotYetDelivery()
{
List<NoticeSchedule> result;
using (IDbConnection conn = this._databaseHelper.GetConnection())
{
try
{
var sql = $"SELECT * FROM {tableName} WHERE IsDelivery = 0";
result = (await conn.QueryAsync<NoticeSchedule>(sql)).ToList();
}
catch (Exception exception)
{
throw exception;
}
return result;
}
}
public async Task UpdateList(List<NoticeSchedule> noticeSchedules, List<string> properties)
{
using (IDbConnection conn = this._databaseHelper.GetConnection())
{
conn.Open();
using (var trans = conn.BeginTransaction())
{
try
{
var sql = GenerateUpdateQuery(properties);
await conn.ExecuteAsync(sql, noticeSchedules, trans);
trans.Commit();
}
catch (Exception exception)
{
trans.Rollback();
throw exception;
}
finally
{
conn.Close();
}
}
}
}
}
}

View File

@ -0,0 +1,14 @@
using SolarPower.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SolarPower.Repository.Interface
{
public interface INoticeScheduleRepository : IRepositoryBase<NoticeSchedule>
{
Task<List<NoticeSchedule>> GetNotYetDelivery();
Task UpdateList(List<NoticeSchedule> noticeSchedules, List<string> properties);
}
}

View File

@ -78,6 +78,7 @@ namespace SolarPower
services.AddTransient<IOverviewRepository, OverviewRepository>(); services.AddTransient<IOverviewRepository, OverviewRepository>();
services.AddTransient<IAnalysisStationCombineRepository,AnalysisStationCombineRepository>(); services.AddTransient<IAnalysisStationCombineRepository,AnalysisStationCombineRepository>();
services.AddTransient<IStationReportRepository, StationReportRepository>(); services.AddTransient<IStationReportRepository, StationReportRepository>();
services.AddTransient<INoticeScheduleRepository, NoticeScheduleRepository>();
#endregion #endregion
double loginExpireMinute = this.Configuration.GetValue<double>("LoginExpireMinute"); double loginExpireMinute = this.Configuration.GetValue<double>("LoginExpireMinute");
@ -122,6 +123,14 @@ namespace SolarPower
//new JobSchedule(jobType: typeof(CalcAvgPowerStationJob), cronExpression: "0/10 * * * * ?") //new JobSchedule(jobType: typeof(CalcAvgPowerStationJob), cronExpression: "0/10 * * * * ?")
); );
#endregion #endregion
#region Email(2)
services.AddSingleton<SendEmailJob>();
services.AddSingleton(
new JobSchedule(jobType: typeof(SendEmailJob), cronExpression: Configuration.GetValue<string>("BackgroundServiceCron:SendEmailJob"))
);
#endregion
services.AddHostedService<QuartzHostedService>(); services.AddHostedService<QuartzHostedService>();
#endregion #endregion
} }

View File

@ -16,11 +16,11 @@
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 發電量</h4>
<div class="ml-auto">kwh</div> <div class="ml-auto">kW h</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>總發電量</p> <p>即時總發電量</p>
<p><span class="color-info-700 fs-xl font-weight-bold" id="today_kwh">126,161.72</span></p> <p><span class="color-info-700 fs-xl font-weight-bold" id="today_kwh">126,161.72</span></p>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -32,7 +32,7 @@
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <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 class="ml-auto">k W/m<sup>2</sup></div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -63,17 +63,17 @@
</div> </div>
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span>有效日照時數</h4>
<div class="ml-auto">hr</div> <div class="ml-auto">hr</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>即時平均 kWh / kWp</p> <p>即時平均有效日照時數</p>
<p><span class="color-info-700 fs-xl font-weight-bold" id="today_kwhkwp">140.39</span> kW/m2</p> <p><span class="color-info-700 fs-xl font-weight-bold" id="today_kwhkwp">140.39</span></p>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>平均 kWh / kWp (30天)</p> <p>平均有效日照時數 (30天)</p>
<p><span class="color-info-700 fs-xl font-weight-bold" id="avg_kwhkwp">4.53</span> kW/m2</p> <p><span class="color-info-700 fs-xl font-weight-bold" id="avg_kwhkwp">4.53</span></p>
</div> </div>
</div> </div>
</div> </div>
@ -264,8 +264,8 @@
'<div id="bodyContent">' + '<div id="bodyContent">' +
'<div class="row">' + '<div class="row">' +
'<div class="col-12">' + '<div class="col-12">' +
'<div>發電量:' + item.today_kWh + '</div>'+ '<div>即時總發電量:' + item.today_kWh + '</div>'+
'<div>日照度:' + item.today_irradiance + '</div>'+ '<div>即時平均日照度:' + item.today_irradiance + '</div>'+
'<div>發電小時:' + item.solarHour + '</div>' + '<div>發電小時:' + item.solarHour + '</div>' +
'<div>裝置容量:' + item.generatingCapacity + '</div>' + '<div>裝置容量:' + item.generatingCapacity + '</div>' +
'<div>天氣:' + + '</div>'+ '<div>天氣:' + + '</div>'+

View File

@ -80,7 +80,7 @@
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 發電量</h4>
<div class="ml-auto">kWh</div> <div class="ml-auto">kW h</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -96,7 +96,7 @@
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <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 class="ml-auto">k W/m<sup>2</sup></div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -127,16 +127,16 @@
</div> </div>
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span>有效日照時數</h4>
<div class="ml-auto">hr</div> <div class="ml-auto">hr</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>即時平均 kWh / kWp</p> <p>即時平均有效日照時數</p>
<p><span class="color-info-700" id="today_kwhkwp">140.39</span></p> <p><span class="color-info-700" id="today_kwhkwp">140.39</span></p>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>平均 kWh / kWp (30天)</p> <p>平均有效日照時數(30天)</p>
<p><span class="color-info-700" id="avg_kwhkwp">4.53</span></p> <p><span class="color-info-700" id="avg_kwhkwp">4.53</span></p>
</div> </div>
</div> </div>

View File

@ -3,7 +3,7 @@
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <h4 class="mb-0 font-weight-bold"><span class="fal fa-bolt mr-1"></span> 發電量</h4>
<div class="ml-auto">kwh</div> <div class="ml-auto">kW h</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -35,7 +35,7 @@
<div class="card irradiance-card"> <div class="card irradiance-card">
<div class="card-header bg-fusion-25 py-2 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> <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 class="ml-auto">k W/m<sup>2</sup></div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -66,16 +66,16 @@
</div> </div>
<div class="card"> <div class="card">
<div class="card-header bg-fusion-25 py-2 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> <h4 class="mb-0 font-weight-bold"><span class="fal fa-sun mr-1"></span>有效日照時數</h4>
<div class="ml-auto">hr</div> <div class="ml-auto">hr</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>即時平均 kWh / kWp</p> <p>即時平均有效日照時數</p>
<p><span class="color-info-700" id="today_kwhkwp">140.39</span></p> <p><span class="color-info-700" id="today_kwhkwp">140.39</span></p>
</div> </div>
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<p>平均 kWh / kWp (30天)</p> <p>平均有效日照時數(30天)</p>
<p><span class="color-info-700" id="avg_kwhkwp">4.53</span></p> <p><span class="color-info-700" id="avg_kwhkwp">4.53</span></p>
</div> </div>
</div> </div>

View File

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