mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-08-31 19:08:29 +00:00
refactor: Refactor DeviceManager and related classes to improve thread safety and performance
- Replaced CCriticalSection with lock statements in DeviceManager for better thread management. - Updated AddDevice and RemoveDevice methods to use Monitor for locking. - Enhanced event handling for device activation and registration. - Modified FileIO class to utilize Task for asynchronous file operations instead of CrestronInvoke. - Improved feedback mechanisms in FeedbackBase and SystemMonitorController using Task.Run. - Refactored GenericQueue to remove Crestron threading dependencies and utilize System.Threading. - Updated BlueJeansPc and VideoCodecBase classes to use Task for asynchronous operations. - Cleaned up unnecessary critical sections and improved code documentation across various files.
This commit is contained in:
parent
426ef4ad6b
commit
346a5e9e57
23 changed files with 998 additions and 912 deletions
|
|
@ -3,287 +3,250 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Formatting = NewtonsoftJson::Newtonsoft.Json.Formatting;
|
||||
using JsonConvert = NewtonsoftJson::Newtonsoft.Json.JsonConvert;
|
||||
using JObject = NewtonsoftJson::Newtonsoft.Json.Linq.JObject;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
using PepperDash.Core.Logging;
|
||||
|
||||
namespace PepperDash.Core.Web;
|
||||
|
||||
/// <summary>
|
||||
/// Web API server
|
||||
/// </summary>
|
||||
public class WebApiServer : IKeyName
|
||||
{
|
||||
private const string SplusKey = "Uninitialized Web API Server";
|
||||
private const string DefaultName = "Web API Server";
|
||||
private const string DefaultBasePath = "/api";
|
||||
|
||||
private readonly object _serverLock = new();
|
||||
private HttpCwsServer _server;
|
||||
|
||||
/// <summary>
|
||||
/// Web API server
|
||||
/// Gets or sets the Key
|
||||
/// </summary>
|
||||
public class WebApiServer : IKeyName
|
||||
public string Key { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Name
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BasePath
|
||||
/// </summary>
|
||||
public string BasePath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IsRegistered
|
||||
/// </summary>
|
||||
public bool IsRegistered { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for S+. Make sure to set necessary properties using init method
|
||||
/// </summary>
|
||||
public WebApiServer()
|
||||
: this(SplusKey, DefaultName, null)
|
||||
{
|
||||
private const string SplusKey = "Uninitialized Web API Server";
|
||||
private const string DefaultName = "Web API Server";
|
||||
private const string DefaultBasePath = "/api";
|
||||
}
|
||||
|
||||
private const uint DebugTrace = 0;
|
||||
private const uint DebugInfo = 1;
|
||||
private const uint DebugVerbose = 2;
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="basePath"></param>
|
||||
public WebApiServer(string key, string basePath)
|
||||
: this(key, DefaultName, basePath)
|
||||
{
|
||||
}
|
||||
|
||||
private readonly CCriticalSection _serverLock = new CCriticalSection();
|
||||
private HttpCwsServer _server;
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="basePath"></param>
|
||||
public WebApiServer(string key, string name, string basePath)
|
||||
{
|
||||
Key = key;
|
||||
Name = string.IsNullOrEmpty(name) ? DefaultName : name;
|
||||
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Key
|
||||
/// </summary>
|
||||
public string Key { get; private set; }
|
||||
if (_server == null) _server = new HttpCwsServer(BasePath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Name
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
_server.setProcessName(Key);
|
||||
_server.HttpRequestHandler = new DefaultRequestHandler();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BasePath
|
||||
/// </summary>
|
||||
public string BasePath { get; private set; }
|
||||
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
|
||||
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IsRegistered
|
||||
/// </summary>
|
||||
public bool IsRegistered { get; private set; }
|
||||
/// <summary>
|
||||
/// Program status event handler
|
||||
/// </summary>
|
||||
/// <param name="programEventType"></param>
|
||||
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||
{
|
||||
if (programEventType != eProgramStatusEventType.Stopping) return;
|
||||
|
||||
/// <summary>
|
||||
/// Http request handler
|
||||
/// </summary>
|
||||
//public IHttpCwsHandler HttpRequestHandler
|
||||
//{
|
||||
// get { return _server.HttpRequestHandler; }
|
||||
// set
|
||||
// {
|
||||
// if (_server == null) return;
|
||||
// _server.HttpRequestHandler = value;
|
||||
// }
|
||||
//}
|
||||
this.LogInformation("Program stopping. stopping server");
|
||||
|
||||
/// <summary>
|
||||
/// Received request event handler
|
||||
/// </summary>
|
||||
//public event EventHandler<HttpCwsRequestEventArgs> ReceivedRequestEvent
|
||||
//{
|
||||
// add { _server.ReceivedRequestEvent += new HttpCwsRequestEventHandler(value); }
|
||||
// remove { _server.ReceivedRequestEvent -= new HttpCwsRequestEventHandler(value); }
|
||||
//}
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for S+. Make sure to set necessary properties using init method
|
||||
/// </summary>
|
||||
public WebApiServer()
|
||||
: this(SplusKey, DefaultName, null)
|
||||
/// <summary>
|
||||
/// Ethernet event handler
|
||||
/// </summary>
|
||||
/// <param name="ethernetEventArgs"></param>
|
||||
void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
|
||||
{
|
||||
// Re-enable the server if the link comes back up and the status should be connected
|
||||
if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp && IsRegistered)
|
||||
{
|
||||
this.LogInformation("Ethernet link up. Server is already registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="basePath"></param>
|
||||
public WebApiServer(string key, string basePath)
|
||||
: this(key, DefaultName, basePath)
|
||||
this.LogInformation("Ethernet link up. Starting server");
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize method
|
||||
/// </summary>
|
||||
public void Initialize(string key, string basePath)
|
||||
{
|
||||
Key = key;
|
||||
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to CWS
|
||||
/// </summary>
|
||||
public void AddRoute(HttpCwsRoute route)
|
||||
{
|
||||
if (route == null)
|
||||
{
|
||||
this.LogWarning("Failed to add route, route parameter is null");
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="basePath"></param>
|
||||
public WebApiServer(string key, string name, string basePath)
|
||||
_server.Routes.Add(route);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a route from CWS
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <summary>
|
||||
/// RemoveRoute method
|
||||
/// </summary>
|
||||
public void RemoveRoute(HttpCwsRoute route)
|
||||
{
|
||||
if (route == null)
|
||||
{
|
||||
Key = key;
|
||||
Name = string.IsNullOrEmpty(name) ? DefaultName : name;
|
||||
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
|
||||
|
||||
if (_server == null) _server = new HttpCwsServer(BasePath);
|
||||
|
||||
_server.setProcessName(Key);
|
||||
_server.HttpRequestHandler = new DefaultRequestHandler();
|
||||
|
||||
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
|
||||
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
||||
this.LogWarning("Failed to remove route, route parameter is null");
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Program status event handler
|
||||
/// </summary>
|
||||
/// <param name="programEventType"></param>
|
||||
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||
{
|
||||
if (programEventType != eProgramStatusEventType.Stopping) return;
|
||||
_server.Routes.Remove(route);
|
||||
}
|
||||
|
||||
Debug.Console(DebugInfo, this, "Program stopping. stopping server");
|
||||
/// <summary>
|
||||
/// GetRouteCollection method
|
||||
/// </summary>
|
||||
public HttpCwsRouteCollection GetRouteCollection()
|
||||
{
|
||||
return _server.Routes;
|
||||
}
|
||||
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ethernet event handler
|
||||
/// </summary>
|
||||
/// <param name="ethernetEventArgs"></param>
|
||||
void CrestronEnvironment_EthernetEventHandler(EthernetEventArgs ethernetEventArgs)
|
||||
{
|
||||
// Re-enable the server if the link comes back up and the status should be connected
|
||||
if (ethernetEventArgs.EthernetEventType == eEthernetEventType.LinkUp && IsRegistered)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Ethernet link up. Server is alreedy registered.");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Console(DebugInfo, this, "Ethernet link up. Starting server");
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize method
|
||||
/// </summary>
|
||||
public void Initialize(string key, string basePath)
|
||||
{
|
||||
Key = key;
|
||||
BasePath = string.IsNullOrEmpty(basePath) ? DefaultBasePath : basePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to CWS
|
||||
/// </summary>
|
||||
public void AddRoute(HttpCwsRoute route)
|
||||
{
|
||||
if (route == null)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Failed to add route, route parameter is null");
|
||||
return;
|
||||
}
|
||||
|
||||
_server.Routes.Add(route);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a route from CWS
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <summary>
|
||||
/// RemoveRoute method
|
||||
/// </summary>
|
||||
public void RemoveRoute(HttpCwsRoute route)
|
||||
{
|
||||
if (route == null)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Failed to remote route, orute parameter is null");
|
||||
return;
|
||||
}
|
||||
|
||||
_server.Routes.Remove(route);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetRouteCollection method
|
||||
/// </summary>
|
||||
public HttpCwsRouteCollection GetRouteCollection()
|
||||
{
|
||||
return _server.Routes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts CWS instance
|
||||
/// </summary>
|
||||
public void Start()
|
||||
/// <summary>
|
||||
/// Starts CWS instance
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
lock (_serverLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_serverLock.Enter();
|
||||
|
||||
if (_server == null)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Server is null, unable to start");
|
||||
this.LogDebug("Server is null, unable to start");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsRegistered)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Server has already been started");
|
||||
this.LogDebug("Server has already been started");
|
||||
return;
|
||||
}
|
||||
|
||||
IsRegistered = _server.Register();
|
||||
|
||||
Debug.Console(DebugInfo, this, "Starting server, registration {0}", IsRegistered ? "was successful" : "failed");
|
||||
this.LogDebug("Starting server, registration {0}", IsRegistered ? "was successful" : "failed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Start Exception Message: {0}", ex.Message);
|
||||
Debug.Console(DebugVerbose, this, "Start Exception StackTrace: {0}", ex.StackTrace);
|
||||
if (ex.InnerException != null)
|
||||
Debug.Console(DebugVerbose, this, "Start Exception InnerException: {0}", ex.InnerException);
|
||||
this.LogException(ex, "Start Exception Message: {0}", ex.Message);
|
||||
this.LogVerbose("Start Exception StackTrace: {0}", ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_serverLock.Leave();
|
||||
}
|
||||
}
|
||||
} // end lock
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop method
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
/// <summary>
|
||||
/// Stop method
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
lock (_serverLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_serverLock.Enter();
|
||||
|
||||
if (_server == null)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Server is null or has already been stopped");
|
||||
this.LogDebug("Server is null or has already been stopped");
|
||||
return;
|
||||
}
|
||||
|
||||
IsRegistered = _server.Unregister() == false;
|
||||
|
||||
Debug.Console(DebugInfo, this, "Stopping server, unregistration {0}", IsRegistered ? "failed" : "was successful");
|
||||
this.LogDebug("Stopping server, unregistration {0}", IsRegistered ? "failed" : "was successful");
|
||||
|
||||
_server.Dispose();
|
||||
_server = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "Server Stop Exception Message: {0}", ex.Message);
|
||||
Debug.Console(DebugVerbose, this, "Server Stop Exception StackTrace: {0}", ex.StackTrace);
|
||||
if (ex.InnerException != null)
|
||||
Debug.Console(DebugVerbose, this, "Server Stop Exception InnerException: {0}", ex.InnerException);
|
||||
this.LogException(ex, "Server Stop Exception Message: {0}", ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_serverLock.Leave();
|
||||
}
|
||||
}
|
||||
} // end lock
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Received request handler
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is here for development and testing
|
||||
/// </remarks>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args)
|
||||
/// <summary>
|
||||
/// Received request handler
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is here for development and testing
|
||||
/// </remarks>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
public void ReceivedRequestEventHandler(object sender, HttpCwsRequestEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
var j = JsonConvert.SerializeObject(args.Context, Formatting.Indented);
|
||||
Debug.Console(DebugVerbose, this, "RecieveRequestEventHandler Context:\x0d\x0a{0}", j);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Console(DebugInfo, this, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message);
|
||||
Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace);
|
||||
if (ex.InnerException != null)
|
||||
Debug.Console(DebugVerbose, this, "ReceivedRequestEventHandler Exception InnerException: {0}", ex.InnerException);
|
||||
}
|
||||
var j = JsonConvert.SerializeObject(args.Context, Formatting.Indented);
|
||||
this.LogVerbose("RecieveRequestEventHandler Context:\x0d\x0a{0}", j);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogException(ex, "ReceivedRequestEventHandler Exception Message: {0}", ex.Message);
|
||||
this.LogVerbose("ReceivedRequestEventHandler Exception StackTrace: {0}", ex.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue