mirror of
https://github.com/Stefan-5422/-T5-Elektrifikatsiya.git
synced 2026-09-04 00:45:58 +02:00
Add ScheduledService and email things ༼ つ ◕_◕ ༽つ
This commit is contained in:
@@ -351,3 +351,4 @@ MigrationBackup/
|
||||
|
||||
# Project specific
|
||||
*.sqlite*
|
||||
/src/Elektrifikatsiya/Elektrifikatsiya/appsettings.Development.json
|
||||
|
||||
@@ -5,10 +5,15 @@ namespace Elektrifikatsiya.Models;
|
||||
|
||||
public class User
|
||||
{
|
||||
[Required]
|
||||
public List<Device> Devices { get; set; } = new();
|
||||
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[Key]
|
||||
public int Id { get; private set; }
|
||||
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Name { get; private set; }
|
||||
|
||||
@@ -18,11 +23,16 @@ public class User
|
||||
[Required]
|
||||
public Role Role { get; set; }
|
||||
|
||||
public string? SessionToken { get; set; }
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
public string? SessionToken
|
||||
{
|
||||
get => _token;
|
||||
set
|
||||
{
|
||||
_token = value;
|
||||
}
|
||||
}
|
||||
|
||||
[Required]
|
||||
public List<Device> Devices { get; set; } = new();
|
||||
private string? _token;
|
||||
|
||||
public User(string name, string passwordHash, Role role)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
@using System.Diagnostics;
|
||||
@using Elektrifikatsiya.Layouts;
|
||||
@using Elektrifikatsiya.Services;
|
||||
@inject IAuthenticationService AuthenticationService;
|
||||
@inject NavigationManager NavigationManager
|
||||
@page "/login"
|
||||
@layout LoginLayout;
|
||||
|
||||
@code {
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
bool isAuthenticated = (await AuthenticationService.IsAuthenticated()).ValueOrDefault;
|
||||
|
||||
if (isAuthenticated)
|
||||
{
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
global using INotificationService = Elektrifikatsiya.Services.INotifcationService;
|
||||
|
||||
using Blazorise;
|
||||
using Blazorise.Bootstrap;
|
||||
using Blazorise.Icons.Material;
|
||||
@@ -14,6 +16,7 @@ using HiveMQtt.Client.Options;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Read configuration
|
||||
@@ -24,8 +27,13 @@ builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddOptions();
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddHostedService<UpdateService>();
|
||||
builder.Services.AddHostedService<ServiceScheduler>();
|
||||
builder.Services.AddSingleton<IUpdateService, UpdateService>();
|
||||
builder.Services.AddSingleton<IDeviceStatusService, DeviceStatusService>();
|
||||
builder.Services.AddSingleton<INotificationService, NotifcationService>();
|
||||
builder.Services.AddSingleton<IScheduledService>(s => s.GetRequiredService<IUpdateService>());
|
||||
builder.Services.AddSingleton<IScheduledService>(s=>s.GetRequiredService<INotificationService>());
|
||||
builder.Services.AddSingleton<IEmailService, EmailService>();
|
||||
builder.Services.AddSingleton<IHiveMQClient, HiveMQClient>((provider)=>
|
||||
{
|
||||
HiveMQClientOptions options = new()
|
||||
@@ -43,7 +51,6 @@ builder.Services.AddTransient<IDeviceManagmentService, DeviceManagmentService>()
|
||||
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||
builder.Services.AddScoped<IAuthorizationService, AuthorizationService>();
|
||||
builder.Services.AddScoped<ICookieService, CookieService>();
|
||||
builder.Services.AddScoped<IEmailService, EmailService>();
|
||||
builder.Services.AddDbContext<MainDatabaseContext>(options => options.UseSqlite("Data Source=./MainDatabase.sqlite"));
|
||||
builder.Services.AddBootstrapProviders();
|
||||
builder.Services.AddHttpClient<IDeviceManagmentService, DeviceManagmentService>();
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Elektrifikatsiya.Utilities;
|
||||
|
||||
namespace Elektrifikatsiya.Services;
|
||||
|
||||
public interface INotifcationService : IScheduledService
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Elektrifikatsiya.Utilities;
|
||||
|
||||
namespace Elektrifikatsiya.Services;
|
||||
|
||||
public interface IUpdateService : IScheduledService
|
||||
{
|
||||
|
||||
}
|
||||
+2
@@ -173,6 +173,8 @@ public class DeviceManagmentService : IDeviceManagmentService
|
||||
|
||||
PublishResult res = await hiveMQClient.PublishAsync($"shellies/shellyplug-s-{device.MacAddress}/relay/0/command", device.Enabled ? "on" : "off");
|
||||
|
||||
device.User = mainDatabaseContext.Users.First(u => u.Id == device.User.Id);
|
||||
|
||||
_ = mainDatabaseContext.Update(device);
|
||||
|
||||
return await Result.Try(Task () => mainDatabaseContext.SaveChangesAsync());
|
||||
|
||||
@@ -38,7 +38,6 @@ namespace Elektrifikatsiya.Services.Implementations
|
||||
{
|
||||
string content = emailSettings.CompiledTemplates[templateKey](templateParameters ?? new());
|
||||
return SendAsync(to, subject, content, from);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Elektrifikatsiya.Utilities;
|
||||
|
||||
namespace Elektrifikatsiya.Services.Implementations;
|
||||
|
||||
public class NotifcationService : INotifcationService
|
||||
{
|
||||
public TimeSpan ExecutionRepeatDelay => TimeSpan.FromSeconds(30);
|
||||
public DateTime FirstExecutionTime => DateTime.Now.AddDays(0);
|
||||
private readonly IEmailService emailService;
|
||||
private readonly ILogger<NotifcationService> logger;
|
||||
|
||||
public NotifcationService(ILogger<NotifcationService> logger, IEmailService emailService)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.emailService = emailService;
|
||||
}
|
||||
|
||||
public async void Update()
|
||||
{
|
||||
//logger.LogInformation("Sending Email");
|
||||
//await emailService.SendWithTemeplateAsync("[email protected]", "AAAA", "DailyNotification", templateParameters: new() { { "yesterday", "10" }, { "yearly", "100" }, { "link", "localhost:5565/yes" } });
|
||||
//logger.LogInformation("Done sending");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Elektrifikatsiya.Utilities;
|
||||
|
||||
namespace Elektrifikatsiya.Services.Implementations;
|
||||
|
||||
public class ServiceScheduler : IHostedService
|
||||
{
|
||||
private readonly ILogger<ServiceScheduler> logger;
|
||||
private readonly IEnumerable<IScheduledService> scheduledServices;
|
||||
private readonly Dictionary<IScheduledService, DateTime> lastExectued;
|
||||
|
||||
private Timer timer = null!;
|
||||
|
||||
public ServiceScheduler(ILogger<ServiceScheduler> logger, IServiceProvider serviceProvider)
|
||||
{
|
||||
this.logger = logger;
|
||||
scheduledServices = serviceProvider.GetServices<IScheduledService>();
|
||||
lastExectued = scheduledServices.ToDictionary(x => x, x => x.FirstExecutionTime);
|
||||
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogInformation("Starting service scheduler...");
|
||||
|
||||
timer = new Timer(async (_) => await Update(), null, TimeSpan.Zero, Timeout.InfiniteTimeSpan);
|
||||
|
||||
logger.LogInformation("Service scheduler started.");
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogInformation("Stopping service scheduler.");
|
||||
|
||||
timer.Dispose();
|
||||
|
||||
logger.LogInformation("Stopped service scheduler.");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task Update()
|
||||
{
|
||||
TimeSpan s = lastExectued.Min(x => (x.Value + x.Key.ExecutionRepeatDelay)) - DateTime.Now;
|
||||
|
||||
if (s < TimeSpan.Zero)
|
||||
{
|
||||
s = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
timer.Change(s, Timeout.InfiniteTimeSpan);
|
||||
|
||||
foreach (IScheduledService scheduledService in scheduledServices.Where(s => s.FirstExecutionTime < DateTime.Now))
|
||||
{
|
||||
if (lastExectued[scheduledService] + scheduledService.ExecutionRepeatDelay <= DateTime.Now)
|
||||
{
|
||||
lastExectued[scheduledService] = DateTime.Now;
|
||||
scheduledService.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,38 +8,29 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Elektrifikatsiya.Services.Implementations;
|
||||
|
||||
public class UpdateService : IHostedService, IDisposable
|
||||
public class UpdateService : IUpdateService
|
||||
{
|
||||
private readonly ILogger<UpdateService> logger;
|
||||
private readonly IDeviceStatusService deviceStatusService;
|
||||
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||
private Timer? timer = null;
|
||||
|
||||
public UpdateService(ILogger<UpdateService> logger, IDeviceStatusService deviceStatusService, IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.deviceStatusService = deviceStatusService;
|
||||
this.serviceScopeFactory = serviceScopeFactory;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
IServiceScope serviceScope = serviceScopeFactory.CreateScope();
|
||||
MainDatabaseContext mainDatabaseContext = serviceScope.ServiceProvider.GetRequiredService<MainDatabaseContext>();
|
||||
|
||||
logger.LogInformation("Starting update service...");
|
||||
|
||||
foreach (Device device in await mainDatabaseContext.Devices.Include(d => d.User).AsNoTracking().ToListAsync(cancellationToken))
|
||||
foreach (Device device in mainDatabaseContext.Devices.Include(d => d.User).AsNoTracking().ToList())
|
||||
{
|
||||
_ = deviceStatusService.TrackDevice(device);
|
||||
}
|
||||
|
||||
timer = new Timer(async (_) => await Update(), null, TimeSpan.Zero, TimeSpan.FromSeconds(15));
|
||||
|
||||
logger.LogInformation("Update service started.");
|
||||
}
|
||||
|
||||
private async Task Update()
|
||||
public DateTime FirstExecutionTime { get; } = DateTime.Now.AddSeconds(15);
|
||||
public TimeSpan ExecutionRepeatDelay { get; } = TimeSpan.FromSeconds(15);
|
||||
|
||||
public async void Update()
|
||||
{
|
||||
Result<List<Device>> getDeviceStatusResult = deviceStatusService.GetDevices();
|
||||
|
||||
@@ -61,26 +52,4 @@ public class UpdateService : IHostedService, IDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogInformation("Stopping update service.");
|
||||
|
||||
_ = timer?.Change(Timeout.Infinite, 0);
|
||||
|
||||
logger.LogInformation("Stopped update service.");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
timer?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Elektrifikatsiya.Utilities;
|
||||
|
||||
public interface IScheduledService
|
||||
{
|
||||
DateTime FirstExecutionTime { get; }
|
||||
TimeSpan ExecutionRepeatDelay { get; }
|
||||
|
||||
void Update();
|
||||
}
|
||||
@@ -7,13 +7,13 @@
|
||||
}
|
||||
},
|
||||
"EmailSettings": {
|
||||
"User": "",
|
||||
"DefaultEmail": "",
|
||||
"Key": "",
|
||||
"User": "[email protected]",
|
||||
"DefaultEmail": "[email protected]",
|
||||
"Key": "xsmtpsib-34d2ebc5edbb9b7bdbb9fd8ad4f724a759135883c52f9a9aadd919f7492f215a-FztV7QTUhdyaSk9p",
|
||||
"Templates": {
|
||||
|
||||
"DailyNotification": "../assets/DailyNotif.html"
|
||||
},
|
||||
"SmtpServer": "",
|
||||
"SmtpPort": 0
|
||||
"SmtpServer": "smtp-relay.sendinblue.com",
|
||||
"SmtpPort": 587
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user