using System.Net; using adas_core.module.ProxyDevices.Devices; using Microsoft.Extensions.Options; namespace adas_core.module.ProxyDevices.Services; /// /// ProxyDeviceService is responsible for managing proxy devices, processing requests, and streaming data from the devices. /// It uses a cache to store device instances for efficient retrieval and ensures that only enabled devices are processed. /// The service handles HTTP requests and returns appropriate responses based on the device's availability and functionality. /// /// The settings for the proxy devices, including their configuration and parameters. public class ProxyDeviceService(IOptions settings) : IProxyDeviceService { /// /// _cache is a dictionary that stores instances of IProxyDevice, keyed by their deviceId. /// private readonly Dictionary _cache = new(); /// /// Process method takes a deviceId as input, retrieves the corresponding device from the cache or creates a new instance if it doesn't exist, and then calls the Process method of the device. /// It returns an HttpResponseMessage based on the outcome of the operation, handling any exceptions that may occur during the process. /// /// The unique identifier of the proxy device to be processed. /// A task that represents the asynchronous operation. The task result contains the HttpResponseMessage returned by the device's Process method. public async Task Process(string deviceId) { try { var device = GetDevice(deviceId); if (device == null) return new HttpResponseMessage(HttpStatusCode.NotFound) { ReasonPhrase = $"Proxy device not found. deviceId:{deviceId}" }; return await device.Process(); } catch (HttpRequestException e) { return new HttpResponseMessage(e.StatusCode ?? HttpStatusCode.NotFound) { ReasonPhrase = e.Message }; } } /// /// Stream method takes a deviceId as input, retrieves the corresponding device from the cache or creates a new instance if it doesn't exist, and then calls the Stream method of the device. /// /// The unique identifier of the proxy device to be streamed. /// A task that represents the asynchronous operation. The task result contains the HttpResponseMessage returned by the device's Stream method. public async Task Stream(string deviceId) { try { var device = GetDevice(deviceId); if (device == null) return new HttpResponseMessage(HttpStatusCode.NotFound) { ReasonPhrase = $"Proxy device not found. deviceId:{deviceId}" }; return await device.Stream(); } catch (HttpRequestException e) { return new HttpResponseMessage(e.StatusCode ?? HttpStatusCode.NotFound) { ReasonPhrase = e.Message }; } } /// /// Retrieves the proxy device instance corresponding to the given deviceId. If the device is not found or not enabled, an HttpRequestException is thrown. /// /// The unique identifier of the proxy device to be retrieved. /// The proxy device instance corresponding to the given deviceId. /// Thrown when the device is not found or not enabled. private IProxyDevice? GetDevice(string deviceId) { var device = settings.Value.FirstOrDefault(d => d.Id == deviceId); if (device is not { Enabled: true }) throw new HttpRequestException("Device not found or not enabled", null, HttpStatusCode.NotFound); IProxyDevice? deviceInstance = null; lock (_cache) { if (_cache.TryGetValue(deviceId, out var value)) { deviceInstance = value; } else { var deviceType = Type.GetType("adas_core.module.ProxyDevices.Devices." + device.Type + "Device") ?? throw new HttpRequestException("Device not implemented", null, HttpStatusCode.NotImplemented); var instance = Activator.CreateInstance(deviceType); if (instance is IProxyDevice proxyDevice) { deviceInstance = proxyDevice; deviceInstance.Initialize(device.Parameters); } _cache.Add(deviceId, deviceInstance); } } return deviceInstance; } }