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] 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