// ReSharper disable MemberCanBePrivate.Global using System; using System.Collections.Generic; using System.Threading; using RGB.NET.Core; namespace RGB.NET.Devices.WLED; /// /// /// Represents a device provider responsible for WS2812B- and WS2811-Led-devices. /// // ReSharper disable once InconsistentNaming // ReSharper disable once UnusedType.Global public sealed class WledDeviceProvider : AbstractRGBDeviceProvider { #region Constants private const int HEARTBEAT_TIMER = 250; #endregion #region Properties & Fields // ReSharper disable once InconsistentNaming private static readonly Lock _lock = new(); private static WledDeviceProvider? _instance; /// /// Gets the singleton instance. /// public static WledDeviceProvider Instance { get { lock (_lock) return _instance ?? new WledDeviceProvider(); } } /// /// Gets a list of all defined device-definitions. /// public List DeviceDefinitions { get; } = []; #endregion #region Constructors /// /// Initializes a new instance of the class. /// /// Thrown if this constructor is called even if there is already an instance of this class. public WledDeviceProvider() { lock (_lock) { if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WledDeviceProvider)}"); _instance = this; } } #endregion #region Methods /// /// Adds the specified to this device-provider. /// /// The to add. public void AddDeviceDefinition(IWledDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition); /// protected override void InitializeSDK() { } /// protected override IEnumerable LoadDevices() { int i = 0; foreach (IWledDeviceDefinition deviceDefinition in DeviceDefinitions) { IDeviceUpdateTrigger updateTrigger = GetUpdateTrigger(i++); WledRGBDevice? device = CreateWledDevice(deviceDefinition, updateTrigger); if (device != null) yield return device; } } private static WledRGBDevice? CreateWledDevice(IWledDeviceDefinition deviceDefinition, IDeviceUpdateTrigger updateTrigger) { WledInfo? wledInfo = WledAPI.Info(deviceDefinition.Address); if (wledInfo == null) return null; return new WledRGBDevice(new WledRGBDeviceInfo(wledInfo, deviceDefinition.Manufacturer, deviceDefinition.Model), deviceDefinition.Address, updateTrigger); } protected override IDeviceUpdateTrigger CreateUpdateTrigger(int id, double updateRateHardLimit) => new DeviceUpdateTrigger(updateRateHardLimit) { HeartbeatTimer = HEARTBEAT_TIMER }; /// protected override void Dispose(bool disposing) { lock (_lock) { base.Dispose(disposing); DeviceDefinitions.Clear(); _instance = null; } } #endregion }