diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Database/MainDatabaseContext.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Database/MainDatabaseContext.cs index 95caf56..63fcd63 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Database/MainDatabaseContext.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Database/MainDatabaseContext.cs @@ -6,11 +6,13 @@ namespace Elektrifikatsiya.Database; public class MainDatabaseContext : DbContext { - public MainDatabaseContext(DbContextOptions dbContextOptions) : base(dbContextOptions) - { - } + public DbSet Devices { get; set; } - public DbSet Users { get; set; } - public DbSet Devices { get; set; } - public DbSet Events { get; set; } + public DbSet Users { get; set; } + + public DbSet EnergyPriceChanges { get; set; } + + public MainDatabaseContext(DbContextOptions dbContextOptions) : base(dbContextOptions) + { + } } \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/EnergyPriceChange.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/EnergyPriceChange.cs new file mode 100644 index 0000000..82214fb --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/EnergyPriceChange.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; + +namespace Elektrifikatsiya.Models; + +public class EnergyPriceChange +{ + [Key] + public DateTime DateTime { get; set; } + public double EnergyPrice { get; set; } + + + public EnergyPriceChange(DateTime dateTime, double energyPrice) + { + DateTime = dateTime; + EnergyPrice = energyPrice; + } + + public EnergyPriceChange(double energyPrice) + { + EnergyPrice = energyPrice; + DateTime = DateTime.Now; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor index 70fc325..5f66bc6 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor @@ -1,5 +1,6 @@ @page "/" @using Blazorise.Components; +@using Elektrifikatsiya.Database; @using Elektrifikatsiya.Models; @using System.Net @using Elektrifikatsiya.Services @@ -7,88 +8,92 @@ @using System.Diagnostics @using Elektrifikatsiya.Services.Implementations @inject IVersionProvider VersionProvider -@inject IDeviceStatusService DeviceStatusService -@inject IEventService EventService - -
- - - - Plugs - - - - - - - - - - @context.Item.Name - - - - - User: @context.Item.User.Name -
- Room: @context.Item.Room -
- - @context.Item.PowerUsage W - -
-
- - - -
-
-
-
-
- - - - Logs - - - +@inject IDeviceStatusService DeviceStatusService; +@inject IDeviceManagmentService DeviceManagmentService; +@inject IEventService EventService; +@inject MainDatabaseContext MainDatabaseContext; - -
- @context.Item.EventName - @context.Item.Date -
- @context.Item.Description -
-
-
-
-
- - - - - - \ No newline at end of file +
+ +
+ + + + Plugs + + + + + + + + + + @context.Item.Name + + + + + User: @context.Item.User.Name +
+ Room: @context.Item.Room +
+ + @context.Item.PowerUsage W + +
+
+ + + +
+
+
+
+
+ + + + Logs + + + + +
+ @context.Item.EventName + @context.Item.Date +
+ @context.Item.Description +
+
+
+
+
+ + + + + + +
diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor.cs index f5dc2b6..6fb0007 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Dashboard.razor.cs @@ -5,88 +5,101 @@ using Elektrifikatsiya.Utilities; using System.Diagnostics; using System.Text; +using Elektrifikatsiya.Services.Implementations; +using Elektrifikatsiya.Database; namespace Elektrifikatsiya.Pages; public partial class Dashboard { - //TODO: insert new event here if plug produces one - List events = new List() { new Event("Text", "Text", DateTime.Today, null ) }; - //TODO: insert new Device here if user adds one - List plugs = new List(); - //code for graph - LineChart lineChart; + //TODO: insert new event here if plug produces one + private List events = new List() { new Event("Text", "Text", DateTime.Today, null) }; - protected override void OnInitialized() - { - plugs = DeviceStatusService.GetDevices().ValueOrDefault ?? new List(); - events = EventService.Events; + private List labels = new List(); - EventService.OnEventCalled += (_, e) => - { - _ = InvokeAsync(StateHasChanged); - }; - DeviceStatusService.OnDeviceStatusChanged += (_, e) => - { - _ = InvokeAsync(StateHasChanged); - }; - } + //code for graph + private LineChart lineChart; - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender) - { - await HandleRedraw(); - } - } + //TODO: insert new Device here if user adds one + private List plugs = new List(); - async Task HandleRedraw() - { - labels.Clear(); - await lineChart.Clear(); - await lineChart.AddLabelsDatasetsAndUpdate(labels, await GetLineChartDataset()); - } + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await HandleRedraw(); + } + } - //TODO: insert dataset of current and last voltage usages - async Task> GetLineChartDataset() - { - return new LineChartDataset - { - Label = "Wattage", - Data = await RandomizeData(), - Fill = true, - PointRadius = 3, - CubicInterpolationMode = "monotone", - }; - } + protected override void OnInitialized() + { + plugs = DeviceStatusService.GetDevices().ValueOrDefault ?? new List(); + events = EventService.Events; - List labels = new List(); + EventService.OnEventCalled += (_, e) => + { + _ = InvokeAsync(StateHasChanged); + }; + DeviceStatusService.OnDeviceStatusChanged += (_, e) => + { + _ = InvokeAsync(StateHasChanged); + }; + } - async Task> RandomizeData() - { - if (plugs.Count == 0) - { - return new(); - } - PrometheusQuery promQueryer = new PrometheusQuery("http://localhost:9090"); + private async Task> GetData() + { + if (plugs.Count == 0) + { + return new(); + } + PrometheusQuery promQueryer = new PrometheusQuery("http://localhost:9090"); - string plugnames = ""; - foreach (Device device in plugs) - { - plugnames += $"shellyplug-s-{device.MacAddress}/relay/0|"; - } - plugnames = plugnames[0..^1]; + string plugnames = ""; + foreach (Device device in plugs) + { + plugnames += $"shellyplug-s-{device.MacAddress}/relay/0|"; + } + plugnames = plugnames[0..^1]; - Debug.WriteLine($$"""sum(power{sensor=~"{{plugnames}}"})[1h:1m]"""); + double energyPrice = MainDatabaseContext.EnergyPriceChanges.OrderByDescending(e =>e.DateTime).FirstOrDefault()?.EnergyPrice ?? 0; - PrometheusDataWrapper? deviceData = (await promQueryer.Query($$"""sum(power{sensor=~"{{plugnames}}"})[1h:1m]"""))?.Data; + PrometheusDataWrapper? deviceData = (await promQueryer.Query($$"""sum(power{sensor=~"{{plugnames}}"})[1h:1m]"""))?.Data; + PrometheusDataWrapper? priceData = (await promQueryer.Query($$"""sum(sum_over_time(power{sensor=~"{{plugnames}}"}[1y])*{{energyPrice}})"""))?.Data; - var r = new Random(DateTime.Now.Millisecond); + Console.WriteLine(priceData.VectorTypeToTimestampFloatTuple()); - return deviceData?.MatrixTypeToTimestampFloatTuple().ValueOrDefault?.Select(x => - { - labels.Add(DateTimeOffset.FromUnixTimeSeconds(long.Parse($"1{x.Item1}0")).UtcDateTime.ToLocalTime().ToShortTimeString()); - return x.Item2; - }).ToList() ?? new List(); - } -} + var r = new Random(DateTime.Now.Millisecond); + + return deviceData?.MatrixTypeToTimestampFloatTuple().ValueOrDefault?.Select(x => + { + labels.Add(DateTimeOffset.FromUnixTimeSeconds(long.Parse($"1{x.Item1}0")).UtcDateTime.ToLocalTime().ToShortTimeString()); + return x.Item2; + }).ToList() ?? new List(); + } + + //TODO: insert dataset of current and last voltage usages + private async Task> GetLineChartDataset() + { + return new LineChartDataset + { + Label = "Wattage", + Data = await GetData(), + Fill = true, + PointRadius = 3, + CubicInterpolationMode = "monotone", + }; + } + + private async Task HandleRedraw() + { + labels.Clear(); + await lineChart.Clear(); + await lineChart.AddLabelsDatasetsAndUpdate(labels, await GetLineChartDataset()); + } + + private async Task Switch(Device device) + { + device.Enabled = !device.Enabled; + _ = await DeviceManagmentService.UpdateDevice(device); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Settings.razor b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Settings.razor index f55ddc8..4b68b99 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Settings.razor +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Pages/Settings.razor @@ -1,5 +1,6 @@ @page "/Settings" @using Blazorise.Components; +@using Elektrifikatsiya.Database; @using Elektrifikatsiya.Models; @using System.Net @using System.Text.Json @@ -9,6 +10,7 @@ @inject IDeviceManagmentService DeviceManagmentService @inject IMessageService MessageService +@inject MainDatabaseContext MainDatabaseContext
@@ -124,7 +126,7 @@ Here you enter your electricity price. This is gonna calculate the overall Price of your System - +
@@ -139,7 +141,9 @@ @code { List plugs = new List(); - private bool hideButtonSettings = true; + bool hideButtonSettings = true; + + double electricityPrice = 0; Device? SelectedDevice = null; Device? DeviceCopy = null; @@ -152,6 +156,8 @@ { plugs = getDevicesResult.Value; } + + electricityPrice = MainDatabaseContext.EnergyPriceChanges.OrderByDescending(e=>e.DateTime).FirstOrDefault()?.EnergyPrice ?? 0; } private void Toggle(Device device) @@ -161,16 +167,19 @@ DeviceCopy = device.CopyDevice(); } - private void OnSave() + private async void OnSave() { - if (hideButtonSettings || DeviceCopy is null || SelectedDevice is null) + if (hideButtonSettings) { + MainDatabaseContext.EnergyPriceChanges.Add(new EnergyPriceChange(electricityPrice)); + await MainDatabaseContext.SaveChangesAsync(); } - else + else if(DeviceCopy is not null && SelectedDevice is not null) { + SelectedDevice.OverwiteDevice(DeviceCopy); - DeviceManagmentService.UpdateDevice(SelectedDevice); + await DeviceManagmentService.UpdateDevice(SelectedDevice); } } diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs index e291139..8072e95 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs @@ -15,7 +15,8 @@ using HiveMQtt.Client.Options; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; - +using Prometheus; +using Prometheus.HttpMetrics; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); @@ -32,7 +33,7 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(s => s.GetRequiredService()); -builder.Services.AddSingleton(s=>s.GetRequiredService()); +builder.Services.AddSingleton(s => s.GetRequiredService()); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton((provider)=> @@ -44,7 +45,7 @@ builder.Services.AddSingleton((provider)=> UseTLS = false, }; - HiveMQClient client = new(options); + HiveMQClient client = new(options); client.ConnectAsync().ConfigureAwait(false); return client; }); @@ -60,7 +61,6 @@ builder.Services.AddBlazorise(options => options.Immediate = true; }); - AddBlazorise(builder.Services); WebApplication app = builder.Build(); @@ -81,6 +81,9 @@ app.UseRouting(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.MapControllers(); +app.MapMetrics(); + +app.UseHttpMetrics(); app.Services.GetRequiredService>().Value.CompileTemplates(); @@ -98,7 +101,7 @@ if (!mainDatabase.Users.Any()) app.Run(); -void AddBlazorise(IServiceCollection services) +static void AddBlazorise(IServiceCollection services) { _ = services.AddBlazorise(); _ = services.AddMaterialProviders(); diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/NotifcationService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/NotifcationService.cs index b87897b..12c6ff0 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/NotifcationService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/NotifcationService.cs @@ -4,7 +4,7 @@ namespace Elektrifikatsiya.Services.Implementations; public class NotifcationService : INotifcationService { - public TimeSpan ExecutionRepeatDelay => TimeSpan.FromSeconds(30); + public TimeSpan ExecutionRepeatDelay => TimeSpan.FromDays(1); public DateTime FirstExecutionTime => DateTime.Now.AddDays(0); private readonly IEmailService emailService; private readonly ILogger logger;