Fully implemented the surface service which contains all storage logic

This commit is contained in:
Robert committed 2019-10-22 22:19:35 +02:00
1 parent 4e2afad268
commit 91cd23dadf
8 files changed
+284 -117

No files matched your search

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Artemis.Core.Events;
using Artemis.Core.Models.Surface;
using Artemis.Core.Services.Interfaces;
namespace Artemis.Core.Services.Storage
{
public interface ISurfaceService : IArtemisService
{
/// <summary>
/// Gets or sets the currently active surface configuration
/// </summary>
SurfaceConfiguration ActiveSurfaceConfiguration { get; set; }
/// <summary>
/// Gets a read-only list of all surface configurations
/// </summary>
ReadOnlyCollection<SurfaceConfiguration> SurfaceConfigurations { get; }
/// <summary>
/// Creates a new surface configuration with the supplied name
/// </summary>
/// <param name="name">The name for the new surface configuration</param>
/// <returns></returns>
SurfaceConfiguration CreateSurfaceConfiguration(string name);
/// <summary>
/// Deletes the supplied surface configuration, surface configuration may not be the active surface configuration
/// </summary>
/// <param name="surfaceConfiguration">The surface configuration to delete, may not be the active surface configuration</param>
void DeleteSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration);
/// <summary>
/// Saves the provided surface configurations to permanent storage
/// </summary>
/// <param name="surfaceConfigurations">The configurations to save</param>
/// <param name="includeDevices">Whether to also save devices</param>
void SaveToRepository(List<SurfaceConfiguration> surfaceConfigurations, bool includeDevices);
/// <summary>
/// Saves the provided surface configuration to permanent storage
/// </summary>
/// <param name="surfaceConfiguration">The configuration to save</param>
/// <param name="includeDevices">Whether to also save devices</param>
void SaveToRepository(SurfaceConfiguration surfaceConfiguration, bool includeDevices);
/// <summary>
/// Occurs when the active device configuration has been changed
/// </summary>
event EventHandler<SurfaceConfigurationEventArgs> ActiveSurfaceConfigurationChanged;
}
}
@@ -1,8 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core.Events;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Surface;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Repositories.Interfaces;
@@ -14,100 +15,155 @@ namespace Artemis.Core.Services.Storage
public class SurfaceService : ISurfaceService
{
private readonly ILogger _logger;
private readonly ISurfaceRepository _surfaceRepository;
private readonly IRgbService _rgbService;
private readonly List<SurfaceConfiguration> _surfaceConfigurations;
private readonly ISurfaceRepository _surfaceRepository;
private SurfaceConfiguration _activeSurfaceConfiguration;
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService)
{
_logger = logger;
_surfaceRepository = surfaceRepository;
_rgbService = rgbService;
_surfaceConfigurations = new List<SurfaceConfiguration>();
LoadFromRepository();
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
}
public async Task<List<SurfaceConfiguration>> GetSurfaceConfigurationsAsync()
public SurfaceConfiguration ActiveSurfaceConfiguration
{
var surfaceEntities = await _surfaceRepository.GetAllAsync();
var configs = new List<SurfaceConfiguration>();
foreach (var surfaceEntity in surfaceEntities)
configs.Add(new SurfaceConfiguration(surfaceEntity));
get => _activeSurfaceConfiguration;
set
{
if (_activeSurfaceConfiguration == value)
return;
return configs;
_activeSurfaceConfiguration = value;
// Mark only the new value as active
foreach (var surfaceConfiguration in _surfaceConfigurations)
surfaceConfiguration.IsActive = false;
_activeSurfaceConfiguration.IsActive = true;
SaveToRepository(_surfaceConfigurations, true);
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(_activeSurfaceConfiguration));
}
}
public async Task<SurfaceConfiguration> GetActiveSurfaceConfigurationAsync()
{
var entity = (await _surfaceRepository.GetAllAsync()).FirstOrDefault(d => d.IsActive);
return entity != null ? new SurfaceConfiguration(entity) : null;
}
public async Task SetActiveSurfaceConfigurationAsync(SurfaceConfiguration surfaceConfiguration)
{
var surfaceEntities = await _surfaceRepository.GetAllAsync();
foreach (var surfaceEntity in surfaceEntities)
surfaceEntity.IsActive = surfaceEntity.Guid == surfaceConfiguration.Guid;
await _surfaceRepository.SaveAsync();
}
public List<SurfaceConfiguration> GetSurfaceConfigurations()
{
var surfaceEntities = _surfaceRepository.GetAll();
var configs = new List<SurfaceConfiguration>();
foreach (var surfaceEntity in surfaceEntities)
configs.Add(new SurfaceConfiguration(surfaceEntity));
return configs;
}
public SurfaceConfiguration GetActiveSurfaceConfiguration()
{
var entity = _surfaceRepository.GetAll().FirstOrDefault(d => d.IsActive);
return entity != null ? new SurfaceConfiguration(entity) : null;
}
public void SetActiveSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration)
{
var surfaceEntities = _surfaceRepository.GetAll();
foreach (var surfaceEntity in surfaceEntities)
surfaceEntity.IsActive = surfaceEntity.Guid == surfaceConfiguration.Guid;
_surfaceRepository.Save();
}
public ReadOnlyCollection<SurfaceConfiguration> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly();
public SurfaceConfiguration CreateSurfaceConfiguration(string name)
{
// Create a blank config
var configuration = new SurfaceConfiguration {Name = name, DeviceConfigurations = new List<SurfaceDeviceConfiguration>()};
var configuration = new SurfaceConfiguration(name);
// Add all current devices
foreach (var rgbDevice in _rgbService.LoadedDevices)
{
var deviceId = GetDeviceId(rgbDevice);
configuration.DeviceConfigurations.Add(new SurfaceDeviceConfiguration(deviceId, rgbDevice.DeviceInfo, configuration));
configuration.DeviceConfigurations.Add(new SurfaceDeviceConfiguration(rgbDevice, deviceId, configuration));
}
_surfaceRepository.Add(configuration.SurfaceEntity);
SaveToRepository(configuration, true);
return configuration;
}
private void ApplyDeviceConfiguration(IRGBDevice rgbDevice, SurfaceConfiguration surface)
public void DeleteSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration)
{
if (surfaceConfiguration == ActiveSurfaceConfiguration)
throw new ArtemisCoreException($"Cannot delete surface configuration '{surfaceConfiguration.Name}' because it is active.");
surfaceConfiguration.Destroy();
_surfaceConfigurations.Remove(surfaceConfiguration);
_surfaceRepository.Remove(surfaceConfiguration.SurfaceEntity);
_surfaceRepository.Save();
}
#region Event handlers
private void RgbServiceOnDeviceLoaded(object sender, DeviceEventArgs e)
{
// Match the newly loaded device with the current config
if (ActiveSurfaceConfiguration != null)
MatchDeviceConfiguration(e.Device, ActiveSurfaceConfiguration);
}
#endregion
#region Repository
private void LoadFromRepository()
{
var configs = _surfaceRepository.GetAll();
foreach (var surfaceEntity in configs)
{
// Create the surface configuration
var surfaceConfiguration = new SurfaceConfiguration(surfaceEntity);
// For each loaded device, match a device configuration
var devices = _rgbService.LoadedDevices;
foreach (var rgbDevice in devices)
MatchDeviceConfiguration(rgbDevice, surfaceConfiguration);
// Finally, add the surface config to the collection
_surfaceConfigurations.Add(surfaceConfiguration);
}
// When all surface configs are loaded, apply the active surface config
var active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
if (active != null)
ActiveSurfaceConfiguration = active;
}
public void SaveToRepository(List<SurfaceConfiguration> surfaceConfigurations, bool includeDevices)
{
foreach (var surfaceConfiguration in surfaceConfigurations)
{
surfaceConfiguration.ApplyToEntity();
if (!includeDevices)
{
foreach (var deviceConfiguration in surfaceConfiguration.DeviceConfigurations)
deviceConfiguration.ApplyToEntity();
}
}
_surfaceRepository.Save();
}
public void SaveToRepository(SurfaceConfiguration surfaceConfiguration, bool includeDevices)
{
surfaceConfiguration.ApplyToEntity();
if (includeDevices)
{
foreach (var deviceConfiguration in surfaceConfiguration.DeviceConfigurations)
deviceConfiguration.ApplyToEntity();
}
_surfaceRepository.Save();
}
#endregion
#region Utilities
private void MatchDeviceConfiguration(IRGBDevice rgbDevice, SurfaceConfiguration surfaceConfiguration)
{
var deviceId = GetDeviceId(rgbDevice);
var deviceConfig = surface.DeviceConfigurations.FirstOrDefault(d => d.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
d.DeviceModel == rgbDevice.DeviceInfo.Model &&
d.DeviceManufacturer == rgbDevice.DeviceInfo.Manufacturer &&
d.DeviceId == deviceId);
var deviceConfig = surfaceConfiguration.DeviceConfigurations.FirstOrDefault(d => d.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
d.DeviceModel == rgbDevice.DeviceInfo.Model &&
d.DeviceManufacturer == rgbDevice.DeviceInfo.Manufacturer &&
d.DeviceId == deviceId);
if (deviceConfig == null)
{
_logger.Information("No active surface config found for {deviceInfo}, device ID: {deviceId}. Adding a new entry.", rgbDevice.DeviceInfo, deviceId);
deviceConfig = new SurfaceDeviceConfiguration(deviceId, rgbDevice.DeviceInfo, surface);
surface.DeviceConfigurations.Add(deviceConfig);
deviceConfig = new SurfaceDeviceConfiguration(rgbDevice, deviceId, surfaceConfiguration);
surfaceConfiguration.DeviceConfigurations.Add(deviceConfig);
}
rgbDevice.Location = new Point(deviceConfig.X, deviceConfig.Y);
OnDeviceConfigurationApplied(new SurfaceConfigurationEventArgs(surface, rgbDevice));
deviceConfig.ApplyToDevice();
}
private int GetDeviceId(IRGBDevice rgbDevice)
@@ -120,43 +176,17 @@ namespace Artemis.Core.Services.Storage
.IndexOf(rgbDevice) + 1;
}
private void RgbServiceOnDeviceLoaded(object sender, DeviceEventArgs e)
{
var activeConfiguration = GetActiveSurfaceConfiguration();
if (activeConfiguration == null)
{
_logger.Information("No active surface config found, cannot apply settings to {deviceInfo}", e.Device.DeviceInfo);
return;
}
ApplyDeviceConfiguration(e.Device, GetActiveSurfaceConfiguration());
}
#endregion
#region Events
public event EventHandler<SurfaceConfigurationEventArgs> SurfaceConfigurationApplied;
public event EventHandler<SurfaceConfigurationEventArgs> ActiveSurfaceConfigurationChanged;
private void OnDeviceConfigurationApplied(SurfaceConfigurationEventArgs e)
protected virtual void OnActiveSurfaceConfigurationChanged(SurfaceConfigurationEventArgs e)
{
SurfaceConfigurationApplied?.Invoke(this, e);
ActiveSurfaceConfigurationChanged?.Invoke(this, e);
}
#endregion
}
public interface ISurfaceService : IArtemisService
{
Task<List<SurfaceConfiguration>> GetSurfaceConfigurationsAsync();
Task<SurfaceConfiguration> GetActiveSurfaceConfigurationAsync();
Task SetActiveSurfaceConfigurationAsync(SurfaceConfiguration surfaceConfiguration);
List<SurfaceConfiguration> GetSurfaceConfigurations();
SurfaceConfiguration GetActiveSurfaceConfiguration();
SurfaceConfiguration CreateSurfaceConfiguration(string name);
void SetActiveSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration);
/// <summary>
/// Occurs when a device has a new surface configuration applied to it
/// </summary>
event EventHandler<SurfaceConfigurationEventArgs> SurfaceConfigurationApplied;
}
}