From 6abd11ac86ab48a70569b850387d294db4d59886 Mon Sep 17 00:00:00 2001 From: Stefan-5422 <32109571+Stefan-5422@users.noreply.github.com> Date: Wed, 8 Feb 2023 08:03:51 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=A7=BEWhoop=20Whoop=20Database=20Time?= =?UTF-8?q?=20=F0=9F=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Database/DeviceManagementDatabaseContext.cs | 4 ++++ .../Elektrifikatsiya/Elektrifikatsiya.csproj | 1 + src/Elektrifikatsiya/Elektrifikatsiya/Program.cs | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs index f182b24..72891f0 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Database/DeviceManagementDatabaseContext.cs @@ -6,5 +6,9 @@ namespace Elektrifikatsiya.Database public class DeviceManagmentDatabaseContext : DbContext { public DbSet Devices { get; set; } + + public DeviceManagmentDatabaseContext(DbContextOptions options) : base(options) + { + } } } diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj b/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj index ff8eb7c..b1f24ea 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs index 44ecc11..6e8892e 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs @@ -1,12 +1,15 @@ using Blazorise; using Blazorise.Icons.Material; using Blazorise.Material; +using Elektrifikatsiya.Database; +using Microsoft.EntityFrameworkCore; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); +builder.Services.AddDbContext((options)=>options.UseSqlite("Data Source=./DeviceManagement.sqlite")); AddBlazorise(builder.Services); @@ -32,6 +35,11 @@ app.UseEndpoints(endpoints => _ = endpoints.MapFallbackToPage("/_Host"); }); +app.MapControllers(); + +AsyncServiceScope scope = app.Services.CreateAsyncScope(); +scope.ServiceProvider.GetRequiredService().Database.EnsureCreated(); + app.Run(); void AddBlazorise(IServiceCollection services) From ba6fdb3fdefb96072e0b23b968818b971b2a9bfb Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:19:07 +0100 Subject: [PATCH 2/3] Add device registration basics --- .../Elektrifikatsiya/Models/Device.cs | 23 +++-- .../Models/DeviceStatusChagedEventArgs.cs | 11 +++ .../Elektrifikatsiya/Program.cs | 30 +++---- .../Services/IDeviceManagmentService.cs | 22 +++++ .../Services/IDeviceStatusService.cs | 16 ++++ .../Implementations/DeviceManagmentService.cs | 85 +++++++++++++++++++ .../Implementations/DeviceStatusService.cs | 48 +++++++++++ .../Services/Implementations/UpdateService.cs | 62 ++++++++++++++ 8 files changed, 274 insertions(+), 23 deletions(-) create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs index 41f3f38..0bcca1a 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/Device.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using System.Net; namespace Elektrifikatsiya.Models; @@ -6,24 +7,30 @@ namespace Elektrifikatsiya.Models; public class Device { [Key] - public string Key { get; private set; } + public string MacAddress { get; private set; } [Required] - public string Name { get; private set; } + public string Name { get; set; } [Required] - public IPAddress Address { get; private set; } + public IPAddress IpAddress { get; set; } + [Required] + public User User { get; set; } + + [NotMapped] public int PowerUsage { get; set; } - public string User { get; set; } + public string Room { get; set; } - public Device(string key, string name, IPAddress address, int powerUsage, string user, string room) + [NotMapped] + public bool Available { get; set; } + + public Device(string macAddress, string name, IPAddress address, User user, string room) { - Key = key; + MacAddress = macAddress; Name = name; - Address = address; - PowerUsage = powerUsage; + IpAddress = address; User = user; Room = room; } diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs new file mode 100644 index 0000000..8b85cd5 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/DeviceStatusChagedEventArgs.cs @@ -0,0 +1,11 @@ +namespace Elektrifikatsiya.Models; + +public class DeviceStatusChagedEventArgs : EventArgs +{ + public string MacAddress { get; set; } + + public DeviceStatusChagedEventArgs(string macAddress) + { + MacAddress = macAddress; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs index 766474c..dfa27db 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Program.cs @@ -2,10 +2,10 @@ using Blazorise; using Blazorise.Bootstrap; using Blazorise.Icons.Material; using Blazorise.Material; -using Elektrifikatsiya.Database; -using Microsoft.EntityFrameworkCore; using Elektrifikatsiya.Database; +using Elektrifikatsiya.Services; +using Elektrifikatsiya.Services.Implementations; using Microsoft.EntityFrameworkCore; @@ -14,8 +14,16 @@ WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); +builder.Services.AddHostedService(); +builder.Services.AddSingleton(); +builder.Services.AddTransient(); builder.Services.AddDbContext(options => options.UseSqlite("Data Source=./UserDatabase.sqlite")); -builder.Services.AddDbContext((options)=>options.UseSqlite("Data Source=./DeviceManagement.sqlite")); +builder.Services.AddDbContext((options) => options.UseSqlite("Data Source=./DeviceManagement.sqlite")); +builder.Services.AddBootstrapProviders(); +builder.Services.AddBlazorise(options => +{ + options.Immediate = true; +}); AddBlazorise(builder.Services); @@ -49,15 +57,7 @@ app.Run(); void AddBlazorise(IServiceCollection services) { - _ = services - .AddBlazorise(); - _ = services - .AddMaterialProviders() - .AddMaterialIcons(); -} -builder.Services - .AddBlazorise(options => - { - options.Immediate = true; - }) - .AddBootstrapProviders(); \ No newline at end of file + _ = services.AddBlazorise(); + _ = services.AddMaterialProviders(); + _ = services.AddMaterialIcons(); +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs new file mode 100644 index 0000000..1da0c91 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs @@ -0,0 +1,22 @@ +using Elektrifikatsiya.Models; + +using FluentResults; + +using System.Net; + +namespace Elektrifikatsiya.Services; + +public interface IDeviceManagmentService +{ + public Task> Register(IPAddress ip, User user, string? name = null, string room = "default"); + + public Task UnRegister(string macAdress); + + public Result GetDevice(string macAdress); + + public Result> GetDevices(); + + public Result> GetDevicesInRoom(string room); + + public Result> GetDevicesOfUser(int userId); +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs new file mode 100644 index 0000000..ef7fab3 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs @@ -0,0 +1,16 @@ +using Elektrifikatsiya.Models; + +using FluentResults; + +namespace Elektrifikatsiya.Services; + +public interface IDeviceStatusService +{ + public event EventHandler OnDeviceStatusChanged; + + public Result> GetDevices(); + + public Result UpdateDeviceStatus(Device device); + + public Result TrackDevice(Device device); +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs new file mode 100644 index 0000000..75e9a65 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs @@ -0,0 +1,85 @@ +using Elektrifikatsiya.Database; +using Elektrifikatsiya.Models; + +using FluentResults; + +using System.Net; + +namespace Elektrifikatsiya.Services.Implementations; + +public class DeviceManagmentService : IDeviceManagmentService +{ + private readonly DeviceManagmentDatabaseContext deviceManagmentDatabaseContext; + private readonly IDeviceStatusService deviceStatusService; + + public DeviceManagmentService(DeviceManagmentDatabaseContext deviceManagmentDatabaseContext, IDeviceStatusService deviceStatusService) + { + this.deviceManagmentDatabaseContext = deviceManagmentDatabaseContext; + this.deviceStatusService = deviceStatusService; + } + + public Result GetDevice(string macAdress) + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + Device? device = getDevicesResult.Value.FirstOrDefault(d => d.MacAddress == macAdress); + + if (device is null) + { + return Result.Fail("Device does not exist!"); + } + + return device; + } + + public Result> GetDevices() + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + return getDevicesResult.Value.ToList(); + } + + public Result> GetDevicesInRoom(string room) + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + return getDevicesResult.Value.Where(d => d.Room == room).ToList(); + } + + public Result> GetDevicesOfUser(int userId) + { + Result> getDevicesResult = deviceStatusService.GetDevices(); + + if (getDevicesResult.IsFailed) + { + return getDevicesResult.ToResult(); + } + + return getDevicesResult.Value.Where(d => d.User.Id == userId).ToList(); + } + + public Task> Register(IPAddress ip, User user, string? name = null, string room = "default") + { + throw new NotImplementedException(); + } + + public Task UnRegister(string macAdress) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs new file mode 100644 index 0000000..8b4263e --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs @@ -0,0 +1,48 @@ +using Elektrifikatsiya.Models; + +using FluentResults; + +namespace Elektrifikatsiya.Services.Implementations; + +public class DeviceStatusService : IDeviceStatusService +{ + public event EventHandler? OnDeviceStatusChanged; + + private readonly Dictionary devices = new(); + + public Result> GetDevices() + { + return devices.Values.ToList(); + } + + public Result UpdateDeviceStatus(Device device) + { + Device? modDevice = devices.GetValueOrDefault(device.MacAddress); + + if (modDevice is null) + { + return Result.Fail("Device not tracked!"); + } + + modDevice.PowerUsage = device.PowerUsage; + modDevice.Available = device.Available; + modDevice.IpAddress = device.IpAddress; + modDevice.Name = device.Name; + + OnDeviceStatusChanged?.Invoke(this, new DeviceStatusChagedEventArgs(device.MacAddress)); + + return Result.Ok(); + } + + public Result TrackDevice(Device device) + { + if (devices.ContainsKey(device.MacAddress)) + { + return Result.Fail("Device already tracked!"); + } + + devices[device.MacAddress] = device; + + return Result.Ok(); + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs new file mode 100644 index 0000000..6271a23 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs @@ -0,0 +1,62 @@ +using Elektrifikatsiya.Database; +using Elektrifikatsiya.Models; + +using Microsoft.EntityFrameworkCore; + +namespace Elektrifikatsiya.Services.Implementations; + +public class UpdateService : IHostedService, IDisposable +{ + private readonly ILogger logger; + private readonly IDeviceStatusService deviceStatusService; + private readonly DeviceManagmentDatabaseContext deviceManagmentDatabaseContext; + private Timer? timer = null; + + public UpdateService(ILogger logger, IDeviceStatusService deviceStatusService, DeviceManagmentDatabaseContext deviceManagmentDatabaseContext) + { + this.logger = logger; + this.deviceStatusService = deviceStatusService; + this.deviceManagmentDatabaseContext = deviceManagmentDatabaseContext; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + logger.LogInformation("Starting update service..."); + + foreach (Device device in await deviceManagmentDatabaseContext.Devices.AsNoTracking().ToListAsync(cancellationToken)) + { + _ = deviceStatusService.TrackDevice(device); + } + + timer = new Timer(Update, null, TimeSpan.Zero, TimeSpan.FromSeconds(15)); + + logger.LogInformation("Update service started."); + } + + private void Update(object? state) + { + //TODO: Update all devices. + } + + 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(); + } +} \ No newline at end of file From 22c4fe1a26a91b7d325150b70dd40549df82c6b5 Mon Sep 17 00:00:00 2001 From: Stefan <32109571+Stefan-5422@users.noreply.github.com> Date: Wed, 1 Mar 2023 11:16:06 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=E0=BC=BC=20=E3=81=A4=20=E2=97=95=5F?= =?UTF-8?q?=E2=97=95=20=E0=BC=BD=E3=81=A4=20Some=20backend=20stuff=20mostl?= =?UTF-8?q?y=20for=20Registration=20=F0=9F=AA=B5=F0=9F=AA=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Elektrifikatsiya/Elektrifikatsiya.csproj | 14 +++- .../Models/PrometheusQueryResult.cs | 73 +++++++++++++++++++ .../Elektrifikatsiya/Models/ShellyResponse.cs | 13 ++++ .../Services/IDeviceManagmentService.cs | 2 +- .../Services/IDeviceStatusService.cs | 2 + .../Implementations/DeviceManagmentService.cs | 50 +++++++++++-- .../Implementations/DeviceStatusService.cs | 5 ++ .../Services/Implementations/UpdateService.cs | 19 ++++- .../Utilities/PrometheusQuery.cs | 25 +++++++ 9 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs create mode 100644 src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj b/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj index 9d16e3c..4dca5d7 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Elektrifikatsiya.csproj @@ -18,12 +18,21 @@ + + + + + + + + + @@ -35,10 +44,7 @@ - - - - + diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs new file mode 100644 index 0000000..9732592 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/PrometheusQueryResult.cs @@ -0,0 +1,73 @@ +using System.Text.Json.Serialization; + +namespace Elektrifikatsiya.Models; + +public enum Status +{ + Success, + Error +} + +public enum ResultType +{ + Matrix, + Vector, + Scalar, + String +} + +public class PrometheusQueryResult +{ + public Status Status { get; set; } + + public string? ErrorType { get; set; } + public string? Error { get; set; } + public List? Warnings { get; set; } + + public PrometheusQueryResult(Status status, string? errorType, string? error, List? warnings) + { + Status = status; + ErrorType = errorType; + Error = error; + Warnings = warnings; + } +} + +internal class PrometheusDataWrapper +{ + public ResultType ResultType { get; set; } + public List Result { get; set; } + + public PrometheusDataWrapper(ResultType resultType, List result) + { + ResultType = resultType; + Result = result; + } +} + +internal class PrometheusDataMetric +{ + [JsonPropertyName("__name__")] public string Name { get; set; } + + public string Job { get; set; } + public string Instance { get; set; } + + public PrometheusDataMetric(string name, string job, string instance) + { + Name = name; + Job = job; + Instance = instance; + } +} + +internal class PrometheusData +{ + public PrometheusDataMetric Metric { get; set; } + public object Value { get; set; } + + public PrometheusData(PrometheusDataMetric metric, object value) + { + Metric = metric; + Value = value; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs new file mode 100644 index 0000000..bf6cd03 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Models/ShellyResponse.cs @@ -0,0 +1,13 @@ +namespace Elektrifikatsiya.Models; + +public class ShellyResponse +{ + public string Type { get; set; } + public string Mac { get; set; } + + public ShellyResponse(string type, string mac) + { + Type = type; + Mac = mac; + } +} \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs index 1da0c91..bda0e67 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceManagmentService.cs @@ -10,7 +10,7 @@ public interface IDeviceManagmentService { public Task> Register(IPAddress ip, User user, string? name = null, string room = "default"); - public Task UnRegister(string macAdress); + public Task Unregister(string macAdress); public Result GetDevice(string macAdress); diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs index ef7fab3..61e1cc1 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/IDeviceStatusService.cs @@ -13,4 +13,6 @@ public interface IDeviceStatusService public Result UpdateDeviceStatus(Device device); public Result TrackDevice(Device device); + + public Result UntrackDevice(string macAddress); } \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs index 75e9a65..b659cf1 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceManagmentService.cs @@ -4,6 +4,7 @@ using Elektrifikatsiya.Models; using FluentResults; using System.Net; +using System.Net.NetworkInformation; namespace Elektrifikatsiya.Services.Implementations; @@ -11,11 +12,13 @@ public class DeviceManagmentService : IDeviceManagmentService { private readonly DeviceManagmentDatabaseContext deviceManagmentDatabaseContext; private readonly IDeviceStatusService deviceStatusService; + private readonly HttpClient httpClient; - public DeviceManagmentService(DeviceManagmentDatabaseContext deviceManagmentDatabaseContext, IDeviceStatusService deviceStatusService) + public DeviceManagmentService(DeviceManagmentDatabaseContext deviceManagmentDatabaseContext, IDeviceStatusService deviceStatusService, HttpClient httpClient) { this.deviceManagmentDatabaseContext = deviceManagmentDatabaseContext; this.deviceStatusService = deviceStatusService; + this.httpClient = httpClient; } public Result GetDevice(string macAdress) @@ -73,13 +76,50 @@ public class DeviceManagmentService : IDeviceManagmentService return getDevicesResult.Value.Where(d => d.User.Id == userId).ToList(); } - public Task> Register(IPAddress ip, User user, string? name = null, string room = "default") + public async Task> Register(IPAddress ip, User user, string? name = null, string room = "default") { - throw new NotImplementedException(); + ShellyResponse? shellyResponse = await httpClient.GetFromJsonAsync($"{ip}/shelly"); + + if(shellyResponse is null || shellyResponse.Type != "SHPLG-S") + { + return Result.Fail("Device is not a \"SHPLG-S\" or not reachable!"); + } + + string mac = shellyResponse.Mac; + + if(PhysicalAddress.TryParse(mac, out _)) + { + return Result.Fail("Invalid mac address!"); + } + + Device device = new Device(mac, name ?? mac, ip, user, room); + + deviceManagmentDatabaseContext.Add(device); + Result saveDatabaseChangesResult = await Result.Try(async Task () => await deviceManagmentDatabaseContext.SaveChangesAsync()); + + Result trackDeviceResult = deviceStatusService.TrackDevice(device); + + return Result.Merge(saveDatabaseChangesResult, trackDeviceResult).ToResult(device); } - public Task UnRegister(string macAdress) + public async Task Unregister(string macAdress) { - throw new NotImplementedException(); + Result getDeviceResult = GetDevice(macAdress); + + if (getDeviceResult.IsFailed) + { + return getDeviceResult.ToResult(); + } + + Result untrackDeviceResult = deviceStatusService.UntrackDevice(macAdress); + + if (untrackDeviceResult.IsFailed) + { + return untrackDeviceResult; + } + + deviceManagmentDatabaseContext.Remove(getDeviceResult.Value); + + return await Result.Try(async Task () => await deviceManagmentDatabaseContext.SaveChangesAsync()); } } \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs index 8b4263e..3574cec 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/DeviceStatusService.cs @@ -45,4 +45,9 @@ public class DeviceStatusService : IDeviceStatusService return Result.Ok(); } + + public Result UntrackDevice(string macAddress) + { + return devices.Remove(macAddress) ? Result.Ok() : Result.Fail("Device is not tracked!"); + } } \ No newline at end of file diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs index 6271a23..980826d 100644 --- a/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Services/Implementations/UpdateService.cs @@ -1,7 +1,8 @@ using Elektrifikatsiya.Database; using Elektrifikatsiya.Models; - +using FluentResults; using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; namespace Elektrifikatsiya.Services.Implementations; @@ -28,14 +29,24 @@ public class UpdateService : IHostedService, IDisposable _ = deviceStatusService.TrackDevice(device); } - timer = new Timer(Update, null, TimeSpan.Zero, TimeSpan.FromSeconds(15)); + timer = new Timer(async (_) => await Update(), null, TimeSpan.Zero, TimeSpan.FromSeconds(15)); logger.LogInformation("Update service started."); } - private void Update(object? state) + private async Task Update() { - //TODO: Update all devices. + Result> getDeviceStatusResult = deviceStatusService.GetDevices(); + + if (getDeviceStatusResult.IsFailed) + { + logger.LogError("Updating devices failed!"); + } + + foreach(Device device in getDeviceStatusResult.Value) + { + //TODO: Some update magic + } } public Task StopAsync(CancellationToken cancellationToken) diff --git a/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs b/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs new file mode 100644 index 0000000..a635857 --- /dev/null +++ b/src/Elektrifikatsiya/Elektrifikatsiya/Utilities/PrometheusQuery.cs @@ -0,0 +1,25 @@ +using System.Net; +using System.Net.Sockets; +using System.Text.Encodings.Web; +using System.Text.Json; +using Elektrifikatsiya.Models; +using FluentResults; + +namespace Elektrifikatsiya.Utilities; + +public class PrometheusQuery +{ + private string connectionString; + private readonly HttpClient client = new(); + + public PrometheusQuery(string connectionString) + { + this.connectionString = connectionString; + client.BaseAddress = new Uri(connectionString); + } + + public Task Query(string query) + { + return client.GetFromJsonAsync($"/v1/query?{UrlEncoder.Create().Encode(query)}"); + } +} \ No newline at end of file